<commit_before>//! Serde integration support.

use std::fmt;
use std::marker::PhantomData;

use serde::*;
use serde::de::{Visitor, Error, Unexpected};

fn i64_to_u64<'d, V: Visitor<'d>, E: Error>(v: V, n: i64) -> Result<V::Value, E> {
	if n >= 0 {
		v.visit_u64(n as u64)
	} else {
		Err(E::invalid_value(Unexpected::Signed(n), &v))
	}
}

/// Ignore deserialization errors and revert to default.
pub fn ignore_errors<'d, T: Deserialize<'d> + Default, D: Deserializer<'d>>(d: D) -> Result<T, D::Error> {
	use serde_json::Value;

	let v = Value::deserialize(d)?;
   	Ok(T::deserialize(v).ok().unwrap_or_default())
}

/// Deserialize a maybe-string ID into a u64.
pub fn deserialize_id<'d, D: Deserializer<'d>>(d: D) -> Result<u64, D::Error> {
	struct IdVisitor;
	impl<'d> Visitor<'d> for IdVisitor {
		type Value = u64;

		fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
			write!(fmt, "a u64 or parseable string")
		}

		fn visit_i64<E: Error>(self, v: i64) -> Result<u64, E> {
			i64_to_u64(self, v)
		}

		fn visit_u64<E: Error>(self, v: u64) -> Result<u64, E> {
			Ok(v)
		}

		fn visit_str<E: Error>(self, v: &str) -> Result<u64, E> {
			v.parse::<u64>().map_err(|_| E::invalid_value(Unexpected::Str(v), &self))
		}
	}

	d.deserialize_any(IdVisitor)
}

/// Deserialize a maybe-string discriminator into a u16.
/// Also enforces 0 <= N <= 9999.
#[allow(unused_comparisons)]
pub fn deserialize_discrim<'d, D: Deserializer<'d>>(d: D) -> Result<u16, D::Error> {
	macro_rules! check {
		($self:ident, $v:ident, $wrong:expr) => {
			if $v >= 0 && $v <= 9999 {
				Ok($v as u16)
			} else {
				Err(E::invalid_value($wrong, &$self))
			}
		}
	}

	struct DiscrimVisitor;
	impl<'d> Visitor<'d> for DiscrimVisitor {
		type Value = u16;

		fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
			write!(fmt, "a u16 in [0, 9999] or parseable string")
		}

		fn visit_i64<E: Error>(self, v: i64) -> Result<u16, E> {
			check!(self, v, Unexpected::Signed(v))
		}

		fn visit_u64<E: Error>(self, v: u64) -> Result<u16, E> {
			check!(self, v, Unexpected::Unsigned(v))
		}

		fn visit_str<E: Error>(self, v: &str) -> Result<u16, E> {
			v.parse::<u16>()
				.map_err(|_| E::invalid_value(Unexpected::Str(v), &self))
				.and_then(|v| self.visit_u16(v))
		}
	}

	d.deserialize_any(DiscrimVisitor)
}

/// Deserialize a single-field struct like a newtype struct.
macro_rules! serial_single_field {
	($typ:ident as $field:ident: $inner:path) => {
		impl ::serde::Serialize for $typ {
			fn serialize<S: ::serde::ser::Serializer>(&self, s: S) -> ::std::result::Result<S::Ok, S::Error> {
				self.$field.serialize(s)
			}
		}

		impl<'d> ::serde::Deserialize<'d> for $typ {
			fn deserialize<D: ::serde::de::Deserializer<'d>>(d: D) -> ::std::result::Result<$typ, D::Error> {
				<$inner as ::serde::de::Deserialize>::deserialize(d).map(|v| $typ { $field: v })
			}
		}
	}
}

/// Special support for the oddly complex `ReactionEmoji`.
pub mod reaction_emoji {
	use super::*;
	use model::{ReactionEmoji, EmojiId};

	#[derive(Serialize)]
	struct EmojiSer<'s> {
		name: &'s str,
		id: Option<EmojiId>
	}

	#[derive(Deserialize)]
	struct EmojiDe {
		name: String,
		id: Option<EmojiId>,
	}

	pub fn serialize<S: Serializer>(v: &ReactionEmoji, s: S) -> Result<S::Ok, S::Error> {
		(match *v {
			ReactionEmoji::Unicode(ref name) => EmojiSer { name: name, id: None },
			ReactionEmoji::Custom { ref name, id } => EmojiSer { name: name, id: Some(id) },
		}).serialize(s)
	}

	pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<ReactionEmoji, D::Error> {
		Ok(match try!(EmojiDe::deserialize(d)) {
			EmojiDe { name, id: None } => ReactionEmoji::Unicode(name),
			EmojiDe { name, id: Some(id) } => ReactionEmoji::Custom { name: name, id: id },
		})
	}
}

/// Support for named enums.
pub mod named {
	use super::*;

	pub trait NamedEnum: Sized {
		fn name(&self) -> &'static str;
		fn from_name(name: &str) -> Option<Self>;
		fn typename() -> &'static str;
	}

	pub fn serialize<T: NamedEnum, S: Serializer>(v: &T, s: S) -> Result<S::Ok, S::Error> {
		v.name().serialize(s)
	}

	pub fn deserialize<'d, T: NamedEnum, D: Deserializer<'d>>(d: D) -> Result<T, D::Error> {
		struct NameVisitor<T>(PhantomData<T>);
		impl<'d, T: NamedEnum> Visitor<'d> for NameVisitor<T> {
			type Value = T;

			fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
				write!(fmt, "a valid {} name", T::typename())
			}

			fn visit_str<E: Error>(self, v: &str) -> Result<T, E> {
				T::from_name(v).ok_or_else(|| E::invalid_value(Unexpected::Str(v), &self))
			}
		}

		d.deserialize_string(NameVisitor(PhantomData))
	}
}
macro_rules! serial_names {
	($typ:ident; $($entry:ident, $value:expr;)*) => {
		impl $typ {
			pub fn name(&self) -> &'static str {
				match *self {
					$($typ::$entry => $value,)*
				}
			}

			pub fn from_name(name: &str) -> Option<Self> {
				match name {
					$($value => Some($typ::$entry),)*
					_ => None,
				}
			}
		}

		impl ::serial::named::NamedEnum for $typ {
			fn name(&self) -> &'static str {
				self.name()
			}

			fn from_name(name: &str) -> Option<Self> {
				Self::from_name(name)
			}

			fn typename() -> &'static str {
				stringify!($typ)
			}
		}
	}
}

/// Support for numeric enums.
pub mod numeric {
	use super::*;

	pub trait NumericEnum: Sized {
		fn num(&self) -> u64;
		fn from_num(num: u64) -> Option<Self>;
		fn typename() -> &'static str;
	}

	pub fn serialize<T: NumericEnum, S: Serializer>(v: &T, s: S) -> Result<S::Ok, S::Error> {
		v.num().serialize(s)
	}

	pub fn deserialize<'d, T: NumericEnum, D: Deserializer<'d>>(d: D) -> Result<T, D::Error> {
		struct NumVisitor<T>(PhantomData<T>);
		impl<'d, T: NumericEnum> Visitor<'d> for NumVisitor<T> {
			type Value = T;

			fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
				write!(fmt, "a valid {} number", T::typename())
			}

			fn visit_i64<E: Error>(self, v: i64) -> Result<T, E> {
				i64_to_u64(self, v)
			}

			fn visit_u64<E: Error>(self, v: u64) -> Result<T, E> {
				T::from_num(v).ok_or_else(|| E::invalid_value(Unexpected::Unsigned(v), &self))
			}
		}

		d.deserialize_string(NumVisitor(PhantomData))
	}
}
macro_rules! serial_numbers {
	($typ:ident; $($entry:ident, $value:expr;)*) => {
		impl $typ {
			pub fn num(&self) -> u64 {
				match *self {
					$($typ::$entry => $value,)*
				}
			}

			pub fn from_num(num: u64) -> Option<Self> {
				match num {
					$($value => Some($typ::$entry),)*
					_ => None,
				}
			}
		}
		impl ::serial::numeric::NumericEnum for $typ {
			fn num(&self) -> u64 {
				self.num()
			}

			fn from_num(num: u64) -> Option<Self> {
				Self::from_num(num)
			}

			fn typename() -> &'static str {
				stringify!($typ)
			}
		}
	}
}

/// Support for using "named" or "numeric" as the default ser/de impl.
macro_rules! serial_use_mapping {
	($typ:ident, $which:ident) => {
		impl ::serde::Serialize for $typ {
			#[inline]
			fn serialize<S: ::serde::ser::Serializer>(&self, s: S) -> ::std::result::Result<S::Ok, S::Error> {
				::serial::$which::serialize(self, s)
			}
		}

		impl<'d> ::serde::Deserialize<'d> for $typ {
			#[inline]
			fn deserialize<D: ::serde::de::Deserializer<'d>>(d: D) -> ::std::result::Result<$typ, D::Error> {
				::serial::$which::deserialize(d)
			}
		}
	}
}
<commit_msg>Update serial.rs<commit_after>//! Serde integration support.

use std::fmt;
use std::marker::PhantomData;

use serde::*;
use serde::de::{Visitor, Error, Unexpected};

fn i64_to_u64<'d, V: Visitor<'d>, E: Error>(v: V, n: i64) -> Result<V::Value, E> {
	if n >= 0 {
		v.visit_u64(n as u64)
	} else {
		Err(E::invalid_value(Unexpected::Signed(n), &v))
	}
}

/// Ignore deserialization errors and revert to default.
pub fn ignore_errors<'d, T: Deserialize<'d> + Default, D: Deserializer<'d>>(d: D) -> Result<T, D::Error> {
	use serde_json::Value;

	let v = Value::deserialize(d)?;
   	Ok(T::deserialize(v).ok().unwrap_or_default())
}

/// Deserialize a maybe-string ID into a u64.
pub fn deserialize_id<'d, D: Deserializer<'d>>(d: D) -> Result<u64, D::Error> {
	struct IdVisitor;
	impl<'d> Visitor<'d> for IdVisitor {
		type Value = u64;

		fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
			write!(fmt, "a u64 or parseable string")
		}

		fn visit_i64<E: Error>(self, v: i64) -> Result<u64, E> {
			i64_to_u64(self, v)
		}

		fn visit_u64<E: Error>(self, v: u64) -> Result<u64, E> {
			Ok(v)
		}

		fn visit_str<E: Error>(self, v: &str) -> Result<u64, E> {
			v.parse::<u64>().map_err(|_| E::invalid_value(Unexpected::Str(v), &self))
		}
	}

	d.deserialize_any(IdVisitor)
}

/// Deserialize a maybe-string discriminator into a u16.
/// Also enforces 0 <= N <= 9999.
#[allow(unused_comparisons)]
pub fn deserialize_discrim<'d, D: Deserializer<'d>>(d: D) -> Result<u16, D::Error> {
	macro_rules! check {
		($self:ident, $v:ident, $wrong:expr) => {
			if $v >= 0 && $v <= 9999 {
				Ok($v as u16)
			} else {
				Err(E::invalid_value($wrong, &$self))
			}
		}
	}

	struct DiscrimVisitor;
	impl<'d> Visitor<'d> for DiscrimVisitor {
		type Value = u16;

		fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
			write!(fmt, "a u16 in [0, 9999] or parseable string")
		}

		fn visit_i64<E: Error>(self, v: i64) -> Result<u16, E> {
			check!(self, v, Unexpected::Signed(v))
		}

		fn visit_u64<E: Error>(self, v: u64) -> Result<u16, E> {
			check!(self, v, Unexpected::Unsigned(v))
		}

		fn visit_str<E: Error>(self, v: &str) -> Result<u16, E> {
			v.parse::<u16>()
				.map_err(|_| E::invalid_value(Unexpected::Str(v), &self))
				.and_then(|v| self.visit_u16(v))
		}
	}

	d.deserialize_any(DiscrimVisitor)
}

/// Deserialize a single-field struct like a newtype struct.
macro_rules! serial_single_field {
	($typ:ident as $field:ident: $inner:path) => {
		impl ::serde::Serialize for $typ {
			fn serialize<S: ::serde::ser::Serializer>(&self, s: S) -> ::std::result::Result<S::Ok, S::Error> {
				self.$field.serialize(s)
			}
		}

		impl<'d> ::serde::Deserialize<'d> for $typ {
			fn deserialize<D: ::serde::de::Deserializer<'d>>(d: D) -> ::std::result::Result<$typ, D::Error> {
				<$inner as ::serde::de::Deserialize>::deserialize(d).map(|v| $typ { $field: v })
			}
		}
	}
}

/// Special support for the oddly complex `ReactionEmoji`.
pub mod reaction_emoji {
	use super::*;
	use model::{ReactionEmoji, EmojiId};

	#[derive(Serialize)]
	struct EmojiSer<'s> {
		name: &'s str,
		id: Option<EmojiId>
	}

	#[derive(Deserialize)]
	struct EmojiDe {
		name: String,
		id: Option<EmojiId>,
	}

	pub fn serialize<S: Serializer>(v: &ReactionEmoji, s: S) -> Result<S::Ok, S::Error> {
		(match *v {
			ReactionEmoji::Unicode(ref name) => EmojiSer { name: name, id: None },
			ReactionEmoji::Custom { ref name, id } => EmojiSer { name: name, id: Some(id) },
		}).serialize(s)
	}

	pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<ReactionEmoji, D::Error> {
		Ok(match try!(EmojiDe::deserialize(d)) {
			EmojiDe { name, id: None } => ReactionEmoji::Unicode(name),
			EmojiDe { name, id: Some(id) } => ReactionEmoji::Custom { name: name, id: id },
		})
	}
}

/// Support for named enums.
pub mod named {
	use super::*;

	pub trait NamedEnum: Sized {
		fn name(&self) -> &'static str;
		fn from_name(name: &str) -> Option<Self>;
		fn typename() -> &'static str;
	}

	pub fn serialize<T: NamedEnum, S: Serializer>(v: &T, s: S) -> Result<S::Ok, S::Error> {
		v.name().serialize(s)
	}

	pub fn deserialize<'d, T: NamedEnum, D: Deserializer<'d>>(d: D) -> Result<T, D::Error> {
		struct NameVisitor<T>(PhantomData<T>);
		impl<'d, T: NamedEnum> Visitor<'d> for NameVisitor<T> {
			type Value = T;

			fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
				write!(fmt, "a valid {} name", T::typename())
			}

			fn visit_str<E: Error>(self, v: &str) -> Result<T, E> {
				T::from_name(v).ok_or_else(|| E::invalid_value(Unexpected::Str(v), &self))
			}
		}

		d.deserialize_string(NameVisitor(PhantomData))
	}
}
macro_rules! serial_names {
	($typ:ident; $($entry:ident, $value:expr;)*) => {
		impl $typ {
			pub fn name(&self) -> &'static str {
				match *self {
					$($typ::$entry => $value,)*
				}
			}

			pub fn from_name(name: &str) -> Option<Self> {
				match name {
					$($value => Some($typ::$entry),)*
					_ => None,
				}
			}
		}

		impl ::serial::named::NamedEnum for $typ {
			fn name(&self) -> &'static str {
				self.name()
			}

			fn from_name(name: &str) -> Option<Self> {
				Self::from_name(name)
			}

			fn typename() -> &'static str {
				stringify!($typ)
			}
		}
	}
}

/// Support for numeric enums.
pub mod numeric {
	use super::*;

	pub trait NumericEnum: Sized {
		fn num(&self) -> u64;
		fn from_num(num: u64) -> Option<Self>;
		fn typename() -> &'static str;
	}

	pub fn serialize<T: NumericEnum, S: Serializer>(v: &T, s: S) -> Result<S::Ok, S::Error> {
		v.num().serialize(s)
	}

	pub fn deserialize<'d, T: NumericEnum, D: Deserializer<'d>>(d: D) -> Result<T, D::Error> {
		struct NumVisitor<T>(PhantomData<T>);
		impl<'d, T: NumericEnum> Visitor<'d> for NumVisitor<T> {
			type Value = T;

			fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
				write!(fmt, "a valid {} number", T::typename())
			}

			fn visit_i64<E: Error>(self, v: i64) -> Result<T, E> {
				i64_to_u64(self, v)
			}

			fn visit_u64<E: Error>(self, v: u64) -> Result<T, E> {
				T::from_num(v).ok_or_else(|| E::invalid_value(Unexpected::Unsigned(v), &self))
			}
		}

		d.deserialize_any(NumVisitor(PhantomData))
	}
}
macro_rules! serial_numbers {
	($typ:ident; $($entry:ident, $value:expr;)*) => {
		impl $typ {
			pub fn num(&self) -> u64 {
				match *self {
					$($typ::$entry => $value,)*
				}
			}

			pub fn from_num(num: u64) -> Option<Self> {
				match num {
					$($value => Some($typ::$entry),)*
					_ => None,
				}
			}
		}
		impl ::serial::numeric::NumericEnum for $typ {
			fn num(&self) -> u64 {
				self.num()
			}

			fn from_num(num: u64) -> Option<Self> {
				Self::from_num(num)
			}

			fn typename() -> &'static str {
				stringify!($typ)
			}
		}
	}
}

/// Support for using "named" or "numeric" as the default ser/de impl.
macro_rules! serial_use_mapping {
	($typ:ident, $which:ident) => {
		impl ::serde::Serialize for $typ {
			#[inline]
			fn serialize<S: ::serde::ser::Serializer>(&self, s: S) -> ::std::result::Result<S::Ok, S::Error> {
				::serial::$which::serialize(self, s)
			}
		}

		impl<'d> ::serde::Deserialize<'d> for $typ {
			#[inline]
			fn deserialize<D: ::serde::de::Deserializer<'d>>(d: D) -> ::std::result::Result<$typ, D::Error> {
				::serial::$which::deserialize(d)
			}
		}
	}
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate router;
extern crate rustc_serialize;

use std::io::Read;

use iron::prelude::*;
use iron::status;
use router::Router;
use rustc_serialize::json;

#[derive(RustcDecodable, RustcEncodable)]
struct Greeting {
    msg: String
}

fn main() {
    let mut router = Router::new();

    router.get("/", hello_world);
    router.post("/set", set_greeting);

    fn hello_world(_: &mut Request) -> IronResult<Response> {
        println!("Request for route '/'");
        let greeting = Greeting { msg: "Hello, World".to_string() };
        let payload = json::encode(&greeting).unwrap();
        println!("Responded with: {}", payload);
        Ok(Response::with((status::Ok, payload)))
    }

    // Receive a message by POST and play it back.
    fn set_greeting(req: &mut Request) -> IronResult<Response> {
        println!("Request for route '/set'");
        let mut payload = String::new();
        req.body.read_to_string(&mut payload).unwrap();
        let request: Greeting = json::decode(&payload).unwrap();
        let greeting = Greeting { msg: request.msg };
        let payload = json::encode(&greeting).unwrap();
        println!("Responded with: {}", payload);
        Ok(Response::with((status::Ok, payload)))
    }

    Iron::new(router).http("localhost:3000").unwrap();
}
<commit_msg>Issue #2: Basic worker setup for handling jobs from HTTP requests<commit_after>extern crate iron;
extern crate router;
extern crate rustc_serialize;

use std::collections::VecDeque;
use std::io::Read;
use std::sync::{Mutex, Arc, Condvar};
use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc;
use std::thread;

use iron::prelude::*;
use iron::status;
use router::Router;
use rustc_serialize::json;

#[derive(RustcDecodable, RustcEncodable)]
struct GetRequest {
    key: String
}

#[derive(RustcDecodable, RustcEncodable)]
struct GetResponse {
    value: u32
}

#[derive(RustcDecodable, RustcEncodable)]
struct SetRequest {
    key: String,
    value: u32
}

#[derive(RustcDecodable, RustcEncodable)]
struct SetResponse {
    status: u32
}

struct Job {
    number: u32,
    chan: Sender<u32>
}

fn get_value(_: &mut Request, queue_mut: &Mutex<VecDeque<Job>>, signal: &Condvar) -> IronResult<Response> {
    println!("Request for route '/json'");
    let (tx, rx) : (Sender<u32>, Receiver<u32>)= mpsc::channel();
    let j = Job { number: 0, chan: tx};
    {
        let mut queue = queue_mut.lock().unwrap();
        queue.push_back(j);
    }
    signal.notify_one();

    let result : u32 = rx.recv().unwrap();
    let response = GetResponse{ value: result };
    let response_string = json::encode(&response).unwrap();

    println!("Responded with: {}", response_string);
    Ok(Response::with((status::Ok, response_string)))
}

fn set_value(req: &mut Request, queue_mut: &Mutex<VecDeque<Job>>, signal: &Condvar) -> IronResult<Response> {
    println!("Request for route '/json/set'");
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();
    let set_req : SetRequest = json::decode(&payload).unwrap();

    let (tx, rx) : (Sender<u32>, Receiver<u32>)= mpsc::channel();

    let j = Job { number: set_req.value, chan: tx};
    {
        let mut queue = queue_mut.lock().unwrap();
        queue.push_back(j);
    }
    signal.notify_all();

    let result : u32 = rx.recv().unwrap();

    let response = SetResponse{ status: result };
    let response_string = json::encode(&response).unwrap();

    println!("Resut for /set/json: {}", response_string);
    Ok(Response::with(status::Ok))
}

fn main() {

    let queue : Arc<Mutex<VecDeque<Job>>> = Arc::new(Mutex::new(VecDeque::new()));
    let signal : Arc<Condvar> = Arc::new(Condvar::new());

    let num_workers = 3;

    for i in 0..num_workers {
        let queue_clone = queue.clone();
        let signal_clone = signal.clone();

        thread::spawn(move || {
            println!("Starting worker {}", i);
            let mut counter = 0;
            let mut j: Job;
            loop {
                loop {
                    let mut q = queue_clone.lock().unwrap();
                    q = signal_clone.wait(q).unwrap();
                    j = match q.pop_front() {
                        Some(x) => x,
                        None => continue
                    };
                    break;
                }
                println!("Worker {}: received job {}", i, counter);
                let new_value = j.number + 100;
                thread::sleep_ms(10000);
                j.chan.send(new_value).unwrap();
                counter += 1;
            }
            println!("Ending worker {}", i);
        });
    }

    let mut router = Router::new();

    let queue_2 = queue.clone();
    let queue_3 = queue.clone();
    let signal_2 = signal.clone();
    let signal_3 = signal.clone();

    router.get("/json", move |r: &mut Request| get_value(r, &queue_2, &signal_2));
    router.post("/json/set", move |r: &mut Request| set_value(r, &queue_3, &signal_3));

    println!("Starting ComposeDB.");
    Iron::new(router).http("localhost:3000").unwrap();

}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the MIT License, <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

use {REMOTE, net2};
use bincode::serde::DeserializeError;
use errors::WireError;
use framed::Proto;
use futures::{self, Async, Future, Stream};
use serde::{Deserialize, Serialize};
use std::io;
use std::net::SocketAddr;
use tokio_core::net::TcpListener;
use tokio_core::reactor::Handle;
use tokio_proto::BindServer;
use tokio_service::NewService;

/// A message from server to client.
pub type Response<T, E> = Result<T, WireError<E>>;

/// Spawns a service that binds to the given address and runs on the default reactor core.
pub fn listen<S, Req, Resp, E>(addr: SocketAddr, new_service: S) -> ListenFuture
    where S: NewService<Request = Result<Req, DeserializeError>,
                        Response = Response<Resp, E>,
                        Error = io::Error> + Send + 'static,
          Req: Deserialize + 'static,
          Resp: Serialize + 'static,
          E: Serialize + 'static
{
    let (tx, rx) = futures::oneshot();
    REMOTE.spawn(move |handle| Ok(tx.complete(listen_with(addr, new_service, handle.clone()))));
    ListenFuture { inner: rx }
}

/// Spawns a service that binds to the given address using the given handle.
pub fn listen_with<S, Req, Resp, E>(addr: SocketAddr,
                                    new_service: S,
                                    handle: Handle)
                                    -> io::Result<SocketAddr>
    where S: NewService<Request = Result<Req, DeserializeError>,
                        Response = Response<Resp, E>,
                        Error = io::Error> + Send + 'static,
          Req: Deserialize + 'static,
          Resp: Serialize + 'static,
          E: Serialize + 'static
{
    let listener = listener(&addr, &handle)?;
    let addr = listener.local_addr()?;

    let handle2 = handle.clone();
    let server = listener.incoming().for_each(move |(socket, _)| {
        Proto::new().bind_server(&handle2, socket, new_service.new_service()?);

        Ok(())
    }).map_err(|e| error!("While processing incoming connections: {}", e));
    handle.spawn(server);
    Ok(addr)
}

fn listener(addr: &SocketAddr,
            handle: &Handle) -> io::Result<TcpListener> {
    const PENDING_CONNECTION_BACKLOG = 1024;

    match *addr {
        SocketAddr::V4(_) => net2::TcpBuilder::new_v4(),
        SocketAddr::V6(_) => net2::TcpBuilder::new_v6()
    }?
    .reuse_address(true)?
    .bind(addr)?
    .listen(PENDING_CONNECTION_BACKLOG)
    .and_then(|l| {
        TcpListener::from_listener(l, addr, handle)
    })
}

/// A future that resolves to a `ServerHandle`.
pub struct ListenFuture {
    inner: futures::Oneshot<io::Result<SocketAddr>>,
}

impl ListenFuture {
    #[doc(hidden)]
    pub fn from_oneshot(rx: futures::Oneshot<io::Result<SocketAddr>>) -> Self {
        ListenFuture { inner: rx }
    }
}

impl Future for ListenFuture {
    type Item = SocketAddr;
    type Error = io::Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        // Can't panic the oneshot is always completed.
        match self.inner.poll().unwrap() {
            Async::Ready(result) => result.map(Async::Ready),
            Async::NotReady => Ok(Async::NotReady),
        }
    }
}
<commit_msg>Make connection backlog arg to listen a const<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the MIT License, <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

use {REMOTE, net2};
use bincode::serde::DeserializeError;
use errors::WireError;
use framed::Proto;
use futures::{self, Async, Future, Stream};
use serde::{Deserialize, Serialize};
use std::io;
use std::net::SocketAddr;
use tokio_core::net::TcpListener;
use tokio_core::reactor::Handle;
use tokio_proto::BindServer;
use tokio_service::NewService;

/// A message from server to client.
pub type Response<T, E> = Result<T, WireError<E>>;

/// Spawns a service that binds to the given address and runs on the default reactor core.
pub fn listen<S, Req, Resp, E>(addr: SocketAddr, new_service: S) -> ListenFuture
    where S: NewService<Request = Result<Req, DeserializeError>,
                        Response = Response<Resp, E>,
                        Error = io::Error> + Send + 'static,
          Req: Deserialize + 'static,
          Resp: Serialize + 'static,
          E: Serialize + 'static
{
    let (tx, rx) = futures::oneshot();
    REMOTE.spawn(move |handle| Ok(tx.complete(listen_with(addr, new_service, handle.clone()))));
    ListenFuture { inner: rx }
}

/// Spawns a service that binds to the given address using the given handle.
pub fn listen_with<S, Req, Resp, E>(addr: SocketAddr,
                                    new_service: S,
                                    handle: Handle)
                                    -> io::Result<SocketAddr>
    where S: NewService<Request = Result<Req, DeserializeError>,
                        Response = Response<Resp, E>,
                        Error = io::Error> + Send + 'static,
          Req: Deserialize + 'static,
          Resp: Serialize + 'static,
          E: Serialize + 'static
{
    let listener = listener(&addr, &handle)?;
    let addr = listener.local_addr()?;

    let handle2 = handle.clone();
    let server = listener.incoming().for_each(move |(socket, _)| {
        Proto::new().bind_server(&handle2, socket, new_service.new_service()?);

        Ok(())
    }).map_err(|e| error!("While processing incoming connections: {}", e));
    handle.spawn(server);
    Ok(addr)
}

fn listener(addr: &SocketAddr,
            handle: &Handle) -> io::Result<TcpListener> {
    const PENDING_CONNECTION_BACKLOG: i32 = 1024;

    match *addr {
        SocketAddr::V4(_) => net2::TcpBuilder::new_v4(),
        SocketAddr::V6(_) => net2::TcpBuilder::new_v6()
    }?
    .reuse_address(true)?
    .bind(addr)?
    .listen(PENDING_CONNECTION_BACKLOG)
    .and_then(|l| {
        TcpListener::from_listener(l, addr, handle)
    })
}

/// A future that resolves to a `ServerHandle`.
pub struct ListenFuture {
    inner: futures::Oneshot<io::Result<SocketAddr>>,
}

impl ListenFuture {
    #[doc(hidden)]
    pub fn from_oneshot(rx: futures::Oneshot<io::Result<SocketAddr>>) -> Self {
        ListenFuture { inner: rx }
    }
}

impl Future for ListenFuture {
    type Item = SocketAddr;
    type Error = io::Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        // Can't panic the oneshot is always completed.
        match self.inner.poll().unwrap() {
            Async::Ready(result) => result.map(Async::Ready),
            Async::NotReady => Ok(Async::NotReady),
        }
    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use std::net::ToSocketAddrs;

use hyper::Server;
use hyper::server::{Listening, Request, Response};
use hyper::uri::RequestUri;
use hyper::header::ContentType;
use hyper::status::StatusCode;

use provider::{StaticProvider};

pub struct StaticWorker {
	listening: Listening,
}

impl Drop for StaticWorker {
	fn drop(&mut self) {
		let _ = self.listening.close();
	}
}

// TODO Add trait StaticMapCreater with fn(path) and update/read method
pub struct StaticServer {
	map: Arc<StaticProvider>,
}

impl StaticServer {

	pub fn new<T: StaticProvider>(map: T) -> Self {
		StaticServer { map: Arc::new(map) }
	}

	pub fn share<To: ToSocketAddrs>(&self, addr: To) -> Result<StaticWorker, ()> {
		let server = match Server::http(addr) {
			Ok(server) => server,
			Err(_) => return Err(()),
		};
		let map = self.map.clone();
		let handler = move |req: Request, mut res: Response| {
			match req.uri {
				RequestUri::AbsolutePath(mut apath) => {
					debug!("Request for static resource {}", apath);
					if apath.ends_with("/") {
						apath.push_str("index.html")
					}
					if let Some(spath) = apath.splitn(2, '?').next() {
						match map.get_content(&spath) {
							Some(item) => {
								*res.status_mut() = StatusCode::Ok;
								res.headers_mut().set(ContentType(item.mime.clone()));
								&res.send(&item.payload).unwrap();
							},
							None => *res.status_mut() = StatusCode::NotFound,
						}
					} else {
						*res.status_mut() = StatusCode::BadRequest;
					}
				},
				_ => *res.status_mut() = StatusCode::BadRequest,
			}
			//res.end();
		};
		// IMPORTANT! Browser blocks when there isn't enough threads!!!
		// That's because workers can't accept incomming connections in keep-alive state.
		match server.handle_threads(handler, 20) {
			Ok(listening) => {
				let worker = StaticWorker{ listening: listening};
				Ok(worker)
			},
			Err(_) => return Err(()),
		}
	}
}
<commit_msg>Fix: add index.html tail for requests with get parameters<commit_after>use std::sync::Arc;
use std::net::ToSocketAddrs;

use hyper::Server;
use hyper::server::{Listening, Request, Response};
use hyper::uri::RequestUri;
use hyper::header::ContentType;
use hyper::status::StatusCode;

use provider::{StaticProvider};

pub struct StaticWorker {
	listening: Listening,
}

impl Drop for StaticWorker {
	fn drop(&mut self) {
		let _ = self.listening.close();
	}
}

// TODO Add trait StaticMapCreater with fn(path) and update/read method
pub struct StaticServer {
	map: Arc<StaticProvider>,
}

impl StaticServer {

	pub fn new<T: StaticProvider>(map: T) -> Self {
		StaticServer { map: Arc::new(map) }
	}

	pub fn share<To: ToSocketAddrs>(&self, addr: To) -> Result<StaticWorker, ()> {
		let server = match Server::http(addr) {
			Ok(server) => server,
			Err(_) => return Err(()),
		};
		let map = self.map.clone();
		let handler = move |req: Request, mut res: Response| {
			match req.uri {
				RequestUri::AbsolutePath(apath) => {
					debug!("Request for static resource {}", apath);
					if let Some(spath) = apath.splitn(2, '?').next() {
						let mut spath = String::from(spath);
						if spath.ends_with("/") {
							spath.push_str("index.html")
						}
						match map.get_content(&spath) {
							Some(item) => {
								*res.status_mut() = StatusCode::Ok;
								res.headers_mut().set(ContentType(item.mime.clone()));
								&res.send(&item.payload).unwrap();
							},
							None => *res.status_mut() = StatusCode::NotFound,
						}
					} else {
						*res.status_mut() = StatusCode::BadRequest;
					}
				},
				_ => *res.status_mut() = StatusCode::BadRequest,
			}
			//res.end();
		};
		// IMPORTANT! Browser blocks when there isn't enough threads!!!
		// That's because workers can't accept incomming connections in keep-alive state.
		match server.handle_threads(handler, 20) {
			Ok(listening) => {
				let worker = StaticWorker{ listening: listening};
				Ok(worker)
			},
			Err(_) => return Err(()),
		}
	}
}
<|endoftext|>


<commit_before>use scaii_defs::protos::endpoint::Endpoint;
use scaii_defs::protos::{ModuleEndpoint, MultiMessage, ScaiiPacket};
use scaii_defs::{Agent, Backend, Module, Recorder, Replay};

use std::collections::HashMap;
use std::error::Error;
use std::fmt;
use std::fmt::{Display, Formatter};

/// Indicates an attempt to reach a module that has
/// not been registered.
#[derive(Clone, PartialEq, Debug)]
pub struct NoSuchEndpointError {
    end: Endpoint,
}

impl Display for NoSuchEndpointError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "No such registered module: {:?}", self.end)
    }
}

impl Error for NoSuchEndpointError {
    fn description(&self) -> &str {
        "Attempt to reach an nonexistant module"
    }
}

/// A simple Router that sends protobuf messages to various modules
#[derive(Default)]
pub struct Router {
    backend: Option<Box<Backend>>,
    agent: Option<Box<Agent>>,
    modules: HashMap<String, Box<Module>>,
    replay: Option<Box<Replay>>,
    recorder: Option<Box<Recorder>>,
}

impl Router {
    /// Initializes an empty Router.
    #[allow(dead_code)]
    pub fn new() -> Self {
        use internal::recorder::RecorderManager;
        Router {
            backend: None,
            agent: None,
            modules: HashMap::new(),
            replay: None,
            recorder: Some(Box::new(RecorderManager::new().expect(
                "Could not determine default replay directory when constructing recorder",
            ))),
        }
    }

    /// Initializes a Router with the specificed Backend instance.
    #[allow(dead_code)]
    pub fn from_backend(backend: Box<Backend>) -> Self {
        use internal::recorder::RecorderManager;
        Router {
            backend: Some(backend),
            agent: None,
            modules: HashMap::new(),
            replay: None,
            recorder: Some(Box::new(RecorderManager::new().expect(
                "Could not determine default replay directory when constructing recorder",
            ))),
        }
    }

    /// /// Initializes a Router with the specificed Agent instance.
    #[allow(dead_code)]
    pub fn from_agent(agent: Box<Agent>) -> Self {
        use internal::recorder::RecorderManager;
        Router {
            backend: None,
            agent: Some(agent),
            modules: HashMap::new(),
            replay: None,
            recorder: Some(Box::new(RecorderManager::new().expect(
                "Could not determine default replay directory when constructing recorder",
            ))),
        }
    }

    /// Decodes a MultiMessage
    /// and routes the resulting packet to the target.
    ///
    /// Any returned values will be any packages routed to the Core,
    /// including Errors the Core needs to forward to the owner module.
    pub fn decode_and_route(&mut self, msg: &MultiMessage) -> Vec<ScaiiPacket> {
        let mut core_msgs: Vec<ScaiiPacket> = Vec::new();
        use scaii_defs::protos::endpoint::Endpoint;
        use scaii_defs::protos::CoreEndpoint;

        for msg in &msg.packets {
            let dest = msg.dest.endpoint.as_ref().expect("Malformed dest field");
            let src = msg.src.endpoint.as_ref().expect("Malformed src field");
            if src == &Endpoint::Core(CoreEndpoint {}) {
                panic!(
                    "FATAL CORE ERROR:\
                     Core should not be using decode_and_route to send its messages."
                )
                //continue;
            }

            if dest == src {
                self.send_error(
                    &format!("Module attempted to send message to itself:\n\t{:?}", msg),
                    src,
                    &Endpoint::Core(CoreEndpoint {}),
                ).unwrap();
                continue;
            }

            match self.route_to(msg) {
                Err(err) => {
                    self.send_error(&format!("{}", err), src, &Endpoint::Core(CoreEndpoint {}))
                        .unwrap();
                }
                Ok(Some(packet)) => core_msgs.push(packet),
                Ok(None) => {}
            }
        }
        core_msgs
    }

    /// Routes the specified ScaiiPacket to the given destination.
    ///
    /// Returns an error if the specified destination does not exist, or if the
    /// target errors on receiving the message.
    pub fn route_to(&mut self, msg: &ScaiiPacket) -> Result<Option<ScaiiPacket>, Box<Error>> {
        let dest = msg.dest.endpoint.as_ref().expect("Malformed dest field");
        //println!("router routed {:?}", msg);
        match *dest {
            Endpoint::Backend(_) => {
                let res = self.backend.as_mut().and_then(|v| Some(v.process_msg(msg)));
                if let Some(Err(err)) = res {
                    return Err(err);
                } else if res.is_none() {
                    return Err(Box::new(NoSuchEndpointError { end: dest.clone() }));
                };

                Ok(None)
            }
            Endpoint::Agent(_) => {
                let res = self.agent.as_mut().and_then(|v| Some(v.process_msg(msg)));
                if let Some(Err(err)) = res {
                    return Err(err);
                } else if res.is_none() {
                    return Err(Box::new(NoSuchEndpointError { end: dest.clone() }));
                };

                Ok(None)
            }
            Endpoint::Core(_) => Ok(Some(msg.clone())),
            Endpoint::Module(ModuleEndpoint { ref name }) => {
                let res = self
                    .modules
                    .get_mut(name)
                    .and_then(|v| Some(v.process_msg(msg)));
                if let Some(Err(err)) = res {
                    return Err(err);
                } else if res.is_none() {
                    return Err(Box::new(NoSuchEndpointError { end: dest.clone() }));
                }

                Ok(None)
            }
            Endpoint::Replay(_) => {
                let res = self.replay.as_mut().and_then(|v| Some(v.process_msg(msg)));
                if let Some(Err(err)) = res {
                    return Err(err);
                } else if res.is_none() {
                    return Err(Box::new(NoSuchEndpointError { end: dest.clone() }));
                };

                Ok(None)
            }
            Endpoint::Recorder(_) => {
                let res = self
                    .recorder
                    .as_mut()
                    .and_then(|v| Some(v.process_msg(msg)));
                if let Some(Err(err)) = res {
                    return Err(err);
                } else if res.is_none() {
                    return Err(Box::new(NoSuchEndpointError { end: dest.clone() }));
                };
                Ok(None)
            }
        }
    }

    /// Processes any messages pending from non-owner modules.
    ///
    /// Any returned values will be any packages routed to the Core,
    /// including Errors the Core needs to forward to the owner module.
    pub fn process_module_messages(&mut self) -> Vec<ScaiiPacket> {
        let mut core_messages = Vec::new();
        // Most of the convoluted stuff here is to appease the borrow checker,
        // who thinks we're borrwing ourselves mutably twice if we call
        // `decode_and_route` within the `if let` or `for` blocks
        let msgs = if let Some(ref mut backend) = self.backend {
            backend.get_messages()
        } else {
            MultiMessage {
                packets: Vec::new(),
            }
        };
        core_messages.append(&mut self.decode_and_route(&msgs));

        let msgs = if let Some(ref mut agent) = self.agent {
            agent.get_messages()
        } else {
            MultiMessage {
                packets: Vec::new(),
            }
        };
        core_messages.append(&mut self.decode_and_route(&msgs));

        let mut msgs = Vec::with_capacity(self.modules.len());
        for module in self.modules.values_mut() {
            msgs.push(module.get_messages())
        }

        for msg in msgs {
            core_messages.append(&mut self.decode_and_route(&msg));
        }

        core_messages
    }

    /// Sends an error with the specified message to the given module
    ///
    /// This directly calls `route_to` for you, and panics on an error
    /// because we can't reasonable handle errors if we can't send them
    pub fn send_error(
        &mut self,
        msg: &str,
        dest: &Endpoint,
        src: &Endpoint,
    ) -> Result<Option<ScaiiPacket>, NoSuchEndpointError> {
        use scaii_defs::protos;
        use scaii_defs::protos::scaii_packet::SpecificMsg;

        if !self.endpoint_exists(dest) {
            return Err(NoSuchEndpointError { end: dest.clone() });
        }

        let error_packet = ScaiiPacket {
            dest: protos::Endpoint {
                endpoint: Some(dest.clone()),
            },
            src: protos::Endpoint {
                endpoint: Some(src.clone()),
            },
            specific_msg: Some(SpecificMsg::Err(protos::Error {
                description: msg.to_string(),
                fatal: None,
                error_info: None,
            })),
        };

        let panic_msg = "FATAL CORE ERROR: Cannot send error message from inside core";
        // At this point, we pretty much can't handle errors anymore
        Ok(self.route_to(&error_packet).expect(panic_msg))
    }

    /// Determines if a given RouterEndpoint has been registered with this Router.
    pub fn endpoint_exists(&self, end: &Endpoint) -> bool {
        match *end {
            Endpoint::Core(_) => true,
            Endpoint::Backend(_) => self.backend.is_some(),
            Endpoint::Agent(_) => self.agent.is_some(),
            Endpoint::Replay(_) => self.replay.is_some(),
            Endpoint::Recorder(_) => self.recorder.is_some(),
            Endpoint::Module(ModuleEndpoint { ref name }) => self.modules.get(name).is_some(),
        }
    }

    /// Returns a reference to the registered backend (if any).
    #[allow(dead_code, borrowed_box)]
    pub fn backend(&self) -> Option<&Box<Backend>> {
        self.backend.as_ref()
    }

    /// Returns a mutable reference to the registered backend (if any).
    #[allow(dead_code, borrowed_box)]
    pub fn backend_mut(&mut self) -> Option<&mut Box<Backend>> {
        self.backend.as_mut()
    }

    /// Registers a new backend, returning the old one if one existed.
    #[allow(dead_code)]
    pub fn register_backend(&mut self, backend: Box<Backend>) -> Option<Box<Backend>> {
        use std::mem;
        mem::replace(&mut self.backend, Some(backend))
    }

    /// Registers a new replayer, returning the old one if one existed.
    #[allow(dead_code)]
    pub fn register_replay(&mut self, replay: Box<Replay>) -> Option<Box<Replay>> {
        use std::mem;
        mem::replace(&mut self.replay, Some(replay))
    }

    #[allow(dead_code, borrowed_box)]
    pub fn replay(&self) -> Option<&Box<Replay>> {
        self.replay.as_ref()
    }

    /// Registers a new recorder, returning the old one if one existed.
    #[allow(dead_code)]
    pub fn register_recorder(&mut self, recorder: Box<Recorder>) -> Option<Box<Recorder>> {
        use std::mem;
        mem::replace(&mut self.recorder, Some(recorder))
    }

    #[allow(dead_code, borrowed_box)]
    pub fn recorder(&self) -> Option<&Box<Recorder>> {
        self.recorder.as_ref()
    }

    /// Returns a reference to the registered agent (if any).
    #[allow(dead_code, borrowed_box)]
    pub fn agent(&self) -> Option<&Box<Agent>> {
        self.agent.as_ref()
    }

    /// Returns a mutable reference to the registered agent (if any).
    #[allow(dead_code, borrowed_box)]
    pub fn agent_mut(&mut self) -> Option<&mut Box<Agent>> {
        self.agent.as_mut()
    }

    /// Registers a new agent, returning the old one if one existed.
    #[allow(dead_code)]
    pub fn register_agent(&mut self, agent: Box<Agent>) -> Option<Box<Agent>> {
        use std::mem;
        mem::replace(&mut self.agent, Some(agent))
    }

    /// Returns a reference to the specified module (if it exists).
    #[allow(dead_code, borrowed_box)]
    pub fn module(&self, name: &str) -> Option<&Box<Module>> {
        self.modules.get(name)
    }

    /// Returns a mutable reference to the specified module (if it exists).
    #[allow(dead_code, borrowed_box)]
    pub fn module_mut(&mut self, name: &str) -> Option<&mut Box<Module>> {
        self.modules.get_mut(name)
    }

    /// Registers the module under the given name. If a module already exists
    /// under this name, it will be returned.
    #[allow(dead_code)]
    pub fn register_module(&mut self, name: String, module: Box<Module>) -> Option<Box<Module>> {
        self.modules.insert(name.clone(), module)
    }
}
<commit_msg>delete commented out line in router.rs<commit_after>use scaii_defs::protos::endpoint::Endpoint;
use scaii_defs::protos::{ModuleEndpoint, MultiMessage, ScaiiPacket};
use scaii_defs::{Agent, Backend, Module, Recorder, Replay};

use std::collections::HashMap;
use std::error::Error;
use std::fmt;
use std::fmt::{Display, Formatter};

/// Indicates an attempt to reach a module that has
/// not been registered.
#[derive(Clone, PartialEq, Debug)]
pub struct NoSuchEndpointError {
    end: Endpoint,
}

impl Display for NoSuchEndpointError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "No such registered module: {:?}", self.end)
    }
}

impl Error for NoSuchEndpointError {
    fn description(&self) -> &str {
        "Attempt to reach an nonexistant module"
    }
}

/// A simple Router that sends protobuf messages to various modules
#[derive(Default)]
pub struct Router {
    backend: Option<Box<Backend>>,
    agent: Option<Box<Agent>>,
    modules: HashMap<String, Box<Module>>,
    replay: Option<Box<Replay>>,
    recorder: Option<Box<Recorder>>,
}

impl Router {
    /// Initializes an empty Router.
    #[allow(dead_code)]
    pub fn new() -> Self {
        use internal::recorder::RecorderManager;
        Router {
            backend: None,
            agent: None,
            modules: HashMap::new(),
            replay: None,
            recorder: Some(Box::new(RecorderManager::new().expect(
                "Could not determine default replay directory when constructing recorder",
            ))),
        }
    }

    /// Initializes a Router with the specificed Backend instance.
    #[allow(dead_code)]
    pub fn from_backend(backend: Box<Backend>) -> Self {
        use internal::recorder::RecorderManager;
        Router {
            backend: Some(backend),
            agent: None,
            modules: HashMap::new(),
            replay: None,
            recorder: Some(Box::new(RecorderManager::new().expect(
                "Could not determine default replay directory when constructing recorder",
            ))),
        }
    }

    /// /// Initializes a Router with the specificed Agent instance.
    #[allow(dead_code)]
    pub fn from_agent(agent: Box<Agent>) -> Self {
        use internal::recorder::RecorderManager;
        Router {
            backend: None,
            agent: Some(agent),
            modules: HashMap::new(),
            replay: None,
            recorder: Some(Box::new(RecorderManager::new().expect(
                "Could not determine default replay directory when constructing recorder",
            ))),
        }
    }

    /// Decodes a MultiMessage
    /// and routes the resulting packet to the target.
    ///
    /// Any returned values will be any packages routed to the Core,
    /// including Errors the Core needs to forward to the owner module.
    pub fn decode_and_route(&mut self, msg: &MultiMessage) -> Vec<ScaiiPacket> {
        let mut core_msgs: Vec<ScaiiPacket> = Vec::new();
        use scaii_defs::protos::endpoint::Endpoint;
        use scaii_defs::protos::CoreEndpoint;

        for msg in &msg.packets {
            let dest = msg.dest.endpoint.as_ref().expect("Malformed dest field");
            let src = msg.src.endpoint.as_ref().expect("Malformed src field");
            if src == &Endpoint::Core(CoreEndpoint {}) {
                panic!(
                    "FATAL CORE ERROR:\
                     Core should not be using decode_and_route to send its messages."
                )
            }

            if dest == src {
                self.send_error(
                    &format!("Module attempted to send message to itself:\n\t{:?}", msg),
                    src,
                    &Endpoint::Core(CoreEndpoint {}),
                ).unwrap();
                continue;
            }

            match self.route_to(msg) {
                Err(err) => {
                    self.send_error(&format!("{}", err), src, &Endpoint::Core(CoreEndpoint {}))
                        .unwrap();
                }
                Ok(Some(packet)) => core_msgs.push(packet),
                Ok(None) => {}
            }
        }
        core_msgs
    }

    /// Routes the specified ScaiiPacket to the given destination.
    ///
    /// Returns an error if the specified destination does not exist, or if the
    /// target errors on receiving the message.
    pub fn route_to(&mut self, msg: &ScaiiPacket) -> Result<Option<ScaiiPacket>, Box<Error>> {
        let dest = msg.dest.endpoint.as_ref().expect("Malformed dest field");
        //println!("router routed {:?}", msg);
        match *dest {
            Endpoint::Backend(_) => {
                let res = self.backend.as_mut().and_then(|v| Some(v.process_msg(msg)));
                if let Some(Err(err)) = res {
                    return Err(err);
                } else if res.is_none() {
                    return Err(Box::new(NoSuchEndpointError { end: dest.clone() }));
                };

                Ok(None)
            }
            Endpoint::Agent(_) => {
                let res = self.agent.as_mut().and_then(|v| Some(v.process_msg(msg)));
                if let Some(Err(err)) = res {
                    return Err(err);
                } else if res.is_none() {
                    return Err(Box::new(NoSuchEndpointError { end: dest.clone() }));
                };

                Ok(None)
            }
            Endpoint::Core(_) => Ok(Some(msg.clone())),
            Endpoint::Module(ModuleEndpoint { ref name }) => {
                let res = self
                    .modules
                    .get_mut(name)
                    .and_then(|v| Some(v.process_msg(msg)));
                if let Some(Err(err)) = res {
                    return Err(err);
                } else if res.is_none() {
                    return Err(Box::new(NoSuchEndpointError { end: dest.clone() }));
                }

                Ok(None)
            }
            Endpoint::Replay(_) => {
                let res = self.replay.as_mut().and_then(|v| Some(v.process_msg(msg)));
                if let Some(Err(err)) = res {
                    return Err(err);
                } else if res.is_none() {
                    return Err(Box::new(NoSuchEndpointError { end: dest.clone() }));
                };

                Ok(None)
            }
            Endpoint::Recorder(_) => {
                let res = self
                    .recorder
                    .as_mut()
                    .and_then(|v| Some(v.process_msg(msg)));
                if let Some(Err(err)) = res {
                    return Err(err);
                } else if res.is_none() {
                    return Err(Box::new(NoSuchEndpointError { end: dest.clone() }));
                };
                Ok(None)
            }
        }
    }

    /// Processes any messages pending from non-owner modules.
    ///
    /// Any returned values will be any packages routed to the Core,
    /// including Errors the Core needs to forward to the owner module.
    pub fn process_module_messages(&mut self) -> Vec<ScaiiPacket> {
        let mut core_messages = Vec::new();
        // Most of the convoluted stuff here is to appease the borrow checker,
        // who thinks we're borrwing ourselves mutably twice if we call
        // `decode_and_route` within the `if let` or `for` blocks
        let msgs = if let Some(ref mut backend) = self.backend {
            backend.get_messages()
        } else {
            MultiMessage {
                packets: Vec::new(),
            }
        };
        core_messages.append(&mut self.decode_and_route(&msgs));

        let msgs = if let Some(ref mut agent) = self.agent {
            agent.get_messages()
        } else {
            MultiMessage {
                packets: Vec::new(),
            }
        };
        core_messages.append(&mut self.decode_and_route(&msgs));

        let mut msgs = Vec::with_capacity(self.modules.len());
        for module in self.modules.values_mut() {
            msgs.push(module.get_messages())
        }

        for msg in msgs {
            core_messages.append(&mut self.decode_and_route(&msg));
        }

        core_messages
    }

    /// Sends an error with the specified message to the given module
    ///
    /// This directly calls `route_to` for you, and panics on an error
    /// because we can't reasonable handle errors if we can't send them
    pub fn send_error(
        &mut self,
        msg: &str,
        dest: &Endpoint,
        src: &Endpoint,
    ) -> Result<Option<ScaiiPacket>, NoSuchEndpointError> {
        use scaii_defs::protos;
        use scaii_defs::protos::scaii_packet::SpecificMsg;

        if !self.endpoint_exists(dest) {
            return Err(NoSuchEndpointError { end: dest.clone() });
        }

        let error_packet = ScaiiPacket {
            dest: protos::Endpoint {
                endpoint: Some(dest.clone()),
            },
            src: protos::Endpoint {
                endpoint: Some(src.clone()),
            },
            specific_msg: Some(SpecificMsg::Err(protos::Error {
                description: msg.to_string(),
                fatal: None,
                error_info: None,
            })),
        };

        let panic_msg = "FATAL CORE ERROR: Cannot send error message from inside core";
        // At this point, we pretty much can't handle errors anymore
        Ok(self.route_to(&error_packet).expect(panic_msg))
    }

    /// Determines if a given RouterEndpoint has been registered with this Router.
    pub fn endpoint_exists(&self, end: &Endpoint) -> bool {
        match *end {
            Endpoint::Core(_) => true,
            Endpoint::Backend(_) => self.backend.is_some(),
            Endpoint::Agent(_) => self.agent.is_some(),
            Endpoint::Replay(_) => self.replay.is_some(),
            Endpoint::Recorder(_) => self.recorder.is_some(),
            Endpoint::Module(ModuleEndpoint { ref name }) => self.modules.get(name).is_some(),
        }
    }

    /// Returns a reference to the registered backend (if any).
    #[allow(dead_code, borrowed_box)]
    pub fn backend(&self) -> Option<&Box<Backend>> {
        self.backend.as_ref()
    }

    /// Returns a mutable reference to the registered backend (if any).
    #[allow(dead_code, borrowed_box)]
    pub fn backend_mut(&mut self) -> Option<&mut Box<Backend>> {
        self.backend.as_mut()
    }

    /// Registers a new backend, returning the old one if one existed.
    #[allow(dead_code)]
    pub fn register_backend(&mut self, backend: Box<Backend>) -> Option<Box<Backend>> {
        use std::mem;
        mem::replace(&mut self.backend, Some(backend))
    }

    /// Registers a new replayer, returning the old one if one existed.
    #[allow(dead_code)]
    pub fn register_replay(&mut self, replay: Box<Replay>) -> Option<Box<Replay>> {
        use std::mem;
        mem::replace(&mut self.replay, Some(replay))
    }

    #[allow(dead_code, borrowed_box)]
    pub fn replay(&self) -> Option<&Box<Replay>> {
        self.replay.as_ref()
    }

    /// Registers a new recorder, returning the old one if one existed.
    #[allow(dead_code)]
    pub fn register_recorder(&mut self, recorder: Box<Recorder>) -> Option<Box<Recorder>> {
        use std::mem;
        mem::replace(&mut self.recorder, Some(recorder))
    }

    #[allow(dead_code, borrowed_box)]
    pub fn recorder(&self) -> Option<&Box<Recorder>> {
        self.recorder.as_ref()
    }

    /// Returns a reference to the registered agent (if any).
    #[allow(dead_code, borrowed_box)]
    pub fn agent(&self) -> Option<&Box<Agent>> {
        self.agent.as_ref()
    }

    /// Returns a mutable reference to the registered agent (if any).
    #[allow(dead_code, borrowed_box)]
    pub fn agent_mut(&mut self) -> Option<&mut Box<Agent>> {
        self.agent.as_mut()
    }

    /// Registers a new agent, returning the old one if one existed.
    #[allow(dead_code)]
    pub fn register_agent(&mut self, agent: Box<Agent>) -> Option<Box<Agent>> {
        use std::mem;
        mem::replace(&mut self.agent, Some(agent))
    }

    /// Returns a reference to the specified module (if it exists).
    #[allow(dead_code, borrowed_box)]
    pub fn module(&self, name: &str) -> Option<&Box<Module>> {
        self.modules.get(name)
    }

    /// Returns a mutable reference to the specified module (if it exists).
    #[allow(dead_code, borrowed_box)]
    pub fn module_mut(&mut self, name: &str) -> Option<&mut Box<Module>> {
        self.modules.get_mut(name)
    }

    /// Registers the module under the given name. If a module already exists
    /// under this name, it will be returned.
    #[allow(dead_code)]
    pub fn register_module(&mut self, name: String, module: Box<Module>) -> Option<Box<Module>> {
        self.modules.insert(name.clone(), module)
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! GSourceFunc functions

use std::cell::RefCell;
use std::ops::DerefMut;
use std::mem::transmute;
use ffi::{gboolean, gpointer, g_idle_add_full, g_timeout_add_full, g_timeout_add_seconds_full};
use translate::ToGlib;

pub struct Continue(pub bool);

impl ToGlib for Continue {
    type GlibType = gboolean;

    #[inline]
    fn to_glib(&self) -> gboolean {
        self.0.to_glib()
    }
}

// Box::into_raw stability workaround
unsafe fn into_raw<T>(b: Box<T>) -> *mut T { transmute(b) }

extern "C" fn trampoline(func: &RefCell<Box<FnMut() -> Continue + 'static>>) -> gboolean {
    func.borrow_mut().deref_mut()().to_glib()
}

extern "C" fn destroy_closure(ptr: gpointer) {
    unsafe {
        // Box::from_raw API stability workaround
        let ptr = ptr as *mut RefCell<Box<FnMut() -> Continue + 'static>>;
        let _: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = transmute(ptr);
    }
}

const G_PRIORITY_DEFAULT: i32 = 0;
const G_PRIORITY_DEFAULT_IDLE: i32 = 200;

/// Adds a function to be called whenever there are no higher priority events pending to the default main loop.
/// The function is given the default idle priority, G_PRIORITY_DEFAULT_IDLE.
/// If the function returns FALSE it is automatically removed from
/// the list of event sources and will not be called again.
///
/// This internally creates a main loop source using g_idle_source_new()
/// and attaches it to the global GMainContext using g_source_attach(),
/// so the callback will be invoked in whichever thread is running that main context.
/// You can do these steps manually if you need greater control or to use a custom main context.
pub fn idle_add<F>(func: F) -> u32
    where F: FnMut() -> Continue + 'static {
    let f: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = Box::new(RefCell::new(Box::new(func)));
    unsafe {
        g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, transmute(trampoline),
            into_raw(f) as gpointer, destroy_closure)
    }
}

/// Sets a function to be called at regular intervals, with the default priority, G_PRIORITY_DEFAULT.
/// The function is called repeatedly until it returns FALSE, at which point the timeout is
/// automatically destroyed and the function will not be called again. The first call to the
/// function will be at the end of the first interval .
///
/// Note that timeout functions may be delayed, due to the processing of other event sources. Thus
/// they should not be relied on for precise timing. After each call to the timeout function, the
/// time of the next timeout is recalculated based on the current time and the given interval (it
/// does not try to 'catch up' time lost in delays).
///
/// If you want to have a timer in the "seconds" range and do not care about the exact time of the
/// first call of the timer, use the g_timeout_add_seconds() function; this function allows for more
/// optimizations and more efficient system power usage.
///
/// This internally creates a main loop source using g_timeout_source_new() and attaches it to the
/// global GMainContext using g_source_attach(), so the callback will be invoked in whichever thread
/// is running that main context. You can do these steps manually if you need greater control or to
/// use a custom main context.
///
/// The interval given is in terms of monotonic time, not wall clock time. See g_get_monotonic_time().
pub fn timeout_add<F>(interval: u32, func: F) -> u32
    where F: FnMut() -> Continue + 'static {
    let f: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = Box::new(RefCell::new(Box::new(func)));
    unsafe {
        g_timeout_add_full(G_PRIORITY_DEFAULT, interval, transmute(trampoline),
            into_raw(f) as gpointer, destroy_closure)
    }
}

/// Sets a function to be called at regular intervals with the default priority, G_PRIORITY_DEFAULT.
/// The function is called repeatedly until it returns FALSE, at which point the timeout is automatically
/// destroyed and the function will not be called again.
///
/// This internally creates a main loop source using g_timeout_source_new_seconds() and attaches it to
/// the main loop context using g_source_attach(). You can do these steps manually if you need greater
/// control. Also see g_timeout_add_seconds_full().
///
/// Note that the first call of the timer may not be precise for timeouts of one second. If you need
/// finer precision and have such a timeout, you may want to use g_timeout_add() instead.
///
/// The interval given is in terms of monotonic time, not wall clock time. See g_get_monotonic_time().
pub fn timeout_add_seconds<F>(interval: u32, func: F) -> u32
    where F: FnMut() -> Continue + 'static {
    let f: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = Box::new(RefCell::new(Box::new(func)));
    unsafe {
        g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, interval, transmute(trampoline),
            into_raw(f) as gpointer, destroy_closure)
    }
}
<commit_msg>Source: Improve doc, fix const names<commit_after>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! Manages available sources of events for the main loop

use std::cell::RefCell;
use std::ops::DerefMut;
use std::mem::transmute;
use ffi::{gboolean, gpointer, g_idle_add_full, g_timeout_add_full, g_timeout_add_seconds_full};
use translate::ToGlib;

/// Return type of idle and timeout functions.
///
/// In the callback, return `Continue(true)` to continue scheduling the callback
/// in the main loop or `Continue(false)` to remove it from the main loop.
pub struct Continue(pub bool);

impl ToGlib for Continue {
    type GlibType = gboolean;

    #[inline]
    fn to_glib(&self) -> gboolean {
        self.0.to_glib()
    }
}

// Box::into_raw stability workaround
unsafe fn into_raw<T>(b: Box<T>) -> *mut T { transmute(b) }

extern "C" fn trampoline(func: &RefCell<Box<FnMut() -> Continue + 'static>>) -> gboolean {
    func.borrow_mut().deref_mut()().to_glib()
}

extern "C" fn destroy_closure(ptr: gpointer) {
    unsafe {
        // Box::from_raw API stability workaround
        let ptr = ptr as *mut RefCell<Box<FnMut() -> Continue + 'static>>;
        let _: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = transmute(ptr);
    }
}

const PRIORITY_DEFAULT: i32 = 0;
const PRIORITY_DEFAULT_IDLE: i32 = 200;

/// Adds a function to be called whenever there are no higher priority events pending to the default main loop.
///
/// The function is given the default idle priority, `PRIORITY_DEFAULT_IDLE`.
/// If the function returns `Continue(false)` it is automatically removed from
/// the list of event sources and will not be called again.
///
/// # Examples
///
/// ```
/// let mut i = 0;
/// idle_add(move || {
///     println!("Idle: {}", i);
///     i += 1;
///     Continue(if i <= 10 { true } else { false })
/// });
/// ```
pub fn idle_add<F>(func: F) -> u32
    where F: FnMut() -> Continue + 'static {
    let f: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = Box::new(RefCell::new(Box::new(func)));
    unsafe {
        g_idle_add_full(PRIORITY_DEFAULT_IDLE, transmute(trampoline),
            into_raw(f) as gpointer, destroy_closure)
    }
}

/// Sets a function to be called at regular intervals, with the default priority, `PRIORITY_DEFAULT`.
///
/// The function is called repeatedly until it returns `Continue(false)`, at which point the timeout is
/// automatically destroyed and the function will not be called again. The first call to the
/// function will be at the end of the first interval .
///
/// Note that timeout functions may be delayed, due to the processing of other event sources. Thus
/// they should not be relied on for precise timing. After each call to the timeout function, the
/// time of the next timeout is recalculated based on the current time and the given interval (it
/// does not try to 'catch up' time lost in delays).
///
/// If you want to have a timer in the "seconds" range and do not care about the exact time of the
/// first call of the timer, use the `timeout_add_seconds()` function; this function allows for more
/// optimizations and more efficient system power usage.
///
/// The interval given is in terms of monotonic time, not wall clock time.
/// See `g_get_monotonic_time()` in glib documentation.
///
/// # Examples
///
/// ```
/// timeout_add(3000, || {
///     println!("This prints once every 3 seconds");
///     Continue(true)
/// });
/// ```
pub fn timeout_add<F>(interval: u32, func: F) -> u32
    where F: FnMut() -> Continue + 'static {
    let f: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = Box::new(RefCell::new(Box::new(func)));
    unsafe {
        g_timeout_add_full(PRIORITY_DEFAULT, interval, transmute(trampoline),
            into_raw(f) as gpointer, destroy_closure)
    }
}

/// Sets a function to be called at regular intervals with the default priority, `PRIORITY_DEFAULT`.
///
/// The function is called repeatedly until it returns `Continue(false)`, at which point the timeout
/// is automatically destroyed and the function will not be called again.
///
/// Note that the first call of the timer may not be precise for timeouts of one second. If you need
/// finer precision and have such a timeout, you may want to use `timeout_add()` instead.
///
/// The interval given is in terms of monotonic time, not wall clock time.
/// See `g_get_monotonic_time()` in glib documentation.
///
/// # Examples
///
/// ```
/// timeout_add_seconds(10, || {
///     println!("This prints once every 10 seconds");
///     Continue(true)
/// });
/// ```
pub fn timeout_add_seconds<F>(interval: u32, func: F) -> u32
    where F: FnMut() -> Continue + 'static {
    let f: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = Box::new(RefCell::new(Box::new(func)));
    unsafe {
        g_timeout_add_seconds_full(PRIORITY_DEFAULT, interval, transmute(trampoline),
            into_raw(f) as gpointer, destroy_closure)
    }
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::process::exit;
use std::sync::mpsc::Sender;

use datatype::{AccessToken, Command, Config, Error, Event, UpdateReport,
               UpdateRequestId, UpdateState, UpdateResultCode};
use datatype::Command::*;
use package_manager::PackageManager;
use http_client::HttpClient2;
use interaction_library::interpreter::Interpreter;
use new_auth_plus::authenticate;
use new_ota_plus::{get_package_updates, download_package_update,
                   post_packages, send_install_report};

#[allow(dead_code)]
pub struct Env<'a> {
    config:       &'a Config,
    access_token: Option<Cow<'a, AccessToken>>,

    // XXX: remove, already in config.
    pkg_manager:  &'a PackageManager,
    http_client:  &'a HttpClient2,
}

// This macro partially applies the config and http client to the passed
// in functions.
macro_rules! partial_apply {
    ([ $( $fun0: ident ),* ], [ $( $fun1: ident ),* ], [ $( $fun2: ident ),* ],  $env: expr, $token: expr) => {
        $(let $fun0 = ||           $fun0($env.config, $env.http_client, $token);)*;
        $(let $fun1 = |arg|        $fun1($env.config, $env.http_client, $token, &arg);)*;
        $(let $fun2 = |arg1, arg2| $fun2($env.config, $env.http_client, $token, &arg1, &arg2);)*;
    }
}

// XXX: Move this somewhere else?
fn install_package_update(config: &Config,
                          http_client: &HttpClient2,
                          token: &AccessToken,
                          id: &UpdateRequestId,
                          tx: &Sender<Event>) -> Result<UpdateReport, Error> {

    match download_package_update(config, http_client, token, id) {

        Ok(path) => {
            info!("Downloaded at {:?}. Installing...", path);
            try!(tx.send(Event::UpdateStateChanged(id.clone(), UpdateState::Installing)));

            let p = try!(path.to_str()
                         .ok_or(Error::ParseError(format!("Path is not valid UTF-8: {:?}", path))));

            match config.ota.package_manager.install_package(p) {

                Ok((code, output)) => {
                    try!(tx.send(Event::UpdateStateChanged(id.clone(), UpdateState::Installed)));
                    Ok(UpdateReport::new(id.clone(), code, output))
                }

                Err((code, output)) => {
                    try!(tx.send(Event::UpdateErrored(id.clone(), format!("{:?}: {:?}", code, output))));
                    Ok(UpdateReport::new(id.clone(), code, output))
                }

            }

        }

        Err(err) => {
            try!(tx.send(Event::UpdateErrored(id.clone(), format!("{:?}", err))));
            Ok(UpdateReport::new(id.clone(),
                              UpdateResultCode::GENERAL_ERROR,
                              format!("Download failed: {:?}", err)))
        }
    }

}

fn interpreter(env: &mut Env, cmd: Command, tx: &Sender<Event>) -> Result<(), Error> {

    Ok(if let Some(token) = env.access_token.to_owned() {

        partial_apply!(
            [get_package_updates],
            [post_packages, send_install_report],
            [install_package_update], &env, &token);

        match cmd {

            Authenticate(_)       => (), // Already authenticated.

            AcceptUpdate(ref id)  => {
                try!(tx.send(Event::UpdateStateChanged(id.clone(), UpdateState::Downloading)));
                let report = try!(install_package_update(id.to_owned(), tx.to_owned()));
                try!(send_install_report(report.clone()));
                info!("Update finished. Report sent: {:?}", report)
            }

            GetPendingUpdates     => {
                let updates = try!(get_package_updates());
                let update_events: Vec<Event> = updates
                    .iter()
                    .map(|id| Event::NewUpdateAvailable(id.clone()))
                    .collect();
                info!("New package updates available: {:?}", update_events);
                try!(tx.send(Event::Batch(update_events)))
            }

            ListInstalledPackages => {
                let pkgs = try!(env.config.ota.package_manager.installed_packages());
                try!(tx.send(Event::FoundInstalledPackages(pkgs.clone())))
            }

            PostInstalledPackages => {
                let pkgs = try!(env.config.ota.package_manager.installed_packages());
                debug!("Found installed packages in the system: {:?}", pkgs);
                try!(post_packages(pkgs));
                info!("Posted installed packages to the server.")
            }

            Shutdown              => exit(0)
        }

    } else {

        match cmd {

            Authenticate(_)               => {
                let token = try!(authenticate(&env.config.auth, env.http_client));
                env.access_token = Some(token.into())
            }

            Shutdown                      => exit(0),

            AcceptUpdate(_)       |
            GetPendingUpdates     |
            ListInstalledPackages |
            PostInstalledPackages         =>
                tx.send(Event::NotAuthenticated)
                  .unwrap_or(error!("not_auth: send failed."))
            }

    })

}

pub struct OurInterpreter;

impl<'a> Interpreter<Env<'a>, Command, Event> for OurInterpreter {

    fn interpret(env: &mut Env, cmd: Command, tx: Sender<Event>) {
        interpreter(env, cmd, &tx)
            .unwrap_or_else(|err| tx.send(Event::Error(format!("{}", err)))
                            .unwrap_or(error!("interpret: send failed.")))
    }

}
<commit_msg>Align.<commit_after>use std::borrow::Cow;
use std::process::exit;
use std::sync::mpsc::Sender;

use datatype::{AccessToken, Command, Config, Error, Event, UpdateReport,
               UpdateRequestId, UpdateState, UpdateResultCode};
use datatype::Command::*;
use package_manager::PackageManager;
use http_client::HttpClient2;
use interaction_library::interpreter::Interpreter;
use new_auth_plus::authenticate;
use new_ota_plus::{get_package_updates, download_package_update,
                   post_packages, send_install_report};

#[allow(dead_code)]
pub struct Env<'a> {
    config:       &'a Config,
    access_token: Option<Cow<'a, AccessToken>>,

    // XXX: remove, already in config.
    pkg_manager:  &'a PackageManager,
    http_client:  &'a HttpClient2,
}

// This macro partially applies the config and http client to the passed
// in functions.
macro_rules! partial_apply {
    ([ $( $fun0: ident ),* ], [ $( $fun1: ident ),* ], [ $( $fun2: ident ),* ],  $env: expr, $token: expr) => {
        $(let $fun0 = ||           $fun0($env.config, $env.http_client, $token);)*;
        $(let $fun1 = |arg|        $fun1($env.config, $env.http_client, $token, &arg);)*;
        $(let $fun2 = |arg1, arg2| $fun2($env.config, $env.http_client, $token, &arg1, &arg2);)*;
    }
}

// XXX: Move this somewhere else?
fn install_package_update(config:      &Config,
                          http_client: &HttpClient2,
                          token:       &AccessToken,
                          id:          &UpdateRequestId,
                          tx:          &Sender<Event>) -> Result<UpdateReport, Error> {

    match download_package_update(config, http_client, token, id) {

        Ok(path) => {
            info!("Downloaded at {:?}. Installing...", path);
            try!(tx.send(Event::UpdateStateChanged(id.clone(), UpdateState::Installing)));

            let p = try!(path.to_str()
                         .ok_or(Error::ParseError(format!("Path is not valid UTF-8: {:?}", path))));

            match config.ota.package_manager.install_package(p) {

                Ok((code, output)) => {
                    try!(tx.send(Event::UpdateStateChanged(id.clone(), UpdateState::Installed)));
                    Ok(UpdateReport::new(id.clone(), code, output))
                }

                Err((code, output)) => {
                    try!(tx.send(Event::UpdateErrored(id.clone(), format!("{:?}: {:?}", code, output))));
                    Ok(UpdateReport::new(id.clone(), code, output))
                }

            }

        }

        Err(err) => {
            try!(tx.send(Event::UpdateErrored(id.clone(), format!("{:?}", err))));
            Ok(UpdateReport::new(id.clone(),
                              UpdateResultCode::GENERAL_ERROR,
                              format!("Download failed: {:?}", err)))
        }
    }

}

fn interpreter(env: &mut Env, cmd: Command, tx: &Sender<Event>) -> Result<(), Error> {

    Ok(if let Some(token) = env.access_token.to_owned() {

        partial_apply!(
            [get_package_updates],
            [post_packages, send_install_report],
            [install_package_update], &env, &token);

        match cmd {

            Authenticate(_)       => (), // Already authenticated.

            AcceptUpdate(ref id)  => {
                try!(tx.send(Event::UpdateStateChanged(id.clone(), UpdateState::Downloading)));
                let report = try!(install_package_update(id.to_owned(), tx.to_owned()));
                try!(send_install_report(report.clone()));
                info!("Update finished. Report sent: {:?}", report)
            }

            GetPendingUpdates     => {
                let updates = try!(get_package_updates());
                let update_events: Vec<Event> = updates
                    .iter()
                    .map(|id| Event::NewUpdateAvailable(id.clone()))
                    .collect();
                info!("New package updates available: {:?}", update_events);
                try!(tx.send(Event::Batch(update_events)))
            }

            ListInstalledPackages => {
                let pkgs = try!(env.config.ota.package_manager.installed_packages());
                try!(tx.send(Event::FoundInstalledPackages(pkgs.clone())))
            }

            PostInstalledPackages => {
                let pkgs = try!(env.config.ota.package_manager.installed_packages());
                debug!("Found installed packages in the system: {:?}", pkgs);
                try!(post_packages(pkgs));
                info!("Posted installed packages to the server.")
            }

            Shutdown              => exit(0)
        }

    } else {

        match cmd {

            Authenticate(_)               => {
                let token = try!(authenticate(&env.config.auth, env.http_client));
                env.access_token = Some(token.into())
            }

            Shutdown                      => exit(0),

            AcceptUpdate(_)       |
            GetPendingUpdates     |
            ListInstalledPackages |
            PostInstalledPackages         =>
                tx.send(Event::NotAuthenticated)
                  .unwrap_or(error!("not_auth: send failed."))
            }

    })

}

pub struct OurInterpreter;

impl<'a> Interpreter<Env<'a>, Command, Event> for OurInterpreter {

    fn interpret(env: &mut Env, cmd: Command, tx: Sender<Event>) {
        interpreter(env, cmd, &tx)
            .unwrap_or_else(|err| tx.send(Event::Error(format!("{}", err)))
                            .unwrap_or(error!("interpret: send failed.")))
    }

}
<|endoftext|>


<commit_before>// Copyright 2019, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use ::ffi::{self, cairo_status_t};
use ::{Status, Surface, UserDataKey};

use libc::{c_void, c_double, c_uchar, c_uint};
use std::any::Any;
use std::cell::{Cell, RefCell};
use std::io;
use std::panic::AssertUnwindSafe;
use std::rc::Rc;

macro_rules! for_stream_constructors {
    ($constructor_ffi: ident) => {
        /// Takes full ownership of the output stream,
        /// which is not allowed to borrow any lifetime shorter than `'static`.
        ///
        /// Because the underlying `cairo_surface_t` is reference-counted,
        /// a lifetime parameter in a Rust wrapper type would not be enough to track
        /// how long it can keep writing to the stream.
        pub fn for_stream<W: io::Write + 'static>(width: f64, height: f64, stream: W) -> Self {
            Self {
                inner: Surface::_for_stream(
                    ffi::$constructor_ffi,
                    width,
                    height,
                    stream,
                ),
            }
        }

        /// Allows writing to a borrowed stream. The lifetime of the borrow is not tracked.
        ///
        /// # Safety
        ///
        /// The value that `stream` points to must live at least until the underlying `cairo_surface_t`
        /// (which maybe be longer then the Rust `PdfSurface` wrapper, because of reference-counting),
        /// or until the output stream is removed from the surface with [`Surface::take_output_stream`].
        ///
        /// Since the former is hard to track for sure, the latter is strongly recommended.
        /// The concrete type behind the `Box<dyn Any>` value returned by `take_output_stream`
        /// is private, so you won’t be able to downcast it.
        /// But removing it anyway ensures that later writes do no go through a dangling pointer.
        pub unsafe fn for_raw_stream<W: io::Write + 'static>(width: f64, height: f64, stream: *mut W) -> Self {
            Self {
                inner: Surface::_for_raw_stream(
                    ffi::$constructor_ffi,
                    width,
                    height,
                    stream,
                ),
            }
        }
    };
}

impl Surface {
    pub(crate) fn _for_stream<W: io::Write + 'static>(
        constructor: Constructor,
        width: f64,
        height: f64,
        stream: W,
    ) -> Self {
        let env_rc = Rc::new(CallbackEnvironment {
            mutable: RefCell::new(MutableCallbackEnvironment {
                stream: Some((Box::new(stream), None)),
                unwind_payload: None,
            }),
            saw_already_borrowed: Cell::new(false),
        });
        let env: *const CallbackEnvironment = &*env_rc;
        unsafe {
            let ptr = constructor(Some(write_callback::<W>), env as *mut c_void, width, height);
            let surface = Surface::from_raw_full(ptr);
            surface.set_user_data(&STREAM_CALLBACK_ENVIRONMENT, env_rc);
            surface
        }
    }

    pub(crate) unsafe fn _for_raw_stream<W: io::Write + 'static>(
        constructor: Constructor,
        width: f64,
        height: f64,
        stream: *mut W,
    ) -> Self {
        Self::_for_stream(constructor, width, height, RawStream(stream))
    }

    /// Finish the surface, then remove and return the output stream if any.
    ///
    /// This calls [`Surface::finish`], to make sure pending writes are done.
    ///
    /// This is relevant for surfaces created for example with [`PdfSurface::for_stream`].
    ///
    /// Use [`Box::downcast`] to recover the concrete stream type.
    ///
    /// # Panics
    ///
    /// This method panics if:
    ///
    /// * This method was already called for this surface, or
    /// * This surface was not created with an output stream in the first place, or
    /// * A previous write to this surface panicked, or
    /// * A previous write happened while another write was ongoing, or
    /// * A write is ongoing now.
    ///
    /// The latter two cases can only occur with a pathological output stream type
    /// that accesses the same surface again from `Write::write_all`.
    pub fn finish_output_stream(&self) -> Result<Box<dyn Any>, StreamWithError> {
        self.finish();

        let env = self.get_user_data_ptr(&STREAM_CALLBACK_ENVIRONMENT)
            .expect("surface without an output stream");

        // Safety: since `STREAM_CALLBACK_ENVIRONMENT` is private and we never
        // call `set_user_data` again or `remove_user_data` with it,
        // the contract of `get_user_data_ptr` says that the user data entry
        // lives as long as the underlying `cairo_surface_t`
        // which is at least as long as `self`.
        let env = unsafe { &*env.as_ptr() };

        if env.saw_already_borrowed.get() {
            panic!("The output stream’s RefCell was already borrowed when cairo attempted a write")
        }

        let mut mutable = env.mutable.borrow_mut();
        if let Some(payload) = mutable.unwind_payload.take() {
            std::panic::resume_unwind(payload)
        }

        let (stream, io_error) = mutable.stream.take().expect("output stream was already taken");
        if let Some(error) = io_error {
            Err(StreamWithError { stream, error })
        } else {
            Ok(stream)
        }
    }
}

pub struct StreamWithError {
    pub stream: Box<dyn Any>,
    pub error: io::Error,
}

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

impl std::fmt::Display for StreamWithError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.error.fmt(f)
    }
}

pub(crate) type Constructor = unsafe extern fn(
    ffi::cairo_write_func_t,
    *mut c_void,
    c_double,
    c_double,
) -> *mut ffi::cairo_surface_t;

static STREAM_CALLBACK_ENVIRONMENT: UserDataKey<CallbackEnvironment> =
    UserDataKey::new();

struct CallbackEnvironment {
    mutable: RefCell<MutableCallbackEnvironment>,
    saw_already_borrowed: Cell<bool>,
}

struct MutableCallbackEnvironment {
    stream: Option<(Box<dyn Any>, Option<io::Error>)>,
    unwind_payload: Option<Box<dyn Any + Send + 'static>>,
}

// Safety: unwinding into C is undefined behavior (https://github.com/rust-lang/rust/issues/58794)
// so code outside of the `catch_unwind` call must never panic.
extern "C" fn write_callback<W: io::Write + 'static>(
    env: *mut c_void,
    data: *mut c_uchar,
    length: c_uint,
) -> cairo_status_t {
    // This is consistent with the type of `env` in `Surface::_for_stream`.
    let env: *const CallbackEnvironment = env as _;

    // Safety: the user data entry keeps `Rc<CallbackEnvironment>` alive
    // until the surface is destroyed.
    // If this is called by cairo, the surface is still alive.
    let env: &CallbackEnvironment = unsafe { &*env };

    if let Ok(mut mutable) = env.mutable.try_borrow_mut() {
        if let MutableCallbackEnvironment {
            stream: Some((
                stream,
                // Don’t attempt another write if a previous one errored or panicked:
                io_error @ None,
            )),
            unwind_payload: unwind_payload @ None,
        } = &mut *mutable {
            // Safety: `write_callback<W>` was instanciated in `Surface::_for_stream`
            // with a W parameter consistent with the box that was unsized to `Box<dyn Any>`.
            let stream = unsafe {
                stream.downcast_mut_unchecked::<W>()
            };
            // Safety: this is the callback contract from cairo’s API
            let data = unsafe {
                std::slice::from_raw_parts(data, length as usize)
            };
            // Because `<W as Write>::write_all` is a generic,
            // we must conservatively assume that it can panic.
            let result = std::panic::catch_unwind(AssertUnwindSafe(|| stream.write_all(data)));
            match result {
                Ok(Ok(())) => {
                    return Status::Success.into()
                }
                Ok(Err(error)) => {
                    *io_error = Some(error);
                }
                Err(payload) => {
                    *unwind_payload = Some(payload);
                }
            }
        }
    } else {
        env.saw_already_borrowed.set(true)
    }
    Status::WriteError.into()
}

struct RawStream<W>(*mut W);

impl<W: io::Write> io::Write for RawStream<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { unsafe { (*self.0).write(buf) }}
    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { unsafe { (*self.0).write_all(buf) }}
    fn flush(&mut self) -> io::Result<()> { unsafe { (*self.0).flush() } }
}

trait AnyExt {
    /// Any::downcast_mut, but YOLO
    unsafe fn downcast_mut_unchecked<T>(&mut self) -> &mut T {
        let ptr = self as *mut Self as *mut T;
        &mut *ptr
    }
}
impl AnyExt for dyn Any {}
<commit_msg>impl From<StreamWithError> for io::Error<commit_after>// Copyright 2019, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use ::ffi::{self, cairo_status_t};
use ::{Status, Surface, UserDataKey};

use libc::{c_void, c_double, c_uchar, c_uint};
use std::any::Any;
use std::cell::{Cell, RefCell};
use std::io;
use std::panic::AssertUnwindSafe;
use std::rc::Rc;

macro_rules! for_stream_constructors {
    ($constructor_ffi: ident) => {
        /// Takes full ownership of the output stream,
        /// which is not allowed to borrow any lifetime shorter than `'static`.
        ///
        /// Because the underlying `cairo_surface_t` is reference-counted,
        /// a lifetime parameter in a Rust wrapper type would not be enough to track
        /// how long it can keep writing to the stream.
        pub fn for_stream<W: io::Write + 'static>(width: f64, height: f64, stream: W) -> Self {
            Self {
                inner: Surface::_for_stream(
                    ffi::$constructor_ffi,
                    width,
                    height,
                    stream,
                ),
            }
        }

        /// Allows writing to a borrowed stream. The lifetime of the borrow is not tracked.
        ///
        /// # Safety
        ///
        /// The value that `stream` points to must live at least until the underlying `cairo_surface_t`
        /// (which maybe be longer then the Rust `PdfSurface` wrapper, because of reference-counting),
        /// or until the output stream is removed from the surface with [`Surface::take_output_stream`].
        ///
        /// Since the former is hard to track for sure, the latter is strongly recommended.
        /// The concrete type behind the `Box<dyn Any>` value returned by `take_output_stream`
        /// is private, so you won’t be able to downcast it.
        /// But removing it anyway ensures that later writes do no go through a dangling pointer.
        pub unsafe fn for_raw_stream<W: io::Write + 'static>(width: f64, height: f64, stream: *mut W) -> Self {
            Self {
                inner: Surface::_for_raw_stream(
                    ffi::$constructor_ffi,
                    width,
                    height,
                    stream,
                ),
            }
        }
    };
}

impl Surface {
    pub(crate) fn _for_stream<W: io::Write + 'static>(
        constructor: Constructor,
        width: f64,
        height: f64,
        stream: W,
    ) -> Self {
        let env_rc = Rc::new(CallbackEnvironment {
            mutable: RefCell::new(MutableCallbackEnvironment {
                stream: Some((Box::new(stream), None)),
                unwind_payload: None,
            }),
            saw_already_borrowed: Cell::new(false),
        });
        let env: *const CallbackEnvironment = &*env_rc;
        unsafe {
            let ptr = constructor(Some(write_callback::<W>), env as *mut c_void, width, height);
            let surface = Surface::from_raw_full(ptr);
            surface.set_user_data(&STREAM_CALLBACK_ENVIRONMENT, env_rc);
            surface
        }
    }

    pub(crate) unsafe fn _for_raw_stream<W: io::Write + 'static>(
        constructor: Constructor,
        width: f64,
        height: f64,
        stream: *mut W,
    ) -> Self {
        Self::_for_stream(constructor, width, height, RawStream(stream))
    }

    /// Finish the surface, then remove and return the output stream if any.
    ///
    /// This calls [`Surface::finish`], to make sure pending writes are done.
    ///
    /// This is relevant for surfaces created for example with [`PdfSurface::for_stream`].
    ///
    /// Use [`Box::downcast`] to recover the concrete stream type.
    ///
    /// # Panics
    ///
    /// This method panics if:
    ///
    /// * This method was already called for this surface, or
    /// * This surface was not created with an output stream in the first place, or
    /// * A previous write to this surface panicked, or
    /// * A previous write happened while another write was ongoing, or
    /// * A write is ongoing now.
    ///
    /// The latter two cases can only occur with a pathological output stream type
    /// that accesses the same surface again from `Write::write_all`.
    pub fn finish_output_stream(&self) -> Result<Box<dyn Any>, StreamWithError> {
        self.finish();

        let env = self.get_user_data_ptr(&STREAM_CALLBACK_ENVIRONMENT)
            .expect("surface without an output stream");

        // Safety: since `STREAM_CALLBACK_ENVIRONMENT` is private and we never
        // call `set_user_data` again or `remove_user_data` with it,
        // the contract of `get_user_data_ptr` says that the user data entry
        // lives as long as the underlying `cairo_surface_t`
        // which is at least as long as `self`.
        let env = unsafe { &*env.as_ptr() };

        if env.saw_already_borrowed.get() {
            panic!("The output stream’s RefCell was already borrowed when cairo attempted a write")
        }

        let mut mutable = env.mutable.borrow_mut();
        if let Some(payload) = mutable.unwind_payload.take() {
            std::panic::resume_unwind(payload)
        }

        let (stream, io_error) = mutable.stream.take().expect("output stream was already taken");
        if let Some(error) = io_error {
            Err(StreamWithError { stream, error })
        } else {
            Ok(stream)
        }
    }
}

pub struct StreamWithError {
    pub stream: Box<dyn Any>,
    pub error: io::Error,
}

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

impl std::fmt::Display for StreamWithError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.error.fmt(f)
    }
}

impl From<StreamWithError> for io::Error {
    fn from(e: StreamWithError) -> Self {
        e.error
    }
}

pub(crate) type Constructor = unsafe extern fn(
    ffi::cairo_write_func_t,
    *mut c_void,
    c_double,
    c_double,
) -> *mut ffi::cairo_surface_t;

static STREAM_CALLBACK_ENVIRONMENT: UserDataKey<CallbackEnvironment> =
    UserDataKey::new();

struct CallbackEnvironment {
    mutable: RefCell<MutableCallbackEnvironment>,
    saw_already_borrowed: Cell<bool>,
}

struct MutableCallbackEnvironment {
    stream: Option<(Box<dyn Any>, Option<io::Error>)>,
    unwind_payload: Option<Box<dyn Any + Send + 'static>>,
}

// Safety: unwinding into C is undefined behavior (https://github.com/rust-lang/rust/issues/58794)
// so code outside of the `catch_unwind` call must never panic.
extern "C" fn write_callback<W: io::Write + 'static>(
    env: *mut c_void,
    data: *mut c_uchar,
    length: c_uint,
) -> cairo_status_t {
    // This is consistent with the type of `env` in `Surface::_for_stream`.
    let env: *const CallbackEnvironment = env as _;

    // Safety: the user data entry keeps `Rc<CallbackEnvironment>` alive
    // until the surface is destroyed.
    // If this is called by cairo, the surface is still alive.
    let env: &CallbackEnvironment = unsafe { &*env };

    if let Ok(mut mutable) = env.mutable.try_borrow_mut() {
        if let MutableCallbackEnvironment {
            stream: Some((
                stream,
                // Don’t attempt another write if a previous one errored or panicked:
                io_error @ None,
            )),
            unwind_payload: unwind_payload @ None,
        } = &mut *mutable {
            // Safety: `write_callback<W>` was instanciated in `Surface::_for_stream`
            // with a W parameter consistent with the box that was unsized to `Box<dyn Any>`.
            let stream = unsafe {
                stream.downcast_mut_unchecked::<W>()
            };
            // Safety: this is the callback contract from cairo’s API
            let data = unsafe {
                std::slice::from_raw_parts(data, length as usize)
            };
            // Because `<W as Write>::write_all` is a generic,
            // we must conservatively assume that it can panic.
            let result = std::panic::catch_unwind(AssertUnwindSafe(|| stream.write_all(data)));
            match result {
                Ok(Ok(())) => {
                    return Status::Success.into()
                }
                Ok(Err(error)) => {
                    *io_error = Some(error);
                }
                Err(payload) => {
                    *unwind_payload = Some(payload);
                }
            }
        }
    } else {
        env.saw_already_borrowed.set(true)
    }
    Status::WriteError.into()
}

struct RawStream<W>(*mut W);

impl<W: io::Write> io::Write for RawStream<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { unsafe { (*self.0).write(buf) }}
    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { unsafe { (*self.0).write_all(buf) }}
    fn flush(&mut self) -> io::Result<()> { unsafe { (*self.0).flush() } }
}

trait AnyExt {
    /// Any::downcast_mut, but YOLO
    unsafe fn downcast_mut_unchecked<T>(&mut self) -> &mut T {
        let ptr = self as *mut Self as *mut T;
        &mut *ptr
    }
}
impl AnyExt for dyn Any {}
<|endoftext|>


<commit_before>use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};

pub struct Stream {
  pub info: StreamInfo,
  pub metadata: Vec<Metadata>,
  pub frames: Vec<Frame>,
}

named!(pub stream <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
      }
    }
  )
);
<commit_msg>Remove stream to stream_parser<commit_after>use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};

pub struct Stream {
  pub info: StreamInfo,
  pub metadata: Vec<Metadata>,
  pub frames: Vec<Frame>,
}

named!(pub stream_parser <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
      }
    }
  )
);
<|endoftext|>