<commit_before>use core::prelude::*;

use free;

pub struct Dict<K, V> {
    root : *mut V,
}

pub struct DictNode<K, V> {
    pub key : K,
    left : *mut V,
    right : *mut V,
}

impl<K,V> DictNode<K,V> {
    #[inline(never)]
    pub fn new(key : K) -> DictNode<K, V> {
        DictNode { key : key, left : null(), right : null() }
    }
}

pub trait DictItem<K> {
    fn node<'a>(&'a mut self) -> &'a mut DictNode<K, Self>;
    // Figure out a way to implement a node->item function, then we can remove
    // "T" from the nodes, do links between nodes instead of items, and use a
    // single copy of the linking code.
}

fn null<T>() -> *mut T { RawPtr::null() }
fn node<'a, K, T : DictItem<K>>(p : *mut T) -> &'a mut DictNode<K, T> {
    unsafe { (*p).node() }
}

impl<K : Ord + Copy, V : DictItem<K>> Dict<K, V> {
    pub fn empty() -> Dict<K, V> {
        Dict { root : null() }
    }

    pub fn find<'a>(&mut self, key : K) -> Option<&'a mut V> {
        return self.find_(key);
    }

    // Return the greatest item with key <= key
    #[inline(never)]
    fn find_<'a>(&self, key : K) -> Option<&'a mut V> {
        let mut item = self.root;
        let mut max = null();
        while item.is_not_null() {
            let ikey : K = node(item).key;
            if ikey <= key {
                if max.is_null() {
                    max = item;
                } else {
                    let maxKey : K = node(max).key;
                    if maxKey < ikey {
                        max = item;
                    }
                }
            }
            item = node(item).right;
        }
        if max.is_null() { None } else { unsafe { Some(&mut *max) } }
    }

    #[inline(always)]
    pub fn find_const<'a>(&self, key : K) -> Option<&'a V> {
        match self.find_(key) {
            Some(x) => Some(&*x),
            None => None
        }
    }

    #[inline(never)]
    pub fn insert<'a>(&mut self, item : *mut V) -> &'a mut V {
        node(item).left = null();
        node(item).right = self.root;
        self.root = item;
        unsafe { &mut *item }
    }

    pub fn remove(&mut self, key: K) {
        let mut p : *mut *mut V = &mut self.root;
        unsafe {
            while (*p).is_not_null() {
                let item = *p;
                if node(item).key == key {
                    *p = node(item).right;
                    free(item);
                    break;
                }
                p = &mut node(item).right as *mut*mut V;
            }
        }
    }

    pub fn remove_range_exclusive(&mut self, start: K, end: K) {
        unsafe {
            let mut p : *mut *mut V = &mut self.root;
            while (*p).is_not_null() {
                let item = *p;
                if start < node(item).key && node(item).key < end {
                    *p = node(item).right;
                    free(item);
                } else {
                    p = &mut node(item).right as *mut*mut V;
                }
            }
        }
    }

    pub fn iter<'a>(&'a self) -> DictIter<'a, V> {
        DictIter { p: self.root }
    }
}

struct DictIter<'a, T> {
    p : *mut T,
}

impl<'a, K : Copy, V : DictItem<K>> Iterator<(K, &'a mut V)> for DictIter<'a, V> {
    fn next(&mut self) -> Option<(K, &'a mut V)> {
        if self.p.is_not_null() {
            let res = self.p;
            self.p = node(res).right;
            unsafe { Some((node(res).key, &mut *res)) }
        } else {
            None
        }
    }
}
<commit_msg>Hmm. 464 bytes saved with more inlining.<commit_after>use core::prelude::*;

use free;

pub struct Dict<K, V> {
    root : *mut V,
}

pub struct DictNode<K, V> {
    pub key : K,
    left : *mut V,
    right : *mut V,
}

impl<K,V> DictNode<K,V> {
    pub fn new(key : K) -> DictNode<K, V> {
        DictNode { key : key, left : null(), right : null() }
    }
}

pub trait DictItem<K> {
    fn node<'a>(&'a mut self) -> &'a mut DictNode<K, Self>;
    // Figure out a way to implement a node->item function, then we can remove
    // "T" from the nodes, do links between nodes instead of items, and use a
    // single copy of the linking code.
}

fn null<T>() -> *mut T { RawPtr::null() }
fn node<'a, K, T : DictItem<K>>(p : *mut T) -> &'a mut DictNode<K, T> {
    unsafe { (*p).node() }
}

impl<K : Ord + Copy, V : DictItem<K>> Dict<K, V> {
    pub fn empty() -> Dict<K, V> {
        Dict { root : null() }
    }

    pub fn find<'a>(&mut self, key : K) -> Option<&'a mut V> {
        return self.find_(key);
    }

    // Return the greatest item with key <= key
    #[inline(never)]
    fn find_<'a>(&self, key : K) -> Option<&'a mut V> {
        let mut item = self.root;
        let mut max = null();
        while item.is_not_null() {
            let ikey : K = node(item).key;
            if ikey <= key {
                if max.is_null() {
                    max = item;
                } else {
                    let maxKey : K = node(max).key;
                    if maxKey < ikey {
                        max = item;
                    }
                }
            }
            item = node(item).right;
        }
        if max.is_null() { None } else { unsafe { Some(&mut *max) } }
    }

    #[inline(always)]
    pub fn find_const<'a>(&self, key : K) -> Option<&'a V> {
        match self.find_(key) {
            Some(x) => Some(&*x),
            None => None
        }
    }

    #[inline(never)]
    pub fn insert<'a>(&mut self, item : *mut V) -> &'a mut V {
        node(item).left = null();
        node(item).right = self.root;
        self.root = item;
        unsafe { &mut *item }
    }

    pub fn remove(&mut self, key: K) {
        let mut p : *mut *mut V = &mut self.root;
        unsafe {
            while (*p).is_not_null() {
                let item = *p;
                if node(item).key == key {
                    *p = node(item).right;
                    free(item);
                    break;
                }
                p = &mut node(item).right as *mut*mut V;
            }
        }
    }

    pub fn remove_range_exclusive(&mut self, start: K, end: K) {
        unsafe {
            let mut p : *mut *mut V = &mut self.root;
            while (*p).is_not_null() {
                let item = *p;
                if start < node(item).key && node(item).key < end {
                    *p = node(item).right;
                    free(item);
                } else {
                    p = &mut node(item).right as *mut*mut V;
                }
            }
        }
    }

    pub fn iter<'a>(&'a self) -> DictIter<'a, V> {
        DictIter { p: self.root }
    }
}

struct DictIter<'a, T> {
    p : *mut T,
}

impl<'a, K : Copy, V : DictItem<K>> Iterator<(K, &'a mut V)> for DictIter<'a, V> {
    fn next(&mut self) -> Option<(K, &'a mut V)> {
        if self.p.is_not_null() {
            let res = self.p;
            self.p = node(res).right;
            unsafe { Some((node(res).key, &mut *res)) }
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>//! The Rust parser.
//!
//! NOTE: The crate is undergoing refactors, don't believe everything the docs
//! say :-)
//!
//! The parser doesn't know about concrete representation of tokens and syntax
//! trees. Abstract [`TokenSource`] and [`TreeSink`] traits are used instead. As
//! a consequence, this crate does not contain a lexer.
//!
//! The [`Parser`] struct from the [`parser`] module is a cursor into the
//! sequence of tokens.  Parsing routines use [`Parser`] to inspect current
//! state and advance the parsing.
//!
//! The actual parsing happens in the [`grammar`] module.
//!
//! Tests for this crate live in the `syntax` crate.
//!
//! [`Parser`]: crate::parser::Parser
#![allow(rustdoc::private_intra_doc_links)]

mod lexed_str;
mod token_set;
mod syntax_kind;
mod event;
mod parser;
mod grammar;
mod input;
mod output;
mod shortcuts;

#[cfg(test)]
mod tests;

pub(crate) use token_set::TokenSet;

pub use crate::{
    input::Input,
    lexed_str::LexedStr,
    output::{Output, Step},
    shortcuts::StrStep,
    syntax_kind::SyntaxKind,
};

/// Parse a prefix of the input as a given syntactic construct.
///
/// This is used by macro-by-example parser to implement things like `$i:item`
/// and the naming of variants follows the naming of macro fragments.
///
/// Note that this is generally non-optional -- the result is intentionally not
/// `Option<Output>`. The way MBE work, by the time we *try* to parse `$e:expr`
/// we already commit to expression. In other words, this API by design can't be
/// used to implement "rollback and try another alternative" logic.
#[derive(Debug)]
pub enum PrefixEntryPoint {
    Vis,
    Block,
    Stmt,
    Pat,
    Ty,
    Expr,
    Path,
    Item,
    MetaItem,
}

impl PrefixEntryPoint {
    pub fn parse(&self, input: &Input) -> Output {
        let entry_point: fn(&'_ mut parser::Parser) = match self {
            PrefixEntryPoint::Vis => grammar::entry::prefix::vis,
            PrefixEntryPoint::Block => grammar::entry::prefix::block,
            PrefixEntryPoint::Stmt => grammar::entry::prefix::stmt,
            PrefixEntryPoint::Pat => grammar::entry::prefix::pat,
            PrefixEntryPoint::Ty => grammar::entry::prefix::ty,
            PrefixEntryPoint::Expr => grammar::entry::prefix::expr,
            PrefixEntryPoint::Path => grammar::entry::prefix::path,
            PrefixEntryPoint::Item => grammar::entry::prefix::item,
            PrefixEntryPoint::MetaItem => grammar::entry::prefix::meta_item,
        };
        let mut p = parser::Parser::new(input);
        entry_point(&mut p);
        let events = p.finish();
        event::process(events)
    }
}

/// Parse the whole of the input as a given syntactic construct.
///
/// This covers two main use-cases:
///
///   * Parsing a Rust file.
///   * Parsing a result of macro expansion.
///
/// That is, for something like
///
/// ```
/// quick_check! {
///    fn prop() {}
/// }
/// ```
///
/// the input to the macro will be parsed with [`PrefixEntryPoint::Item`], and
/// the result will be [`TopEntryPoint::Items`].
///
/// This *should* (but currently doesn't) guarantee that all input is consumed.
#[derive(Debug)]
pub enum TopEntryPoint {
    SourceFile,
    MacroStmts,
    MacroItems,
    Pattern,
    Type,
    Expr,
    MetaItem,
}

impl TopEntryPoint {
    pub fn parse(&self, input: &Input) -> Output {
        let entry_point: fn(&'_ mut parser::Parser) = match self {
            TopEntryPoint::SourceFile => grammar::entry::top::source_file,
            TopEntryPoint::MacroStmts => grammar::entry::top::macro_stmts,
            TopEntryPoint::MacroItems => grammar::entry::top::macro_items,
            // FIXME
            TopEntryPoint::Pattern => grammar::entry::prefix::pat,
            TopEntryPoint::Type => grammar::entry::prefix::ty,
            TopEntryPoint::Expr => grammar::entry::prefix::expr,
            TopEntryPoint::MetaItem => grammar::entry::prefix::meta_item,
        };
        let mut p = parser::Parser::new(input);
        entry_point(&mut p);
        let events = p.finish();
        event::process(events)
    }
}

/// rust-analyzer parser allows you to choose one of the possible entry points.
///
/// The primary consumer of this API are declarative macros, `$x:expr` matchers
/// are implemented by calling into the parser with non-standard entry point.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum ParserEntryPoint {
    Path,
    Expr,
    StatementOptionalSemi,
    Type,
    Pattern,
    Item,
    MetaItem,
    Attr,
}

/// Parse given tokens into the given sink as a rust file.
pub fn parse_source_file(input: &Input) -> Output {
    TopEntryPoint::SourceFile.parse(input)
}

/// Parses the given [`Input`] into [`Output`] assuming that the top-level
/// syntactic construct is the given [`ParserEntryPoint`].
///
/// Both input and output here are fairly abstract. The overall flow is that the
/// caller has some "real" tokens, converts them to [`Input`], parses them to
/// [`Output`], and then converts that into a "real" tree. The "real" tree is
/// made of "real" tokens, so this all hinges on rather tight coordination of
/// indices between the four stages.
pub fn parse(inp: &Input, entry_point: ParserEntryPoint) -> Output {
    let entry_point: fn(&'_ mut parser::Parser) = match entry_point {
        ParserEntryPoint::Path => grammar::entry::prefix::path,
        ParserEntryPoint::Expr => grammar::entry::prefix::expr,
        ParserEntryPoint::Type => grammar::entry::prefix::ty,
        ParserEntryPoint::Pattern => grammar::entry::prefix::pat,
        ParserEntryPoint::Item => grammar::entry::prefix::item,
        ParserEntryPoint::MetaItem => grammar::entry::prefix::meta_item,
        ParserEntryPoint::StatementOptionalSemi => grammar::entry_points::stmt_optional_semi,
        ParserEntryPoint::Attr => grammar::entry_points::attr,
    };

    let mut p = parser::Parser::new(inp);
    entry_point(&mut p);
    let events = p.finish();
    event::process(events)
}

/// A parsing function for a specific braced-block.
pub struct Reparser(fn(&mut parser::Parser));

impl Reparser {
    /// If the node is a braced block, return the corresponding `Reparser`.
    pub fn for_node(
        node: SyntaxKind,
        first_child: Option<SyntaxKind>,
        parent: Option<SyntaxKind>,
    ) -> Option<Reparser> {
        grammar::reparser(node, first_child, parent).map(Reparser)
    }

    /// Re-parse given tokens using this `Reparser`.
    ///
    /// Tokens must start with `{`, end with `}` and form a valid brace
    /// sequence.
    pub fn parse(self, tokens: &Input) -> Output {
        let Reparser(r) = self;
        let mut p = parser::Parser::new(tokens);
        r(&mut p);
        let events = p.finish();
        event::process(events)
    }
}
<commit_msg>dead code<commit_after>//! The Rust parser.
//!
//! NOTE: The crate is undergoing refactors, don't believe everything the docs
//! say :-)
//!
//! The parser doesn't know about concrete representation of tokens and syntax
//! trees. Abstract [`TokenSource`] and [`TreeSink`] traits are used instead. As
//! a consequence, this crate does not contain a lexer.
//!
//! The [`Parser`] struct from the [`parser`] module is a cursor into the
//! sequence of tokens.  Parsing routines use [`Parser`] to inspect current
//! state and advance the parsing.
//!
//! The actual parsing happens in the [`grammar`] module.
//!
//! Tests for this crate live in the `syntax` crate.
//!
//! [`Parser`]: crate::parser::Parser
#![allow(rustdoc::private_intra_doc_links)]

mod lexed_str;
mod token_set;
mod syntax_kind;
mod event;
mod parser;
mod grammar;
mod input;
mod output;
mod shortcuts;

#[cfg(test)]
mod tests;

pub(crate) use token_set::TokenSet;

pub use crate::{
    input::Input,
    lexed_str::LexedStr,
    output::{Output, Step},
    shortcuts::StrStep,
    syntax_kind::SyntaxKind,
};

/// Parse a prefix of the input as a given syntactic construct.
///
/// This is used by macro-by-example parser to implement things like `$i:item`
/// and the naming of variants follows the naming of macro fragments.
///
/// Note that this is generally non-optional -- the result is intentionally not
/// `Option<Output>`. The way MBE work, by the time we *try* to parse `$e:expr`
/// we already commit to expression. In other words, this API by design can't be
/// used to implement "rollback and try another alternative" logic.
#[derive(Debug)]
pub enum PrefixEntryPoint {
    Vis,
    Block,
    Stmt,
    Pat,
    Ty,
    Expr,
    Path,
    Item,
    MetaItem,
}

impl PrefixEntryPoint {
    pub fn parse(&self, input: &Input) -> Output {
        let entry_point: fn(&'_ mut parser::Parser) = match self {
            PrefixEntryPoint::Vis => grammar::entry::prefix::vis,
            PrefixEntryPoint::Block => grammar::entry::prefix::block,
            PrefixEntryPoint::Stmt => grammar::entry::prefix::stmt,
            PrefixEntryPoint::Pat => grammar::entry::prefix::pat,
            PrefixEntryPoint::Ty => grammar::entry::prefix::ty,
            PrefixEntryPoint::Expr => grammar::entry::prefix::expr,
            PrefixEntryPoint::Path => grammar::entry::prefix::path,
            PrefixEntryPoint::Item => grammar::entry::prefix::item,
            PrefixEntryPoint::MetaItem => grammar::entry::prefix::meta_item,
        };
        let mut p = parser::Parser::new(input);
        entry_point(&mut p);
        let events = p.finish();
        event::process(events)
    }
}

/// Parse the whole of the input as a given syntactic construct.
///
/// This covers two main use-cases:
///
///   * Parsing a Rust file.
///   * Parsing a result of macro expansion.
///
/// That is, for something like
///
/// ```
/// quick_check! {
///    fn prop() {}
/// }
/// ```
///
/// the input to the macro will be parsed with [`PrefixEntryPoint::Item`], and
/// the result will be [`TopEntryPoint::Items`].
///
/// This *should* (but currently doesn't) guarantee that all input is consumed.
#[derive(Debug)]
pub enum TopEntryPoint {
    SourceFile,
    MacroStmts,
    MacroItems,
    Pattern,
    Type,
    Expr,
    MetaItem,
}

impl TopEntryPoint {
    pub fn parse(&self, input: &Input) -> Output {
        let entry_point: fn(&'_ mut parser::Parser) = match self {
            TopEntryPoint::SourceFile => grammar::entry::top::source_file,
            TopEntryPoint::MacroStmts => grammar::entry::top::macro_stmts,
            TopEntryPoint::MacroItems => grammar::entry::top::macro_items,
            // FIXME
            TopEntryPoint::Pattern => grammar::entry::prefix::pat,
            TopEntryPoint::Type => grammar::entry::prefix::ty,
            TopEntryPoint::Expr => grammar::entry::prefix::expr,
            TopEntryPoint::MetaItem => grammar::entry::prefix::meta_item,
        };
        let mut p = parser::Parser::new(input);
        entry_point(&mut p);
        let events = p.finish();
        event::process(events)
    }
}

/// rust-analyzer parser allows you to choose one of the possible entry points.
///
/// The primary consumer of this API are declarative macros, `$x:expr` matchers
/// are implemented by calling into the parser with non-standard entry point.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum ParserEntryPoint {
    Path,
    Expr,
    StatementOptionalSemi,
    Type,
    Pattern,
    Item,
    Attr,
}

/// Parse given tokens into the given sink as a rust file.
pub fn parse_source_file(input: &Input) -> Output {
    TopEntryPoint::SourceFile.parse(input)
}

/// Parses the given [`Input`] into [`Output`] assuming that the top-level
/// syntactic construct is the given [`ParserEntryPoint`].
///
/// Both input and output here are fairly abstract. The overall flow is that the
/// caller has some "real" tokens, converts them to [`Input`], parses them to
/// [`Output`], and then converts that into a "real" tree. The "real" tree is
/// made of "real" tokens, so this all hinges on rather tight coordination of
/// indices between the four stages.
pub fn parse(inp: &Input, entry_point: ParserEntryPoint) -> Output {
    let entry_point: fn(&'_ mut parser::Parser) = match entry_point {
        ParserEntryPoint::Path => grammar::entry::prefix::path,
        ParserEntryPoint::Expr => grammar::entry::prefix::expr,
        ParserEntryPoint::Type => grammar::entry::prefix::ty,
        ParserEntryPoint::Pattern => grammar::entry::prefix::pat,
        ParserEntryPoint::Item => grammar::entry::prefix::item,
        ParserEntryPoint::StatementOptionalSemi => grammar::entry_points::stmt_optional_semi,
        ParserEntryPoint::Attr => grammar::entry_points::attr,
    };

    let mut p = parser::Parser::new(inp);
    entry_point(&mut p);
    let events = p.finish();
    event::process(events)
}

/// A parsing function for a specific braced-block.
pub struct Reparser(fn(&mut parser::Parser));

impl Reparser {
    /// If the node is a braced block, return the corresponding `Reparser`.
    pub fn for_node(
        node: SyntaxKind,
        first_child: Option<SyntaxKind>,
        parent: Option<SyntaxKind>,
    ) -> Option<Reparser> {
        grammar::reparser(node, first_child, parent).map(Reparser)
    }

    /// Re-parse given tokens using this `Reparser`.
    ///
    /// Tokens must start with `{`, end with `}` and form a valid brace
    /// sequence.
    pub fn parse(self, tokens: &Input) -> Output {
        let Reparser(r) = self;
        let mut p = parser::Parser::new(tokens);
        r(&mut p);
        let events = p.finish();
        event::process(events)
    }
}
<|endoftext|>


<commit_before>use std::fmt::{self, Formatter, Display};

struct City {
    name: &'static str,
    // 纬度
    lat: f32,
    // 经度
    lon: f32,
}

impl Display for City {
    // `f` 是一个缓冲区（buffer），此方法必须将格式化的字符串写入其中
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let lat_c = if self.lat >= 0.0 { 'N' } else { 'S' };
        let lon_c = if self.lon >= 0.0 { 'E' } else { 'W' };

        // `write!` 和 `format!` 类似，但它会将格式化后的字符串写入到一个缓冲区
        // 中（第一个除数f）
        write!(f, "{}: {:.3}°{} {:.3}°{}",
               self.name, self.lat.abs(), lat_c, self.lon.abs(), lon_c)
    }
}

#[derive(Debug)]
struct Color {
    red: u8,
    green: u8,
    blue: u8,
}

fn main() {
    for city in [
        City { name: "Dublin", lat: 53.347778, lon: -6.259722 },
        City { name: "Oslo", lat: 59.95, lon: 10.75 },
        City { name: "Vancouver", lat: 49.25, lon: -123.1 },
    ].iter() {
        println!("{}", *city);
    }
    for color in [
        Color { red: 128, green: 255, blue: 90 },
        Color { red: 0, green: 3, blue: 254 },
        Color { red: 0, green: 0, blue: 0 },
    ].iter() {
        // 一旦添加了针对 fmt::Display 的实现，则要用 {} 对输出内容进行转换
        println!("{:?}", *color)
    }
}
<commit_msg>Create show.rs<commit_after>use std::fmt::{self, Formatter, Display};

struct City {
    name: &'static str,
    // 纬度
    lat: f32,
    // 经度
    lon: f32,
}

impl Display for City {
    // `f` 是一个缓冲区（buffer），此方法必须将格式化的字符串写入其中
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let lat_c = if self.lat >= 0.0 { 'N' } else { 'S' };
        let lon_c = if self.lon >= 0.0 { 'E' } else { 'W' };

        // `write!` 和 `format!` 类似，但它会将格式化后的字符串写入到一个缓冲区
        // 中（第一个参数f）
        write!(f, "{}: {:.3}°{} {:.3}°{}",
               self.name, self.lat.abs(), lat_c, self.lon.abs(), lon_c)
    }
}

#[derive(Debug)]
struct Color {
    red: u8,
    green: u8,
    blue: u8,
}

fn main() {
    for city in [
        City { name: "Dublin", lat: 53.347778, lon: -6.259722 },
        City { name: "Oslo", lat: 59.95, lon: 10.75 },
        City { name: "Vancouver", lat: 49.25, lon: -123.1 },
    ].iter() {
        println!("{}", *city);
    }
    for color in [
        Color { red: 128, green: 255, blue: 90 },
        Color { red: 0, green: 3, blue: 254 },
        Color { red: 0, green: 0, blue: 0 },
    ].iter() {
        // 一旦添加了针对 fmt::Display 的实现，则要用 {} 对输出内容进行转换
        println!("{:?}", *color)
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]
#![allow(non_snake_case)]

extern crate test;
extern crate ndarray;

use ndarray::{Array, S, Si};
use ndarray::{arr0, arr1, arr2};
use ndarray::Indexes;

#[test]
fn test_matmul_rcarray()
{
    let mut A = Array::<uint, _>::zeros((2, 3));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    let mut B = Array::<uint, _>::zeros((3, 4));
    for (i, elt) in B.iter_mut().enumerate() {
        *elt = i;
    }

    let c = A.mat_mul(&B);
    println!("A = \n{}", A);
    println!("B = \n{}", B);
    println!("A x B = \n{}", c);
    unsafe {
        let result = Array::from_vec_dim((2, 4), vec![20u, 23, 26, 29, 56, 68, 80, 92]);
        assert_eq!(c.shape(), result.shape());
        assert!(c.iter().zip(result.iter()).all(|(a,b)| a == b));
        assert!(c == result);
    }
}

#[test]
fn test_slice()
{
    let mut A = Array::<uint, _>::zeros((3, 4));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    let vi = A.slice(&[Si(1, None, 1), Si(0, None, 2)]);
    assert_eq!(vi.dim(), (2, 2));
    let vi = A.slice(&[S, S]);
    assert_eq!(vi.shape(), A.shape());
    assert!(vi.iter().zip(A.iter()).all(|(a, b)| a == b));
}

#[test]
fn test_index()
{
    let mut A = Array::<uint, _>::zeros((2, 3));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    for ((i, j), a) in Indexes::new2(2, 3).zip(A.iter()) {
        assert_eq!(*a, A[(i, j)]);
    }

    let vi = A.slice(&[Si(1, None, 1), Si(0, None, 2)]);
    let mut it = vi.iter();
    for ((i, j), x) in Indexes::new2(1, 2).zip(it.by_ref()) {
        assert_eq!(*x, vi[(i, j)]);
    }
    assert!(it.next().is_none());
}

#[test]
fn test_add()
{
    let mut A = Array::<uint, _>::zeros((2, 2));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    let B = A.clone();
    A.iadd(&B);
    assert_eq!(A[(0,0)], 0u);
    assert_eq!(A[(0,1)], 2u);
    assert_eq!(A[(1,0)], 4u);
    assert_eq!(A[(1,1)], 6u);
}

#[test]
fn test_multidim()
{
    let mut mat = Array::zeros(2*3*4*5*6).reshape((2,3,4,5,6));
    mat[(0,0,0,0,0)] = 22u8;
    {
        for (i, elt) in mat.iter_mut().enumerate() {
            *elt = i as u8;
        }
    }
    //println!("shape={}, strides={}", mat.shape(), mat.strides);
    assert_eq!(mat.dim(), (2,3,4,5,6));
}

/*
array([[[ 7,  6],
        [ 5,  4],
        [ 3,  2],
        [ 1,  0]],

       [[15, 14],
        [13, 12],
        [11, 10],
        [ 9,  8]]])
*/
#[test]
fn test_negative_stride_rcarray()
{
    let mut mat = Array::zeros((2, 4, 2));
    mat[(0, 0, 0)] = 1.0f32;
    for (i, elt) in mat.iter_mut().enumerate() {
        *elt = i as f32;
    }

    {
        let vi = mat.slice(&[S, Si(0, None, -1), Si(0, None, -1)]);
        assert_eq!(vi.dim(), (2,4,2));
        // Test against sequential iterator
        let seq = [7f32,6., 5.,4.,3.,2.,1.,0.,15.,14.,13., 12.,11.,  10.,   9.,   8.];
        for (a, b) in vi.clone().iter().zip(seq.iter()) {
            assert_eq!(*a, *b);
        }
    }
    {
        let vi = mat.slice(&[S, Si(0, None, -5), S]);
        let seq = [6_f32, 7., 14., 15.];
        for (a, b) in vi.iter().zip(seq.iter()) {
            assert_eq!(*a, *b);
        }
    }
}

#[test]
fn test_cow()
{
    let mut mat = Array::<int, _>::zeros((2,2));
    mat[(0, 0)] = 1;
    let n = mat.clone();
    mat[(0, 1)] = 2;
    mat[(1, 0)] = 3;
    mat[(1, 1)] = 4;
    assert_eq!(mat[(0,0)], 1);
    assert_eq!(mat[(0,1)], 2);
    assert_eq!(n[(0,0)], 1);
    assert_eq!(n[(0,1)], 0);
    let mut rev = mat.reshape(4).slice(&[Si(0, None, -1)]);
    assert_eq!(rev[0], 4);
    assert_eq!(rev[1], 3);
    assert_eq!(rev[2], 2);
    assert_eq!(rev[3], 1);
    let before = rev.clone();
    // mutation
    rev[0] = 5;
    assert_eq!(rev[0], 5);
    assert_eq!(rev[1], 3);
    assert_eq!(rev[2], 2);
    assert_eq!(rev[3], 1);
    assert_eq!(before[0], 4);
    assert_eq!(before[1], 3);
    assert_eq!(before[2], 2);
    assert_eq!(before[3], 1);
}

#[test]
fn test_sub()
{
    let mat = Array::range(0.0f32, 16.0).reshape((2, 4, 2));
    let s1 = mat.subview(0,0);
    let s2 = mat.subview(0,1);
    assert_eq!(s1.dim(), (4, 2));
    assert_eq!(s2.dim(), (4, 2));
    let n = Array::range(8.0f32, 16.0).reshape((4,2));
    assert_eq!(n, s2);
    let m = Array::from_vec(vec![2f32, 3., 10., 11.]).reshape((2, 2));
    assert_eq!(m, mat.subview(1, 1));
}

#[test]
fn diag()
{
    let d = arr2::<f32>(&[&[1., 2., 3.0f32]]).diag();
    assert_eq!(d.dim(), 1);
    let d = arr2::<f32>(&[&[1., 2., 3.0f32], &[0., 0., 0.]]).diag();
    assert_eq!(d.dim(), 2);
    let d = arr2::<f32>(&[]).diag();
    assert_eq!(d.dim(), 0);
    let d = Array::<f32, _>::zeros(()).diag();
    assert_eq!(d.dim(), 1);
}

#[test]
fn swapaxes()
{
    let mut a = arr2::<f32>(&[&[1., 2.], &[3., 4.0f32]]);
    let     b = arr2::<f32>(&[&[1., 3.], &[2., 4.0f32]]);
    assert!(a != b);
    a.swap_axes(0, 1);
    assert_eq!(a, b);
    a.swap_axes(1, 1);
    assert_eq!(a, b);
    assert!(a.raw_data() == [1., 2., 3., 4.]);
    assert!(b.raw_data() == [1., 3., 2., 4.]);
}

#[test]
fn standard_layout()
{
    let mut a = arr2::<f32>(&[&[1., 2.], &[3., 4.0]]);
    assert!(a.is_standard_layout());
    a.swap_axes(0, 1);
    assert!(!a.is_standard_layout());
    a.swap_axes(0, 1);
    assert!(a.is_standard_layout());
    let x1 = a.subview(0, 0);
    assert!(x1.is_standard_layout());
    let x2 = a.subview(1, 0);
    assert!(!x2.is_standard_layout());
}

#[test]
fn assign()
{
    let mut a = arr2::<f32>(&[&[1., 2.], &[3., 4.]]);
    let     b = arr2::<f32>(&[&[1., 3.], &[2., 4.]]);
    a.assign(&b);
    assert_eq!(a, b);

    /* Test broadcasting */
    a.assign(&Array::zeros(1));
    assert_eq!(a, Array::zeros((2, 2)));
}

#[test]
fn dyn_dimension()
{
    let a = arr2::<f32>(&[&[1., 2.], &[3., 4.0]]).reshape(vec![2, 2]);
    assert_eq!(&a - &a, Array::zeros(vec![2, 2]));

    let mut dim = Vec::from_elem(1024, 1);
    dim.as_mut_slice()[16] = 4;
    dim.as_mut_slice()[17] = 3;
    let z = Array::<f32, _>::zeros(dim.clone());
    assert_eq!(z.shape(), dim.as_slice());
}

#[test]
fn sum_mean()
{
    let a = arr2::<f32>(&[&[1., 2.], &[3., 4.]]);
    assert_eq!(a.sum(0), arr1(&[4., 6.]));
    assert_eq!(a.sum(1), arr1(&[3., 7.]));
    assert_eq!(a.mean(0), arr1(&[2., 3.]));
    assert_eq!(a.mean(1), arr1(&[1.5, 3.5]));
    assert_eq!(a.sum(1).sum(0), arr0(10.));
}

#[test]
fn iter_size_hint()
{
    let mut a = arr2::<f32>(&[&[1., 2.], &[3., 4.]]);
    {
        let mut it = a.iter();
        assert_eq!(it.size_hint(), (4, Some(4)));
        it.next();
        assert_eq!(it.size_hint().val0(), 3);
        it.next();
        assert_eq!(it.size_hint().val0(), 2);
        it.next();
        assert_eq!(it.size_hint().val0(), 1);
        it.next();
        assert_eq!(it.size_hint().val0(), 0);
        assert!(it.next().is_none());
        assert_eq!(it.size_hint().val0(), 0);
    }

    a.swap_axes(0, 1);
    {
        let mut it = a.iter();
        assert_eq!(it.size_hint(), (4, Some(4)));
        it.next();
        assert_eq!(it.size_hint().val0(), 3);
        it.next();
        assert_eq!(it.size_hint().val0(), 2);
        it.next();
        assert_eq!(it.size_hint().val0(), 1);
        it.next();
        assert_eq!(it.size_hint().val0(), 0);
        assert!(it.next().is_none());
        assert_eq!(it.size_hint().val0(), 0);
    }
}

#[test]
fn zero_axes()
{
    let a = arr1::<f32>(&[]);
    for _ in a.iter() {
        assert!(false);
    }
    println!("{}", a);
    let b = arr2::<f32>(&[&[], &[], &[], &[]]);
    println!("{}\n{}", b.shape(), b);

    // we can even get a subarray of b
    let bsub = b.subview(0, 2);
    assert_eq!(bsub.dim(), 0);
}

#[test]
fn equality()
{
    let a = arr2::<f32>(&[&[1., 2.], &[3., 4.]]);
    let mut b = arr2::<f32>(&[&[1., 2.], &[2., 4.]]);
    assert!(a != b);
    b[(1, 0)] = 3.;
    assert!(a == b);

    // make sure we can compare different shapes without failure.
    let c = arr2::<f32>(&[&[1., 2.]]);
    assert!(a != c);
}

#[test]
fn map1()
{
    let a = arr2::<f32>(&[&[1., 2.], &[3., 4.]]);
    let b = a.map(|&x| (x / 3.) as int);
    assert_eq!(b, arr2(&[&[0, 0], &[1, 1]]));
    // test map to reference with array's lifetime.
    let c = a.map(|x| x);
    assert_eq!(a[(0, 0)], *c[(0, 0)]);
}
<commit_msg>Remove use of tuple traits<commit_after>#![feature(phase)]
#![allow(non_snake_case)]

extern crate test;
extern crate ndarray;

use ndarray::{Array, S, Si};
use ndarray::{arr0, arr1, arr2};
use ndarray::Indexes;

#[test]
fn test_matmul_rcarray()
{
    let mut A = Array::<uint, _>::zeros((2, 3));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    let mut B = Array::<uint, _>::zeros((3, 4));
    for (i, elt) in B.iter_mut().enumerate() {
        *elt = i;
    }

    let c = A.mat_mul(&B);
    println!("A = \n{}", A);
    println!("B = \n{}", B);
    println!("A x B = \n{}", c);
    unsafe {
        let result = Array::from_vec_dim((2, 4), vec![20u, 23, 26, 29, 56, 68, 80, 92]);
        assert_eq!(c.shape(), result.shape());
        assert!(c.iter().zip(result.iter()).all(|(a,b)| a == b));
        assert!(c == result);
    }
}

#[test]
fn test_slice()
{
    let mut A = Array::<uint, _>::zeros((3, 4));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    let vi = A.slice(&[Si(1, None, 1), Si(0, None, 2)]);
    assert_eq!(vi.dim(), (2, 2));
    let vi = A.slice(&[S, S]);
    assert_eq!(vi.shape(), A.shape());
    assert!(vi.iter().zip(A.iter()).all(|(a, b)| a == b));
}

#[test]
fn test_index()
{
    let mut A = Array::<uint, _>::zeros((2, 3));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    for ((i, j), a) in Indexes::new2(2, 3).zip(A.iter()) {
        assert_eq!(*a, A[(i, j)]);
    }

    let vi = A.slice(&[Si(1, None, 1), Si(0, None, 2)]);
    let mut it = vi.iter();
    for ((i, j), x) in Indexes::new2(1, 2).zip(it.by_ref()) {
        assert_eq!(*x, vi[(i, j)]);
    }
    assert!(it.next().is_none());
}

#[test]
fn test_add()
{
    let mut A = Array::<uint, _>::zeros((2, 2));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    let B = A.clone();
    A.iadd(&B);
    assert_eq!(A[(0,0)], 0u);
    assert_eq!(A[(0,1)], 2u);
    assert_eq!(A[(1,0)], 4u);
    assert_eq!(A[(1,1)], 6u);
}

#[test]
fn test_multidim()
{
    let mut mat = Array::zeros(2*3*4*5*6).reshape((2,3,4,5,6));
    mat[(0,0,0,0,0)] = 22u8;
    {
        for (i, elt) in mat.iter_mut().enumerate() {
            *elt = i as u8;
        }
    }
    //println!("shape={}, strides={}", mat.shape(), mat.strides);
    assert_eq!(mat.dim(), (2,3,4,5,6));
}

/*
array([[[ 7,  6],
        [ 5,  4],
        [ 3,  2],
        [ 1,  0]],

       [[15, 14],
        [13, 12],
        [11, 10],
        [ 9,  8]]])
*/
#[test]
fn test_negative_stride_rcarray()
{
    let mut mat = Array::zeros((2, 4, 2));
    mat[(0, 0, 0)] = 1.0f32;
    for (i, elt) in mat.iter_mut().enumerate() {
        *elt = i as f32;
    }

    {
        let vi = mat.slice(&[S, Si(0, None, -1), Si(0, None, -1)]);
        assert_eq!(vi.dim(), (2,4,2));
        // Test against sequential iterator
        let seq = [7f32,6., 5.,4.,3.,2.,1.,0.,15.,14.,13., 12.,11.,  10.,   9.,   8.];
        for (a, b) in vi.clone().iter().zip(seq.iter()) {
            assert_eq!(*a, *b);
        }
    }
    {
        let vi = mat.slice(&[S, Si(0, None, -5), S]);
        let seq = [6_f32, 7., 14., 15.];
        for (a, b) in vi.iter().zip(seq.iter()) {
            assert_eq!(*a, *b);
        }
    }
}

#[test]
fn test_cow()
{
    let mut mat = Array::<int, _>::zeros((2,2));
    mat[(0, 0)] = 1;
    let n = mat.clone();
    mat[(0, 1)] = 2;
    mat[(1, 0)] = 3;
    mat[(1, 1)] = 4;
    assert_eq!(mat[(0,0)], 1);
    assert_eq!(mat[(0,1)], 2);
    assert_eq!(n[(0,0)], 1);
    assert_eq!(n[(0,1)], 0);
    let mut rev = mat.reshape(4).slice(&[Si(0, None, -1)]);
    assert_eq!(rev[0], 4);
    assert_eq!(rev[1], 3);
    assert_eq!(rev[2], 2);
    assert_eq!(rev[3], 1);
    let before = rev.clone();
    // mutation
    rev[0] = 5;
    assert_eq!(rev[0], 5);
    assert_eq!(rev[1], 3);
    assert_eq!(rev[2], 2);
    assert_eq!(rev[3], 1);
    assert_eq!(before[0], 4);
    assert_eq!(before[1], 3);
    assert_eq!(before[2], 2);
    assert_eq!(before[3], 1);
}

#[test]
fn test_sub()
{
    let mat = Array::range(0.0f32, 16.0).reshape((2, 4, 2));
    let s1 = mat.subview(0,0);
    let s2 = mat.subview(0,1);
    assert_eq!(s1.dim(), (4, 2));
    assert_eq!(s2.dim(), (4, 2));
    let n = Array::range(8.0f32, 16.0).reshape((4,2));
    assert_eq!(n, s2);
    let m = Array::from_vec(vec![2f32, 3., 10., 11.]).reshape((2, 2));
    assert_eq!(m, mat.subview(1, 1));
}

#[test]
fn diag()
{
    let d = arr2::<f32>(&[&[1., 2., 3.0f32]]).diag();
    assert_eq!(d.dim(), 1);
    let d = arr2::<f32>(&[&[1., 2., 3.0f32], &[0., 0., 0.]]).diag();
    assert_eq!(d.dim(), 2);
    let d = arr2::<f32>(&[]).diag();
    assert_eq!(d.dim(), 0);
    let d = Array::<f32, _>::zeros(()).diag();
    assert_eq!(d.dim(), 1);
}

#[test]
fn swapaxes()
{
    let mut a = arr2::<f32>(&[&[1., 2.], &[3., 4.0f32]]);
    let     b = arr2::<f32>(&[&[1., 3.], &[2., 4.0f32]]);
    assert!(a != b);
    a.swap_axes(0, 1);
    assert_eq!(a, b);
    a.swap_axes(1, 1);
    assert_eq!(a, b);
    assert!(a.raw_data() == [1., 2., 3., 4.]);
    assert!(b.raw_data() == [1., 3., 2., 4.]);
}

#[test]
fn standard_layout()
{
    let mut a = arr2::<f32>(&[&[1., 2.], &[3., 4.0]]);
    assert!(a.is_standard_layout());
    a.swap_axes(0, 1);
    assert!(!a.is_standard_layout());
    a.swap_axes(0, 1);
    assert!(a.is_standard_layout());
    let x1 = a.subview(0, 0);
    assert!(x1.is_standard_layout());
    let x2 = a.subview(1, 0);
    assert!(!x2.is_standard_layout());
}

#[test]
fn assign()
{
    let mut a = arr2::<f32>(&[&[1., 2.], &[3., 4.]]);
    let     b = arr2::<f32>(&[&[1., 3.], &[2., 4.]]);
    a.assign(&b);
    assert_eq!(a, b);

    /* Test broadcasting */
    a.assign(&Array::zeros(1));
    assert_eq!(a, Array::zeros((2, 2)));
}

#[test]
fn dyn_dimension()
{
    let a = arr2::<f32>(&[&[1., 2.], &[3., 4.0]]).reshape(vec![2, 2]);
    assert_eq!(&a - &a, Array::zeros(vec![2, 2]));

    let mut dim = Vec::from_elem(1024, 1);
    dim.as_mut_slice()[16] = 4;
    dim.as_mut_slice()[17] = 3;
    let z = Array::<f32, _>::zeros(dim.clone());
    assert_eq!(z.shape(), dim.as_slice());
}

#[test]
fn sum_mean()
{
    let a = arr2::<f32>(&[&[1., 2.], &[3., 4.]]);
    assert_eq!(a.sum(0), arr1(&[4., 6.]));
    assert_eq!(a.sum(1), arr1(&[3., 7.]));
    assert_eq!(a.mean(0), arr1(&[2., 3.]));
    assert_eq!(a.mean(1), arr1(&[1.5, 3.5]));
    assert_eq!(a.sum(1).sum(0), arr0(10.));
}

#[test]
fn iter_size_hint()
{
    let mut a = arr2::<f32>(&[&[1., 2.], &[3., 4.]]);
    {
        let mut it = a.iter();
        assert_eq!(it.size_hint(), (4, Some(4)));
        it.next();
        assert_eq!(it.size_hint().0, 3);
        it.next();
        assert_eq!(it.size_hint().0, 2);
        it.next();
        assert_eq!(it.size_hint().0, 1);
        it.next();
        assert_eq!(it.size_hint().0, 0);
        assert!(it.next().is_none());
        assert_eq!(it.size_hint().0, 0);
    }

    a.swap_axes(0, 1);
    {
        let mut it = a.iter();
        assert_eq!(it.size_hint(), (4, Some(4)));
        it.next();
        assert_eq!(it.size_hint().0, 3);
        it.next();
        assert_eq!(it.size_hint().0, 2);
        it.next();
        assert_eq!(it.size_hint().0, 1);
        it.next();
        assert_eq!(it.size_hint().0, 0);
        assert!(it.next().is_none());
        assert_eq!(it.size_hint().0, 0);
    }
}

#[test]
fn zero_axes()
{
    let a = arr1::<f32>(&[]);
    for _ in a.iter() {
        assert!(false);
    }
    println!("{}", a);
    let b = arr2::<f32>(&[&[], &[], &[], &[]]);
    println!("{}\n{}", b.shape(), b);

    // we can even get a subarray of b
    let bsub = b.subview(0, 2);
    assert_eq!(bsub.dim(), 0);
}

#[test]
fn equality()
{
    let a = arr2::<f32>(&[&[1., 2.], &[3., 4.]]);
    let mut b = arr2::<f32>(&[&[1., 2.], &[2., 4.]]);
    assert!(a != b);
    b[(1, 0)] = 3.;
    assert!(a == b);

    // make sure we can compare different shapes without failure.
    let c = arr2::<f32>(&[&[1., 2.]]);
    assert!(a != c);
}

#[test]
fn map1()
{
    let a = arr2::<f32>(&[&[1., 2.], &[3., 4.]]);
    let b = a.map(|&x| (x / 3.) as int);
    assert_eq!(b, arr2(&[&[0, 0], &[1, 1]]));
    // test map to reference with array's lifetime.
    let c = a.map(|x| x);
    assert_eq!(a[(0, 0)], *c[(0, 0)]);
}
<|endoftext|>


<commit_before>extern crate rand;
use rand::{thread_rng, Rng};

pub struct Robot {
    name: String,
}

fn generate_name() -> String {
    let mut s = String::with_capacity(5);
    static LETTERS: &'static [u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    static NUMBERS: &'static [u8] = b"0123456789";
    for _ in 0..2 {
        s.push(thread_rng().choose(LETTERS).unwrap().clone() as char);
    }
    for _ in 0..3 {
        s.push(thread_rng().choose(NUMBERS).unwrap().clone() as char);
    }
    s
}

impl Robot {
    pub fn new() -> Robot {
        Robot {
            name: generate_name(),
        }
    }

    pub fn name<'a>(&'a self) -> &'a str {
        &self.name[..]
    }

    pub fn reset_name(&mut self) {
        self.name = generate_name();
    }
}
<commit_msg>robot-name: remove unneeded lifetimes<commit_after>extern crate rand;
use rand::{thread_rng, Rng};

pub struct Robot {
    name: String,
}

fn generate_name() -> String {
    let mut s = String::with_capacity(5);
    static LETTERS: &'static [u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    static NUMBERS: &'static [u8] = b"0123456789";
    for _ in 0..2 {
        s.push(thread_rng().choose(LETTERS).unwrap().clone() as char);
    }
    for _ in 0..3 {
        s.push(thread_rng().choose(NUMBERS).unwrap().clone() as char);
    }
    s
}

impl Robot {
    pub fn new() -> Robot {
        Robot {
            name: generate_name(),
        }
    }

    pub fn name(&self) -> &str {
        &self.name[..]
    }

    pub fn reset_name(&mut self) {
        self.name = generate_name();
    }
}
<|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.

//! Exonum global variables which stored in blockchain as utf8 encoded json.

use std::collections::{BTreeMap, HashSet};

use serde::de::Error;
use serde_json::{self, Error as JsonError};

use storage::StorageValue;
use crypto::{hash, CryptoHash, PublicKey, Hash};
use helpers::{Height, Milliseconds};

/// Public keys of a validator.
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ValidatorKeys {
    /// Consensus key is used for messages related to the consensus algorithm.
    #[doc(hidden)]
    pub consensus_key: PublicKey,
    /// Service key is used for services.
    pub service_key: PublicKey,
}

/// Exonum blockchain global configuration.
/// This configuration must be same for any exonum node in the certain network on given height.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct StoredConfiguration {
    /// Link to the previous configuration.
    /// For configuration in the genesis block `hash` is just an array of zeros.
    pub previous_cfg_hash: Hash,
    /// The height, starting from which this configuration becomes actual.
    pub actual_from: Height,
    /// List of validators' consensus and service public keys.
    pub validator_keys: Vec<ValidatorKeys>,
    /// Consensus algorithm parameters.
    pub consensus: ConsensusConfig,
    /// Services specific variables.
    /// Keys are `service_name` from `Service` trait and values are the serialized json.
    pub services: BTreeMap<String, serde_json::Value>,
}

/// Consensus algorithm parameters.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct ConsensusConfig {
    /// Interval between rounds.
    pub round_timeout: Milliseconds,
    /// Period of sending a Status message.
    pub status_timeout: Milliseconds,
    /// Peer exchange timeout.
    pub peers_timeout: Milliseconds,
    /// Maximum number of transactions per block.
    pub txs_block_limit: u32,
    /// Maximum message length (in bytes).
    pub max_message_len: u32,
    /// `TimeoutAdjuster` configuration.
    pub timeout_adjuster: TimeoutAdjusterConfig,
}

impl ConsensusConfig {
    /// Default value for max_message_len.
    pub const DEFAULT_MESSAGE_MAX_LEN: u32 = 1024 * 1024; // 1 MB
}

impl Default for ConsensusConfig {
    fn default() -> Self {
        ConsensusConfig {
            round_timeout: 3000,
            status_timeout: 5000,
            peers_timeout: 10_000,
            txs_block_limit: 1000,
            max_message_len: Self::DEFAULT_MESSAGE_MAX_LEN,
            timeout_adjuster: TimeoutAdjusterConfig::Constant { timeout: 500 },
        }
    }
}

impl StoredConfiguration {
    /// Tries to serialize given configuration into the utf8 encoded json.
    pub fn try_serialize(&self) -> Result<Vec<u8>, JsonError> {
        serde_json::to_vec(&self)
    }

    /// Tries to deserialize `StorageConfiguration` from the given utf8 encoded json.
    pub fn try_deserialize(serialized: &[u8]) -> Result<StoredConfiguration, JsonError> {
        let config: StoredConfiguration = serde_json::from_slice(serialized)?;

        // Check that there are no duplicated keys.
        {
            let mut keys = HashSet::with_capacity(config.validator_keys.len() * 2);
            for k in &config.validator_keys {
                keys.insert(k.consensus_key);
                keys.insert(k.service_key);
            }
            if keys.len() != config.validator_keys.len() * 2 {
                return Err(JsonError::custom(
                    "Duplicated keys are found: each consensus and service key must be unique",
                ));
            }
        }

        // Check timeout adjuster.
        let propose_timeout = match config.consensus.timeout_adjuster {
            // There is no need to validate `Constant` timeout adjuster.
            TimeoutAdjusterConfig::Constant { timeout } => timeout,
            TimeoutAdjusterConfig::Dynamic { min, max, .. } => {
                if min >= max {
                    return Err(JsonError::custom(format!(
                        "Dynamic adjuster: minimal timeout should be less then maximal: \
                        min = {}, max = {}",
                        min,
                        max
                    )));
                }
                max
            }
            TimeoutAdjusterConfig::MovingAverage {
                min,
                max,
                adjustment_speed,
                optimal_block_load,
            } => {
                if min >= max {
                    return Err(JsonError::custom(format!(
                        "Moving average adjuster: minimal timeout must be less then maximal: \
                        min = {}, max = {}",
                        min,
                        max
                    )));
                }
                if adjustment_speed <= 0. || adjustment_speed > 1. {
                    return Err(JsonError::custom(format!(
                        "Moving average adjuster: adjustment speed must be in the (0..1] range: {}",
                        adjustment_speed,
                    )));
                }
                if optimal_block_load <= 0. || optimal_block_load > 1. {
                    return Err(JsonError::custom(format!(
                        "Moving average adjuster: block load must be in the (0..1] range: {}",
                        adjustment_speed,
                    )));
                }
                max
            }
        };

        if config.consensus.round_timeout <= propose_timeout {
            return Err(JsonError::custom(format!(
                "consensus.round_timeout({}) must be strictly larger than \
                consensus.timeout_adjuster.timeout({})",
                config.consensus.round_timeout,
                propose_timeout
            )));
        }

        if config.consensus.round_timeout <= 2 * propose_timeout {
            warn!(
                "It is recommended that consensus.round_timeout({})  \
                be at least twice as large as consensus.timeout_adjuster.timeout({})",
                config.consensus.round_timeout,
                propose_timeout
            );
        }

        Ok(config)
    }
}

impl CryptoHash for StoredConfiguration {
    fn hash(&self) -> Hash {
        let vec_bytes = self.try_serialize().unwrap();
        hash(&vec_bytes)
    }
}

impl StorageValue for StoredConfiguration {
    fn into_bytes(self) -> Vec<u8> {
        self.try_serialize().unwrap()
    }

    fn from_bytes(v: ::std::borrow::Cow<[u8]>) -> Self {
        StoredConfiguration::try_deserialize(v.as_ref()).unwrap()
    }
}

/// `TimeoutAdjuster` config.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[serde(tag = "type")]
pub enum TimeoutAdjusterConfig {
    /// Constant timeout adjuster config.
    Constant {
        /// Timeout value.
        timeout: Milliseconds,
    },
    /// Dynamic timeout adjuster configuration.
    Dynamic {
        /// Minimal timeout.
        min: Milliseconds,
        /// Maximal timeout.
        max: Milliseconds,
        /// Transactions threshold starting from which the adjuster returns the minimal timeout.
        threshold: u32,
    },
    /// Moving average timeout adjuster configuration.
    MovingAverage {
        /// Minimal timeout.
        min: Milliseconds,
        /// Maximal timeout.
        max: Milliseconds,
        /// Speed of the adjustment.
        adjustment_speed: f64,
        /// Optimal block load depending on the `txs_block_limit` from the `ConsensusConfig`.
        optimal_block_load: f64,
    },
}

#[cfg(test)]
mod tests {
    use toml;
    use serde::{Serialize, Deserialize};

    use std::fmt::Debug;

    use crypto::{Seed, gen_keypair_from_seed};
    use super::*;

    // TOML doesn't support all rust types, but `StoredConfiguration` must be able to save as TOML.
    #[test]
    fn stored_configuration_toml() {
        let original = create_test_configuration();
        let toml = toml::to_string(&original).unwrap();
        let deserialized: StoredConfiguration = toml::from_str(&toml).unwrap();
        assert_eq!(original, deserialized);
    }

    #[test]
    fn stored_configuration_serialize_deserialize() {
        let configuration = create_test_configuration();
        assert_eq!(configuration, serialize_deserialize(&configuration));
    }

    #[test]
    #[should_panic(expected = "Duplicated keys are found")]
    fn stored_configuration_duplicated_keys() {
        let mut configuration = create_test_configuration();
        configuration.validator_keys.push(ValidatorKeys {
            consensus_key: PublicKey::zero(),
            service_key: PublicKey::zero(),
        });
        serialize_deserialize(&configuration);
    }

    #[test]
    fn constant_adjuster_config_toml() {
        let config = TimeoutAdjusterConfig::Constant { timeout: 500 };
        check_toml_roundtrip(&config);
    }

    #[test]
    fn dynamic_adjuster_config_toml() {
        let config = TimeoutAdjusterConfig::Dynamic {
            min: 1,
            max: 1000,
            threshold: 10,
        };
        check_toml_roundtrip(&config);
    }

    #[test]
    fn moving_average_adjuster_config_toml() {
        let config = TimeoutAdjusterConfig::MovingAverage {
            min: 1,
            max: 1000,
            adjustment_speed: 0.5,
            optimal_block_load: 0.75,
        };
        check_toml_roundtrip(&config);
    }

    #[test]
    #[should_panic(expected = "Dynamic adjuster: minimal timeout should be less then maximal")]
    fn dynamic_adjuster_min_max() {
        let mut configuration = create_test_configuration();
        configuration.consensus.timeout_adjuster = TimeoutAdjusterConfig::Dynamic {
            min: 10,
            max: 0,
            threshold: 1,
        };
        serialize_deserialize(&configuration);
    }

    #[test]
    #[should_panic(expected = "Moving average adjuster: minimal timeout must be less then maximal")]
    fn moving_average_adjuster_min_max() {
        let mut configuration = create_test_configuration();
        configuration.consensus.timeout_adjuster = TimeoutAdjusterConfig::MovingAverage {
            min: 10,
            max: 0,
            adjustment_speed: 0.7,
            optimal_block_load: 0.5,
        };
        serialize_deserialize(&configuration);
    }

    // TODO: Remove `#[rustfmt_skip]` after https://github.com/rust-lang-nursery/rustfmt/issues/1777
    // is fixed.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    #[test]
    #[should_panic(expected = "Moving average adjuster: adjustment speed must be in the (0..1]")]
    fn moving_average_adjuster_negative_adjustment_speed() {
        let mut configuration = create_test_configuration();
        configuration.consensus.timeout_adjuster = TimeoutAdjusterConfig::MovingAverage {
            min: 1,
            max: 20,
            adjustment_speed: -0.7,
            optimal_block_load: 0.5,
        };
        serialize_deserialize(&configuration);
    }

    // TODO: Remove `#[rustfmt_skip]` after https://github.com/rust-lang-nursery/rustfmt/issues/1777
    // is fixed.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    #[test]
    #[should_panic(expected = "Moving average adjuster: adjustment speed must be in the (0..1]")]
    fn moving_average_adjuster_invalid_adjustment_speed() {
        let mut configuration = create_test_configuration();
        configuration.consensus.timeout_adjuster = TimeoutAdjusterConfig::MovingAverage {
            min: 10,
            max: 20,
            adjustment_speed: 1.5,
            optimal_block_load: 0.5,
        };
        serialize_deserialize(&configuration);
    }

    // TODO: Remove `#[rustfmt_skip]` after https://github.com/rust-lang-nursery/rustfmt/issues/1777
    // is fixed.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    #[test]
    #[should_panic(expected = "Moving average adjuster: block load must be in the (0..1] range")]
    fn moving_average_adjuster_negative_block_load() {
        let mut configuration = create_test_configuration();
        configuration.consensus.timeout_adjuster = TimeoutAdjusterConfig::MovingAverage {
            min: 10,
            max: 20,
            adjustment_speed: 0.7,
            optimal_block_load: -0.5,
        };
        serialize_deserialize(&configuration);
    }

    // TODO: Remove `#[rustfmt_skip]` after https://github.com/rust-lang-nursery/rustfmt/issues/1777
    // is fixed.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    #[test]
    #[should_panic(expected = "Moving average adjuster: block load must be in the (0..1] range")]
    fn moving_average_adjuster_invalid_block_load() {
        let mut configuration = create_test_configuration();
        configuration.consensus.timeout_adjuster = TimeoutAdjusterConfig::MovingAverage {
            min: 10,
            max: 20,
            adjustment_speed: 0.7,
            optimal_block_load: 2.0,
        };
        serialize_deserialize(&configuration);
    }

    fn create_test_configuration() -> StoredConfiguration {
        let validator_keys = (1..4)
            .map(|i| {
                ValidatorKeys {
                    consensus_key: gen_keypair_from_seed(&Seed::new([i; 32])).0,
                    service_key: gen_keypair_from_seed(&Seed::new([i * 10; 32])).0,
                }
            })
            .collect();

        StoredConfiguration {
            previous_cfg_hash: Hash::zero(),
            actual_from: Height(42),
            validator_keys,
            consensus: ConsensusConfig::default(),
            services: BTreeMap::new(),
        }
    }

    fn serialize_deserialize(configuration: &StoredConfiguration) -> StoredConfiguration {
        let serialized = configuration.try_serialize().unwrap();
        StoredConfiguration::try_deserialize(&serialized).unwrap()
    }

    fn check_toml_roundtrip<T>(original: &T)
    where
        for<'de> T: Serialize + Deserialize<'de> + PartialEq + Debug,
    {
        let toml = toml::to_string(original).unwrap();
        let deserialized: T = toml::from_str(&toml).unwrap();
        assert_eq!(*original, deserialized);
    }
}
<commit_msg>Add tests<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.

//! Exonum global variables which stored in blockchain as utf8 encoded json.

use std::collections::{BTreeMap, HashSet};

use serde::de::Error;
use serde_json::{self, Error as JsonError};

use storage::StorageValue;
use crypto::{hash, CryptoHash, PublicKey, Hash};
use helpers::{Height, Milliseconds};

/// Public keys of a validator.
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ValidatorKeys {
    /// Consensus key is used for messages related to the consensus algorithm.
    #[doc(hidden)]
    pub consensus_key: PublicKey,
    /// Service key is used for services.
    pub service_key: PublicKey,
}

/// Exonum blockchain global configuration.
/// This configuration must be same for any exonum node in the certain network on given height.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct StoredConfiguration {
    /// Link to the previous configuration.
    /// For configuration in the genesis block `hash` is just an array of zeros.
    pub previous_cfg_hash: Hash,
    /// The height, starting from which this configuration becomes actual.
    pub actual_from: Height,
    /// List of validators' consensus and service public keys.
    pub validator_keys: Vec<ValidatorKeys>,
    /// Consensus algorithm parameters.
    pub consensus: ConsensusConfig,
    /// Services specific variables.
    /// Keys are `service_name` from `Service` trait and values are the serialized json.
    pub services: BTreeMap<String, serde_json::Value>,
}

/// Consensus algorithm parameters.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct ConsensusConfig {
    /// Interval between rounds.
    pub round_timeout: Milliseconds,
    /// Period of sending a Status message.
    pub status_timeout: Milliseconds,
    /// Peer exchange timeout.
    pub peers_timeout: Milliseconds,
    /// Maximum number of transactions per block.
    pub txs_block_limit: u32,
    /// Maximum message length (in bytes).
    pub max_message_len: u32,
    /// `TimeoutAdjuster` configuration.
    pub timeout_adjuster: TimeoutAdjusterConfig,
}

impl ConsensusConfig {
    /// Default value for max_message_len.
    pub const DEFAULT_MESSAGE_MAX_LEN: u32 = 1024 * 1024; // 1 MB
}

impl Default for ConsensusConfig {
    fn default() -> Self {
        ConsensusConfig {
            round_timeout: 3000,
            status_timeout: 5000,
            peers_timeout: 10_000,
            txs_block_limit: 1000,
            max_message_len: Self::DEFAULT_MESSAGE_MAX_LEN,
            timeout_adjuster: TimeoutAdjusterConfig::Constant { timeout: 500 },
        }
    }
}

impl StoredConfiguration {
    /// Tries to serialize given configuration into the utf8 encoded json.
    pub fn try_serialize(&self) -> Result<Vec<u8>, JsonError> {
        serde_json::to_vec(&self)
    }

    /// Tries to deserialize `StorageConfiguration` from the given utf8 encoded json.
    pub fn try_deserialize(serialized: &[u8]) -> Result<StoredConfiguration, JsonError> {
        let config: StoredConfiguration = serde_json::from_slice(serialized)?;

        // Check that there are no duplicated keys.
        {
            let mut keys = HashSet::with_capacity(config.validator_keys.len() * 2);
            for k in &config.validator_keys {
                keys.insert(k.consensus_key);
                keys.insert(k.service_key);
            }
            if keys.len() != config.validator_keys.len() * 2 {
                return Err(JsonError::custom(
                    "Duplicated keys are found: each consensus and service key must be unique",
                ));
            }
        }

        // Check timeout adjuster.
        let propose_timeout = match config.consensus.timeout_adjuster {
            // There is no need to validate `Constant` timeout adjuster.
            TimeoutAdjusterConfig::Constant { timeout } => timeout,
            TimeoutAdjusterConfig::Dynamic { min, max, .. } => {
                if min >= max {
                    return Err(JsonError::custom(format!(
                        "Dynamic adjuster: minimal timeout should be less then maximal: \
                        min = {}, max = {}",
                        min,
                        max
                    )));
                }
                max
            }
            TimeoutAdjusterConfig::MovingAverage {
                min,
                max,
                adjustment_speed,
                optimal_block_load,
            } => {
                if min >= max {
                    return Err(JsonError::custom(format!(
                        "Moving average adjuster: minimal timeout must be less then maximal: \
                        min = {}, max = {}",
                        min,
                        max
                    )));
                }
                if adjustment_speed <= 0. || adjustment_speed > 1. {
                    return Err(JsonError::custom(format!(
                        "Moving average adjuster: adjustment speed must be in the (0..1] range: {}",
                        adjustment_speed,
                    )));
                }
                if optimal_block_load <= 0. || optimal_block_load > 1. {
                    return Err(JsonError::custom(format!(
                        "Moving average adjuster: block load must be in the (0..1] range: {}",
                        adjustment_speed,
                    )));
                }
                max
            }
        };

        if config.consensus.round_timeout <= propose_timeout {
            return Err(JsonError::custom(format!(
                "round_timeout({}) must be strictly larger than propose_timeout({})",
                config.consensus.round_timeout,
                propose_timeout
            )));
        }

        if config.consensus.round_timeout <= 2 * propose_timeout {
            warn!(
                "It is recommended that round_timeout({}) be at least twice as large \
                as propose_timeout({})",
                config.consensus.round_timeout,
                propose_timeout
            );
        }

        Ok(config)
    }
}

impl CryptoHash for StoredConfiguration {
    fn hash(&self) -> Hash {
        let vec_bytes = self.try_serialize().unwrap();
        hash(&vec_bytes)
    }
}

impl StorageValue for StoredConfiguration {
    fn into_bytes(self) -> Vec<u8> {
        self.try_serialize().unwrap()
    }

    fn from_bytes(v: ::std::borrow::Cow<[u8]>) -> Self {
        StoredConfiguration::try_deserialize(v.as_ref()).unwrap()
    }
}

/// `TimeoutAdjuster` config.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[serde(tag = "type")]
pub enum TimeoutAdjusterConfig {
    /// Constant timeout adjuster config.
    Constant {
        /// Timeout value.
        timeout: Milliseconds,
    },
    /// Dynamic timeout adjuster configuration.
    Dynamic {
        /// Minimal timeout.
        min: Milliseconds,
        /// Maximal timeout.
        max: Milliseconds,
        /// Transactions threshold starting from which the adjuster returns the minimal timeout.
        threshold: u32,
    },
    /// Moving average timeout adjuster configuration.
    MovingAverage {
        /// Minimal timeout.
        min: Milliseconds,
        /// Maximal timeout.
        max: Milliseconds,
        /// Speed of the adjustment.
        adjustment_speed: f64,
        /// Optimal block load depending on the `txs_block_limit` from the `ConsensusConfig`.
        optimal_block_load: f64,
    },
}

#[cfg(test)]
mod tests {
    use toml;
    use serde::{Serialize, Deserialize};

    use std::fmt::Debug;

    use crypto::{Seed, gen_keypair_from_seed};
    use super::*;

    // TOML doesn't support all rust types, but `StoredConfiguration` must be able to save as TOML.
    #[test]
    fn stored_configuration_toml() {
        let original = create_test_configuration();
        let toml = toml::to_string(&original).unwrap();
        let deserialized: StoredConfiguration = toml::from_str(&toml).unwrap();
        assert_eq!(original, deserialized);
    }

    #[test]
    fn stored_configuration_serialize_deserialize() {
        let configuration = create_test_configuration();
        assert_eq!(configuration, serialize_deserialize(&configuration));
    }

    #[test]
    #[should_panic(expected = "Duplicated keys are found")]
    fn stored_configuration_duplicated_keys() {
        let mut configuration = create_test_configuration();
        configuration.validator_keys.push(ValidatorKeys {
            consensus_key: PublicKey::zero(),
            service_key: PublicKey::zero(),
        });
        serialize_deserialize(&configuration);
    }

    #[test]
    fn constant_adjuster_config_toml() {
        let config = TimeoutAdjusterConfig::Constant { timeout: 500 };
        check_toml_roundtrip(&config);
    }

    #[test]
    fn dynamic_adjuster_config_toml() {
        let config = TimeoutAdjusterConfig::Dynamic {
            min: 1,
            max: 1000,
            threshold: 10,
        };
        check_toml_roundtrip(&config);
    }

    #[test]
    fn moving_average_adjuster_config_toml() {
        let config = TimeoutAdjusterConfig::MovingAverage {
            min: 1,
            max: 1000,
            adjustment_speed: 0.5,
            optimal_block_load: 0.75,
        };
        check_toml_roundtrip(&config);
    }

    #[test]
    #[should_panic(expected = "Dynamic adjuster: minimal timeout should be less then maximal")]
    fn dynamic_adjuster_min_max() {
        let mut configuration = create_test_configuration();
        configuration.consensus.timeout_adjuster = TimeoutAdjusterConfig::Dynamic {
            min: 10,
            max: 0,
            threshold: 1,
        };
        serialize_deserialize(&configuration);
    }

    #[test]
    #[should_panic(expected = "Moving average adjuster: minimal timeout must be less then maximal")]
    fn moving_average_adjuster_min_max() {
        let mut configuration = create_test_configuration();
        configuration.consensus.timeout_adjuster = TimeoutAdjusterConfig::MovingAverage {
            min: 10,
            max: 0,
            adjustment_speed: 0.7,
            optimal_block_load: 0.5,
        };
        serialize_deserialize(&configuration);
    }

    // TODO: Remove `#[rustfmt_skip]` after https://github.com/rust-lang-nursery/rustfmt/issues/1777
    // is fixed.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    #[test]
    #[should_panic(expected = "Moving average adjuster: adjustment speed must be in the (0..1]")]
    fn moving_average_adjuster_negative_adjustment_speed() {
        let mut configuration = create_test_configuration();
        configuration.consensus.timeout_adjuster = TimeoutAdjusterConfig::MovingAverage {
            min: 1,
            max: 20,
            adjustment_speed: -0.7,
            optimal_block_load: 0.5,
        };
        serialize_deserialize(&configuration);
    }

    // TODO: Remove `#[rustfmt_skip]` after https://github.com/rust-lang-nursery/rustfmt/issues/1777
    // is fixed.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    #[test]
    #[should_panic(expected = "Moving average adjuster: adjustment speed must be in the (0..1]")]
    fn moving_average_adjuster_invalid_adjustment_speed() {
        let mut configuration = create_test_configuration();
        configuration.consensus.timeout_adjuster = TimeoutAdjusterConfig::MovingAverage {
            min: 10,
            max: 20,
            adjustment_speed: 1.5,
            optimal_block_load: 0.5,
        };
        serialize_deserialize(&configuration);
    }

    // TODO: Remove `#[rustfmt_skip]` after https://github.com/rust-lang-nursery/rustfmt/issues/1777
    // is fixed.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    #[test]
    #[should_panic(expected = "Moving average adjuster: block load must be in the (0..1] range")]
    fn moving_average_adjuster_negative_block_load() {
        let mut configuration = create_test_configuration();
        configuration.consensus.timeout_adjuster = TimeoutAdjusterConfig::MovingAverage {
            min: 10,
            max: 20,
            adjustment_speed: 0.7,
            optimal_block_load: -0.5,
        };
        serialize_deserialize(&configuration);
    }

    // TODO: Remove `#[rustfmt_skip]` after https://github.com/rust-lang-nursery/rustfmt/issues/1777
    // is fixed.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    #[test]
    #[should_panic(expected = "Moving average adjuster: block load must be in the (0..1] range")]
    fn moving_average_adjuster_invalid_block_load() {
        let mut configuration = create_test_configuration();
        configuration.consensus.timeout_adjuster = TimeoutAdjusterConfig::MovingAverage {
            min: 10,
            max: 20,
            adjustment_speed: 0.7,
            optimal_block_load: 2.0,
        };
        serialize_deserialize(&configuration);
    }

    #[test]
    #[should_panic(expected = "round_timeout(50) must be strictly larger than propose_timeout(50)")]
    fn constant_adjuster_invalid_timeout() {
        let mut configuration = create_test_configuration();
        configuration.consensus.round_timeout = 50;
        configuration.consensus.timeout_adjuster = TimeoutAdjusterConfig::Constant { timeout: 50 };
        serialize_deserialize(&configuration);
    }

    #[test]
    #[should_panic(expected = "round_timeout(50) must be strictly larger than propose_timeout(50)")]
    fn dynamic_adjuster_invalid_timeout() {
        let mut configuration = create_test_configuration();
        configuration.consensus.round_timeout = 50;
        configuration.consensus.timeout_adjuster = TimeoutAdjusterConfig::Dynamic {
            min: 10,
            max: 50,
            threshold: 1,
        };
        serialize_deserialize(&configuration);
    }

    #[test]
    #[should_panic(expected = "round_timeout(50) must be strictly larger than propose_timeout(50)")]
    fn moving_average_adjuster_invalid_timeout() {
        let mut configuration = create_test_configuration();
        configuration.consensus.round_timeout = 50;
        configuration.consensus.timeout_adjuster = TimeoutAdjusterConfig::MovingAverage {
            min: 10,
            max: 50,
            adjustment_speed: 0.7,
            optimal_block_load: 0.2,
        };
        serialize_deserialize(&configuration);
    }

    fn create_test_configuration() -> StoredConfiguration {
        let validator_keys = (1..4)
            .map(|i| {
                ValidatorKeys {
                    consensus_key: gen_keypair_from_seed(&Seed::new([i; 32])).0,
                    service_key: gen_keypair_from_seed(&Seed::new([i * 10; 32])).0,
                }
            })
            .collect();

        StoredConfiguration {
            previous_cfg_hash: Hash::zero(),
            actual_from: Height(42),
            validator_keys,
            consensus: ConsensusConfig::default(),
            services: BTreeMap::new(),
        }
    }

    fn serialize_deserialize(configuration: &StoredConfiguration) -> StoredConfiguration {
        let serialized = configuration.try_serialize().unwrap();
        StoredConfiguration::try_deserialize(&serialized).unwrap()
    }

    fn check_toml_roundtrip<T>(original: &T)
    where
        for<'de> T: Serialize + Deserialize<'de> + PartialEq + Debug,
    {
        let toml = toml::to_string(original).unwrap();
        let deserialized: T = toml::from_str(&toml).unwrap();
        assert_eq!(*original, deserialized);
    }
}
<|endoftext|>