<commit_before>//! In-memory representation of a single Syslog message.

use std::string::String;
use std::collections::BTreeMap;
use std::convert::Into;

use rustc_serialize::{Encodable,Encoder};

#[allow(non_camel_case_types)]
pub type time_t = i64;
#[allow(non_camel_case_types)]
pub type pid_t = i32;
#[allow(non_camel_case_types)]
pub type msgid_t = String;
pub type MessageType = String;

use severity;
use facility;

#[derive(Clone,Debug,PartialEq,Eq)]
/// ProcIDs are usually numeric PIDs; however, on some systems, they may be something else
pub enum ProcIdType {
    PID(pid_t),
    Name(String)
}

impl Encodable for ProcIdType {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error>
    {
        match *self {
            ProcIdType::PID(ref p) => s.emit_i32(*p),
            ProcIdType::Name(ref n) => s.emit_str(n)
        }
    }
}

pub type SDIDType = String;
pub type SDParamIDType = String;
pub type SDParamValueType = String;

pub type StructuredDataElement = BTreeMap<SDParamIDType, SDParamValueType>;

#[derive(Clone,Debug,PartialEq,Eq)]
/// Container for the StructuredData component of a syslog message.
///
/// This is a map from SD_ID to pairs of SD_ParamID, SD_ParamValue
///
/// The spec does not forbid repeated keys. However, for convenience, we *do* forbid repeated keys.
/// That is to say, if you have a message like
///
/// [foo bar="baz" bar="bing"]
///
/// There's no way to retrieve the original "baz" mapping.
pub struct StructuredData {
    elements: BTreeMap<SDIDType, StructuredDataElement>,
}

impl Encodable for StructuredData {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error>
    {
        self.elements.encode(s)
    }
}

impl StructuredData {
    pub fn new_empty() -> StructuredData
    {
        StructuredData {
            elements: BTreeMap::new()
        }
    }

    /// Insert a new (sd_id, sd_param_id) -> sd_value mapping into the StructuredData
    pub fn insert_tuple<SI, SPI, SPV> (&mut self, sd_id: SI, sd_param_id: SPI, sd_param_value: SPV) -> ()
        where SI: Into<SDIDType>, SPI: Into<SDParamIDType>, SPV: Into<SDParamValueType>
    {
        let mut sub_map = self.elements.entry(sd_id.into()).or_insert(BTreeMap::new());
        sub_map.insert(sd_param_id.into(), sd_param_value.into());
    }

    /// Lookup by SDID, SDParamID pair
    pub fn find_tuple<'b>(&'b self, sd_id: &str, sd_param_id: &str) -> Option<&'b SDParamValueType>
    {
        // TODO: use traits to make these based on the public types isntead of &str
        if let Some(sub_map) = self.elements.get(sd_id) {
            if let Some(value) = sub_map.get(sd_param_id) {
                Some(value)
            } else {
                None
            }
        } else {
            None
        }
    }

    /// Find all param/value mappings for a given SDID
    pub fn find_sdid<'b>(&'b self, sd_id: &str) -> Option<&'b BTreeMap<SDParamIDType, SDParamValueType>>
    {
        self.elements.get(sd_id)
    }

    /// The number of distinct SD_IDs
    pub fn len(&self) -> usize
    {
        self.elements.len()
    }
}

#[derive(Clone,Debug,RustcEncodable)]
pub struct SyslogMessage {
    pub severity: severity::SyslogSeverity,
    pub facility: facility::SyslogFacility,
    pub version: i32,
    pub timestamp: Option<time_t>,
    pub hostname: Option<String>,
    pub appname: Option<String>,
    pub procid: Option<ProcIdType>,
    pub msgid: Option<msgid_t>,
    pub sd: StructuredData,
    pub msg: String,
}

#[cfg(test)]
mod tests {
    use rustc_serialize::json;
    use super::{StructuredData,SyslogMessage};
    use severity::SyslogSeverity::*;
    use facility::SyslogFacility::*;

    #[test]
    fn test_structured_data_basic() {
        let mut s = StructuredData::new_empty();
        s.insert_tuple("foo", "bar", "baz");
        let v = s.find_tuple("foo", "bar").expect("should find foo/bar");
        assert_eq!(v, "baz");
        assert!(s.find_tuple("foo", "baz").is_none());
    }

    #[test]
    fn test_structured_data_serialization() {
        let mut s = StructuredData::new_empty();
        s.insert_tuple("foo", "bar", "baz");
        s.insert_tuple("foo", "baz", "bar");
        s.insert_tuple("faa", "bar", "baz");
        let encoded = json::encode(&s).expect("Should encode to JSON");
        assert_eq!(encoded, r#"{"faa":{"bar":"baz"},"foo":{"bar":"baz","baz":"bar"}}"#);
    }

    #[test]
    fn test_serialization() {
        let m = SyslogMessage {
            severity: SEV_INFO,
            facility: LOG_KERN,
            version: 1,
            timestamp: None,
            hostname: None,
            appname: None,
            procid: None,
            msgid: None,
            sd: StructuredData::new_empty(),
            msg: String::from("")
        };

        let encoded = json::encode(&m).expect("Should encode to JSON");
        println!("{:?}", encoded);
        // XXX: we don't have a guaranteed order, I don't think, so this might break with minor
        // version changes. *shrug*
        assert_eq!(encoded, "{\"severity\":\"info\",\"facility\":\"kern\",\"version\":1,\"timestamp\":null,\"hostname\":null,\"appname\":null,\"procid\":null,\"msgid\":null,\"sd\":{},\"msg\":\"\"}");
    }
}
<commit_msg>Add deref to StructuredMessage<commit_after>//! In-memory representation of a single Syslog message.

use std::string::String;
use std::collections::BTreeMap;
use std::convert::Into;
use std::ops;

use rustc_serialize::{Encodable,Encoder};

#[allow(non_camel_case_types)]
pub type time_t = i64;
#[allow(non_camel_case_types)]
pub type pid_t = i32;
#[allow(non_camel_case_types)]
pub type msgid_t = String;
pub type MessageType = String;

use severity;
use facility;

#[derive(Clone,Debug,PartialEq,Eq)]
/// ProcIDs are usually numeric PIDs; however, on some systems, they may be something else
pub enum ProcIdType {
    PID(pid_t),
    Name(String)
}

impl Encodable for ProcIdType {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error>
    {
        match *self {
            ProcIdType::PID(ref p) => s.emit_i32(*p),
            ProcIdType::Name(ref n) => s.emit_str(n)
        }
    }
}

pub type SDIDType = String;
pub type SDParamIDType = String;
pub type SDParamValueType = String;

pub type StructuredDataElement = BTreeMap<SDParamIDType, SDParamValueType>;

#[derive(Clone,Debug,PartialEq,Eq)]
/// Container for the StructuredData component of a syslog message.
///
/// This is a map from SD_ID to pairs of SD_ParamID, SD_ParamValue
///
/// The spec does not forbid repeated keys. However, for convenience, we *do* forbid repeated keys.
/// That is to say, if you have a message like
///
/// [foo bar="baz" bar="bing"]
///
/// There's no way to retrieve the original "baz" mapping.
pub struct StructuredData {
    elements: BTreeMap<SDIDType, StructuredDataElement>,
}

impl ops::Deref for StructuredData {
    type Target = BTreeMap<SDIDType, StructuredDataElement>;
    fn deref(&self) -> &Self::Target {
        &self.elements
    }
}

impl Encodable for StructuredData {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error>
    {
        self.elements.encode(s)
    }
}

impl StructuredData {
    pub fn new_empty() -> StructuredData
    {
        StructuredData {
            elements: BTreeMap::new()
        }
    }

    /// Insert a new (sd_id, sd_param_id) -> sd_value mapping into the StructuredData
    pub fn insert_tuple<SI, SPI, SPV> (&mut self, sd_id: SI, sd_param_id: SPI, sd_param_value: SPV) -> ()
        where SI: Into<SDIDType>, SPI: Into<SDParamIDType>, SPV: Into<SDParamValueType>
    {
        let mut sub_map = self.elements.entry(sd_id.into()).or_insert(BTreeMap::new());
        sub_map.insert(sd_param_id.into(), sd_param_value.into());
    }

    /// Lookup by SDID, SDParamID pair
    pub fn find_tuple<'b>(&'b self, sd_id: &str, sd_param_id: &str) -> Option<&'b SDParamValueType>
    {
        // TODO: use traits to make these based on the public types isntead of &str
        if let Some(sub_map) = self.elements.get(sd_id) {
            if let Some(value) = sub_map.get(sd_param_id) {
                Some(value)
            } else {
                None
            }
        } else {
            None
        }
    }

    /// Find all param/value mappings for a given SDID
    pub fn find_sdid<'b>(&'b self, sd_id: &str) -> Option<&'b BTreeMap<SDParamIDType, SDParamValueType>>
    {
        self.elements.get(sd_id)
    }

    /// The number of distinct SD_IDs
    pub fn len(&self) -> usize
    {
        self.elements.len()
    }
}

#[derive(Clone,Debug,RustcEncodable)]
pub struct SyslogMessage {
    pub severity: severity::SyslogSeverity,
    pub facility: facility::SyslogFacility,
    pub version: i32,
    pub timestamp: Option<time_t>,
    pub hostname: Option<String>,
    pub appname: Option<String>,
    pub procid: Option<ProcIdType>,
    pub msgid: Option<msgid_t>,
    pub sd: StructuredData,
    pub msg: String,
}

#[cfg(test)]
mod tests {
    use rustc_serialize::json;
    use super::{StructuredData,SyslogMessage};
    use severity::SyslogSeverity::*;
    use facility::SyslogFacility::*;

    #[test]
    fn test_structured_data_basic() {
        let mut s = StructuredData::new_empty();
        s.insert_tuple("foo", "bar", "baz");
        let v = s.find_tuple("foo", "bar").expect("should find foo/bar");
        assert_eq!(v, "baz");
        assert!(s.find_tuple("foo", "baz").is_none());
    }

    #[test]
    fn test_structured_data_serialization() {
        let mut s = StructuredData::new_empty();
        s.insert_tuple("foo", "bar", "baz");
        s.insert_tuple("foo", "baz", "bar");
        s.insert_tuple("faa", "bar", "baz");
        let encoded = json::encode(&s).expect("Should encode to JSON");
        assert_eq!(encoded, r#"{"faa":{"bar":"baz"},"foo":{"bar":"baz","baz":"bar"}}"#);
    }

    #[test]
    fn test_serialization() {
        let m = SyslogMessage {
            severity: SEV_INFO,
            facility: LOG_KERN,
            version: 1,
            timestamp: None,
            hostname: None,
            appname: None,
            procid: None,
            msgid: None,
            sd: StructuredData::new_empty(),
            msg: String::from("")
        };

        let encoded = json::encode(&m).expect("Should encode to JSON");
        println!("{:?}", encoded);
        // XXX: we don't have a guaranteed order, I don't think, so this might break with minor
        // version changes. *shrug*
        assert_eq!(encoded, "{\"severity\":\"info\",\"facility\":\"kern\",\"version\":1,\"timestamp\":null,\"hostname\":null,\"appname\":null,\"procid\":null,\"msgid\":null,\"sd\":{},\"msg\":\"\"}");
    }

    #[test]
    fn test_deref_structureddata() {
        let mut s = StructuredData::new_empty();
        s.insert_tuple("foo", "bar", "baz");
        s.insert_tuple("foo", "baz", "bar");
        s.insert_tuple("faa", "bar", "baz");
        assert_eq!("baz", s.get("foo").and_then(|foo| foo.get("bar")).unwrap());
        assert_eq!("bar", s.get("foo").and_then(|foo| foo.get("baz")).unwrap());
        assert_eq!("baz", s.get("faa").and_then(|foo| foo.get("bar")).unwrap());
    }
}
<|endoftext|>


<commit_before>#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

#![crate_type = "dylib"]

#![feature(io, path, fs, old_io, rustc_private, plugin_registrar)]

extern crate rustc;
extern crate "rustc-serialize" as rustc_serialize;
extern crate "oauth-client" as oauth;
extern crate "twitter-api" as twitter;

use std::old_io::stdio;
use rustc::plugin::Registry;
use config::Config;
use oauth::Token;

mod config;

fn console_input(prompt: &str) -> String {
    print!("{}\n\t", prompt);
    let line = stdio::stdin().read_line().unwrap();
    line.trim().to_string()
}

#[plugin_registrar]
pub fn plugin_registrar(_reg: &mut Registry) {
    let conf = match config::read() {
        Some(c) => c,
        None => {
            let consumer_key    = console_input("input your consumer key:");
            let consumer_secret = console_input("input your consumer secret:");
            let consumer = Token::new(consumer_key, consumer_secret);

            let request = twitter::get_request_token(&consumer);
            println!("open the following url:");
            println!("\t{}", twitter::get_authorize_url(&request));
            let pin = console_input("input pin:");
            let access = twitter::get_access_token(&consumer, &request, &pin);

            let c = Config {
                consumer_key: consumer.key.to_string(),
                consumer_secret: consumer.secret.to_string(),
                access_key: access.key.to_string(),
                access_secret: access.secret.to_string()
            };
            config::write(&c);
            c
        }
    };

    let consumer = Token::new(conf.consumer_key, conf.consumer_secret);
    let access = Token::new(conf.access_key, conf.access_secret);

    twitter::tweet(&consumer, &access, "あなたとRust, 今すぐコンパイル");
}
<commit_msg>update to rustc 1.0.0-nightly (e2fa53e59 2015-03-20) (built 2015-03-21)<commit_after>#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

#![crate_type = "dylib"]

#![feature(rustc_private, plugin_registrar)]

extern crate rustc;
extern crate "rustc-serialize" as rustc_serialize;
extern crate "oauth-client" as oauth;
extern crate "twitter-api" as twitter;

use std::io;
use rustc::plugin::Registry;
use config::Config;
use oauth::Token;

mod config;

fn console_input(prompt: &str) -> String {
    print!("{}\n\t", prompt);
    let mut line = String::new();
    let _ = io::stdin().read_line(&mut line).unwrap();
    line.trim().to_string()
}

#[plugin_registrar]
pub fn plugin_registrar(_reg: &mut Registry) {
    let conf = match config::read() {
        Some(c) => c,
        None => {
            let consumer_key    = console_input("input your consumer key:");
            let consumer_secret = console_input("input your consumer secret:");
            let consumer = Token::new(consumer_key, consumer_secret);

            let request = twitter::get_request_token(&consumer);
            println!("open the following url:");
            println!("\t{}", twitter::get_authorize_url(&request));
            let pin = console_input("input pin:");
            let access = twitter::get_access_token(&consumer, &request, &pin);

            let c = Config {
                consumer_key: consumer.key.to_string(),
                consumer_secret: consumer.secret.to_string(),
                access_key: access.key.to_string(),
                access_secret: access.secret.to_string()
            };
            config::write(&c);
            c
        }
    };

    let consumer = Token::new(conf.consumer_key, conf.consumer_secret);
    let access = Token::new(conf.access_key, conf.access_secret);

    twitter::tweet(&consumer, &access, "あなたとRust, 今すぐコンパイル");
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

#[derive(Clone, Debug)]
pub struct Message {
    uuid: PatternId,
    name: Option<PatternId>,
    data: BTreeMap<String, String>
}

impl Message {
    pub fn uuid(&self) -> &PatternId {
        &self.uuid
    }

    pub fn name(&self) -> Option<&PatternId> {
        self.name.as_ref()
    }

    pub fn get(&self, key: &str) -> Option<&String> {
        self.data.get(key)
    }
}

pub struct Builder {
    uuid: PatternId,
    name: Option<PatternId>,
    data: BTreeMap<String, String>
}

impl Builder {
    pub fn new(uuid: &str) -> Builder {
        Builder {
            uuid: PatternId::Uuid(uuid.to_string()),
            name: None,
            data: BTreeMap::new()
        }
    }

    pub fn name(&mut self, name: String) -> &mut Builder {
        self.name = Some(PatternId::Name(name));
        self
    }

    pub fn pair(&mut self, key: String, value: String) -> &mut Builder {
        self.data.insert(key, value);
        self
    }

    pub fn build(&self) -> Message {
        Message {
            uuid: self.uuid.clone(),
            name: self.name.clone(),
            data: self.data.clone()
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum PatternId {
    Uuid(String),
    Name(String)
}
<commit_msg>PatternId: implement serde::de::Deserialize trait<commit_after>use std::collections::BTreeMap;

#[derive(Clone, Debug)]
pub struct Message {
    uuid: PatternId,
    name: Option<PatternId>,
    data: BTreeMap<String, String>
}

impl Message {
    pub fn uuid(&self) -> &PatternId {
        &self.uuid
    }

    pub fn name(&self) -> Option<&PatternId> {
        self.name.as_ref()
    }

    pub fn get(&self, key: &str) -> Option<&String> {
        self.data.get(key)
    }
}

pub struct Builder {
    uuid: PatternId,
    name: Option<PatternId>,
    data: BTreeMap<String, String>
}

impl Builder {
    pub fn new(uuid: &str) -> Builder {
        Builder {
            uuid: PatternId::Uuid(uuid.to_string()),
            name: None,
            data: BTreeMap::new()
        }
    }

    pub fn name(&mut self, name: String) -> &mut Builder {
        self.name = Some(PatternId::Name(name));
        self
    }

    pub fn pair(&mut self, key: String, value: String) -> &mut Builder {
        self.data.insert(key, value);
        self
    }

    pub fn build(&self) -> Message {
        Message {
            uuid: self.uuid.clone(),
            name: self.name.clone(),
            data: self.data.clone()
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum PatternId {
    Uuid(String),
    Name(String)
}

mod deser {
    use super::PatternId;
    use serde;
    use serde::de::Deserialize;

    const VARIANTS: &'static [&'static str] = &["uuid", "name"];

    impl serde::Deserialize for PatternId {
        fn deserialize<D>(deserializer: &mut D) -> Result<PatternId, D::Error>
            where D: serde::de::Deserializer
        {
            deserializer.visit_enum("PatternId", VARIANTS, PatternIdVisitor)
        }
    }

    enum Field {
        Uuid,
        Name,
    }

    impl serde::Deserialize for Field {
        fn deserialize<D>(deserializer: &mut D) -> Result<Field, D::Error>
            where D: serde::de::Deserializer
        {
            struct FieldVisitor;

            impl serde::de::Visitor for FieldVisitor {
                type Value = Field;

                fn visit_str<E>(&mut self, value: &str) -> Result<Field, E>
                    where E: serde::de::Error
                {
                    match value {
                        "uuid" => Ok(Field::Uuid),
                        "name" => Ok(Field::Name),
                        name @ _ => Err(serde::de::Error::unknown_field(name)),
                    }
                }
            }

            deserializer.visit(FieldVisitor)
        }
    }

    struct PatternIdVisitor;

    impl serde::de::EnumVisitor for PatternIdVisitor {
        type Value = PatternId;

        fn visit<V>(&mut self, mut visitor: V) -> Result<PatternId, V::Error>
            where V: serde::de::VariantVisitor
        {
            match try!(visitor.visit_variant()) {
                Field::Uuid => {
                    let value = try!(visitor.visit_newtype());
                    Ok(PatternId::Uuid(value))
                },
                Field::Name => {
                    let value = try!(visitor.visit_newtype());
                    Ok(PatternId::Name(value))
                },
            }
        }
    }
}
<|endoftext|>


<commit_before>/// A comonoid in a monoidal category is a monoid
/// in the dual category, what is the problem?
///
/// Being the dual to a monoid, it consists of:
///
/// - The dual to unit, a function from `T` to `()` called `counit`.
/// - The dual to multiplication, a function from `T` to `(T, T)` called `comult`.
///
/// It is useful within Rust's ownership type system,
/// to represent a type that can be both cloned and destroyed.
///
/// There is a trivial implementation of this trait for every
/// type that implements `Clone`, as reflected by the `Comonoidal`
/// newtype wrapper, with `discard` as `counit`, and `duplicate` as `comult`.
/// The behaviour of `counit` and `comult` can be altered by the
/// implementation of [`Drop`](http://doc.rust-lang.org/std/ops/trait.Drop.html)
/// and [`Clone`](http://doc.rust-lang.org/std/clone/trait.Clone.html),
/// respectively.
pub trait Comonoid {
    /// The dual to the monoidal unit.
    fn counit(self) -> ();
    /// The dual to the monoidal multiplication.
    fn comult(self) -> (Self, Self);
}

/// Takes ownership of a value and returns `()`,
/// rendering it unusable.
pub fn discard<T>(_: T) -> () {}
/// Takes ownership of a value and returns a tuple of
/// clones.
pub fn duplicate<T>(a: T) -> (T, T) where T: Clone {
(a.clone(), a)
}

/// A newtype wrapper to make a comonoid out of any
/// cloneable type.
pub struct Comonoidal<T>(T);

impl<T> From<T> for Comonoidal<T> {
    fn from(a: T) -> Comonoidal<T> { Comonoidal(a) }
}

impl<T> AsRef<T> for Comonoidal<T> {
    fn as_ref(&self) -> &T { &self.0 }
}

impl<T> AsMut<T> for Comonoidal<T> {
    fn as_mut(&mut self) -> &mut T { &mut self.0 }
}

impl<T> Clone for Comonoidal<T> where T: Clone {
    fn clone(&self) -> Self {
        let a = self.0.clone();
        Comonoidal(a)
    }
}

impl<T> Comonoid for Comonoidal<T> where T: Clone {
    fn counit(self) -> () { discard(self) }
    fn comult(self) -> (Self, Self) { duplicate(self) }
}

#[test]
fn test_counit() {
    let x = from(42);
    assert_eq!(Comonoid::counit(x), ());
}

#[test]
fn test_comult() {
    let x = from(42);
    let (y, z) = Comonoid::comult(x);
    assert_eq!(y.0, 42);
    assert_eq!(z.0, 42);
}
<commit_msg>use methods on object for tests<commit_after>/// A comonoid in a monoidal category is a monoid
/// in the dual category, what is the problem?
///
/// Being the dual to a monoid, it consists of:
///
/// - The dual to unit, a function from `T` to `()` called `counit`.
/// - The dual to multiplication, a function from `T` to `(T, T)` called `comult`.
///
/// It is useful within Rust's ownership type system,
/// to represent a type that can be both cloned and destroyed.
///
/// There is a trivial implementation of this trait for every
/// type that implements `Clone`, as reflected by the `Comonoidal`
/// newtype wrapper, with `discard` as `counit`, and `duplicate` as `comult`.
/// The behaviour of `counit` and `comult` can be altered by the
/// implementation of [`Drop`](http://doc.rust-lang.org/std/ops/trait.Drop.html)
/// and [`Clone`](http://doc.rust-lang.org/std/clone/trait.Clone.html),
/// respectively.
pub trait Comonoid {
    /// The dual to the monoidal unit.
    fn counit(self) -> ();
    /// The dual to the monoidal multiplication.
    fn comult(self) -> (Self, Self);
}

/// Takes ownership of a value and returns `()`,
/// rendering it unusable.
pub fn discard<T>(_: T) -> () {}
/// Takes ownership of a value and returns a tuple of
/// clones.
pub fn duplicate<T>(a: T) -> (T, T) where T: Clone {
(a.clone(), a)
}

/// A newtype wrapper to make a comonoid out of any
/// cloneable type.
pub struct Comonoidal<T>(T);

impl<T> From<T> for Comonoidal<T> {
    fn from(a: T) -> Comonoidal<T> { Comonoidal(a) }
}

impl<T> AsRef<T> for Comonoidal<T> {
    fn as_ref(&self) -> &T { &self.0 }
}

impl<T> AsMut<T> for Comonoidal<T> {
    fn as_mut(&mut self) -> &mut T { &mut self.0 }
}

impl<T> Clone for Comonoidal<T> where T: Clone {
    fn clone(&self) -> Self {
        let a = self.0.clone();
        Comonoidal(a)
    }
}

impl<T> Comonoid for Comonoidal<T> where T: Clone {
    fn counit(self) -> () { discard(self) }
    fn comult(self) -> (Self, Self) { duplicate(self) }
}

#[test]
fn test_counit() {
    let x = Comonoidal(42);
    assert_eq!(x.counit(), ());
}

#[test]
fn test_comult() {
    let x = Comonoidal(42);
    let (y, z) = x.comult();
    assert_eq!(y.0, 42);
    assert_eq!(z.0, 42);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

//! Non-modal message dialogs.

use std::rc::Rc;

use gtk::{self, Continue};
use mg_settings::{EnumFromStr, EnumMetaData, SettingCompletion};
use mg_settings::settings;

use super::{Application, SpecialCommand};

const INFO_MESSAGE_DURATION: u32 = 5000;

impl<Comm, Sett, Spec> Application<Comm, Sett, Spec>
    where Spec: SpecialCommand + 'static,
          Comm: EnumFromStr + EnumMetaData + 'static,
          Sett: settings::Settings + EnumMetaData + SettingCompletion + 'static,
{
    /// Show an error to the user.
    pub fn error(&self, error: &str) {
        error!("{}", error);
        self.message.set_text(error);
        self.status_bar.hide_entry();
        self.status_bar.color_red();
    }

    /// Show an information message to the user for 5 seconds.
    pub fn info(app: &Rc<Self>, message: &str) {
        info!("{}", message);
        app.message.set_text(message);
        app.reset_colors();
        let app = app.clone();
        let message = Some(message.to_string());
        gtk::timeout_add(INFO_MESSAGE_DURATION, move || {
            if app.message.get_text() == message {
                app.message.set_text("");
            }
            Continue(false)
        });
    }

    /// Show a message to the user.
    pub fn message(&self, message: &str) {
        self.message.set_text(message);
        self.status_bar.color_blue();
    }

    /// Show a warning message to the user for 5 seconds.
    pub fn warning(app: &Rc<Self>, message: &str) {
        warn!("{}", message);
        app.message.set_text(message);
        let app = app.clone();
        let message = Some(message.to_string());
        app.status_bar.color_orange();
        gtk::timeout_add(INFO_MESSAGE_DURATION, move || {
            if app.message.get_text() == message {
                app.message.set_text("");
                app.reset_colors();
            }
            Continue(false)
        });
    }
}
<commit_msg>Added an alert() method to show the message in blue.<commit_after>/*
 * Copyright (c) 2016 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

//! Non-modal message dialogs.

use std::rc::Rc;

use gtk::{self, Continue};
use mg_settings::{EnumFromStr, EnumMetaData, SettingCompletion};
use mg_settings::settings;

use super::{Application, SpecialCommand};

const INFO_MESSAGE_DURATION: u32 = 5000;

impl<Comm, Sett, Spec> Application<Comm, Sett, Spec>
    where Spec: SpecialCommand + 'static,
          Comm: EnumFromStr + EnumMetaData + 'static,
          Sett: settings::Settings + EnumMetaData + SettingCompletion + 'static,
{
    /// Show an alert message to the user.
    pub fn alert(&self, message: &str) {
        self.message.set_text(message);
        self.status_bar.color_blue();
    }

    /// Show an error to the user.
    pub fn error(&self, error: &str) {
        error!("{}", error);
        self.message.set_text(error);
        self.status_bar.hide_entry();
        self.status_bar.color_red();
    }

    /// Show an information message to the user for 5 seconds.
    pub fn info(app: &Rc<Self>, message: &str) {
        info!("{}", message);
        app.message.set_text(message);
        app.reset_colors();
        let app = app.clone();
        let message = Some(message.to_string());
        gtk::timeout_add(INFO_MESSAGE_DURATION, move || {
            if app.message.get_text() == message {
                app.message.set_text("");
            }
            Continue(false)
        });
    }

    /// Show a message to the user.
    pub fn message(&self, message: &str) {
        self.message.set_text(message);
    }

    /// Show a warning message to the user for 5 seconds.
    pub fn warning(app: &Rc<Self>, message: &str) {
        warn!("{}", message);
        app.message.set_text(message);
        let app = app.clone();
        let message = Some(message.to_string());
        app.status_bar.color_orange();
        gtk::timeout_add(INFO_MESSAGE_DURATION, move || {
            if app.message.get_text() == message {
                app.message.set_text("");
                app.reset_colors();
            }
            Continue(false)
        });
    }
}
<|endoftext|>


<commit_before>//! A minimal implementation of SHA1 for rust.
//!
//! Example:
//!
//! ```rust
//! extern crate "sha1-hasher" as sha1;
//!
//! # fn main() {
//!
//! let mut m = sha1::Sha1::new();
//! m.write("Hello World!".as_bytes());
//! assert_eq!(&*m.hexdigest(), "2ef7bde608ce5404e97d5f042f95f89f1c232871");
//! # }
//! ```

#![feature(collections)]
#![feature(core)]
#![feature(hash)]
#![feature(old_io)]

#![allow(unused_features)]
#![feature(test)]

#[cfg(test)] extern crate test;

use std::old_io::{Writer, BufWriter};
use std::old_io::IoResult;
use std::default::Default;

/// Represents a Sha1 hash object in memory.
#[derive(Clone)]
pub struct Sha1 {
    state: [u32; 5],
    data: Vec<u8>,
    len: u64,
}

const DEFAULT_STATE : [u32; 5] =
    [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];

fn to_hex(input: &[u8]) -> String {
    let mut s = String::new();
    for b in input.iter() {
        s.push_str(&*format!("{:02x}", *b));
    }
    return s;
}

impl Default for Sha1 {
    #[inline]
    fn default() -> Sha1 {
        Sha1::new()
    }
}

impl Writer for Sha1 {
    fn write_all(&mut self, bytes: &[u8]) -> IoResult<()> {
        let mut d = self.data.clone();
        self.data.clear();

        d.push_all(bytes);

        for chunk in d[..].chunks(64) {
            if chunk.len() == 64 {
                self.len += 64;
                self.process_block(chunk);
            } else {
                self.data.push_all(chunk);
            }
        }

        Ok(())
        //Ok(bytes.len())
    }

    fn flush(&mut self) -> IoResult<()> {
        Ok(())
    }
}

impl Sha1 {

    /// Creates an fresh sha1 hash object.
    pub fn new() -> Sha1 {
        Sha1 {
            state: DEFAULT_STATE,
            data: Vec::new(),
            len: 0,
        }
    }

    pub fn reset(&mut self) {
        self.state = DEFAULT_STATE;
        self.data.clear();
        self.len = 0;
    }

    pub fn finish(&self) -> Vec<u8> {
        let mut buf = [0u8; 20].to_vec();
        self.output(&mut *buf);
        buf
    }

    fn process_block(&mut self, block: &[u8]) {
        assert_eq!(block.len(), 64);

        let mut words = [0u32; 80];
        for (i, chunk) in block.chunks(4).enumerate() {
            words[i] = (chunk[3] as u32) |
                       ((chunk[2] as u32) << 8) |
                       ((chunk[1] as u32) << 16) |
                       ((chunk[0] as u32) << 24);
        }

        fn ff(b: u32, c: u32, d: u32) -> u32 { d ^ (b & (c ^ d)) }
        fn gg(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }
        fn hh(b: u32, c: u32, d: u32) -> u32 { (b & c) | (d & (b | c)) }
        fn ii(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }

        fn left_rotate(x: u32, n: u32) -> u32 { (x << n) | (x >> (32 - n)) }

        for i in range(16, 80) {
            let n = words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16];
            words[i] = left_rotate(n, 1);
        }

        let mut a = self.state[0];
        let mut b = self.state[1];
        let mut c = self.state[2];
        let mut d = self.state[3];
        let mut e = self.state[4];

        for i in range(0, 80) {
            let (f, k) = match i {
                0 ... 19 => (ff(b, c, d), 0x5a827999),
                20 ... 39 => (gg(b, c, d), 0x6ed9eba1),
                40 ... 59 => (hh(b, c, d), 0x8f1bbcdc),
                60 ... 79 => (ii(b, c, d), 0xca62c1d6),
                _ => (0, 0),
            };

            let tmp = left_rotate(a, 5) + f + e + k + words[i];
            e = d;
            d = c;
            c = left_rotate(b, 30);
            b = a;
            a = tmp;
        }

        self.state[0] += a;
        self.state[1] += b;
        self.state[2] += c;
        self.state[3] += d;
        self.state[4] += e;
    }

    /// Retrieve digest result.  The output must be large enough to
    /// contain result (20 bytes).
    pub fn output(&self, out: &mut [u8]) {
        // these are unlikely to fail, since we're writing to memory
        #![allow(unused_must_use)]

        let mut m = Sha1 {
            state: self.state.clone(),
            data: Vec::new(),
            len: 0,
        };

        let mut w = Vec::<u8>::new();
        w.write_all(&*self.data);
        w.write_u8(0x80u8);
        let padding = 64 - ((self.data.len() + 9) % 64);
        for _ in range(0, padding) {
            w.write_u8(0u8);
        }
        w.write_be_u64((self.data.len() as u64 + self.len) * 8);
        for chunk in w[..].chunks(64) {
            m.process_block(chunk);
        }

        let mut w = BufWriter::new(out);
        for &n in m.state.iter() {
            w.write_be_u32(n);
        }
    }

    pub fn hexdigest(&self) -> String {
        to_hex(&*self.finish())
    }
}

#[cfg(test)]
mod tests {
    use test::Bencher;
    use super::{Sha1, to_hex};

    #[test]
    fn test_simple() {
        let mut m = Sha1::new();

        let tests = [
            ("The quick brown fox jumps over the lazy dog",
            "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"),
            ("The quick brown fox jumps over the lazy cog",
            "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"),
            ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"),
            ("testing\n", "9801739daae44ec5293d4e1f53d3f4d2d426d91c"),
            ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "025ecbd5d70f8fb3c5457cd96bab13fda305dc59"),
        ];

        for &(s, ref h) in tests.iter() {
            let data = s.as_bytes();

            m.reset();
            m.write_all(data).unwrap();
            let hh = m.hexdigest();

            assert_eq!(hh.len(), h.len());
            assert_eq!(&*hh, *h);
        }
    }

    #[test]
    fn test_dirty_run() {
        let mut m = Sha1::new();

        m.write_all(b"123").unwrap();
        let out1 = m.finish();

        m.write_all(b"123").unwrap();
        let out2 = m.finish();

        assert!(out1 != out2);
        assert_eq!(&*to_hex(&*out1), "40bd001563085fc35165329ea1ff5c5ecbdbbeef");
        assert_eq!(&*to_hex(&*out2), "601f1889667efaebb33b8c12572835da3f027f78");
    }

    #[bench]
    fn test_sha1_speed(b: &mut Bencher) {
        let mut m = Sha1::new();
        let s = "The quick brown fox jumps over the lazy dog.";
        let n = 1000u64;

        b.bytes = n * s.len() as u64;
        b.iter(|| {
            m.reset();
            for _ in range(0, n) {
                m.write_all(s.as_bytes()).unwrap();
            }
            assert_eq!(m.hexdigest(), "7ca27655f67fceaa78ed2e645a81c7f1d6e249d2");
        });
    }
}
<commit_msg>switch to new io lib<commit_after>//! A minimal implementation of SHA1 for rust.
//!
//! Example:
//!
//! ```rust
//! extern crate "sha1-hasher" as sha1;
//! use std::io::Write;
//!
//! # fn main() {
//!
//! let mut m = sha1::Sha1::new();
//! m.write("Hello World!".as_bytes());
//! assert_eq!(&*m.hexdigest(), "2ef7bde608ce5404e97d5f042f95f89f1c232871");
//! # }
//! ```

#![feature(collections)]
#![feature(core)]
#![feature(hash)]
#![feature(io)]

#![allow(unused_features)]
#![feature(test)]

#[cfg(test)] extern crate test;

use std::io::{Write, BufWriter};
use std::io::Result as IoResult;
use std::num::Int;
use std::default::Default;
use std::mem::transmute;

/// Represents a Sha1 hash object in memory.
#[derive(Clone)]
pub struct Sha1 {
    state: [u32; 5],
    data: Vec<u8>,
    len: u64,
}

const DEFAULT_STATE : [u32; 5] =
    [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];

fn to_hex(input: &[u8]) -> String {
    let mut s = String::new();
    for b in input.iter() {
        s.push_str(&*format!("{:02x}", *b));
    }
    return s;
}

impl Default for Sha1 {
    #[inline]
    fn default() -> Sha1 {
        Sha1::new()
    }
}

impl Write for Sha1 {
    fn write(&mut self, bytes: &[u8]) -> IoResult<usize> {
        let mut d = self.data.clone();
        self.data.clear();

        d.push_all(bytes);

        for chunk in d[..].chunks(64) {
            if chunk.len() == 64 {
                self.len += 64;
                self.process_block(chunk);
            } else {
                self.data.push_all(chunk);
            }
        }

        Ok(bytes.len())
    }

    fn flush(&mut self) -> IoResult<()> {
        Ok(())
    }
}

impl Sha1 {

    /// Creates an fresh sha1 hash object.
    pub fn new() -> Sha1 {
        Sha1 {
            state: DEFAULT_STATE,
            data: Vec::new(),
            len: 0,
        }
    }

    pub fn reset(&mut self) {
        self.state = DEFAULT_STATE;
        self.data.clear();
        self.len = 0;
    }

    pub fn finish(&self) -> Vec<u8> {
        let mut buf = [0u8; 20].to_vec();
        self.output(&mut *buf);
        buf
    }

    fn process_block(&mut self, block: &[u8]) {
        assert_eq!(block.len(), 64);

        let mut words = [0u32; 80];
        for (i, chunk) in block.chunks(4).enumerate() {
            words[i] = (chunk[3] as u32) |
                       ((chunk[2] as u32) << 8) |
                       ((chunk[1] as u32) << 16) |
                       ((chunk[0] as u32) << 24);
        }

        fn ff(b: u32, c: u32, d: u32) -> u32 { d ^ (b & (c ^ d)) }
        fn gg(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }
        fn hh(b: u32, c: u32, d: u32) -> u32 { (b & c) | (d & (b | c)) }
        fn ii(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }

        fn left_rotate(x: u32, n: u32) -> u32 { (x << n) | (x >> (32 - n)) }

        for i in range(16, 80) {
            let n = words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16];
            words[i] = left_rotate(n, 1);
        }

        let mut a = self.state[0];
        let mut b = self.state[1];
        let mut c = self.state[2];
        let mut d = self.state[3];
        let mut e = self.state[4];

        for i in range(0, 80) {
            let (f, k) = match i {
                0 ... 19 => (ff(b, c, d), 0x5a827999),
                20 ... 39 => (gg(b, c, d), 0x6ed9eba1),
                40 ... 59 => (hh(b, c, d), 0x8f1bbcdc),
                60 ... 79 => (ii(b, c, d), 0xca62c1d6),
                _ => (0, 0),
            };

            let tmp = left_rotate(a, 5) + f + e + k + words[i];
            e = d;
            d = c;
            c = left_rotate(b, 30);
            b = a;
            a = tmp;
        }

        self.state[0] += a;
        self.state[1] += b;
        self.state[2] += c;
        self.state[3] += d;
        self.state[4] += e;
    }

    /// Retrieve digest result.  The output must be large enough to
    /// contain result (20 bytes).
    pub fn output(&self, out: &mut [u8]) {
        // these are unlikely to fail, since we're writing to memory
        #![allow(unused_must_use)]

        let mut m = Sha1 {
            state: self.state.clone(),
            data: Vec::new(),
            len: 0,
        };

        let mut w = Vec::<u8>::with_capacity(137);
        w.push_all(&*self.data);
        w.push_all(&[0x80u8]);
        let padding = 64 - ((self.data.len() + 9) % 64);
        for _ in range(0, padding) {
            w.push(0u8);
        }
        w.push_all(unsafe { &transmute::<_, [u8; 8]>(((self.data.len() as u64 + self.len) * 8).to_be()) });
        for chunk in w[..].chunks(64) {
            m.process_block(chunk);
        }

        let mut w = BufWriter::new(out);
        for &n in m.state.iter() {
            w.write_all(unsafe { &transmute::<_, [u8; 4]>(n.to_be()) });
        }
    }

    pub fn hexdigest(&self) -> String {
        to_hex(&*self.finish())
    }
}

#[cfg(test)]
mod tests {
    use std::io::Write;
    use test::Bencher;
    use super::{Sha1, to_hex};

    #[test]
    fn test_simple() {
        let mut m = Sha1::new();

        let tests = [
            ("The quick brown fox jumps over the lazy dog",
            "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"),
            ("The quick brown fox jumps over the lazy cog",
            "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"),
            ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"),
            ("testing\n", "9801739daae44ec5293d4e1f53d3f4d2d426d91c"),
            ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "025ecbd5d70f8fb3c5457cd96bab13fda305dc59"),
        ];

        for &(s, ref h) in tests.iter() {
            let data = s.as_bytes();

            m.reset();
            m.write(data).unwrap();
            let hh = m.hexdigest();

            assert_eq!(hh.len(), h.len());
            assert_eq!(&*hh, *h);
        }
    }

    #[test]
    fn test_dirty_run() {
        let mut m = Sha1::new();

        m.write(b"123").unwrap();
        let out1 = m.finish();

        m.write_all(b"123").unwrap();
        let out2 = m.finish();

        assert!(out1 != out2);
        assert_eq!(&*to_hex(&*out1), "40bd001563085fc35165329ea1ff5c5ecbdbbeef");
        assert_eq!(&*to_hex(&*out2), "601f1889667efaebb33b8c12572835da3f027f78");
    }

    #[bench]
    fn test_sha1_speed(b: &mut Bencher) {
        let mut m = Sha1::new();
        let s = "The quick brown fox jumps over the lazy dog.";
        let n = 1000u64;

        b.bytes = n * s.len() as u64;
        b.iter(|| {
            m.reset();
            for _ in range(0, n) {
                m.write_all(s.as_bytes()).unwrap();
            }
            assert_eq!(m.hexdigest(), "7ca27655f67fceaa78ed2e645a81c7f1d6e249d2");
        });
    }
}
<|endoftext|>


<commit_before>#![crate_name = "tiny-http"]
#![crate_type = "lib"]
#![license = "Apache"]

extern crate semver;
extern crate url;

use std::io::{Acceptor, BufferedReader, IoResult, Listener, RefReader, RefWriter};
use std::io::net::ip;
use std::io::net::tcp;
use std::io::util::LimitReader;
use std::sync;

pub use common::Header;
pub use common::Method;
pub use common::StatusCode;
pub use response::Response;

mod client;
mod common;
mod response;

/// The main class of this library.
/// Create a new server using `Server::new()`.
pub struct Server {
    connections_receiver: Receiver<IoResult<client::ClientConnection>>,
    requests_receiver: sync::Mutex<Vec<Receiver<Request>>>,
}

/// Represents an HTTP request made by a client.
pub struct Request {
    read_socket: LimitReader<BufferedReader<tcp::TcpStream>>,
    write_socket: tcp::TcpStream,
    method: Method,
    path: url::Path,
    http_version: semver::Version,
    headers: Vec<Header>,
    body_length: uint,
}

impl Server {
    /// Builds a new server on port 80 that listens to all inputs.
    pub fn new() -> IoResult<Server> {
        Server::new_with_port(80)
    }

    /// Builds a new server on a given port and that listens to all inputs.
    pub fn new_with_port(port: ip::Port) -> IoResult<Server> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: port})
    }

    /// Builds a new server that listens on the specified address.
    pub fn new_with_addr(addr: &ip::SocketAddr) -> IoResult<Server> {
        // building the TcpAcceptor
        let server = try!(tcp::TcpListener::bind(
            format!("{}", addr.ip).as_slice(), addr.port).listen());

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are returned in the receiver
        let (tx, rx) = channel();
        spawn(proc() {
            let mut server = server;

            loop {
                let val = server.accept().map(|sock| client::ClientConnection::new(sock));

                match tx.send_opt(val) {
                    Err(_) => break,
                    _ => ()
                }
            }
        });

        // result
        Ok(Server {
            connections_receiver: rx,
            requests_receiver: sync::Mutex::new(Vec::new()),
        })
    }

    /// Returns the number of clients currently connected to the server.
    pub fn get_num_connections(&self) -> uint {
        self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    pub fn recv(&self) -> Request {
        loop {
            match self.try_recv() {
                Some(rq) => return rq,
                None => ()
            };
        }
    }

    /// Same as `recv()` but doesn't block.
    pub fn try_recv(&self) -> Option<Request> {
        self.process_new_clients();

        // TODO: rewrite this
        {
            let mut locked_receivers = self.requests_receiver.lock();
            for rx in locked_receivers.iter() {
                let attempt = rx.try_recv();
                if attempt.is_ok() {       // TODO: remove the channel if it is closed
                    return Some(attempt.unwrap());
                }
            }
        }

        None
    }

    /// Does not block.
    fn process_new_clients(&self) {
        let mut new_clients = Vec::new();

        // we add all the elements available on connections_receiver to new_clients
        loop {
            match self.connections_receiver.try_recv() {
                Ok(client) => new_clients.push(client),
                Err(_) => break
            }
        }

        // for each new client, spawning a task that will
        // continuously try to read a Request
        for client in new_clients.move_iter().filter_map(|c| c.ok()) {
            let (tx, rx) = channel();
            spawn(proc() {
                let mut client = client;
                // TODO: when the channel is being closed, immediatly notify the task
                client.advance(|rq| tx.send_opt(rq).is_ok());
            });
            self.requests_receiver.lock().push(rx);
        }
    }
}

impl Request {
    /// Returns the method requested by the client (eg. GET, POST, etc.)
    pub fn get_method<'a>(&'a self) -> &'a Method {
        &self.method
    }

    /// Returns the resource requested by the client.
    pub fn get_url<'a>(&'a self) -> &'a url::Path {
        &self.path
    }

    /// Returns a list of all headers sent by the client.
    pub fn get_headers<'a>(&'a self) -> &'a [Header] {
        self.headers.as_slice()
    }

    /// Returns the length of the body in bytes.
    pub fn get_body_length(&self) -> uint {
        self.body_length
    }

    /// Allows to read the body of the request.
    pub fn as_reader<'a>(&'a mut self)
        -> RefReader<'a, LimitReader<BufferedReader<tcp::TcpStream>>>
    {
        fn as_reader_impl<'a, R: Reader>(elem: &'a mut R) -> RefReader<'a, R> {
            elem.by_ref()
        }
        as_reader_impl(&mut self.read_socket)
    }

    // TODO: turn this into a function that consumes the Request
    fn as_raw_writer<'a>(&'a mut self) -> RefWriter<'a, tcp::TcpStream> {
        Request::as_raw_writer_impl(&mut self.write_socket)
    }

    fn as_raw_writer_impl<'a, W: Writer>(elem: &'a mut W) -> RefWriter<'a, W> {
        elem.by_ref()
    }

    /// Sends a response to this request.
    pub fn respond<R: Reader>(self, response: Response<R>) {
        match response.raw_print(self.write_socket) {
            Ok(_) => (),
            Err(err) => println!("error while sending answer: {}", err)     // TODO: handle better?
        }
    }
}

impl std::fmt::Show for Request {
    fn fmt(&self, formatter: &mut std::fmt::Formatter)
        -> Result<(), std::fmt::FormatError>
    {
        (format!("Request({} {})",
            self.method, self.path)).fmt(formatter)
    }
}
<commit_msg>Fix multiple requests with bodies not working<commit_after>#![crate_name = "tiny-http"]
#![crate_type = "lib"]
#![license = "Apache"]

extern crate semver;
extern crate url;

use std::io::{Acceptor, BufferedReader, IoResult, Listener, RefReader, RefWriter};
use std::io::net::ip;
use std::io::net::tcp;
use std::io::util::LimitReader;
use std::sync;

pub use common::Header;
pub use common::Method;
pub use common::StatusCode;
pub use response::Response;

mod client;
mod common;
mod response;

/// The main class of this library.
/// Create a new server using `Server::new()`.
pub struct Server {
    connections_receiver: Receiver<IoResult<client::ClientConnection>>,
    requests_receiver: sync::Mutex<Vec<Receiver<Request>>>,
}

/// Represents an HTTP request made by a client.
pub struct Request {
    read_socket: LimitReader<BufferedReader<tcp::TcpStream>>,
    write_socket: tcp::TcpStream,
    method: Method,
    path: url::Path,
    http_version: semver::Version,
    headers: Vec<Header>,
    body_length: uint,
}

impl Server {
    /// Builds a new server on port 80 that listens to all inputs.
    pub fn new() -> IoResult<Server> {
        Server::new_with_port(80)
    }

    /// Builds a new server on a given port and that listens to all inputs.
    pub fn new_with_port(port: ip::Port) -> IoResult<Server> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: port})
    }

    /// Builds a new server that listens on the specified address.
    pub fn new_with_addr(addr: &ip::SocketAddr) -> IoResult<Server> {
        // building the TcpAcceptor
        let server = try!(tcp::TcpListener::bind(
            format!("{}", addr.ip).as_slice(), addr.port).listen());

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are returned in the receiver
        let (tx, rx) = channel();
        spawn(proc() {
            let mut server = server;

            loop {
                let val = server.accept().map(|sock| client::ClientConnection::new(sock));

                match tx.send_opt(val) {
                    Err(_) => break,
                    _ => ()
                }
            }
        });

        // result
        Ok(Server {
            connections_receiver: rx,
            requests_receiver: sync::Mutex::new(Vec::new()),
        })
    }

    /// Returns the number of clients currently connected to the server.
    pub fn get_num_connections(&self) -> uint {
        self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    pub fn recv(&self) -> Request {
        loop {
            match self.try_recv() {
                Some(rq) => return rq,
                None => ()
            };
        }
    }

    /// Same as `recv()` but doesn't block.
    pub fn try_recv(&self) -> Option<Request> {
        self.process_new_clients();

        // TODO: rewrite this
        {
            let mut locked_receivers = self.requests_receiver.lock();
            for rx in locked_receivers.iter() {
                let attempt = rx.try_recv();
                if attempt.is_ok() {       // TODO: remove the channel if it is closed
                    return Some(attempt.unwrap());
                }
            }
        }

        None
    }

    /// Does not block.
    fn process_new_clients(&self) {
        let mut new_clients = Vec::new();

        // we add all the elements available on connections_receiver to new_clients
        loop {
            match self.connections_receiver.try_recv() {
                Ok(client) => new_clients.push(client),
                Err(_) => break
            }
        }

        // for each new client, spawning a task that will
        // continuously try to read a Request
        for client in new_clients.move_iter().filter_map(|c| c.ok()) {
            let (tx, rx) = channel();
            spawn(proc() {
                let mut client = client;
                // TODO: when the channel is being closed, immediatly notify the task
                client.advance(|rq| tx.send_opt(rq).is_ok());
            });
            self.requests_receiver.lock().push(rx);
        }
    }
}

impl Request {
    /// Returns the method requested by the client (eg. GET, POST, etc.)
    pub fn get_method<'a>(&'a self) -> &'a Method {
        &self.method
    }

    /// Returns the resource requested by the client.
    pub fn get_url<'a>(&'a self) -> &'a url::Path {
        &self.path
    }

    /// Returns a list of all headers sent by the client.
    pub fn get_headers<'a>(&'a self) -> &'a [Header] {
        self.headers.as_slice()
    }

    /// Returns the length of the body in bytes.
    pub fn get_body_length(&self) -> uint {
        self.body_length
    }

    /// Allows to read the body of the request.
    pub fn as_reader<'a>(&'a mut self)
        -> RefReader<'a, LimitReader<BufferedReader<tcp::TcpStream>>>
    {
        fn as_reader_impl<'a, R: Reader>(elem: &'a mut R) -> RefReader<'a, R> {
            elem.by_ref()
        }
        as_reader_impl(&mut self.read_socket)
    }

    // TODO: turn this into a function that consumes the Request
    fn as_raw_writer<'a>(&'a mut self) -> RefWriter<'a, tcp::TcpStream> {
        Request::as_raw_writer_impl(&mut self.write_socket)
    }

    fn as_raw_writer_impl<'a, W: Writer>(elem: &'a mut W) -> RefWriter<'a, W> {
        elem.by_ref()
    }

    /// Sends a response to this request.
    pub fn respond<R: Reader>(self, response: Response<R>) {
        Request::finish_reading(self.read_socket);

        match response.raw_print(self.write_socket) {
            Ok(_) => (),
            Err(err) => println!("error while sending answer: {}", err)     // TODO: handle better?
        }
    }

    /// Consumes the rest of the request's body in the TcpStream.
    fn finish_reading(reader: LimitReader<BufferedReader<tcp::TcpStream>>) {
        let remaining_to_read = reader.limit();
        let underlying = reader.unwrap().consume(remaining_to_read);
    }
}

impl std::fmt::Show for Request {
    fn fmt(&self, formatter: &mut std::fmt::Formatter)
        -> Result<(), std::fmt::FormatError>
    {
        (format!("Request({} {})",
            self.method, self.path)).fmt(formatter)
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate pretty_assertions;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

// we get an unused import when using macro use, but a
// "this has no effect without macro_use" message otherwise
#[allow(unused_imports)]
#[macro_use]
extern crate snapshot_proc_macro;

pub use snapshot_proc_macro::*;

use std::collections::BTreeMap;
use std::fmt::Debug;
use std::fs::{create_dir_all, File, OpenOptions};
use std::io::{BufReader, BufWriter};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use serde::Serialize;
use serde::de::DeserializeOwned;

pub type SnapFileContents = BTreeMap<String, Snapshot<serde_json::Value>>;

pub trait Snapable {}
impl<T> Snapable for T where T: Debug + DeserializeOwned + Serialize {}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct Snapshot<S: Snapable> {
    pub file: String,
    pub module_path: String,
    pub test_function: String,
    pub recorded_value: S,
}

impl<S> Snapshot<S>
    where S: Snapable + Debug + DeserializeOwned + PartialEq + Serialize
{
    pub fn check_snapshot(&self, manifest_dir: &str) {
        let SnapFileSpec {
            absolute_path,
            relative_path,
            ..
        } = self.path(manifest_dir);

        let snap_file = match File::open(&absolute_path) {
            Ok(f) => f,
            Err(why) => {
                panic!("Unable to open snapshot file {:?}: {:?}",
                       relative_path,
                       why.kind())
            }
        };

        let rdr = BufReader::new(snap_file);
        let mut module_snapshots: SnapFileContents = match serde_json::from_reader(rdr) {
            Ok(ps) => ps,
            Err(why) => {
                panic!("Unable to parse previous snapshot:\n{:#?}", why);
            }
        };

        let snap_key = self.module_key();
        let previous_snapshot = match module_snapshots.remove(&snap_key) {
            Some(s) => s,
            None => {
                panic!("Unable to find snapshot for test {:?} in {:?}",
                       snap_key,
                       relative_path)
            }
        };

        let Snapshot {
            recorded_value,
            file,
            module_path,
            test_function,
        } = previous_snapshot;

        match serde_json::from_value(recorded_value) {
            Ok(recorded_value) => {
                assert_eq!(self.file,
                           file,
                           "Filename for snapshot test function doesn't match recorded one");

                assert_eq!(self.module_path,
                           module_path,
                           "Module paths for snapshot test function doesn't match recorded one");

                assert_eq!(self.test_function,
                           test_function,
                           "Test function name doesn't match recorded one");

                assert_eq!(self.recorded_value,
                           recorded_value,
                           "Test output doesn't match recorded snapshot!");
            }
            Err(why) => {
                panic!("Unable to parse existing snapshot as correct type: {:?}",
                       why)
            }
        }
    }

    pub fn update_snapshot(&self, manifest_dir: &str) {
        let SnapFileSpec {
            dir: snap_dir,
            absolute_path,
            relative_path,
            ..
        } = self.path(manifest_dir);

        let mut dir_to_create = PathBuf::from(manifest_dir);
        dir_to_create.push(snap_dir.clone());
        match create_dir_all(&dir_to_create) {
            Ok(_) => (),
            Err(why) => {
                panic!("Unable to create snapshots directory {:?}: {:?}",
                       snap_dir,
                       why.kind())
            }
        }

        let mut existing_snaps: SnapFileContents = match File::open(&absolute_path) {
            Ok(f) => {
                let mut rdr = BufReader::new(f);
                let mut contents = String::new();
                rdr.read_to_string(&mut contents)
                    .expect("Unable to read snapshot file we just opened.");

                match serde_json::from_str(&contents) {
                    Ok(v) => v,
                    Err(why) => {
                        panic!("Unable to parse potentially corrupt snapshot file {:?}: {:?}",
                               relative_path,
                               why)
                    }
                }
            }
            Err(why) => {
                match why.kind() {
                    ::std::io::ErrorKind::NotFound => SnapFileContents::new(),
                    _ => {
                        panic!("Unable to open existing snapshot file {:?}: {:?}",
                               relative_path,
                               why.kind())
                    }
                }
            }

        };

        // now we need to update the particular snapshot we care about
        existing_snaps.insert(self.module_key(), self.create_deserializable());

        let writer =
            BufWriter::new(OpenOptions::new()
                               .read(true)
                               .write(true)
                               .create(true)
                               .open(&absolute_path)
                               .expect("Unable to open/create file that we just opened/created!",));

        match serde_json::to_writer_pretty(writer, &existing_snaps) {
            Ok(_) => (),
            Err(why) => {
                panic!("Unable to serialize or write snapshot result to {:?}: {:?}",
                       relative_path,
                       why)
            }
        }
    }

    fn module_key(&self) -> String {
        let mut snapshot_key = self.module_path.to_owned();
        snapshot_key.push_str("::");
        snapshot_key.push_str(&self.test_function);
        snapshot_key
    }

    fn create_deserializable(&self) -> Snapshot<serde_json::Value> {
        match serde_json::to_value(&self.recorded_value) {
            Ok(v) => {
                Snapshot {
                    file: self.file.clone(),
                    test_function: self.test_function.clone(),
                    module_path: self.module_path.clone(),
                    recorded_value: v,
                }
            }
            Err(why) => panic!("Unable to serialize test value: {:?}", why),
        }
    }

    fn path(&self, manifest_dir: &str) -> SnapFileSpec {
        let file_path = &Path::new(&self.file);

        let mut components = file_path.components();

        // strip the filename
        let mut filename = components.next_back().unwrap().as_os_str().to_owned();
        filename.push(".snap");

        let mut dir = PathBuf::new();
        for directory in components {
            dir.push(directory.as_os_str());
        }

        dir.push("__snapshots__");

        let mut absolute_path = PathBuf::from(manifest_dir);
        absolute_path.push(dir.clone());
        absolute_path.push(filename.clone());

        let mut relative_path = PathBuf::from(dir.clone());
        relative_path.push(filename.clone());

        SnapFileSpec {
            dir,
            absolute_path,
            relative_path,
        }
    }
}

struct SnapFileSpec {
    dir: PathBuf,
    relative_path: PathBuf,
    absolute_path: PathBuf,
}
<commit_msg>update rustfmt<commit_after>#[macro_use]
extern crate pretty_assertions;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

// we get an unused import when using macro use, but a
// "this has no effect without macro_use" message otherwise
#[allow(unused_imports)]
#[macro_use]
extern crate snapshot_proc_macro;

pub use snapshot_proc_macro::*;

use serde::de::DeserializeOwned;
use serde::Serialize;
use std::collections::BTreeMap;
use std::fmt::Debug;
use std::fs::{create_dir_all, File, OpenOptions};
use std::io::prelude::*;
use std::io::{BufReader, BufWriter};
use std::path::{Path, PathBuf};

pub type SnapFileContents = BTreeMap<String, Snapshot<serde_json::Value>>;

pub trait Snapable {}
impl<T> Snapable for T where T: Debug + DeserializeOwned + Serialize {}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct Snapshot<S: Snapable> {
    pub file: String,
    pub module_path: String,
    pub test_function: String,
    pub recorded_value: S,
}

impl<S> Snapshot<S>
where
    S: Snapable + Debug + DeserializeOwned + PartialEq + Serialize,
{
    pub fn check_snapshot(&self, manifest_dir: &str) {
        let SnapFileSpec {
            absolute_path,
            relative_path,
            ..
        } = self.path(manifest_dir);

        let snap_file = match File::open(&absolute_path) {
            Ok(f) => f,
            Err(why) => panic!(
                "Unable to open snapshot file {:?}: {:?}",
                relative_path,
                why.kind()
            ),
        };

        let rdr = BufReader::new(snap_file);
        let mut module_snapshots: SnapFileContents = match serde_json::from_reader(rdr) {
            Ok(ps) => ps,
            Err(why) => {
                panic!("Unable to parse previous snapshot:\n{:#?}", why);
            }
        };

        let snap_key = self.module_key();
        let previous_snapshot = match module_snapshots.remove(&snap_key) {
            Some(s) => s,
            None => panic!(
                "Unable to find snapshot for test {:?} in {:?}",
                snap_key, relative_path
            ),
        };

        let Snapshot {
            recorded_value,
            file,
            module_path,
            test_function,
        } = previous_snapshot;

        match serde_json::from_value(recorded_value) {
            Ok(recorded_value) => {
                assert_eq!(
                    self.file, file,
                    "Filename for snapshot test function doesn't match recorded one"
                );

                assert_eq!(
                    self.module_path, module_path,
                    "Module paths for snapshot test function doesn't match recorded one"
                );

                assert_eq!(
                    self.test_function, test_function,
                    "Test function name doesn't match recorded one"
                );

                assert_eq!(
                    self.recorded_value, recorded_value,
                    "Test output doesn't match recorded snapshot!"
                );
            }
            Err(why) => panic!(
                "Unable to parse existing snapshot as correct type: {:?}",
                why
            ),
        }
    }

    pub fn update_snapshot(&self, manifest_dir: &str) {
        let SnapFileSpec {
            dir: snap_dir,
            absolute_path,
            relative_path,
            ..
        } = self.path(manifest_dir);

        let mut dir_to_create = PathBuf::from(manifest_dir);
        dir_to_create.push(snap_dir.clone());
        match create_dir_all(&dir_to_create) {
            Ok(_) => (),
            Err(why) => panic!(
                "Unable to create snapshots directory {:?}: {:?}",
                snap_dir,
                why.kind()
            ),
        }

        let mut existing_snaps: SnapFileContents = match File::open(&absolute_path) {
            Ok(f) => {
                let mut rdr = BufReader::new(f);
                let mut contents = String::new();
                rdr.read_to_string(&mut contents)
                    .expect("Unable to read snapshot file we just opened.");

                match serde_json::from_str(&contents) {
                    Ok(v) => v,
                    Err(why) => panic!(
                        "Unable to parse potentially corrupt snapshot file {:?}: {:?}",
                        relative_path, why
                    ),
                }
            }
            Err(why) => match why.kind() {
                ::std::io::ErrorKind::NotFound => SnapFileContents::new(),
                _ => panic!(
                    "Unable to open existing snapshot file {:?}: {:?}",
                    relative_path,
                    why.kind()
                ),
            },
        };

        // now we need to update the particular snapshot we care about
        existing_snaps.insert(self.module_key(), self.create_deserializable());

        let writer = BufWriter::new(
            OpenOptions::new()
                .read(true)
                .write(true)
                .create(true)
                .open(&absolute_path)
                .expect("Unable to open/create file that we just opened/created!"),
        );

        match serde_json::to_writer_pretty(writer, &existing_snaps) {
            Ok(_) => (),
            Err(why) => panic!(
                "Unable to serialize or write snapshot result to {:?}: {:?}",
                relative_path, why
            ),
        }
    }

    fn module_key(&self) -> String {
        let mut snapshot_key = self.module_path.to_owned();
        snapshot_key.push_str("::");
        snapshot_key.push_str(&self.test_function);
        snapshot_key
    }

    fn create_deserializable(&self) -> Snapshot<serde_json::Value> {
        match serde_json::to_value(&self.recorded_value) {
            Ok(v) => Snapshot {
                file: self.file.clone(),
                test_function: self.test_function.clone(),
                module_path: self.module_path.clone(),
                recorded_value: v,
            },
            Err(why) => panic!("Unable to serialize test value: {:?}", why),
        }
    }

    fn path(&self, manifest_dir: &str) -> SnapFileSpec {
        let file_path = &Path::new(&self.file);

        let mut components = file_path.components();

        // strip the filename
        let mut filename = components.next_back().unwrap().as_os_str().to_owned();
        filename.push(".snap");

        let mut dir = PathBuf::new();
        for directory in components {
            dir.push(directory.as_os_str());
        }

        dir.push("__snapshots__");

        let mut absolute_path = PathBuf::from(manifest_dir);
        absolute_path.push(dir.clone());
        absolute_path.push(filename.clone());

        let mut relative_path = PathBuf::from(dir.clone());
        relative_path.push(filename.clone());

        SnapFileSpec {
            dir,
            absolute_path,
            relative_path,
        }
    }
}

struct SnapFileSpec {
    dir: PathBuf,
    relative_path: PathBuf,
    absolute_path: PathBuf,
}
<|endoftext|>


<commit_before>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! The time oracle service for Exonum

/*
#![deny(missing_debug_implementations)]
#![deny(missing_docs)]
*/

extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate exonum;
extern crate router;
extern crate bodyparser;
extern crate iron;

use iron::prelude::*;
use iron::Handler;
use router::Router;

use std::time::SystemTime;

use exonum::blockchain::{Blockchain, Service, ServiceContext, Schema, Transaction, ApiContext};
use exonum::messages::{RawTransaction, FromRaw, Message};
use exonum::encoding::serialize::json::reexport::Value;
use exonum::storage::{Fork, Snapshot, MapIndex, Entry};
use exonum::crypto::{PublicKey, Hash};
use exonum::encoding;
use exonum::helpers::fabric::{ServiceFactory, Context};
use exonum::api::Api;

const SERVICE_ID: u16 = 4;
const TX_TIME_ID: u16 = 1;
const SERVICE_NAME: &str = "exonum_time";

// SCHEMA

encoding_struct! {
    struct Time {
        const SIZE = 12;

        field time:     SystemTime  [00 => 12]
    }
}

pub struct TimeSchema<T> {
    view: T,
}

impl<T: AsRef<Snapshot>> TimeSchema<T> {
    pub fn new(view: T) -> Self {
        TimeSchema { view }
    }

    pub fn validators_time(&self) -> MapIndex<&Snapshot, PublicKey, Time> {
        MapIndex::new(
            SERVICE_NAME.to_string() + ".validators_time",
            self.view.as_ref(),
        )
    }

    pub fn time(&self) -> Entry<&Snapshot, Time> {
        Entry::new(SERVICE_NAME.to_string() + ".time", self.view.as_ref())
    }
}

impl<'a> TimeSchema<&'a mut Fork> {
    pub fn validators_time_mut(&mut self) -> MapIndex<&mut Fork, PublicKey, Time> {
        MapIndex::new(SERVICE_NAME.to_string() + ".validators_time", self.view)
    }

    pub fn time_mut(&mut self) -> Entry<&mut Fork, Time> {
        Entry::new(SERVICE_NAME.to_string() + "exonum_time.time", self.view)
    }
}

// TRANSACTION

message! {
    struct TxTime {
        const TYPE = SERVICE_ID;
        const ID = TX_TIME_ID;
        const SIZE = 44;

        field time:     SystemTime  [00 => 12]
        field pub_key:  &PublicKey  [12 => 44]
    }
}

impl Transaction for TxTime {
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    fn execute(&self, view: &mut Fork) {
        let validator_keys = Schema::new(&view).actual_configuration().validator_keys;

        if !validator_keys.iter().any(|&validator| {
            validator.service_key == *self.pub_key()
        })
        {
            return;
        }

        let mut schema = TimeSchema::new(view);
        match schema.validators_time().get(self.pub_key()) {
            Some(ref storage_time) if storage_time.time() >= self.time() => {
                return;
            }
            _ => {
                schema.validators_time_mut().put(
                    self.pub_key(),
                    Time::new(self.time()),
                )
            }
        }

        let mut validators_time: Vec<SystemTime>;
        {
            let idx = schema.validators_time();
            validators_time = idx.iter()
                .filter_map(|pair| {
                    validator_keys
                        .iter()
                        .find(|validator| validator.service_key == pair.0)
                        .map(|_| pair.1.time())
                })
                .collect();
        }

        let max_byzantine_nodes = validator_keys.len() / 3;
        if validators_time.len() <= max_byzantine_nodes {
            return;
        }

        validators_time.sort_by(|a, b| b.cmp(a));

        match schema.time().get() {
            Some(ref current_time)
                if current_time.time() >= validators_time[max_byzantine_nodes] => {
                return;
            }
            _ => {
                schema.time_mut().set(Time::new(
                    validators_time[max_byzantine_nodes],
                ));
            }
        }
    }
}

// API

#[derive(Serialize, Deserialize)]
pub struct TxResponse {
    pub tx_hash: Hash,
}

#[derive(Clone)]
struct TimeApi {
    blockchain: Blockchain,
}

impl TimeApi {
    fn get_current_time(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        let current_time = schema.time().get();
        self.ok_response(&serde_json::to_value(current_time).unwrap())
    }

    fn get_validators_time(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        let idx = schema.validators_time();
        let validators_time: Vec<Time> = idx.values().collect();
        if validators_time.is_empty() {
            self.not_found_response(&serde_json::to_value("Validators time database if empty")
                .unwrap())
        } else {
            self.ok_response(&serde_json::to_value(validators_time).unwrap())
        }
    }

    fn wire_private(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_validators_time = move |req: &mut Request| self_.get_validators_time(req);
        router.get(
            "/validators_time",
            get_validators_time,
            "get_validators_time",
        );
    }
}

impl Api for TimeApi {
    fn wire(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_current_time = move |req: &mut Request| self_.get_current_time(req);
        router.get("/current_time", get_current_time, "get_current_time");
    }
}

// SERVICE DECLARATION

pub struct TimeService;

impl TimeService {
    pub fn new() -> TimeService {
        TimeService {}
    }
}

impl Service for TimeService {
    fn service_name(&self) -> &'static str {
        SERVICE_NAME
    }

    fn service_id(&self) -> u16 {
        SERVICE_ID
    }

    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
        match raw.message_type() {
            TX_TIME_ID => Ok(Box::new(TxTime::from_raw(raw)?)),
            _ => {
                let error =
                    encoding::Error::IncorrectMessageType { message_type: raw.message_type() };
                Err(error)
            }
        }
    }

    fn initialize(&self, _fork: &mut Fork) -> Value {
        Value::Null
    }

    fn handle_commit(&self, context: &mut ServiceContext) {
        let (pub_key, sec_key) = (*context.public_key(), context.secret_key().clone());
        context.add_transaction(Box::new(TxTime::new(SystemTime::now(), &pub_key, &sec_key)));
    }

    fn private_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi { blockchain: ctx.blockchain().clone() };
        api.wire_private(&mut router);
        Some(Box::new(router))
    }

    fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi { blockchain: ctx.blockchain().clone() };
        api.wire(&mut router);
        Some(Box::new(router))
    }
}

pub struct TimeServiceFactory;

impl ServiceFactory for TimeServiceFactory {
    fn make_service(&mut self, _: &Context) -> Box<Service> {
        Box::new(TimeService::new())
    }
}
<commit_msg>Small edit<commit_after>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! The time oracle service for Exonum

/*
#![deny(missing_debug_implementations)]
#![deny(missing_docs)]
*/

extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate exonum;
extern crate router;
extern crate bodyparser;
extern crate iron;

use iron::prelude::*;
use iron::Handler;
use router::Router;

use std::time::SystemTime;

use exonum::blockchain::{Blockchain, Service, ServiceContext, Schema, Transaction, ApiContext};
use exonum::messages::{RawTransaction, FromRaw, Message};
use exonum::encoding::serialize::json::reexport::Value;
use exonum::storage::{Fork, Snapshot, MapIndex, Entry};
use exonum::crypto::{PublicKey, Hash};
use exonum::encoding;
use exonum::helpers::fabric::{ServiceFactory, Context};
use exonum::api::Api;

const SERVICE_ID: u16 = 4;
const TX_TIME_ID: u16 = 1;
const SERVICE_NAME: &str = "exonum_time";

// SCHEMA

encoding_struct! {
    struct Time {
        const SIZE = 12;

        field time:     SystemTime  [00 => 12]
    }
}

pub struct TimeSchema<T> {
    view: T,
}

impl<T: AsRef<Snapshot>> TimeSchema<T> {
    pub fn new(view: T) -> Self {
        TimeSchema { view }
    }

    pub fn validators_time(&self) -> MapIndex<&Snapshot, PublicKey, Time> {
        MapIndex::new(
            SERVICE_NAME.to_string() + ".validators_time",
            self.view.as_ref(),
        )
    }

    pub fn time(&self) -> Entry<&Snapshot, Time> {
        Entry::new(SERVICE_NAME.to_string() + ".time", self.view.as_ref())
    }
}

impl<'a> TimeSchema<&'a mut Fork> {
    pub fn validators_time_mut(&mut self) -> MapIndex<&mut Fork, PublicKey, Time> {
        MapIndex::new(SERVICE_NAME.to_string() + ".validators_time", self.view)
    }

    pub fn time_mut(&mut self) -> Entry<&mut Fork, Time> {
        Entry::new(SERVICE_NAME.to_string() + ".time", self.view)
    }
}

// TRANSACTION

message! {
    struct TxTime {
        const TYPE = SERVICE_ID;
        const ID = TX_TIME_ID;
        const SIZE = 44;

        field time:     SystemTime  [00 => 12]
        field pub_key:  &PublicKey  [12 => 44]
    }
}

impl Transaction for TxTime {
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    fn execute(&self, view: &mut Fork) {
        let validator_keys = Schema::new(&view).actual_configuration().validator_keys;

        if !validator_keys.iter().any(|&validator| {
            validator.service_key == *self.pub_key()
        })
        {
            return;
        }

        let mut schema = TimeSchema::new(view);
        match schema.validators_time().get(self.pub_key()) {
            Some(ref storage_time) if storage_time.time() >= self.time() => {
                return;
            }
            _ => {
                schema.validators_time_mut().put(
                    self.pub_key(),
                    Time::new(self.time()),
                )
            }
        }

        let mut validators_time: Vec<SystemTime>;
        {
            let idx = schema.validators_time();
            validators_time = idx.iter()
                .filter_map(|pair| {
                    validator_keys
                        .iter()
                        .find(|validator| validator.service_key == pair.0)
                        .map(|_| pair.1.time())
                })
                .collect();
        }

        let max_byzantine_nodes = validator_keys.len() / 3;
        if validators_time.len() <= max_byzantine_nodes {
            return;
        }

        validators_time.sort_by(|a, b| b.cmp(a));

        match schema.time().get() {
            Some(ref current_time)
                if current_time.time() >= validators_time[max_byzantine_nodes] => {
                return;
            }
            _ => {
                schema.time_mut().set(Time::new(
                    validators_time[max_byzantine_nodes],
                ));
            }
        }
    }
}

// API

#[derive(Serialize, Deserialize)]
pub struct TxResponse {
    pub tx_hash: Hash,
}

#[derive(Clone)]
struct TimeApi {
    blockchain: Blockchain,
}

impl TimeApi {
    fn get_current_time(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        let current_time = schema.time().get();
        self.ok_response(&serde_json::to_value(current_time).unwrap())
    }

    fn get_validators_time(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        let idx = schema.validators_time();
        let validators_time: Vec<Time> = idx.values().collect();
        if validators_time.is_empty() {
            self.not_found_response(&serde_json::to_value("Validators time database if empty")
                .unwrap())
        } else {
            self.ok_response(&serde_json::to_value(validators_time).unwrap())
        }
    }

    fn wire_private(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_validators_time = move |req: &mut Request| self_.get_validators_time(req);
        router.get(
            "/validators_time",
            get_validators_time,
            "get_validators_time",
        );
    }
}

impl Api for TimeApi {
    fn wire(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_current_time = move |req: &mut Request| self_.get_current_time(req);
        router.get("/current_time", get_current_time, "get_current_time");
    }
}

// SERVICE DECLARATION

pub struct TimeService;

impl TimeService {
    pub fn new() -> TimeService {
        TimeService {}
    }
}

impl Service for TimeService {
    fn service_name(&self) -> &'static str {
        SERVICE_NAME
    }

    fn service_id(&self) -> u16 {
        SERVICE_ID
    }

    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
        match raw.message_type() {
            TX_TIME_ID => Ok(Box::new(TxTime::from_raw(raw)?)),
            _ => {
                let error =
                    encoding::Error::IncorrectMessageType { message_type: raw.message_type() };
                Err(error)
            }
        }
    }

    fn initialize(&self, _fork: &mut Fork) -> Value {
        Value::Null
    }

    fn handle_commit(&self, context: &mut ServiceContext) {
        let (pub_key, sec_key) = (*context.public_key(), context.secret_key().clone());
        context.add_transaction(Box::new(TxTime::new(SystemTime::now(), &pub_key, &sec_key)));
    }

    fn private_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi { blockchain: ctx.blockchain().clone() };
        api.wire_private(&mut router);
        Some(Box::new(router))
    }

    fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi { blockchain: ctx.blockchain().clone() };
        api.wire(&mut router);
        Some(Box::new(router))
    }
}

pub struct TimeServiceFactory;

impl ServiceFactory for TimeServiceFactory {
    fn make_service(&mut self, _: &Context) -> Box<Service> {
        Box::new(TimeService::new())
    }
}
<|endoftext|>