<commit_before>//! Iron's HTTP Response representation and associated methods.

use std::io::{IoResult, File, MemReader};
use std::path::BytesContainer;

use typemap::TypeMap;
use plugin::Extensible;
use http::status::{Status, InternalServerError, NotFound};
use http::status::Ok as OkStatus;
use http::headers::response::HeaderCollection;
use http::headers::content_type::MediaType;

pub use http::server::response::ResponseWriter as HttpResponse;

use contenttype::get_content_type;

/// The response representation given to `Middleware`
pub struct Response {
    /// The body of the response.
    ///
    /// This is a Reader for generality, most data should
    /// be sent using either `serve` or `serve_file`.
    ///
    /// Arbitrary Readers can be sent by assigning to body.
    pub body: Option<Box<Reader>>,

    /// The headers of the response.
    pub headers: Box<HeaderCollection>,

    /// The response status-code.
    pub status: Option<Status>,

    /// A TypeMap to be used as an extensible storage for data
    /// associated with this Response.
    pub extensions: TypeMap
}

impl Response {
    /// Construct a blank Response
    pub fn new() -> Response {
        Response {
            headers: box HeaderCollection::new(),
            status: None, // Start with no response code.
            body: None, // Start with no body.
            extensions: TypeMap::new()
        }
    }

    /// Write the `Status` and data to the `Response`.
    pub fn serve<S: BytesContainer>(&mut self, status: Status, body: S) {
        self.status = Some(status);
        self.body = Some(box MemReader::new(body.container_as_bytes().to_vec()) as Box<Reader>);
    }

    /// Serve the file located at `path`.
    ///
    /// This usually means a request has been handled, and `Middleware`
    /// may want to `Unwind` after a file is served. If the status should be
    /// anything other than `200`, `Middleware` must set it, including in
    /// the case of an `Err`.
    ///
    /// `serve_file` will error if the file does not exist, the process
    /// does not have correct permissions, or it has other issues in reading
    /// from the file. `Middleware` should handle this gracefully.
    pub fn serve_file(&mut self, path: &Path) -> IoResult<()> {
        let file = try!(File::open(path));
        self.headers.content_type = path.extension_str().and_then(get_content_type);
        self.body = Some(box file as Box<Reader>);
        self.status = Some(OkStatus);
        Ok(())
    }

    // `write_back` is used to put all the data added to `self`
    // back onto an `HttpResponse` so that it is sent back to the
    // client.
    //
    // `write_back` consumes the `Response`.
    #[doc(hidden)]
    pub fn write_back(self, http_res: &mut HttpResponse) {
        http_res.headers = self.headers.clone();

        // Default to a 404 if no response code was set
        http_res.status = self.status.clone().unwrap_or(NotFound);

        // Read the body into the http_res body
        let mut body = self.body.unwrap_or_else(|| box MemReader::new(vec![]) as Box<Reader>);
        let _ = match body.read_to_end() {
            Ok(body_content) => {
                let plain_txt: MediaType = get_content_type("txt").unwrap();

                // Set content length and type
                http_res.headers.content_length =
                    Some(body_content.len());
                http_res.headers.content_type =
                    Some(http_res.headers.content_type.clone().unwrap_or(plain_txt));

                // Write the body
                http_res.write(body_content.as_slice())
            },
            Err(e) => Err(e)
        // Catch errors from reading + writing
        }.map_err(|e| {
            error!("Error reading/writing body: {}", e);
            http_res.status = InternalServerError;
            let _ = http_res.write(b"Internal Server Error")
                // Something is really, really wrong.
                .map_err(|e| error!("Error writing error message: {}", e));
        });
    }
}

// Allow plugins to attach to responses.
impl Extensible for Response {
    fn extensions(&self) -> &TypeMap {
        &self.extensions
    }

    fn extensions_mut(&mut self) -> &mut TypeMap {
        &mut self.extensions
    }
}

#[test]
fn matches_content_type () {
    let path = &Path::new("test.txt");
    let content_type = path.extension_str().and_then(get_content_type).unwrap();

    assert_eq!(content_type.type_.as_slice(), "text");
    assert_eq!(content_type.subtype.as_slice(), "plain");
}
<commit_msg>(feat) Eradicated Option::unwrap.<commit_after>//! Iron's HTTP Response representation and associated methods.

use std::io::{IoResult, File, MemReader};
use std::path::BytesContainer;

use typemap::TypeMap;
use plugin::Extensible;
use http::status::{Status, InternalServerError, NotFound};
use http::status::Ok as OkStatus;
use http::headers::response::HeaderCollection;
use http::headers::content_type::MediaType;

pub use http::server::response::ResponseWriter as HttpResponse;

use contenttype::get_content_type;

/// The response representation given to `Middleware`
pub struct Response {
    /// The body of the response.
    ///
    /// This is a Reader for generality, most data should
    /// be sent using either `serve` or `serve_file`.
    ///
    /// Arbitrary Readers can be sent by assigning to body.
    pub body: Option<Box<Reader>>,

    /// The headers of the response.
    pub headers: Box<HeaderCollection>,

    /// The response status-code.
    pub status: Option<Status>,

    /// A TypeMap to be used as an extensible storage for data
    /// associated with this Response.
    pub extensions: TypeMap
}

impl Response {
    /// Construct a blank Response
    pub fn new() -> Response {
        Response {
            headers: box HeaderCollection::new(),
            status: None, // Start with no response code.
            body: None, // Start with no body.
            extensions: TypeMap::new()
        }
    }

    /// Write the `Status` and data to the `Response`.
    pub fn serve<S: BytesContainer>(&mut self, status: Status, body: S) {
        self.status = Some(status);
        self.body = Some(box MemReader::new(body.container_as_bytes().to_vec()) as Box<Reader>);
    }

    /// Serve the file located at `path`.
    ///
    /// This usually means a request has been handled, and `Middleware`
    /// may want to `Unwind` after a file is served. If the status should be
    /// anything other than `200`, `Middleware` must set it, including in
    /// the case of an `Err`.
    ///
    /// `serve_file` will error if the file does not exist, the process
    /// does not have correct permissions, or it has other issues in reading
    /// from the file. `Middleware` should handle this gracefully.
    pub fn serve_file(&mut self, path: &Path) -> IoResult<()> {
        let file = try!(File::open(path));
        self.headers.content_type = path.extension_str().and_then(get_content_type);
        self.body = Some(box file as Box<Reader>);
        self.status = Some(OkStatus);
        Ok(())
    }

    // `write_back` is used to put all the data added to `self`
    // back onto an `HttpResponse` so that it is sent back to the
    // client.
    //
    // `write_back` consumes the `Response`.
    #[doc(hidden)]
    pub fn write_back(self, http_res: &mut HttpResponse) {
        http_res.headers = self.headers.clone();

        // Default to a 404 if no response code was set
        http_res.status = self.status.clone().unwrap_or(NotFound);

        // Read the body into the http_res body
        let mut body = self.body.unwrap_or_else(|| box MemReader::new(vec![]) as Box<Reader>);
        let _ = match body.read_to_end() {
            Ok(body_content) => {
                let plain_txt = MediaType {
                    type_: "text".to_string(),
                    subtype: "plain".to_string(),
                    parameters: vec![]
                };

                // Set content length and type
                http_res.headers.content_length =
                    Some(body_content.len());
                http_res.headers.content_type =
                    Some(http_res.headers.content_type.clone().unwrap_or(plain_txt));

                // Write the body
                http_res.write(body_content.as_slice())
            },
            Err(e) => Err(e)
        // Catch errors from reading + writing
        }.map_err(|e| {
            error!("Error reading/writing body: {}", e);
            http_res.status = InternalServerError;
            let _ = http_res.write(b"Internal Server Error")
                // Something is really, really wrong.
                .map_err(|e| error!("Error writing error message: {}", e));
        });
    }
}

// Allow plugins to attach to responses.
impl Extensible for Response {
    fn extensions(&self) -> &TypeMap {
        &self.extensions
    }

    fn extensions_mut(&mut self) -> &mut TypeMap {
        &mut self.extensions
    }
}

#[test]
fn matches_content_type () {
    let path = &Path::new("test.txt");
    let content_type = path.extension_str().and_then(get_content_type).unwrap();

    assert_eq!(content_type.type_.as_slice(), "text");
    assert_eq!(content_type.subtype.as_slice(), "plain");
}
<|endoftext|>


<commit_before>#![feature(path, core, io)]
extern crate fragments;
use fragments::Template;
use std::borrow::ToOwned;
use std::old_io::{BufferedReader, File};
use std::path::Path;

fn main() {
	//Load the content of a file into a Template
	//The file contains the text 'Hello, [[:name]]!', in this example
	let file = File::open(&Path::new("path/to/my/template.txt"));
	let mut template = match Template::from_buffer(&mut BufferedReader::new(file)) {
		Ok(template) => template,
		Err(e) => panic!(e)
	};

	//Insert something into the `name` placeholder
	template.insert("name".to_owned(), "Peter");

	//Templates can be printed as they are
	//Result: 'Hello, Peter!'
	println!("Result: '{}'", template);
}<commit_msg>path -> old_path<commit_after>#![feature(path, core, io)]
extern crate fragments;
use fragments::Template;
use std::borrow::ToOwned;
use std::old_io::{BufferedReader, File};
use std::old_path::Path;

fn main() {
	//Load the content of a file into a Template
	//The file contains the text 'Hello, [[:name]]!', in this example
	let file = File::open(&Path::new("path/to/my/template.txt"));
	let mut template = match Template::from_buffer(&mut BufferedReader::new(file)) {
		Ok(template) => template,
		Err(e) => panic!(e)
	};

	//Insert something into the `name` placeholder
	template.insert("name".to_owned(), "Peter");

	//Templates can be printed as they are
	//Result: 'Hello, Peter!'
	println!("Result: '{}'", template);
}<|endoftext|>


<commit_before>#[legacy_exports];
export FreeTypeNativeFont, with_test_native_font, create;

use font::{FontMetrics, FractionalPixel};

use util::*;
use vec_as_buf = vec::as_imm_buf;
use ptr::{addr_of, null};
use cast::reinterpret_cast;
use glyph::GlyphIndex;
use font::FontMetrics;
use azure::freetype;
use freetype::{ FT_Error, FT_Library, FT_Face, FT_Long, FT_ULong, FT_UInt, FT_GlyphSlot };
use freetype::bindgen::{
    FT_Init_FreeType,
    FT_Done_FreeType,
    FT_New_Memory_Face,
    FT_Done_Face,
    FT_Get_Char_Index,
    FT_Load_Glyph,
    FT_Set_Char_Size
};

fn float_to_fixed_ft(f: float) -> i32 {
    float_to_fixed(26, f)
}

fn fixed_to_float_ft(f: i32) -> float {
    fixed_to_float(26, f)
}

struct FreeTypeNativeFont {
    /// The font binary. This must stay valid for the lifetime of the font
    buf: @~[u8],
    face: FT_Face,

    drop {
        assert self.face.is_not_null();
        if !FT_Done_Face(self.face).succeeded() {
            fail ~"FT_Done_Face failed";
        }
    }
}

fn FreeTypeNativeFont(face: FT_Face, buf: @~[u8]) -> FreeTypeNativeFont {
    assert face.is_not_null();
    FreeTypeNativeFont { buf: buf, face: face }
}

impl FreeTypeNativeFont {

    fn glyph_index(codepoint: char) -> Option<GlyphIndex> {
        assert self.face.is_not_null();
        let idx = FT_Get_Char_Index(self.face, codepoint as FT_ULong);
        return if idx != 0 as FT_UInt {
            Some(idx as GlyphIndex)
        } else {
            debug!("Invalid codepoint: %?", codepoint);
            None
        };
    }

    // FIXME: What unit is this returning? Let's have a custom type
    fn glyph_h_advance(glyph: GlyphIndex) -> Option<FractionalPixel> {
        assert self.face.is_not_null();
        let res =  FT_Load_Glyph(self.face, glyph as FT_UInt, 0);
        if res.succeeded() {
            unsafe {
                let void_glyph = (*self.face).glyph;
                let slot: FT_GlyphSlot = reinterpret_cast(&void_glyph);
                assert slot.is_not_null();
                let advance = (*slot).metrics.horiAdvance;
                debug!("h_advance for %? is %?", glyph, advance);
                let advance = advance as i32;
                return Some(fixed_to_float_ft(advance) as FractionalPixel);
            }
        } else {
            debug!("Unable to load glyph %?. reason: %?", glyph, res);
            return None;
        }
    }

    fn get_metrics() -> FontMetrics {
        /* TODO: complete me (Issue #76) */
        return FontMetrics {
            underline_size:   0.0,
            underline_offset: 0.0,
            leading:          0.0,
            x_height:         0.0,
            em_size:          gfx::geometry::au(0),
            em_height:        0.0,
            em_ascent:        0.0,
            em_descent:       0.0,
            max_advance:      0.0
        }
    }
}

pub fn create(lib: &FT_Library, buf: @~[u8]) -> Result<FreeTypeNativeFont, ()> {
    assert lib.is_not_null();
    let face: FT_Face = null();
    return vec_as_buf(*buf, |cbuf, _len| {
           if FT_New_Memory_Face(*lib, cbuf, (*buf).len() as FT_Long,
                                 0 as FT_Long, addr_of(&face)).succeeded() {
               // FIXME: These values are placeholders
               let res = FT_Set_Char_Size(face, 0, 20*64, 0, 72);
               if !res.succeeded() { fail ~"unable to set font char size" }
               Ok(FreeTypeNativeFont(face, buf))
           } else {
               Err(())
           }
    })
}

trait FTErrorMethods {
    fn succeeded() -> bool;
}

impl FT_Error : FTErrorMethods {
    fn succeeded() -> bool { self == 0 as FT_Error }
}

fn with_test_native_font(f: fn@(nf: &NativeFont)) {
    use font::test_font_bin;
    use unwrap_result = result::unwrap;

    with_lib(|lib| {
        let buf = @test_font_bin();
        let font = unwrap_result(create(lib, move buf));
        f(&font);
    })
}

fn with_lib(f: fn@((&FT_Library))) {
    let lib: FT_Library = null();
    assert FT_Init_FreeType(addr_of(&lib)).succeeded();
    f(&lib);
    FT_Done_FreeType(lib);
}

#[test]
fn create_should_return_err_if_buf_is_bogus() {
    with_lib(|lib| {
        let buf = @~[];
        assert create(lib, buf).is_err();
    })
}
<commit_msg>Correct fixed point conversion in ft_native_font<commit_after>#[legacy_exports];
export FreeTypeNativeFont, with_test_native_font, create;

use font::{FontMetrics, FractionalPixel};

use util::*;
use vec_as_buf = vec::as_imm_buf;
use ptr::{addr_of, null};
use cast::reinterpret_cast;
use glyph::GlyphIndex;
use font::FontMetrics;
use azure::freetype;
use freetype::{ FT_Error, FT_Library, FT_Face, FT_Long, FT_ULong, FT_UInt, FT_GlyphSlot };
use freetype::bindgen::{
    FT_Init_FreeType,
    FT_Done_FreeType,
    FT_New_Memory_Face,
    FT_Done_Face,
    FT_Get_Char_Index,
    FT_Load_Glyph,
    FT_Set_Char_Size
};

fn float_to_fixed_ft(f: float) -> i32 {
    float_to_fixed(6, f)
}

fn fixed_to_float_ft(f: i32) -> float {
    fixed_to_float(6, f)
}

struct FreeTypeNativeFont {
    /// The font binary. This must stay valid for the lifetime of the font
    buf: @~[u8],
    face: FT_Face,

    drop {
        assert self.face.is_not_null();
        if !FT_Done_Face(self.face).succeeded() {
            fail ~"FT_Done_Face failed";
        }
    }
}

fn FreeTypeNativeFont(face: FT_Face, buf: @~[u8]) -> FreeTypeNativeFont {
    assert face.is_not_null();
    FreeTypeNativeFont { buf: buf, face: face }
}

impl FreeTypeNativeFont {

    fn glyph_index(codepoint: char) -> Option<GlyphIndex> {
        assert self.face.is_not_null();
        let idx = FT_Get_Char_Index(self.face, codepoint as FT_ULong);
        return if idx != 0 as FT_UInt {
            Some(idx as GlyphIndex)
        } else {
            debug!("Invalid codepoint: %?", codepoint);
            None
        };
    }

    // FIXME: What unit is this returning? Let's have a custom type
    fn glyph_h_advance(glyph: GlyphIndex) -> Option<FractionalPixel> {
        assert self.face.is_not_null();
        let res =  FT_Load_Glyph(self.face, glyph as FT_UInt, 0);
        if res.succeeded() {
            unsafe {
                let void_glyph = (*self.face).glyph;
                let slot: FT_GlyphSlot = reinterpret_cast(&void_glyph);
                assert slot.is_not_null();
                debug!("metrics: %?", (*slot).metrics);
                let advance = (*slot).metrics.horiAdvance;
                debug!("h_advance for %? is %?", glyph, advance);
                let advance = advance as i32;
                return Some(fixed_to_float_ft(advance) as FractionalPixel);
            }
        } else {
            debug!("Unable to load glyph %?. reason: %?", glyph, res);
            return None;
        }
    }

    fn get_metrics() -> FontMetrics {
        /* TODO: complete me (Issue #76) */
        return FontMetrics {
            underline_size:   0.0,
            underline_offset: 0.0,
            leading:          0.0,
            x_height:         0.0,
            em_size:          gfx::geometry::au(0),
            em_height:        0.0,
            em_ascent:        0.0,
            em_descent:       0.0,
            max_advance:      0.0
        }
    }
}

pub fn create(lib: &FT_Library, buf: @~[u8]) -> Result<FreeTypeNativeFont, ()> {
    assert lib.is_not_null();
    let face: FT_Face = null();
    return vec_as_buf(*buf, |cbuf, _len| {
           if FT_New_Memory_Face(*lib, cbuf, (*buf).len() as FT_Long,
                                 0 as FT_Long, addr_of(&face)).succeeded() {
               // FIXME: These values are placeholders
               let res = FT_Set_Char_Size(face, 0, 20*64, 0, 72);
               if !res.succeeded() { fail ~"unable to set font char size" }
               Ok(FreeTypeNativeFont(face, buf))
           } else {
               Err(())
           }
    })
}

trait FTErrorMethods {
    fn succeeded() -> bool;
}

impl FT_Error : FTErrorMethods {
    fn succeeded() -> bool { self == 0 as FT_Error }
}

fn with_test_native_font(f: fn@(nf: &NativeFont)) {
    use font::test_font_bin;
    use unwrap_result = result::unwrap;

    with_lib(|lib| {
        let buf = @test_font_bin();
        let font = unwrap_result(create(lib, move buf));
        f(&font);
    })
}

fn with_lib(f: fn@((&FT_Library))) {
    let lib: FT_Library = null();
    assert FT_Init_FreeType(addr_of(&lib)).succeeded();
    f(&lib);
    FT_Done_FreeType(lib);
}

#[test]
fn create_should_return_err_if_buf_is_bogus() {
    with_lib(|lib| {
        let buf = @~[];
        assert create(lib, buf).is_err();
    })
}
<|endoftext|>


<commit_before>/*
 * UpdateHub
 * Copyright (C) 2017
 * O.S. Systems Sofware LTDA: contact@ossystems.com.br
 *
 * SPDX-License-Identifier:     GPL-2.0
 */

use serde_ini;

use std::io;
use std::time::Duration;

use de_helpers::{bool_from_str, duration_from_str, vec_from_str};

const SYSTEM_SETTINGS_PATH: &str = "/etc/updatehub.conf";

#[derive(Default, PartialEq, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Settings {
    pub polling: Polling,
    pub storage: Storage,
    pub update: Update,
    pub network: Network,
    pub firmware: Firmware,
}

impl Settings {
    pub fn new() -> Self {
        Settings::default()
    }

    pub fn load(self) -> Result<Self, SettingsError> {
        use std::fs::File;
        use std::io::Read;
        use std::path::Path;

        let path = Path::new(SYSTEM_SETTINGS_PATH);

        if path.exists() {
            info!("Loading system settings from '{}'...",
                  path.to_string_lossy());

            let mut content = String::new();
            File::open(path)?.read_to_string(&mut content)?;

            Ok(self.parse(&content)?)
        } else {
            debug!("System settings file {} does not exists.",
                   path.to_string_lossy());
            info!("Using default system settings...");
            Ok(self)
        }
    }

    fn parse(self, content: &str) -> Result<Self, SettingsError> {
        fn has_protocol_prefix(server: &str) -> bool {
            server.starts_with("http://") || server.starts_with("https://")
        }

        fn has_valid_polling_interval(interval: &Duration) -> bool {
            (*interval >= Duration::new(60, 0))
        }

        let settings = serde_ini::from_str::<Settings>(content)?;

        if !has_valid_polling_interval(&settings.polling.interval) {
            error!("Invalid setting for polling interval. The interval cannot be less than 60 seconds");
            return Err(SettingsError::InvalidInterval);
        }

        if !has_protocol_prefix(&settings.network.server_address) {
            error!("Invalid setting for server address. The server address must use the protocol prefix");
            return Err(SettingsError::InvalidServerAddress);
        }

        Ok(settings)
    }
}

#[derive(Debug)]
pub enum SettingsError {
    Io(io::Error),
    Ini(serde_ini::de::Error),
    InvalidInterval,
    InvalidServerAddress,
}

impl From<io::Error> for SettingsError {
    fn from(err: io::Error) -> SettingsError {
        SettingsError::Io(err)
    }
}

impl From<serde_ini::de::Error> for SettingsError {
    fn from(err: serde_ini::de::Error) -> SettingsError {
        SettingsError::Ini(err)
    }
}

#[derive(Deserialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub struct Polling {
    #[serde(deserialize_with = "duration_from_str")] pub interval: Duration,
    #[serde(deserialize_with = "bool_from_str")] pub enabled: bool,
}

impl Default for Polling {
    fn default() -> Self {
        Polling { interval: Duration::new(86_400, 0), // 1 day
                  enabled: true, }
    }
}

#[derive(Deserialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub struct Storage {
    #[serde(deserialize_with = "bool_from_str")] pub read_only: bool,
    pub runtime_settings: String,
}

impl Default for Storage {
    fn default() -> Self {
        Storage { read_only: false,
                  runtime_settings: "/var/lib/updatehub.conf".to_string(), }
    }
}

#[derive(Deserialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub struct Update {
    pub download_dir: String,
    #[serde(rename = "SupportedInstallModes")]
    #[serde(deserialize_with = "vec_from_str")]
    pub install_modes: Vec<String>,
}

impl Default for Update {
    fn default() -> Self {
        Update { download_dir: "/tmp/updatehub".to_string(),
                 install_modes: ["dry-run", "copy", "flash", "imxkobs", "raw", "tarball", "ubifs"].iter()
                                                                                .map(|i| {
                                                                                i.to_string()
                                                                                })
                                                                                .collect(), }
    }
}

#[derive(Deserialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub struct Network {
    pub server_address: String,
}

impl Default for Network {
    fn default() -> Self {
        Network { server_address: "https://api.updatehub.io".to_string(), }
    }
}

#[derive(Deserialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub struct Firmware {
    pub metadata_path: String,
}

impl Default for Firmware {
    fn default() -> Self {
        Firmware { metadata_path: "/usr/share/updatehub".to_string(), }
    }
}

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

    #[test]
    fn ok() {
        let ini = r"
[Polling]
Interval=60s
Enabled=false

[Storage]
ReadOnly=true
RuntimeSettings=/run/updatehub/state

[Update]
DownloadDir=/tmp/download
SupportedInstallModes=mode1,mode2

[Network]
ServerAddress=http://localhost

[Firmware]
MetadataPath=/tmp/metadata
";

        let expected =
            Settings { polling: Polling { interval: Duration::new(60, 0),
                                          enabled: false, },
                       storage: Storage { read_only: true,
                                          runtime_settings: "/run/updatehub/state".to_string(), },
                       update: Update { download_dir: "/tmp/download".to_string(),
                                        install_modes: ["mode1", "mode2"].iter().map(|i| i.to_string()).collect(), },
                       network: Network { server_address: "http://localhost".to_string(), },
                       firmware: Firmware { metadata_path: "/tmp/metadata".to_string(), }, };

        assert!(serde_ini::from_str::<Settings>(&ini).map_err(|e| println!("{}", e))
                                                     .ok() == Some(expected));
    }

    #[test]
    fn invalid_polling_interval() {
        let ini = r"
[Polling]
Interval=59s
Enabled=false

[Storage]
ReadOnly=true
RuntimeSettings=/run/updatehub/state

[Update]
DownloadDir=/tmp/download
SupportedInstallModes=mode1,mode2

[Network]
ServerAddress=http://localhost

[Firmware]
MetadataPath=/tmp/metadata
";
        assert!(Settings::new().parse(&ini).is_err());
    }

    #[test]
    fn invalid_network_server_address() {
        let ini = r"
[Polling]
Interval=60s
Enabled=false

[Storage]
ReadOnly=true
RuntimeSettings=/run/updatehub/state

[Update]
DownloadDir=/tmp/download
SupportedInstallModes=mode1,mode2

[Network]
ServerAddress=localhost

[Firmware]
MetadataPath=/tmp/metadata
";
        assert!(Settings::new().parse(&ini).is_err());
    }

    #[test]
    fn default() {
        let settings = Settings::new();
        let expected = Settings {
            polling: Polling {
                interval: Duration::new(86_400, 0),
                enabled: true,
            },
            storage: Storage {
                read_only: false,
                runtime_settings: "/var/lib/updatehub.conf".to_string(),
            },
            update: Update {
                download_dir: "/tmp/updatehub".to_string(),
                install_modes: ["dry-run", "copy", "flash", "imxkobs", "raw", "tarball", "ubifs"]
                    .iter()
                    .map(|i| i.to_string())
                    .collect(),
            },
            network: Network { server_address: "https://api.updatehub.io".to_string() },
            firmware: Firmware { metadata_path: "/usr/share/updatehub".to_string() },
        };

        assert!(Some(settings) == Some(expected));
    }
}
<commit_msg>settings: Prefer use .into() instead of .to_string()<commit_after>/*
 * UpdateHub
 * Copyright (C) 2017
 * O.S. Systems Sofware LTDA: contact@ossystems.com.br
 *
 * SPDX-License-Identifier:     GPL-2.0
 */

use serde_ini;

use std::io;
use std::time::Duration;

use de_helpers::{bool_from_str, duration_from_str, vec_from_str};

const SYSTEM_SETTINGS_PATH: &str = "/etc/updatehub.conf";

#[derive(Default, PartialEq, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Settings {
    pub polling: Polling,
    pub storage: Storage,
    pub update: Update,
    pub network: Network,
    pub firmware: Firmware,
}

impl Settings {
    pub fn new() -> Self {
        Settings::default()
    }

    pub fn load(self) -> Result<Self, SettingsError> {
        use std::fs::File;
        use std::io::Read;
        use std::path::Path;

        let path = Path::new(SYSTEM_SETTINGS_PATH);

        if path.exists() {
            info!("Loading system settings from '{}'...",
                  path.to_string_lossy());

            let mut content = String::new();
            File::open(path)?.read_to_string(&mut content)?;

            Ok(self.parse(&content)?)
        } else {
            debug!("System settings file {} does not exists.",
                   path.to_string_lossy());
            info!("Using default system settings...");
            Ok(self)
        }
    }

    fn parse(self, content: &str) -> Result<Self, SettingsError> {
        fn has_protocol_prefix(server: &str) -> bool {
            server.starts_with("http://") || server.starts_with("https://")
        }

        fn has_valid_polling_interval(interval: &Duration) -> bool {
            (*interval >= Duration::new(60, 0))
        }

        let settings = serde_ini::from_str::<Settings>(content)?;

        if !has_valid_polling_interval(&settings.polling.interval) {
            error!("Invalid setting for polling interval. The interval cannot be less than 60 seconds");
            return Err(SettingsError::InvalidInterval);
        }

        if !has_protocol_prefix(&settings.network.server_address) {
            error!("Invalid setting for server address. The server address must use the protocol prefix");
            return Err(SettingsError::InvalidServerAddress);
        }

        Ok(settings)
    }
}

#[derive(Debug)]
pub enum SettingsError {
    Io(io::Error),
    Ini(serde_ini::de::Error),
    InvalidInterval,
    InvalidServerAddress,
}

impl From<io::Error> for SettingsError {
    fn from(err: io::Error) -> SettingsError {
        SettingsError::Io(err)
    }
}

impl From<serde_ini::de::Error> for SettingsError {
    fn from(err: serde_ini::de::Error) -> SettingsError {
        SettingsError::Ini(err)
    }
}

#[derive(Deserialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub struct Polling {
    #[serde(deserialize_with = "duration_from_str")] pub interval: Duration,
    #[serde(deserialize_with = "bool_from_str")] pub enabled: bool,
}

impl Default for Polling {
    fn default() -> Self {
        Polling { interval: Duration::new(86_400, 0), // 1 day
                  enabled: true, }
    }
}

#[derive(Deserialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub struct Storage {
    #[serde(deserialize_with = "bool_from_str")] pub read_only: bool,
    pub runtime_settings: String,
}

impl Default for Storage {
    fn default() -> Self {
        Storage { read_only: false,
                  runtime_settings: "/var/lib/updatehub.conf".into(), }
    }
}

#[derive(Deserialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub struct Update {
    pub download_dir: String,
    #[serde(rename = "SupportedInstallModes")]
    #[serde(deserialize_with = "vec_from_str")]
    pub install_modes: Vec<String>,
}

impl Default for Update {
    fn default() -> Self {
        Update { download_dir: "/tmp/updatehub".into(),
                 install_modes: ["dry-run", "copy", "flash", "imxkobs", "raw", "tarball", "ubifs"].iter()
                                                                                .map(|i| {
                                                                                i.to_string()
                                                                                })
                                                                                .collect(), }
    }
}

#[derive(Deserialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub struct Network {
    pub server_address: String,
}

impl Default for Network {
    fn default() -> Self {
        Network { server_address: "https://api.updatehub.io".into(), }
    }
}

#[derive(Deserialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub struct Firmware {
    pub metadata_path: String,
}

impl Default for Firmware {
    fn default() -> Self {
        Firmware { metadata_path: "/usr/share/updatehub".into(), }
    }
}

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

    #[test]
    fn ok() {
        let ini = r"
[Polling]
Interval=60s
Enabled=false

[Storage]
ReadOnly=true
RuntimeSettings=/run/updatehub/state

[Update]
DownloadDir=/tmp/download
SupportedInstallModes=mode1,mode2

[Network]
ServerAddress=http://localhost

[Firmware]
MetadataPath=/tmp/metadata
";

        let expected =
            Settings { polling: Polling { interval: Duration::new(60, 0),
                                          enabled: false, },
                       storage: Storage { read_only: true,
                                          runtime_settings: "/run/updatehub/state".into(), },
                       update: Update { download_dir: "/tmp/download".into(),
                                        install_modes: ["mode1", "mode2"].iter().map(|i| i.to_string()).collect(), },
                       network: Network { server_address: "http://localhost".into(), },
                       firmware: Firmware { metadata_path: "/tmp/metadata".into(), }, };

        assert!(serde_ini::from_str::<Settings>(&ini).map_err(|e| println!("{}", e))
                                                     .ok() == Some(expected));
    }

    #[test]
    fn invalid_polling_interval() {
        let ini = r"
[Polling]
Interval=59s
Enabled=false

[Storage]
ReadOnly=true
RuntimeSettings=/run/updatehub/state

[Update]
DownloadDir=/tmp/download
SupportedInstallModes=mode1,mode2

[Network]
ServerAddress=http://localhost

[Firmware]
MetadataPath=/tmp/metadata
";
        assert!(Settings::new().parse(&ini).is_err());
    }

    #[test]
    fn invalid_network_server_address() {
        let ini = r"
[Polling]
Interval=60s
Enabled=false

[Storage]
ReadOnly=true
RuntimeSettings=/run/updatehub/state

[Update]
DownloadDir=/tmp/download
SupportedInstallModes=mode1,mode2

[Network]
ServerAddress=localhost

[Firmware]
MetadataPath=/tmp/metadata
";
        assert!(Settings::new().parse(&ini).is_err());
    }

    #[test]
    fn default() {
        let settings = Settings::new();
        let expected = Settings {
            polling: Polling {
                interval: Duration::new(86_400, 0),
                enabled: true,
            },
            storage: Storage {
                read_only: false,
                runtime_settings: "/var/lib/updatehub.conf".into(),
            },
            update: Update {
                download_dir: "/tmp/updatehub".into(),
                install_modes: ["dry-run", "copy", "flash", "imxkobs", "raw", "tarball", "ubifs"]
                    .iter()
                    .map(|i| i.to_string())
                    .collect(),
            },
            network: Network { server_address: "https://api.updatehub.io".into() },
            firmware: Firmware { metadata_path: "/usr/share/updatehub".into() },
        };

        assert!(Some(settings) == Some(expected));
    }
}
<|endoftext|>


<commit_before>//! "Stripped-down" versions of the core state events.
//!
//! Each "stripped" event includes only the `content`, `type`, and `state_key` fields of its full
//! version. These stripped types are useful for APIs where the a is providing the content of a
//! state event to be created, when the other fields can be inferred from a larger context, or where
//! the other fields are otherwise inapplicable.

use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::Error;
use serde_json::{Value, from_value};

use EventType;
use room::aliases::AliasesEventContent;
use room::avatar::AvatarEventContent;
use room::canonical_alias::CanonicalAliasEventContent;
use room::create::CreateEventContent;
use room::guest_access::GuestAccessEventContent;
use room::history_visibility::HistoryVisibilityEventContent;
use room::join_rules::JoinRulesEventContent;
use room::member::MemberEventContent;
use room::name::NameEventContent;
use room::power_levels::PowerLevelsEventContent;
use room::third_party_invite::ThirdPartyInviteEventContent;
use room::topic::TopicEventContent;

/// A stripped-down version of a state event that is included along with some other events.
#[derive(Clone, Debug)]
pub enum StrippedState {
    /// A stripped-down version of the *m.room.aliases* event.
    RoomAliases(StrippedRoomAliases),

    /// A stripped-down version of the *m.room.avatar* event.
    RoomAvatar(StrippedRoomAvatar),

    /// A stripped-down version of the *m.room.canonical_alias* event.
    RoomCanonicalAlias(StrippedRoomCanonicalAlias),

    /// A striped-down version of the *m.room.create* event.
    RoomCreate(StrippedRoomCreate),

    /// A stripped-down version of the *m.room.guest_access* event.
    RoomGuestAccess(StrippedRoomGuestAccess),

    /// A stripped-down version of the *m.room.history_visibility* event.
    RoomHistoryVisibility(StrippedRoomHistoryVisibility),

    /// A stripped-down version of the *m.room.join_rules* event.
    RoomJoinRules(StrippedRoomJoinRules),

    /// A stripped-down version of the *m.room.member* event.
    RoomMember(StrippedRoomMember),

    /// A stripped-down version of the *m.room.name* event.
    RoomName(StrippedRoomName),

    /// A stripped-down version of the *m.room.power_levels* event.
    RoomPowerLevels(StrippedRoomPowerLevels),

    /// A stripped-down version of the *m.room.third_party_invite* event.
    RoomThirdPartyInvite(StrippedRoomThirdPartyInvite),

    /// A stripped-down version of the *m.room.topic* event.
    RoomTopic(StrippedRoomTopic),
}

/// A "stripped-down" version of a core state event.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StrippedStateContent<C> where C: for<'a> Deserialize<'a> + Serialize {
    /// Data specific to the event type.
    #[serde(bound(deserialize = ""))]
    pub content: C,
    /// The type of the event.
    #[serde(rename="type")]
    pub event_type: EventType,
    /// A key that determines which piece of room state the event represents.
    pub state_key: String,
}

impl Serialize for StrippedState {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        match *self {
            StrippedState::RoomAliases(ref event) => event.serialize(serializer),
            StrippedState::RoomAvatar(ref event) => event.serialize(serializer),
            StrippedState::RoomCanonicalAlias(ref event) => event.serialize(serializer),
            StrippedState::RoomCreate(ref event) => event.serialize(serializer),
            StrippedState::RoomGuestAccess(ref event) => event.serialize(serializer),
            StrippedState::RoomHistoryVisibility(ref event) => event.serialize(serializer),
            StrippedState::RoomJoinRules(ref event) => event.serialize(serializer),
            StrippedState::RoomMember(ref event) => event.serialize(serializer),
            StrippedState::RoomName(ref event) => event.serialize(serializer),
            StrippedState::RoomPowerLevels(ref event) => event.serialize(serializer),
            StrippedState::RoomThirdPartyInvite(ref event) => event.serialize(serializer),
            StrippedState::RoomTopic(ref event) => event.serialize(serializer),
        }
    }
}

impl<'de> Deserialize<'de> for StrippedState {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
        let value: Value = Deserialize::deserialize(deserializer)?;

        let event_type_value = match value.get("type") {
            Some(value) => value.clone(),
            None => return Err(D::Error::missing_field("type")),
        };

        let event_type = match from_value::<EventType>(event_type_value.clone()) {
            Ok(event_type) => event_type,
            Err(error) => return Err(D::Error::custom(error.to_string())),
        };

        match event_type {
            EventType::RoomAliases => {
                let event = match from_value::<StrippedRoomAliases>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomAliases(event))
            },
            EventType::RoomAvatar => {
                let event = match from_value::<StrippedRoomAvatar>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomAvatar(event))
            },
            EventType::RoomCanonicalAlias => {
                let event = match from_value::<StrippedRoomCanonicalAlias>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomCanonicalAlias(event))
            },
            EventType::RoomCreate => {
                let event = match from_value::<StrippedRoomCreate>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomCreate(event))
            },
            EventType::RoomGuestAccess => {
                let event = match from_value::<StrippedRoomGuestAccess>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomGuestAccess(event))
            },
            EventType::RoomHistoryVisibility => {
                let event = match from_value::<StrippedRoomHistoryVisibility>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomHistoryVisibility(event))
            },
            EventType::RoomJoinRules => {
                let event = match from_value::<StrippedRoomJoinRules>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomJoinRules(event))
            },
            EventType::RoomMember => {
                let event = match from_value::<StrippedRoomMember>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomMember(event))
            },
            EventType::RoomName => {
                let event = match from_value::<StrippedRoomName>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomName(event))
            },
            EventType::RoomPowerLevels => {
                let event = match from_value::<StrippedRoomPowerLevels>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomPowerLevels(event))
            },
            EventType::RoomThirdPartyInvite => {
                let event = match from_value::<StrippedRoomThirdPartyInvite>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomThirdPartyInvite(event))
            },
            EventType::RoomTopic => {
                let event = match from_value::<StrippedRoomTopic>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomTopic(event))
            },
            _ => {
                return Err(D::Error::custom("not a state event".to_string()));
            }
        }
    }
}

/// A stripped-down version of the *m.room.aliases* event.
pub type StrippedRoomAliases = StrippedStateContent<AliasesEventContent>;

/// A stripped-down version of the *m.room.avatar* event.
pub type StrippedRoomAvatar = StrippedStateContent<AvatarEventContent>;

/// A stripped-down version of the *m.room.canonical_alias* event.
pub type StrippedRoomCanonicalAlias = StrippedStateContent<CanonicalAliasEventContent>;

/// A stripped-down version of the *m.room.create* event.
pub type StrippedRoomCreate = StrippedStateContent<CreateEventContent>;

/// A stripped-down version of the *m.room.guest_access* event.
pub type StrippedRoomGuestAccess = StrippedStateContent<GuestAccessEventContent>;

/// A stripped-down version of the *m.room.history_visibility* event.
pub type StrippedRoomHistoryVisibility = StrippedStateContent<HistoryVisibilityEventContent>;

/// A stripped-down version of the *m.room.join_rules* event.
pub type StrippedRoomJoinRules = StrippedStateContent<JoinRulesEventContent>;

/// A stripped-down version of the *m.room.member* event.
pub type StrippedRoomMember = StrippedStateContent<MemberEventContent>;

/// A stripped-down version of the *m.room.name* event.
pub type StrippedRoomName = StrippedStateContent<NameEventContent>;

/// A stripped-down version of the *m.room.power_levels* event.
pub type StrippedRoomPowerLevels = StrippedStateContent<PowerLevelsEventContent>;

/// A stripped-down version of the *m.room.third_party_invite* event.
pub type StrippedRoomThirdPartyInvite = StrippedStateContent<ThirdPartyInviteEventContent>;

/// A stripped-down version of the *m.room.topic* event.
pub type StrippedRoomTopic = StrippedStateContent<TopicEventContent>;

#[cfg(test)]
mod tests {
    use EventType;
    use room::join_rules::JoinRule;
    use room::topic::TopicEventContent;
    use serde_json::{from_str, to_string};
    use super::{StrippedRoomTopic, StrippedState};

    #[test]
    fn serialize_stripped_state_event() {
        let content = StrippedRoomTopic {
            content: TopicEventContent { topic: "Testing room".to_string() },
            state_key: "".to_string(),
            event_type: EventType::RoomTopic
        };

        let event = StrippedState::RoomTopic(content);

        assert_eq!(
            to_string(&event).unwrap(),
            r#"{"content":{"topic":"Testing room"},"type":"m.room.topic","state_key":""}"#
        );
    }

    #[test]
    fn deserialize_stripped_state_events() {
        let name_event = r#"{
            "type": "m.room.name",
            "state_key": "",
            "content": {"name": "Ruma"}
        }"#;

        let join_rules_event = r#"{
            "type": "m.room.join_rules",
            "state_key": "",
            "content": { "join_rule": "public" }
        }"#;

        let avatar_event = r#"{
            "type": "m.room.avatar",
            "state_key": "",
            "content": {
                "info": {
                    "height": 128,
                    "width": 128,
                    "mimetype": "image/jpeg",
                    "size": 1024
                },
                "thumbnail_info": {
                    "height": 16,
                    "width": 16,
                    "mimetype": "image/jpeg",
                    "size": 32
                },
                "thumbnail_url": "https://domain.com/image-thumbnail.jpg",
                "url": "https://domain.com/image.jpg"
            }
        }"#;

        match from_str::<StrippedState>(name_event).unwrap() {
            StrippedState::RoomName(event) => {
                assert_eq!(event.content.name, "Ruma");
                assert_eq!(event.event_type, EventType::RoomName);
                assert_eq!(event.state_key, "");
            },
            _ => {
                assert!(false);
            }
        };

        match from_str::<StrippedState>(join_rules_event).unwrap() {
            StrippedState::RoomJoinRules(event) => {
                assert_eq!(event.content.join_rule, JoinRule::Public);
                assert_eq!(event.event_type, EventType::RoomJoinRules);
                assert_eq!(event.state_key, "");
            },
            _ => {
                assert!(false);
            }
        };

        match from_str::<StrippedState>(avatar_event).unwrap() {
            StrippedState::RoomAvatar(event) => {
                assert_eq!(event.content.info.height, 128);
                assert_eq!(event.content.info.width, 128);
                assert_eq!(event.content.info.mimetype, "image/jpeg");
                assert_eq!(event.content.info.size, 1024);
                assert_eq!(event.content.thumbnail_info.size, 32);
                assert_eq!(event.content.url, "https://domain.com/image.jpg");
                assert_eq!(event.event_type, EventType::RoomAvatar);
                assert_eq!(event.state_key, "");
            },
            _ => {
                assert!(false);
            }
        };
    }
}
<commit_msg>Remove de/serialize bounds from StrippedStateContent.<commit_after>//! "Stripped-down" versions of the core state events.
//!
//! Each "stripped" event includes only the `content`, `type`, and `state_key` fields of its full
//! version. These stripped types are useful for APIs where the a is providing the content of a
//! state event to be created, when the other fields can be inferred from a larger context, or where
//! the other fields are otherwise inapplicable.

use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::Error;
use serde_json::{Value, from_value};

use EventType;
use room::aliases::AliasesEventContent;
use room::avatar::AvatarEventContent;
use room::canonical_alias::CanonicalAliasEventContent;
use room::create::CreateEventContent;
use room::guest_access::GuestAccessEventContent;
use room::history_visibility::HistoryVisibilityEventContent;
use room::join_rules::JoinRulesEventContent;
use room::member::MemberEventContent;
use room::name::NameEventContent;
use room::power_levels::PowerLevelsEventContent;
use room::third_party_invite::ThirdPartyInviteEventContent;
use room::topic::TopicEventContent;

/// A stripped-down version of a state event that is included along with some other events.
#[derive(Clone, Debug)]
pub enum StrippedState {
    /// A stripped-down version of the *m.room.aliases* event.
    RoomAliases(StrippedRoomAliases),

    /// A stripped-down version of the *m.room.avatar* event.
    RoomAvatar(StrippedRoomAvatar),

    /// A stripped-down version of the *m.room.canonical_alias* event.
    RoomCanonicalAlias(StrippedRoomCanonicalAlias),

    /// A striped-down version of the *m.room.create* event.
    RoomCreate(StrippedRoomCreate),

    /// A stripped-down version of the *m.room.guest_access* event.
    RoomGuestAccess(StrippedRoomGuestAccess),

    /// A stripped-down version of the *m.room.history_visibility* event.
    RoomHistoryVisibility(StrippedRoomHistoryVisibility),

    /// A stripped-down version of the *m.room.join_rules* event.
    RoomJoinRules(StrippedRoomJoinRules),

    /// A stripped-down version of the *m.room.member* event.
    RoomMember(StrippedRoomMember),

    /// A stripped-down version of the *m.room.name* event.
    RoomName(StrippedRoomName),

    /// A stripped-down version of the *m.room.power_levels* event.
    RoomPowerLevels(StrippedRoomPowerLevels),

    /// A stripped-down version of the *m.room.third_party_invite* event.
    RoomThirdPartyInvite(StrippedRoomThirdPartyInvite),

    /// A stripped-down version of the *m.room.topic* event.
    RoomTopic(StrippedRoomTopic),
}

/// A "stripped-down" version of a core state event.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StrippedStateContent<C> {
    /// Data specific to the event type.
    pub content: C,
    /// The type of the event.
    #[serde(rename="type")]
    pub event_type: EventType,
    /// A key that determines which piece of room state the event represents.
    pub state_key: String,
}

impl Serialize for StrippedState {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        match *self {
            StrippedState::RoomAliases(ref event) => event.serialize(serializer),
            StrippedState::RoomAvatar(ref event) => event.serialize(serializer),
            StrippedState::RoomCanonicalAlias(ref event) => event.serialize(serializer),
            StrippedState::RoomCreate(ref event) => event.serialize(serializer),
            StrippedState::RoomGuestAccess(ref event) => event.serialize(serializer),
            StrippedState::RoomHistoryVisibility(ref event) => event.serialize(serializer),
            StrippedState::RoomJoinRules(ref event) => event.serialize(serializer),
            StrippedState::RoomMember(ref event) => event.serialize(serializer),
            StrippedState::RoomName(ref event) => event.serialize(serializer),
            StrippedState::RoomPowerLevels(ref event) => event.serialize(serializer),
            StrippedState::RoomThirdPartyInvite(ref event) => event.serialize(serializer),
            StrippedState::RoomTopic(ref event) => event.serialize(serializer),
        }
    }
}

impl<'de> Deserialize<'de> for StrippedState {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
        let value: Value = Deserialize::deserialize(deserializer)?;

        let event_type_value = match value.get("type") {
            Some(value) => value.clone(),
            None => return Err(D::Error::missing_field("type")),
        };

        let event_type = match from_value::<EventType>(event_type_value.clone()) {
            Ok(event_type) => event_type,
            Err(error) => return Err(D::Error::custom(error.to_string())),
        };

        match event_type {
            EventType::RoomAliases => {
                let event = match from_value::<StrippedRoomAliases>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomAliases(event))
            },
            EventType::RoomAvatar => {
                let event = match from_value::<StrippedRoomAvatar>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomAvatar(event))
            },
            EventType::RoomCanonicalAlias => {
                let event = match from_value::<StrippedRoomCanonicalAlias>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomCanonicalAlias(event))
            },
            EventType::RoomCreate => {
                let event = match from_value::<StrippedRoomCreate>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomCreate(event))
            },
            EventType::RoomGuestAccess => {
                let event = match from_value::<StrippedRoomGuestAccess>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomGuestAccess(event))
            },
            EventType::RoomHistoryVisibility => {
                let event = match from_value::<StrippedRoomHistoryVisibility>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomHistoryVisibility(event))
            },
            EventType::RoomJoinRules => {
                let event = match from_value::<StrippedRoomJoinRules>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomJoinRules(event))
            },
            EventType::RoomMember => {
                let event = match from_value::<StrippedRoomMember>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomMember(event))
            },
            EventType::RoomName => {
                let event = match from_value::<StrippedRoomName>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomName(event))
            },
            EventType::RoomPowerLevels => {
                let event = match from_value::<StrippedRoomPowerLevels>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomPowerLevels(event))
            },
            EventType::RoomThirdPartyInvite => {
                let event = match from_value::<StrippedRoomThirdPartyInvite>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomThirdPartyInvite(event))
            },
            EventType::RoomTopic => {
                let event = match from_value::<StrippedRoomTopic>(value) {
                    Ok(event) => event,
                    Err(error) => return Err(D::Error::custom(error.to_string())),
                };

                Ok(StrippedState::RoomTopic(event))
            },
            _ => {
                return Err(D::Error::custom("not a state event".to_string()));
            }
        }
    }
}

/// A stripped-down version of the *m.room.aliases* event.
pub type StrippedRoomAliases = StrippedStateContent<AliasesEventContent>;

/// A stripped-down version of the *m.room.avatar* event.
pub type StrippedRoomAvatar = StrippedStateContent<AvatarEventContent>;

/// A stripped-down version of the *m.room.canonical_alias* event.
pub type StrippedRoomCanonicalAlias = StrippedStateContent<CanonicalAliasEventContent>;

/// A stripped-down version of the *m.room.create* event.
pub type StrippedRoomCreate = StrippedStateContent<CreateEventContent>;

/// A stripped-down version of the *m.room.guest_access* event.
pub type StrippedRoomGuestAccess = StrippedStateContent<GuestAccessEventContent>;

/// A stripped-down version of the *m.room.history_visibility* event.
pub type StrippedRoomHistoryVisibility = StrippedStateContent<HistoryVisibilityEventContent>;

/// A stripped-down version of the *m.room.join_rules* event.
pub type StrippedRoomJoinRules = StrippedStateContent<JoinRulesEventContent>;

/// A stripped-down version of the *m.room.member* event.
pub type StrippedRoomMember = StrippedStateContent<MemberEventContent>;

/// A stripped-down version of the *m.room.name* event.
pub type StrippedRoomName = StrippedStateContent<NameEventContent>;

/// A stripped-down version of the *m.room.power_levels* event.
pub type StrippedRoomPowerLevels = StrippedStateContent<PowerLevelsEventContent>;

/// A stripped-down version of the *m.room.third_party_invite* event.
pub type StrippedRoomThirdPartyInvite = StrippedStateContent<ThirdPartyInviteEventContent>;

/// A stripped-down version of the *m.room.topic* event.
pub type StrippedRoomTopic = StrippedStateContent<TopicEventContent>;

#[cfg(test)]
mod tests {
    use EventType;
    use room::join_rules::JoinRule;
    use room::topic::TopicEventContent;
    use serde_json::{from_str, to_string};
    use super::{StrippedRoomTopic, StrippedState};

    #[test]
    fn serialize_stripped_state_event() {
        let content = StrippedRoomTopic {
            content: TopicEventContent { topic: "Testing room".to_string() },
            state_key: "".to_string(),
            event_type: EventType::RoomTopic
        };

        let event = StrippedState::RoomTopic(content);

        assert_eq!(
            to_string(&event).unwrap(),
            r#"{"content":{"topic":"Testing room"},"type":"m.room.topic","state_key":""}"#
        );
    }

    #[test]
    fn deserialize_stripped_state_events() {
        let name_event = r#"{
            "type": "m.room.name",
            "state_key": "",
            "content": {"name": "Ruma"}
        }"#;

        let join_rules_event = r#"{
            "type": "m.room.join_rules",
            "state_key": "",
            "content": { "join_rule": "public" }
        }"#;

        let avatar_event = r#"{
            "type": "m.room.avatar",
            "state_key": "",
            "content": {
                "info": {
                    "height": 128,
                    "width": 128,
                    "mimetype": "image/jpeg",
                    "size": 1024
                },
                "thumbnail_info": {
                    "height": 16,
                    "width": 16,
                    "mimetype": "image/jpeg",
                    "size": 32
                },
                "thumbnail_url": "https://domain.com/image-thumbnail.jpg",
                "url": "https://domain.com/image.jpg"
            }
        }"#;

        match from_str::<StrippedState>(name_event).unwrap() {
            StrippedState::RoomName(event) => {
                assert_eq!(event.content.name, "Ruma");
                assert_eq!(event.event_type, EventType::RoomName);
                assert_eq!(event.state_key, "");
            },
            _ => {
                assert!(false);
            }
        };

        match from_str::<StrippedState>(join_rules_event).unwrap() {
            StrippedState::RoomJoinRules(event) => {
                assert_eq!(event.content.join_rule, JoinRule::Public);
                assert_eq!(event.event_type, EventType::RoomJoinRules);
                assert_eq!(event.state_key, "");
            },
            _ => {
                assert!(false);
            }
        };

        match from_str::<StrippedState>(avatar_event).unwrap() {
            StrippedState::RoomAvatar(event) => {
                assert_eq!(event.content.info.height, 128);
                assert_eq!(event.content.info.width, 128);
                assert_eq!(event.content.info.mimetype, "image/jpeg");
                assert_eq!(event.content.info.size, 1024);
                assert_eq!(event.content.thumbnail_info.size, 32);
                assert_eq!(event.content.url, "https://domain.com/image.jpg");
                assert_eq!(event.event_type, EventType::RoomAvatar);
                assert_eq!(event.state_key, "");
            },
            _ => {
                assert!(false);
            }
        };
    }
}
<|endoftext|>


<commit_before>use std::marker;
use std::string::ToString;

pub trait FrameRate {
  const FPS: u32;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate2400;

impl FrameRate for FrameRate2400 {
    const FPS: u32 = 24;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate2500;

impl FrameRate for FrameRate2500 {
    const FPS: u32 = 25;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate3000;

impl FrameRate for FrameRate3000 {
    const FPS: u32 = 30;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate5000;

impl FrameRate for FrameRate5000 {
    const FPS: u32 = 50;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate6000;

impl FrameRate for FrameRate6000 {
    const FPS: u32 = 60;
}

#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct Timecode<FrameRate> {
  pub hours: u8,
  pub minutes: u8,
  pub seconds: u8,
  pub frame: u8,
  pub drop_frame: bool,
  pub color_frame: bool,
  frame_rate: marker::PhantomData::<FrameRate>,
}

impl<FrameRate> ToString for Timecode<FrameRate> {
  fn to_string(&self) -> String {
    let separator = match self.drop_frame {
      true => ';',
      false => ':',
    };

    format!(
      "{:02}:{:02}:{:02}{}{:02}",
      self.hours, self.minutes, self.seconds, separator, self.frame
    )
  }
}

impl<FrameRate> From<u32> for Timecode<FrameRate> {
  fn from(frames: u32) -> Self {
    let fps = 24;

    let hours = frames / (60 * 60 * fps);
    let minutes = (frames / (60 * fps)) - hours * 60;
    let seconds = (frames / fps) - minutes * 60 - hours * 60 * 60;
    let frame = frames - seconds * fps - minutes * 60 * fps - hours * 60 * 60 * fps;
    let drop_frame = false;
    let color_frame = false;

    log::trace!("{} {} {} {}", hours, minutes, seconds, frame);

    Timecode {
      hours: hours as u8,
      minutes: minutes as u8,
      seconds: seconds as u8,
      frame: frame as u8,
      drop_frame,
      color_frame,
      frame_rate: marker::PhantomData
    }
  }
}

impl<FrameRate> Timecode<FrameRate> {
  pub fn parse_smpte_331m(data: &[u8]) -> Option<Self> {
    if data.len() != 17 {
      return None;
    }
    match data[0] {
      0x81 => Timecode::<FrameRate>::parse_smpte_12m(&data[1..]),
      _ => None,
    }
  }

  pub fn parse_smpte_12m(data: &[u8]) -> Option<Self> {
    if data.len() < 4 {
      return None;
    }

    let mask_tens_2 = 0b0011_0000;
    let mask_tens_3 = 0b0111_0000;

    let frame = Timecode::<FrameRate>::get_number(data[0], mask_tens_2);
    let seconds = Timecode::<FrameRate>::get_number(data[1], mask_tens_3);
    let minutes = Timecode::<FrameRate>::get_number(data[2], mask_tens_3);
    let hours = Timecode::<FrameRate>::get_number(data[3], mask_tens_2);

    let color_frame = (data[0] & 0b1000_0000) != 0;
    let drop_frame = (data[0] & 0b0100_0000) != 0;

    Some(Timecode::<FrameRate> {
      hours,
      minutes,
      seconds,
      frame,
      drop_frame,
      color_frame,
      frame_rate: marker::PhantomData::<FrameRate>,
    })
  }

  fn get_number(data: u8, mask_tens: u8) -> u8 {
    let mask_unit = 0x0F;

    let tens = (data & mask_tens) >> 4;
    let unit = data & mask_unit;

    (10 * tens) + unit
  }
}

#[test]
fn timecode_from_frame() {
  let t1 = Timecode::<FrameRate2400>::from(24 * 60 * 60 * 10);
  assert_eq!(t1.hours, 10);
  assert_eq!(t1.minutes, 0);
  assert_eq!(t1.seconds, 0);
  assert_eq!(t1.frame, 0);

  let t1 = Timecode::<FrameRate2400>::from(24 * 60 * 60);
  assert_eq!(t1.hours, 1);
  assert_eq!(t1.minutes, 0);
  assert_eq!(t1.seconds, 0);
  assert_eq!(t1.frame, 0);

  let t2 = Timecode::<FrameRate2400>::from(24 * 60 * 60 - 1);
  assert_eq!(t2.hours, 0);
  assert_eq!(t2.minutes, 59);
  assert_eq!(t2.seconds, 59);
  assert_eq!(t2.frame, 23);

  let t2 = Timecode::<FrameRate2400>::from(24 * 60);
  assert_eq!(t2.hours, 0);
  assert_eq!(t2.minutes, 1);
  assert_eq!(t2.seconds, 0);
  assert_eq!(t2.frame, 0);

  let t2 = Timecode::<FrameRate2400>::from(24 * 60 - 1);
  assert_eq!(t2.hours, 0);
  assert_eq!(t2.minutes, 0);
  assert_eq!(t2.seconds, 59);
  assert_eq!(t2.frame, 23);

  let t3 = Timecode::<FrameRate2400>::from(24);
  assert_eq!(t3.hours, 0);
  assert_eq!(t3.minutes, 0);
  assert_eq!(t3.seconds, 1);
  assert_eq!(t3.frame, 0);

  let t3 = Timecode::<FrameRate2400>::from(23);
  assert_eq!(t3.hours, 0);
  assert_eq!(t3.minutes, 0);
  assert_eq!(t3.seconds, 0);
  assert_eq!(t3.frame, 23);
}
<commit_msg>support fps to get timecode from number of frames<commit_after>use std::marker;
use std::string::ToString;

pub trait FrameRate {
  const FPS: u32;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate2400;

impl FrameRate for FrameRate2400 {
    const FPS: u32 = 24;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate2500;

impl FrameRate for FrameRate2500 {
    const FPS: u32 = 25;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate3000;

impl FrameRate for FrameRate3000 {
    const FPS: u32 = 30;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate5000;

impl FrameRate for FrameRate5000 {
    const FPS: u32 = 50;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate6000;

impl FrameRate for FrameRate6000 {
    const FPS: u32 = 60;
}

#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct Timecode<FrameRate> {
  pub hours: u8,
  pub minutes: u8,
  pub seconds: u8,
  pub frame: u8,
  pub drop_frame: bool,
  pub color_frame: bool,
  frame_rate: marker::PhantomData::<FrameRate>,
}

impl<FrameRate> ToString for Timecode<FrameRate> {
  fn to_string(&self) -> String {
    let separator = match self.drop_frame {
      true => ';',
      false => ':',
    };

    format!(
      "{:02}:{:02}:{:02}{}{:02}",
      self.hours, self.minutes, self.seconds, separator, self.frame
    )
  }
}

impl<FrameRate> From<(u32, u32)> for Timecode<FrameRate> {
  fn from((frames, fps): (u32, u32)) -> Self {
    let hours = frames / (60 * 60 * fps);
    let minutes = (frames / (60 * fps)) - hours * 60;
    let seconds = (frames / fps) - minutes * 60 - hours * 60 * 60;
    let frame = frames - seconds * fps - minutes * 60 * fps - hours * 60 * 60 * fps;
    let drop_frame = false;
    let color_frame = false;

    log::trace!("{} {} {} {}", hours, minutes, seconds, frame);

    Timecode {
      hours: hours as u8,
      minutes: minutes as u8,
      seconds: seconds as u8,
      frame: frame as u8,
      drop_frame,
      color_frame,
      frame_rate: marker::PhantomData
    }
  }
}

impl<FrameRate> Timecode<FrameRate> {
  pub fn parse_smpte_331m(data: &[u8]) -> Option<Self> {
    if data.len() != 17 {
      return None;
    }
    match data[0] {
      0x81 => Timecode::<FrameRate>::parse_smpte_12m(&data[1..]),
      _ => None,
    }
  }

  pub fn parse_smpte_12m(data: &[u8]) -> Option<Self> {
    if data.len() < 4 {
      return None;
    }

    let mask_tens_2 = 0b0011_0000;
    let mask_tens_3 = 0b0111_0000;

    let frame = Timecode::<FrameRate>::get_number(data[0], mask_tens_2);
    let seconds = Timecode::<FrameRate>::get_number(data[1], mask_tens_3);
    let minutes = Timecode::<FrameRate>::get_number(data[2], mask_tens_3);
    let hours = Timecode::<FrameRate>::get_number(data[3], mask_tens_2);

    let color_frame = (data[0] & 0b1000_0000) != 0;
    let drop_frame = (data[0] & 0b0100_0000) != 0;

    Some(Timecode::<FrameRate> {
      hours,
      minutes,
      seconds,
      frame,
      drop_frame,
      color_frame,
      frame_rate: marker::PhantomData::<FrameRate>,
    })
  }

  fn get_number(data: u8, mask_tens: u8) -> u8 {
    let mask_unit = 0x0F;

    let tens = (data & mask_tens) >> 4;
    let unit = data & mask_unit;

    (10 * tens) + unit
  }
}

#[test]
fn timecode_from_frame() {
  let t1 = Timecode::<FrameRate2400>::from((24 * 60 * 60 * 10, 24));
  assert_eq!(t1.hours, 10);
  assert_eq!(t1.minutes, 0);
  assert_eq!(t1.seconds, 0);
  assert_eq!(t1.frame, 0);

  let t1 = Timecode::<FrameRate2400>::from((24 * 60 * 60, 24));
  assert_eq!(t1.hours, 1);
  assert_eq!(t1.minutes, 0);
  assert_eq!(t1.seconds, 0);
  assert_eq!(t1.frame, 0);

  let t2 = Timecode::<FrameRate2400>::from((24 * 60 * 60 - 1, 24));
  assert_eq!(t2.hours, 0);
  assert_eq!(t2.minutes, 59);
  assert_eq!(t2.seconds, 59);
  assert_eq!(t2.frame, 23);

  let t2 = Timecode::<FrameRate2400>::from((24 * 60, 24));
  assert_eq!(t2.hours, 0);
  assert_eq!(t2.minutes, 1);
  assert_eq!(t2.seconds, 0);
  assert_eq!(t2.frame, 0);

  let t2 = Timecode::<FrameRate2400>::from((24 * 60 - 1, 24));
  assert_eq!(t2.hours, 0);
  assert_eq!(t2.minutes, 0);
  assert_eq!(t2.seconds, 59);
  assert_eq!(t2.frame, 23);

  let t3 = Timecode::<FrameRate2400>::from((24, 24));
  assert_eq!(t3.hours, 0);
  assert_eq!(t3.minutes, 0);
  assert_eq!(t3.seconds, 1);
  assert_eq!(t3.frame, 0);

  let t3 = Timecode::<FrameRate2400>::from((23, 24));
  assert_eq!(t3.hours, 0);
  assert_eq!(t3.minutes, 0);
  assert_eq!(t3.seconds, 0);
  assert_eq!(t3.frame, 23);
}
<|endoftext|>


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

pub struct Translator
{
  rules: HashMap<(char, char), char>,
}

impl Translator
{
  pub fn new() -> Translator
  {
    Translator
    {
      rules: HashMap::new(),
    }
  }

  pub fn default() -> Translator
  {
    Translator
    {
      rules: HashMap::new(),
    }
  }

  fn translate_char(&self, current : char, previous : char) -> char
  {
    match self.rules.get(&(current, previous))
    {
      Some(result) => *result,
      None => match self.rules.get(&(current, ' '))
      {
        Some(result) => *result,
        None => current,
      }
    }
  }

  pub fn translate(&self, text : &str) -> String
  {
    let mut result = String::with_capacity(text.len());

    let mut previous = ' ';
    for c in text.chars()
    {
      previous = self.translate_char(c, previous);
      result.push(previous);
    }

    result
  }
}
<commit_msg>Default translating rules (incomplete)<commit_after>use std::collections::HashMap;

pub struct Translator
{
  rules: HashMap<(char, char), char>,
}

impl Translator
{
  pub fn new() -> Translator
  {
    Translator
    {
      rules: HashMap::new(),
    }
  }

  pub fn default() -> Translator
  {
    Translator
    {
      rules: get_default_rules(),
    }
  }

  fn translate_char(&self, current : char, previous : char) -> char
  {
    match self.rules.get(&(current, previous))
    {
      Some(result) => *result,
      None => match self.rules.get(&(current, ' '))
      {
        Some(result) => *result,
        None => current,
      }
    }
  }

  pub fn translate(&self, text : &str) -> String
  {
    let mut result = String::with_capacity(text.len());

    let mut previous = ' ';
    for c in text.chars()
    {
      previous = self.translate_char(c, previous);
      result.push(previous);
    }

    result
  }
}

fn get_default_rules() -> HashMap<(char, char), char>
{
  let mut result = HashMap::with_capacity(50);

  result.insert(('a', ' '), 'a');

  result
}
<|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.
use futures::{self, Future, Stream, Sink};
use futures::stream::Wait;
use futures::sync::mpsc;
use tokio_core::reactor::Core;
use tokio_timer::{TimeoutStream, Timer};

use std::net::SocketAddr;
use std::thread;
use std::time::{self, Duration};

use crypto::{gen_keypair, PublicKey, Signature};
use messages::{MessageWriter, RawMessage, Connect, Message};
use events::{NetworkEvent, NetworkRequest};
use events::network::{NetworkPart, NetworkConfiguration};
use node::{NodeChannel, EventsPoolCapacity};

#[derive(Debug)]
pub struct TestHandler {
    listen_address: SocketAddr,
    network_events_rx: Wait<TimeoutStream<mpsc::Receiver<NetworkEvent>>>,
    network_requests_tx: mpsc::Sender<NetworkRequest>,
}

impl TestHandler {
    pub fn new(
        listen_address: SocketAddr,
        network_requests_tx: mpsc::Sender<NetworkRequest>,
        network_events_rx: mpsc::Receiver<NetworkEvent>,
    ) -> TestHandler {
        let timer = Timer::default();
        let receiver = timer.timeout_stream(network_events_rx, Duration::from_secs(30));
        TestHandler {
            listen_address,
            network_requests_tx,
            network_events_rx: receiver.wait(),
        }
    }

    pub fn wait_for_event(&mut self) -> Result<NetworkEvent, ()> {
        let event = self.network_events_rx.next().unwrap()?;
        Ok(event)
    }

    pub fn connect_with(&self, addr: SocketAddr) {
        let connect = connect_message(self.listen_address);
        self.network_requests_tx
            .clone()
            .send(NetworkRequest::SendMessage(addr, connect.raw().clone()))
            .wait()
            .unwrap();
    }

    pub fn disconnect_with(&self, addr: SocketAddr) {
        self.network_requests_tx
            .clone()
            .send(NetworkRequest::DisconnectWithPeer(addr))
            .wait()
            .unwrap();
    }

    pub fn send_to(&self, addr: SocketAddr, raw: RawMessage) {
        self.network_requests_tx
            .clone()
            .send(NetworkRequest::SendMessage(addr, raw))
            .wait()
            .unwrap();
    }

    pub fn wait_for_connect(&mut self) -> Connect {
        match self.wait_for_event() {
            Ok(NetworkEvent::PeerConnected(_addr, connect)) => connect,
            Ok(other) => panic!("Unexpected connect received, {:?}", other),
            Err(e) => panic!("An error occured, {:?}", e),
        }
    }

    pub fn wait_for_disconnect(&mut self) -> SocketAddr {
        match self.wait_for_event() {
            Ok(NetworkEvent::PeerDisconnected(addr)) => addr,
            Ok(other) => panic!("Unexpected disconnect received, {:?}", other),
            Err(e) => panic!("An error occured, {:?}", e),
        }
    }

    pub fn wait_for_message(&mut self) -> RawMessage {
        match self.wait_for_event() {
            Ok(NetworkEvent::MessageReceived(_addr, msg)) => msg,
            Ok(other) => panic!("Unexpected message received, {:?}", other),
            Err(e) => panic!("An error occured, {:?}", e),
        }
    }
}

impl Drop for TestHandler {
    fn drop(&mut self) {
        if !::std::thread::panicking() {
            self.network_requests_tx
                .clone()
                .send(NetworkRequest::Shutdown)
                .wait()
                .unwrap();
        }
    }
}

#[derive(Debug)]
pub struct TestEvents {
    pub listen_address: SocketAddr,
    pub network_config: NetworkConfiguration,
    pub events_config: EventsPoolCapacity,
}

struct TestHandlerPart {
    handler: TestHandler,
    core: Core,
}

impl TestEvents {
    pub fn with_addr(listen_address: SocketAddr) -> TestEvents {
        TestEvents {
            listen_address,
            network_config: NetworkConfiguration::default(),
            events_config: EventsPoolCapacity::default(),
        }
    }

    pub fn spawn<F>(self, test_fn: F) -> thread::JoinHandle<()>
    where
        F: Fn(&mut TestHandler) + 'static + Send,
    {
        thread::spawn(move || {
            let (handler_part, network_part) = self.into_reactor();
            let network_thread = thread::spawn(move || network_part.run().unwrap());

            let mut handler = handler_part.handler;

            let mut core = handler_part.core;
            let test_fut = futures::lazy(move || -> Result<(), ()> {
                test_fn(&mut handler);
                Ok(())
            });
            core.run(test_fut).unwrap();
            network_thread.join().unwrap();
        })
    }

    fn into_reactor(self) -> (TestHandlerPart, NetworkPart) {
        let channel = NodeChannel::new(self.events_config);
        let core = Core::new().unwrap();
        let network_config = self.network_config;
        let (network_tx, network_rx) = channel.network_events;
        let network_requests_tx = channel.network_requests.0.clone();

        let network_part = NetworkPart {
            listen_address: self.listen_address,
            network_config,
            network_requests: channel.network_requests,
            network_tx: network_tx.clone(),
        };

        let handler_part = TestHandlerPart {
            core,
            handler: TestHandler::new(self.listen_address, network_requests_tx, network_rx),
        };
        (handler_part, network_part)
    }
}

pub fn connect_message(addr: SocketAddr) -> Connect {
    let time = time::UNIX_EPOCH;
    Connect::new_with_signature(&PublicKey::zero(), addr, time, &Signature::zero())
}

pub fn raw_message(id: u16, len: usize) -> RawMessage {
    let writer = MessageWriter::new(
        ::messages::PROTOCOL_MAJOR_VERSION,
        ::messages::TEST_NETWORK_ID,
        0,
        id,
        len,
    );
    RawMessage::new(writer.sign(&gen_keypair().1))
}

#[test]
fn test_network_handshake() {
    let addrs: [SocketAddr; 2] =
        ["127.0.0.1:17230".parse().unwrap(), "127.0.0.1:17231".parse().unwrap()];

    let e1 = TestEvents::with_addr(addrs[0]);
    let e2 = TestEvents::with_addr(addrs[1]);

    let c1 = connect_message(addrs[0]);
    let c2 = connect_message(addrs[1]);

    let t1 = e1.spawn(move |e: &mut TestHandler| {
        e.connect_with(addrs[1]);
        assert_eq!(e.wait_for_connect(), c2);
        e.disconnect_with(addrs[1]);
        assert_eq!(e.wait_for_disconnect(), addrs[1]);
    });
    let t2 = e2.spawn(move |e: &mut TestHandler| {
        assert_eq!(e.wait_for_connect(), c1);
        e.connect_with(addrs[0]);
        assert_eq!(e.wait_for_disconnect(), addrs[0]);
    });

    t1.join().unwrap();
    t2.join().unwrap();
}

#[test]
fn test_network_big_message() {
    let addrs: [SocketAddr; 2] =
        ["127.0.0.1:17200".parse().unwrap(), "127.0.0.1:17201".parse().unwrap()];

    let msg1 = raw_message(15, 100000);
    let msg2 = raw_message(16, 400);

    let e1 = TestEvents::with_addr(addrs[0]);
    let e2 = TestEvents::with_addr(addrs[1]);

    let m1 = msg1.clone();
    let m2 = msg2.clone();
    let t1 = e1.spawn(move |e: &mut TestHandler| {
        e.connect_with(addrs[1]);
        e.wait_for_connect();

        e.send_to(addrs[1], m1.clone());
        e.send_to(addrs[1], m2.clone());
        e.send_to(addrs[1], m1.clone());

        assert_eq!(e.wait_for_message(), m2);
        assert_eq!(e.wait_for_message(), m1);
        assert_eq!(e.wait_for_message(), m2);

        e.disconnect_with(addrs[1]);
        assert_eq!(e.wait_for_disconnect(), addrs[1]);
    });

    let m1 = msg1.clone();
    let m2 = msg2.clone();
    let t2 = e2.spawn(move |e: &mut TestHandler| {
        e.connect_with(addrs[0]);
        e.wait_for_connect();

        e.send_to(addrs[0], m2.clone());
        e.send_to(addrs[0], m1.clone());
        e.send_to(addrs[0], m2.clone());

        assert_eq!(e.wait_for_message(), m1);
        assert_eq!(e.wait_for_message(), m2);
        assert_eq!(e.wait_for_message(), m1);

        e.disconnect_with(addrs[0]);
        assert_eq!(e.wait_for_disconnect(), addrs[0]);
    });

    t2.join().unwrap();
    t1.join().unwrap();
}

#[test]
fn test_network_reconnect() {
    let addrs: [SocketAddr; 2] =
        ["127.0.0.1:19100".parse().unwrap(), "127.0.0.1:19101".parse().unwrap()];

    let msg = raw_message(11, 400);
    let c1 = connect_message(addrs[0]);
    let c2 = connect_message(addrs[1]);
    let msg_cloned = msg.clone();
    let t1 = TestEvents::with_addr(addrs[0]).spawn(move |e: &mut TestHandler| {
        // Handle first attempt
        e.connect_with(addrs[1]);
        assert_eq!(e.wait_for_connect(), c2);
        assert_eq!(e.wait_for_message(), msg_cloned);
        assert_eq!(e.wait_for_disconnect(), addrs[1]);
        // Handle second attempt
        assert_eq!(e.wait_for_connect(), c2);
        e.connect_with(addrs[1]);
        assert_eq!(e.wait_for_message(), msg_cloned);
        assert_eq!(e.wait_for_disconnect(), addrs[1]);
    });
    // First connect attempt.
    let c1_cloned = c1.clone();
    let msg_cloned = msg.clone();
    TestEvents::with_addr(addrs[1])
        .spawn(move |e: &mut TestHandler| {
            assert_eq!(e.wait_for_connect(), c1_cloned);
            e.connect_with(addrs[0]);
            e.send_to(addrs[0], msg_cloned.clone());
            e.disconnect_with(addrs[0]);
            assert_eq!(e.wait_for_disconnect(), addrs[0]);
        })
        .join()
        .unwrap();
    // Second connect attempt.
    let c1_cloned = c1.clone();
    let msg_cloned = msg.clone();
    TestEvents::with_addr(addrs[1])
        .spawn(move |e: &mut TestHandler| {
            e.connect_with(addrs[0]);
            assert_eq!(e.wait_for_connect(), c1_cloned);
            e.send_to(addrs[0], msg_cloned.clone());
            e.disconnect_with(addrs[0]);
            assert_eq!(e.wait_for_disconnect(), addrs[0]);
        })
        .join()
        .unwrap();
    // Wait for first server
    t1.join().unwrap();
}
<commit_msg>Fix race condition in network test.<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.
use futures::{self, Future, Sink, Stream};
use futures::stream::Wait;
use futures::sync::mpsc;
use tokio_core::reactor::Core;
use tokio_timer::{TimeoutStream, Timer};

use std::net::SocketAddr;
use std::thread;
use std::time::{self, Duration};

use crypto::{gen_keypair, PublicKey, Signature};
use messages::{Connect, Message, MessageWriter, RawMessage};
use events::{NetworkEvent, NetworkRequest};
use events::network::{NetworkConfiguration, NetworkPart};
use node::{EventsPoolCapacity, NodeChannel};

#[derive(Debug)]
pub struct TestHandler {
    listen_address: SocketAddr,
    network_events_rx: Wait<TimeoutStream<mpsc::Receiver<NetworkEvent>>>,
    network_requests_tx: mpsc::Sender<NetworkRequest>,
}

impl TestHandler {
    pub fn new(
        listen_address: SocketAddr,
        network_requests_tx: mpsc::Sender<NetworkRequest>,
        network_events_rx: mpsc::Receiver<NetworkEvent>,
    ) -> TestHandler {
        let timer = Timer::default();
        let receiver = timer.timeout_stream(network_events_rx, Duration::from_secs(30));
        TestHandler {
            listen_address,
            network_requests_tx,
            network_events_rx: receiver.wait(),
        }
    }

    pub fn wait_for_event(&mut self) -> Result<NetworkEvent, ()> {
        let event = self.network_events_rx.next().unwrap()?;
        Ok(event)
    }

    pub fn connect_with(&self, addr: SocketAddr) {
        let connect = connect_message(self.listen_address);
        self.network_requests_tx
            .clone()
            .send(NetworkRequest::SendMessage(addr, connect.raw().clone()))
            .wait()
            .unwrap();
    }

    pub fn disconnect_with(&self, addr: SocketAddr) {
        self.network_requests_tx
            .clone()
            .send(NetworkRequest::DisconnectWithPeer(addr))
            .wait()
            .unwrap();
    }

    pub fn send_to(&self, addr: SocketAddr, raw: RawMessage) {
        self.network_requests_tx
            .clone()
            .send(NetworkRequest::SendMessage(addr, raw))
            .wait()
            .unwrap();
    }

    pub fn wait_for_connect(&mut self) -> Connect {
        match self.wait_for_event() {
            Ok(NetworkEvent::PeerConnected(_addr, connect)) => connect,
            Ok(other) => panic!("Unexpected connect received, {:?}", other),
            Err(e) => panic!("An error during wait for connect occured, {:?}", e),
        }
    }

    pub fn wait_for_disconnect(&mut self) -> SocketAddr {
        match self.wait_for_event() {
            Ok(NetworkEvent::PeerDisconnected(addr)) => addr,
            Ok(other) => panic!("Unexpected disconnect received, {:?}", other),
            Err(e) => panic!("An error during wait for disconnect occured, {:?}", e),
        }
    }

    pub fn wait_for_message(&mut self) -> RawMessage {
        match self.wait_for_event() {
            Ok(NetworkEvent::MessageReceived(_addr, msg)) => msg,
            Ok(other) => panic!("Unexpected message received, {:?}", other),
            Err(e) => panic!("An error during wait for message occured, {:?}", e),
        }
    }
}

impl Drop for TestHandler {
    fn drop(&mut self) {
        if !::std::thread::panicking() {
            self.network_requests_tx
                .clone()
                .send(NetworkRequest::Shutdown)
                .wait()
                .unwrap();
        }
    }
}

#[derive(Debug)]
pub struct TestEvents {
    pub listen_address: SocketAddr,
    pub network_config: NetworkConfiguration,
    pub events_config: EventsPoolCapacity,
}

struct TestHandlerPart {
    handler: TestHandler,
    core: Core,
}

impl TestEvents {
    pub fn with_addr(listen_address: SocketAddr) -> TestEvents {
        TestEvents {
            listen_address,
            network_config: NetworkConfiguration::default(),
            events_config: EventsPoolCapacity::default(),
        }
    }

    pub fn spawn<F>(self, test_fn: F) -> thread::JoinHandle<()>
    where
        F: Fn(&mut TestHandler) + 'static + Send,
    {
        thread::spawn(move || {
            let (handler_part, network_part) = self.into_reactor();
            let network_thread = thread::spawn(move || network_part.run().unwrap());

            let mut handler = handler_part.handler;

            let mut core = handler_part.core;
            let test_fut = futures::lazy(move || -> Result<(), ()> {
                test_fn(&mut handler);
                Ok(())
            });
            core.run(test_fut).unwrap();
            network_thread.join().unwrap();
        })
    }

    fn into_reactor(self) -> (TestHandlerPart, NetworkPart) {
        let channel = NodeChannel::new(self.events_config);
        let core = Core::new().unwrap();
        let network_config = self.network_config;
        let (network_tx, network_rx) = channel.network_events;
        let network_requests_tx = channel.network_requests.0.clone();

        let network_part = NetworkPart {
            listen_address: self.listen_address,
            network_config,
            network_requests: channel.network_requests,
            network_tx: network_tx.clone(),
        };

        let handler_part = TestHandlerPart {
            core,
            handler: TestHandler::new(self.listen_address, network_requests_tx, network_rx),
        };
        (handler_part, network_part)
    }
}

pub fn connect_message(addr: SocketAddr) -> Connect {
    let time = time::UNIX_EPOCH;
    Connect::new_with_signature(&PublicKey::zero(), addr, time, &Signature::zero())
}

pub fn raw_message(id: u16, len: usize) -> RawMessage {
    let writer = MessageWriter::new(
        ::messages::PROTOCOL_MAJOR_VERSION,
        ::messages::TEST_NETWORK_ID,
        0,
        id,
        len,
    );
    RawMessage::new(writer.sign(&gen_keypair().1))
}

#[test]
fn test_network_handshake() {
    let addrs: [SocketAddr; 2] =
        ["127.0.0.1:17230".parse().unwrap(), "127.0.0.1:17231".parse().unwrap()];

    let e1 = TestEvents::with_addr(addrs[0]);
    let e2 = TestEvents::with_addr(addrs[1]);

    let c1 = connect_message(addrs[0]);
    let c2 = connect_message(addrs[1]);

    let t1 = e1.spawn(move |e: &mut TestHandler| {
        e.connect_with(addrs[1]);
        assert_eq!(e.wait_for_connect(), c2);
        e.disconnect_with(addrs[1]);
        assert_eq!(e.wait_for_disconnect(), addrs[1]);
    });
    let t2 = e2.spawn(move |e: &mut TestHandler| {
        assert_eq!(e.wait_for_connect(), c1);
        e.connect_with(addrs[0]);
        assert_eq!(e.wait_for_disconnect(), addrs[0]);
    });

    t1.join().unwrap();
    t2.join().unwrap();
}

#[test]
fn test_network_big_message() {
    let addrs: [SocketAddr; 2] =
        ["127.0.0.1:17200".parse().unwrap(), "127.0.0.1:17201".parse().unwrap()];

    let msg1 = raw_message(15, 100000);
    let msg2 = raw_message(16, 400);

    let e1 = TestEvents::with_addr(addrs[0]);
    let e2 = TestEvents::with_addr(addrs[1]);

    let m1 = msg1.clone();
    let m2 = msg2.clone();
    let t1 = e1.spawn(move |e: &mut TestHandler| {
        e.connect_with(addrs[1]);
        e.wait_for_connect();

        e.send_to(addrs[1], m1.clone());
        e.send_to(addrs[1], m2.clone());
        e.send_to(addrs[1], m1.clone());

        assert_eq!(e.wait_for_message(), m2);
        assert_eq!(e.wait_for_message(), m1);
        assert_eq!(e.wait_for_message(), m2);

        e.disconnect_with(addrs[1]);
        assert_eq!(e.wait_for_disconnect(), addrs[1]);
    });

    let m1 = msg1.clone();
    let m2 = msg2.clone();
    let t2 = e2.spawn(move |e: &mut TestHandler| {
        e.connect_with(addrs[0]);
        e.wait_for_connect();

        e.send_to(addrs[0], m2.clone());
        e.send_to(addrs[0], m1.clone());
        e.send_to(addrs[0], m2.clone());

        assert_eq!(e.wait_for_message(), m1);
        assert_eq!(e.wait_for_message(), m2);
        assert_eq!(e.wait_for_message(), m1);

        e.disconnect_with(addrs[0]);
        assert_eq!(e.wait_for_disconnect(), addrs[0]);
    });

    t2.join().unwrap();
    t1.join().unwrap();
}

#[test]
fn test_network_reconnect() {
    let addrs: [SocketAddr; 2] =
        ["127.0.0.1:19100".parse().unwrap(), "127.0.0.1:19101".parse().unwrap()];

    let msg = raw_message(11, 1000);
    let c1 = connect_message(addrs[0]);
    let c2 = connect_message(addrs[1]);
    let msg_cloned = msg.clone();
    let t1 = TestEvents::with_addr(addrs[0]).spawn(move |e: &mut TestHandler| {
        // Handle first attempt
        e.connect_with(addrs[1]);
        assert_eq!(e.wait_for_connect(), c2);
        assert_eq!(e.wait_for_message(), msg_cloned);
        assert_eq!(e.wait_for_disconnect(), addrs[1]);
        // Handle second attempt
        assert_eq!(e.wait_for_connect(), c2);
        e.connect_with(addrs[1]);
        assert_eq!(e.wait_for_message(), msg_cloned);
        e.disconnect_with(addrs[1]);
        assert_eq!(e.wait_for_disconnect(), addrs[1]);
    });
    // First connect attempt.
    let c1_cloned = c1.clone();
    let msg_cloned = msg.clone();
    TestEvents::with_addr(addrs[1])
        .spawn(move |e: &mut TestHandler| {
            assert_eq!(e.wait_for_connect(), c1_cloned);
            e.connect_with(addrs[0]);
            e.send_to(addrs[0], msg_cloned.clone());
            e.disconnect_with(addrs[0]);
            assert_eq!(e.wait_for_disconnect(), addrs[0]);
        })
        .join()
        .unwrap();
    // Second connect attempt.
    let c1_cloned = c1.clone();
    let msg_cloned = msg.clone();
    TestEvents::with_addr(addrs[1])
        .spawn(move |e: &mut TestHandler| {
            e.connect_with(addrs[0]);
            assert_eq!(e.wait_for_connect(), c1_cloned);
            e.send_to(addrs[0], msg_cloned.clone());
            e.disconnect_with(addrs[0]);
            assert_eq!(e.wait_for_disconnect(), addrs[0]);
        })
        .join()
        .unwrap();
    // Wait for first server
    t1.join().unwrap();
}
<|endoftext|>


<commit_before>use serde::ser::Serializer;
use serde::de::Deserializer;

/// A marker for a request that a expects a specific value.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum Exactly<Id> {
    /// No constraint.
    Empty,

    /// Expect a specific value.
    Exactly(Id),

    /// Two conflicting constraints (or more) have been put on the value.
    Conflict,
}

impl<T> Exactly<T> where T: PartialEq {
    /// Combine two constraints.
    pub fn and(self, other: Self) -> Self {
        use self::Exactly::*;
        match (self, other) {
            (Conflict, _) | (_, Conflict) => Conflict,
            (Empty, x@_) | (x@_, Empty) => x,
            (Exactly(x), Exactly(y)) =>
                if x == y {
                    Exactly(y)
                } else {
                    Conflict
                }
        }
    }

    pub fn is_empty(&self) -> bool {
        match *self {
            Exactly::Empty => true,
            _ => false,
        }
    }
}

impl<T> Default for Exactly<T> {
    fn default() -> Self {
        Exactly::Empty
    }
}
<commit_msg>[fxbox/taxonomy] Implemented Exactly::matches<commit_after>use serde::ser::Serializer;
use serde::de::Deserializer;

/// A marker for a request that a expects a specific value.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum Exactly<T> {
    /// No constraint.
    Empty,

    /// Expect a specific value.
    Exactly(T),

    /// Two conflicting constraints (or more) have been put on the value.
    Conflict,
}

impl<T> Exactly<T> where T: PartialEq {
    /// Combine two constraints.
    pub fn and(self, other: Self) -> Self {
        use self::Exactly::*;
        match (self, other) {
            (Conflict, _) | (_, Conflict) => Conflict,
            (Empty, x@_) | (x@_, Empty) => x,
            (Exactly(x), Exactly(y)) =>
                if x == y {
                    Exactly(y)
                } else {
                    Conflict
                }
        }
    }

    pub fn is_empty(&self) -> bool {
        match *self {
            Exactly::Empty => true,
            _ => false,
        }
    }

    pub fn matches(&self, value: &T) -> bool {
        match *self {
            Exactly::Exactly(ref id) => id == value,
            Exactly::Empty => true,
            _ => false
        }
    }
}

impl<T> Default for Exactly<T> {
    fn default() -> Self {
        Exactly::Empty
    }
}
<|endoftext|>