<commit_before>// This module defines constants and functions for working with zakocmp
// configuration files.

use std::io::{Error, ErrorKind};
use std::result::Result;

// Enumerates the string representations of known policies.
const POLICY_REPR_IGNORE: &str = "ignore";
const POLICY_REPR_NOADD: &str = "noadd";
const POLICY_REPR_NODELETE: &str = "nodelete";
const POLICY_REPR_NOMODIFY: &str = "nomodify";
const POLICY_REPR_IMMUTABLE: &str = "immutable";

// Represents known policies as integers.
pub const POLICY_IGNORE: i32 = 0;
pub const POLICY_NOADD: i32 = 1 << 0;
pub const POLICY_NODELETE: i32 = 1 << 1;
pub const POLICY_NOMODIFY: i32 = 1 << 2;
pub const POLICY_IMMUTABLE: i32 = POLICY_NOADD | POLICY_NODELETE | POLICY_NOMODIFY;

// Borrows the string representation of one policy `token` and returns
// the equivalent integral representation.
fn policy_token_as_int(token: &str) -> Result<i32, Error> {
    match token {
        POLICY_REPR_IGNORE => Ok(POLICY_IGNORE),
        POLICY_REPR_NOADD => Ok(POLICY_NOADD),
        POLICY_REPR_NODELETE => Ok(POLICY_NODELETE),
        POLICY_REPR_NOMODIFY => Ok(POLICY_NOMODIFY),
        POLICY_REPR_IMMUTABLE => Ok(POLICY_IMMUTABLE),
        _ => Err(Error::new(
            ErrorKind::InvalidInput,
            format!("bad token: ``{}''", token),
        )),
    }
}

/// Borrows the string representation of a combined `policy` and returns
/// the equivalent integral representation. This function expects
/// `policy` to comprise one or more policy tokens separated by commas.
///
/// # Examples
///
/// ```
/// # mod zakocmp;
/// let policy: i32 = config::policy_repr_as_int(&"immutable").unwrap();
/// assert!(policy == config::POLICY_IMMUTABLE);
/// ```
///
/// ```
/// # mod zakocmp;
/// // Multiple policies are bitwise OR'd together.
/// let policy: i32 = config::policy_repr_as_int(
///     &"noadd,nomodify").unwrap();
/// assert!(policy == config::POLICY_NOADD | config::POLICY_NOMODIFY);
/// ```
///
/// ```
/// # mod zakocmp;
/// // The biggest bitwise OR equals POLICY_IMMUTABLE.
/// let policy: i32 = config::policy_repr_as_int(
///     &"noadd,nodelete,nomodify").unwrap();
/// assert!(policy == config::POLICY_IMMUTABLE);
/// ```
///
/// # Failures
///
/// ```
/// # mod zakocmp;
/// // Obi-wan was witty, but not good at dictating zakocmp policy.
/// assert!(!config::policy_repr_as_int(&"hello there!").is_ok());
/// ```
///
pub fn policy_repr_as_int(policy: &str) -> Result<i32, Error> {
    let mut policy_int: i32 = POLICY_IGNORE;
    for token in policy.split(",") {
        policy_int |= policy_token_as_int(token)?;
    }
    return Ok(policy_int);
}

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

    #[test]
    fn test_bare_noadd() {
        let policy: i32 = match policy_repr_as_int(&"noadd") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NOADD);
    }

    #[test]
    fn test_bare_nodelete() {
        let policy: i32 = match policy_repr_as_int(&"nodelete") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NODELETE);
    }

    #[test]
    fn test_bare_nomodify() {
        let policy: i32 = match policy_repr_as_int(&"nomodify") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NOMODIFY);
    }

    #[test]
    fn test_combo_policy() {
        let policy: i32 = match policy_repr_as_int(&"noadd,nodelete") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NOADD | POLICY_NODELETE);
    }

    #[test]
    fn test_repetitive_policy() {
        let policy: i32 =
            match policy_repr_as_int(&"noadd,noadd,noadd,noadd,nodelete,nodelete,nodelete,noadd") {
                Ok(value) => value,
                Err(oof) => panic!(oof),
            };
        assert!(policy == POLICY_NOADD | POLICY_NODELETE);
    }
}
<commit_msg>zakocmp: refactor policy tokenizer<commit_after>// This module defines constants and functions for working with zakocmp
// configuration files.

use std::io::{Error, ErrorKind};
use std::result::Result;
use std::vec::Vec;

// Enumerates the string representations of known policies.
const POLICY_REPR_IGNORE: &str = "ignore";
const POLICY_REPR_NOADD: &str = "noadd";
const POLICY_REPR_NODELETE: &str = "nodelete";
const POLICY_REPR_NOMODIFY: &str = "nomodify";
const POLICY_REPR_IMMUTABLE: &str = "immutable";

// Represents known policies as integers.
pub const POLICY_IGNORE: i32 = 0;
pub const POLICY_NOADD: i32 = 1 << 0;
pub const POLICY_NODELETE: i32 = 1 << 1;
pub const POLICY_NOMODIFY: i32 = 1 << 2;
pub const POLICY_IMMUTABLE: i32 = POLICY_NOADD | POLICY_NODELETE | POLICY_NOMODIFY;

// Borrows the string representation of one policy `token` and returns
// the equivalent integral representation.
fn policy_token_as_int(token: &str) -> Result<i32, Error> {
    match token {
        POLICY_REPR_IGNORE => Ok(POLICY_IGNORE),
        POLICY_REPR_NOADD => Ok(POLICY_NOADD),
        POLICY_REPR_NODELETE => Ok(POLICY_NODELETE),
        POLICY_REPR_NOMODIFY => Ok(POLICY_NOMODIFY),
        POLICY_REPR_IMMUTABLE => Ok(POLICY_IMMUTABLE),
        _ => Err(Error::new(
            ErrorKind::InvalidInput,
            format!("bad token: ``{}''", token),
        )),
    }
}

/// Borrows the string representation of a combined `policy` and returns
/// the equivalent integral representation. This function expects
/// `policy` to comprise one or more policy tokens separated by commas.
///
/// # Examples
///
/// ```
/// # mod zakocmp;
/// let policy: i32 = config::policy_repr_as_int(&"immutable").unwrap();
/// assert!(policy == config::POLICY_IMMUTABLE);
/// ```
///
/// ```
/// # mod zakocmp;
/// // Multiple policies are bitwise OR'd together.
/// let policy: i32 = config::policy_repr_as_int(
///     &"noadd,nomodify").unwrap();
/// assert!(policy == config::POLICY_NOADD | config::POLICY_NOMODIFY);
/// ```
///
/// ```
/// # mod zakocmp;
/// // The biggest bitwise OR equals POLICY_IMMUTABLE.
/// let policy: i32 = config::policy_repr_as_int(
///     &"noadd,nodelete,nomodify").unwrap();
/// assert!(policy == config::POLICY_IMMUTABLE);
/// ```
///
/// # Failures
///
/// ```
/// # mod zakocmp;
/// // Obi-wan was witty, but not good at dictating zakocmp policy.
/// assert!(!config::policy_repr_as_int(&"hello there!").is_ok());
/// ```
///
pub fn policy_repr_as_int(policy: &str) -> Result<i32, Error> {
    let policy_ints: Vec<i32> = policy
        .split(",")
        .map(|tok| policy_token_as_int(tok))
        .collect::<Result<Vec<i32>, Error>>()?;
    return Ok(policy_ints
        .iter()
        .fold(POLICY_IGNORE, |accum, elem| accum | elem));
}

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

    #[test]
    fn test_bare_noadd() {
        let policy: i32 = match policy_repr_as_int(&"noadd") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NOADD);
    }

    #[test]
    fn test_bare_nodelete() {
        let policy: i32 = match policy_repr_as_int(&"nodelete") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NODELETE);
    }

    #[test]
    fn test_bare_nomodify() {
        let policy: i32 = match policy_repr_as_int(&"nomodify") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NOMODIFY);
    }

    #[test]
    fn test_combo_policy() {
        let policy: i32 = match policy_repr_as_int(&"noadd,nodelete") {
            Ok(value) => value,
            Err(oof) => panic!(oof),
        };
        assert!(policy == POLICY_NOADD | POLICY_NODELETE);
    }

    #[test]
    fn test_repetitive_policy() {
        let policy: i32 =
            match policy_repr_as_int(&"noadd,noadd,noadd,noadd,nodelete,nodelete,nodelete,noadd") {
                Ok(value) => value,
                Err(oof) => panic!(oof),
            };
        assert!(policy == POLICY_NOADD | POLICY_NODELETE);
    }
}
<|endoftext|>


<commit_before>use crate::{channels::Channels, Result};
use parking_lot::Mutex;
use std::{
    fmt,
    sync::Arc,
    time::{Duration, Instant},
};

#[derive(Clone)]
pub struct Heartbeat {
    channels: Channels,
    inner: Arc<Mutex<Inner>>,
}

impl Heartbeat {
    pub(crate) fn new(channels: Channels) -> Self {
        let inner = Default::default();
        Self { channels, inner }
    }

    pub(crate) fn set_timeout(&self, timeout: Duration) {
        self.inner.lock().timeout = Some(timeout);
    }

    pub fn get_heartbeat(&self) -> Option<Duration> {
        self.inner.lock().timeout
    }

    pub fn poll_timeout(&self) -> Result<Option<Duration>> {
        self.inner.lock().poll_timeout(&self.channels)
    }

    pub fn send(&self) -> Result<()> {
        self.channels.send_heartbeat()
    }

    pub(crate) fn update_last_write(&self) {
        self.inner.lock().update_last_write();
    }

    pub(crate) fn cancel(&self) {
        self.inner.lock().timeout = None;
    }
}

impl fmt::Debug for Heartbeat {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Heartbeat").finish()
    }
}

struct Inner {
    last_write: Instant,
    timeout: Option<Duration>,
}

impl Default for Inner {
    fn default() -> Self {
        Self {
            last_write: Instant::now(),
            timeout: None,
        }
    }
}

impl Inner {
    fn poll_timeout(&mut self, channels: &Channels) -> Result<Option<Duration>> {
        self.timeout
            .map(|timeout| {
                timeout
                    .checked_sub(self.last_write.elapsed())
                    .map(Ok)
                    .unwrap_or_else(|| {
                        // Update last_write so that if we cannot write to the socket yet, we don't enqueue countless heartbeats
                        self.update_last_write();
                        channels.send_heartbeat()?;
                        Ok(timeout)
                    })
            })
            .transpose()
    }

    fn update_last_write(&mut self) {
        self.last_write = Instant::now();
    }
}
<commit_msg>heartbeat: always sleep at least 1ms<commit_after>use crate::{channels::Channels, Result};
use parking_lot::Mutex;
use std::{
    fmt,
    sync::Arc,
    time::{Duration, Instant},
};

#[derive(Clone)]
pub struct Heartbeat {
    channels: Channels,
    inner: Arc<Mutex<Inner>>,
}

impl Heartbeat {
    pub(crate) fn new(channels: Channels) -> Self {
        let inner = Default::default();
        Self { channels, inner }
    }

    pub(crate) fn set_timeout(&self, timeout: Duration) {
        self.inner.lock().timeout = Some(timeout);
    }

    pub fn get_heartbeat(&self) -> Option<Duration> {
        self.inner.lock().timeout
    }

    pub fn poll_timeout(&self) -> Result<Option<Duration>> {
        self.inner.lock().poll_timeout(&self.channels)
    }

    pub fn send(&self) -> Result<()> {
        self.channels.send_heartbeat()
    }

    pub(crate) fn update_last_write(&self) {
        self.inner.lock().update_last_write();
    }

    pub(crate) fn cancel(&self) {
        self.inner.lock().timeout = None;
    }
}

impl fmt::Debug for Heartbeat {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Heartbeat").finish()
    }
}

struct Inner {
    last_write: Instant,
    timeout: Option<Duration>,
}

impl Default for Inner {
    fn default() -> Self {
        Self {
            last_write: Instant::now(),
            timeout: None,
        }
    }
}

impl Inner {
    fn poll_timeout(&mut self, channels: &Channels) -> Result<Option<Duration>> {
        self.timeout
            .map(|timeout| {
                timeout
                    .checked_sub(self.last_write.elapsed())
                    .map(|timeout| timeout.max(Duration::from_millis(1)))
                    .map(Ok)
                    .unwrap_or_else(|| {
                        // Update last_write so that if we cannot write to the socket yet, we don't enqueue countless heartbeats
                        self.update_last_write();
                        channels.send_heartbeat()?;
                        Ok(timeout)
                    })
            })
            .transpose()
    }

    fn update_last_write(&mut self) {
        self.last_write = Instant::now();
    }
}
<|endoftext|>


<commit_before>use std::{io, mem};
use std::net::IpAddr;
use std::str::FromStr;
use domain::bits::DNameBuf;
use futures::{Async, Future, Poll};
use tokio_core::reactor;

//============ Low-level API =================================================

pub mod dns;
pub mod files;

//============ High-level API ================================================

pub fn get_host_by_name(name: &str) -> Result<Option<HostEnt>, io::Error> {
    let mut core = reactor::Core::new()?;
    let handle = core.handle();
    core.run(poll_host_by_name(name, &handle))
}

pub fn get_host_by_addr(addr: IpAddr) -> Result<Option<HostEnt>, io::Error> {
    let mut core = reactor::Core::new()?;
    let handle = core.handle();
    core.run(poll_host_by_addr(addr, &handle))
}

/// Returns host information for a given host name.
///
/// The name is either a hostname, an IPv4 or IPv6 address in its standard
/// text notation. In the latter two cases, no lookups are performed and a
/// `HostEnt` is returned with `name` as the canonical name, the parsed
/// address as the sole address, and no aliases.
///
/// Otherwise the name is interpreted as a host name and lookups according to
/// the system configuraition are performed.
///
/// The function returns a future that performes all necessary IO via the
/// tokio reactor given by `reactor`.
///
/// # Limitations
///
/// For this initial version of the crate, the lookup is a `files` lookup
/// first and only if that does not succeed, a DNS query for both A and AAAA
/// records. This initial version also does not yet fill the aliases list of
/// the returned `HostEnt`.
pub fn poll_host_by_name(name: &str, reactor: &reactor::Handle)
                         -> HostByName {
    HostByName::new(name, reactor)
}

pub fn poll_host_by_addr(addr: IpAddr, reactor: &reactor::Handle)
                         -> HostByAddr {
    unimplemented!()
}

//------------ HostEnt -------------------------------------------------------

pub struct HostEnt {
    pub name: String,
    pub aliases: Vec<String>,
    pub addrs: Vec<IpAddr>,
}

//------------ HostByName ----------------------------------------------------

pub struct HostByName(ByNameInner);

enum ByNameInner {
    Files(HostEnt),
    Dns(dns::HostByName),
    Error(io::Error),
    Done,
}

impl HostByName {
    pub fn new(name: &str, reactor: &reactor::Handle) -> Self {
        let name = match DNameBuf::from_str(name) {
            Ok(name) => name,
            Err(e) => {
                return HostByName(ByNameInner::Error(
                    io::Error::new(io::ErrorKind::Other, e)
                ))
            }
        };
        HostByName(match files::get_host_by_name(&name) {
            Ok(Some(ent)) => ByNameInner::Files(ent),
            Ok(None) => ByNameInner::Dns(dns::HostByName::new(name, reactor)),
            Err(err) => ByNameInner::Error(err),
        })
    }
}

impl Future for HostByName {
    type Item = Option<HostEnt>;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.0 {
            ByNameInner::Dns(ref mut lookup) => return lookup.poll(),
            _ => { }
        }
        match mem::replace(&mut self.0, ByNameInner::Done) {
            ByNameInner::Files(res) => Ok(Async::Ready(Some(res))),
            ByNameInner::Error(err) => Err(err),
            ByNameInner::Done => panic!("polling a resolved HostByName"),
            _ => panic!()
        }
    }
}

//------------ HostByAddr ----------------------------------------------------

pub struct HostByAddr;

impl Future for HostByAddr {
    type Item = Option<HostEnt>;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        unimplemented!()
    }
}

<commit_msg>HostByName: handle names that are IP addresses.<commit_after>use std::{io, mem};
use std::net::IpAddr;
use std::str::FromStr;
use domain::bits::DNameBuf;
use futures::{Async, Future, Poll};
use tokio_core::reactor;

//============ Low-level API =================================================

pub mod dns;
pub mod files;

//============ High-level API ================================================

pub fn get_host_by_name(name: &str) -> Result<Option<HostEnt>, io::Error> {
    let mut core = reactor::Core::new()?;
    let handle = core.handle();
    core.run(poll_host_by_name(name, &handle))
}

pub fn get_host_by_addr(addr: IpAddr) -> Result<Option<HostEnt>, io::Error> {
    let mut core = reactor::Core::new()?;
    let handle = core.handle();
    core.run(poll_host_by_addr(addr, &handle))
}

/// Returns host information for a given host name.
///
/// The name is either a hostname, an IPv4 or IPv6 address in its standard
/// text notation. In the latter two cases, no lookups are performed and a
/// `HostEnt` is returned with `name` as the canonical name, the parsed
/// address as the sole address, and no aliases.
///
/// Otherwise the name is interpreted as a host name and lookups according to
/// the system configuraition are performed.
///
/// The function returns a future that performes all necessary IO via the
/// tokio reactor given by `reactor`.
///
/// # Limitations
///
/// For this initial version of the crate, the lookup is a `files` lookup
/// first and only if that does not succeed, a DNS query for both A and AAAA
/// records. This initial version also does not yet fill the aliases list of
/// the returned `HostEnt`.
pub fn poll_host_by_name(name: &str, reactor: &reactor::Handle)
                         -> HostByName {
    HostByName::new(name, reactor)
}

pub fn poll_host_by_addr(addr: IpAddr, reactor: &reactor::Handle)
                         -> HostByAddr {
    unimplemented!()
}

//------------ HostEnt -------------------------------------------------------

pub struct HostEnt {
    pub name: String,
    pub aliases: Vec<String>,
    pub addrs: Vec<IpAddr>,
}

//------------ HostByName ----------------------------------------------------

pub struct HostByName(ByNameInner);

enum ByNameInner {
    Files(HostEnt),
    Dns(dns::HostByName),
    Error(io::Error),
    Done,
}

impl HostByName {
    pub fn new(name: &str, reactor: &reactor::Handle) -> Self {
        if let Ok(addr) = IpAddr::from_str(name) {
            return HostByName(ByNameInner::Files(HostEnt {
                name: name.into(),
                aliases: Vec::new(),
                addrs: vec!(addr),
            }))
        }
        let name = match DNameBuf::from_str(name) {
            Ok(name) => name,
            Err(e) => {
                return HostByName(ByNameInner::Error(
                    io::Error::new(io::ErrorKind::Other, e)
                ))
            }
        };
        HostByName(match files::get_host_by_name(&name) {
            Ok(Some(ent)) => ByNameInner::Files(ent),
            Ok(None) => ByNameInner::Dns(dns::HostByName::new(name, reactor)),
            Err(err) => ByNameInner::Error(err),
        })
    }
}

impl Future for HostByName {
    type Item = Option<HostEnt>;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.0 {
            ByNameInner::Dns(ref mut lookup) => return lookup.poll(),
            _ => { }
        }
        match mem::replace(&mut self.0, ByNameInner::Done) {
            ByNameInner::Files(res) => Ok(Async::Ready(Some(res))),
            ByNameInner::Error(err) => Err(err),
            ByNameInner::Done => panic!("polling a resolved HostByName"),
            _ => panic!()
        }
    }
}

//------------ HostByAddr ----------------------------------------------------

pub struct HostByAddr;

impl Future for HostByAddr {
    type Item = Option<HostEnt>;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        unimplemented!()
    }
}

<|endoftext|>


<commit_before>extern crate cairo;

#[repr(C)]
pub struct RsvgPathBuilder {
    path_data: Vec<cairo::PathSegment>,
    last_move_to_index: Option<usize>
}

impl RsvgPathBuilder {
    fn move_to (&mut self, x: f64, y: f64) {
        self.path_data.push (cairo::PathSegment::MoveTo ((x, y)));
        self.last_move_to_index = Some (self.path_data.len () - 1);
    }

    fn line_to (&mut self, x: f64, y: f64) {
        self.path_data.push (cairo::PathSegment::LineTo ((x, y)));
    }

    fn curve_to (&mut self, x2: f64, y2: f64, x3: f64, y3: f64, x4: f64, y4: f64) {
        self.path_data.push (cairo::PathSegment::CurveTo ((x2, y2), (x3, y3), (x4, y4)));
    }

    fn close_path (&mut self) {
        if let Some (idx) = self.last_move_to_index {
            let segment = self.path_data[idx];

            if let cairo::PathSegment::MoveTo ((x, y)) = segment {
                self.move_to (x, y);
            } else {
                unreachable! ();
            }
        }
    }
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_new () -> *mut RsvgPathBuilder {
    let builder = RsvgPathBuilder {
        path_data: Vec::new (),
        last_move_to_index: None
    };

    let boxed_builder = Box::new (builder);

    Box::into_raw (boxed_builder)
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_destroy (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let _ = Box::from_raw (raw_builder);
}

#[no_mangle]
pub extern fn rsvg_path_builder_move_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.move_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_line_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.line_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_curve_to (raw_builder: *mut RsvgPathBuilder,
                                          x2: f64, y2: f64,
                                          x3: f64, y3: f64,
                                          x4: f64, y4: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.curve_to (x2, y2, x3, y3, x4, y4);
}

#[no_mangle]
pub extern fn rsvg_path_builder_close_path (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.close_path ();
}
<commit_msg>path_builder.rs: Rename path_data to path_segments to reflect its PathSegment elements<commit_after>extern crate cairo;

#[repr(C)]
pub struct RsvgPathBuilder {
    path_segments: Vec<cairo::PathSegment>,
    last_move_to_index: Option<usize>
}

impl RsvgPathBuilder {
    fn move_to (&mut self, x: f64, y: f64) {
        self.path_segments.push (cairo::PathSegment::MoveTo ((x, y)));
        self.last_move_to_index = Some (self.path_segments.len () - 1);
    }

    fn line_to (&mut self, x: f64, y: f64) {
        self.path_segments.push (cairo::PathSegment::LineTo ((x, y)));
    }

    fn curve_to (&mut self, x2: f64, y2: f64, x3: f64, y3: f64, x4: f64, y4: f64) {
        self.path_segments.push (cairo::PathSegment::CurveTo ((x2, y2), (x3, y3), (x4, y4)));
    }

    fn close_path (&mut self) {
        if let Some (idx) = self.last_move_to_index {
            let segment = self.path_segments[idx];

            if let cairo::PathSegment::MoveTo ((x, y)) = segment {
                self.move_to (x, y);
            } else {
                unreachable! ();
            }
        }
    }
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_new () -> *mut RsvgPathBuilder {
    let builder = RsvgPathBuilder {
        path_segments: Vec::new (),
        last_move_to_index: None
    };

    let boxed_builder = Box::new (builder);

    Box::into_raw (boxed_builder)
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_destroy (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let _ = Box::from_raw (raw_builder);
}

#[no_mangle]
pub extern fn rsvg_path_builder_move_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.move_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_line_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.line_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_curve_to (raw_builder: *mut RsvgPathBuilder,
                                          x2: f64, y2: f64,
                                          x3: f64, y3: f64,
                                          x4: f64, y4: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.curve_to (x2, y2, x3, y3, x4, y4);
}

#[no_mangle]
pub extern fn rsvg_path_builder_close_path (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.close_path ();
}
<|endoftext|>


<commit_before>// Copyright 2021 Luis Cáceres
//
// 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 std::ffi::CStr;

use {rust_icu_sys as sys, rust_icu_sys::versioned_function, rust_icu_sys::*};

/// Get an iterator over all canonical converter names available to ICU.
///
/// The [AvailableConverters] iterator efficiently implements [Iterator::count] and [Iterator::nth]
/// to avoid calling `ucnv_getAvailableName` unnecessarily.
///
/// This interface wraps around `ucnv_countAvailable` and `ucnv_getAvailableName`.
pub fn available_converters() -> AvailableConverters {
    AvailableConverters {
        n: 0,
        count: unsafe { versioned_function!(ucnv_countAvailable)() } as u32,
    }
}

/// See [available_converters()]
pub struct AvailableConverters {
    n: u32,
    count: u32,
}

impl AvailableConverters {
    #[inline(always)]
    fn elements_left(&self) -> usize {
        self.count.saturating_sub(self.n) as usize
    }
}

impl Iterator for AvailableConverters {
    type Item = String;

    fn next(&mut self) -> Option<Self::Item> {
        let name_c_str = unsafe { versioned_function!(ucnv_getAvailableName)(self.n as i32) };
        if name_c_str.is_null() {
            return None;
        }

        self.n += 1;
        unsafe {
            Some(
                CStr::from_ptr(name_c_str)
                    .to_str()
                    .expect("converter name should be UTF-8 compatible")
                    .to_string(),
            )
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let count = self.elements_left();
        (count, Some(count))
    }

    fn count(self) -> usize {
        self.elements_left()
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        if n >= self.elements_left() {
            self.n = self.count;
            None
        } else {
            self.n += n as u32;
            self.next()
        }
    }
}

impl ExactSizeIterator for AvailableConverters {}

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

    #[test]
    fn test_available_converter_names() {
        let converters = available_converters();
        let converters_count = converters.len();

        let mut count = 0usize;
        for _ in converters {
            count += 1;
        }

        assert_eq!(converters_count, count);
    }
}<commit_msg>Add interface to query converter aliases<commit_after>// Copyright 2021 Luis Cáceres
//
// 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 std::ffi::{CStr, CString};

use {rust_icu_sys as sys, rust_icu_sys::versioned_function, rust_icu_sys::*};

/// Get an iterator over all canonical converter names available to ICU.
///
/// The [AvailableConverters] iterator efficiently implements [Iterator::count] and [Iterator::nth]
/// to avoid calling `ucnv_getAvailableName` unnecessarily.
///
/// This interface wraps around `ucnv_countAvailable` and `ucnv_getAvailableName`.
pub fn available_converters() -> AvailableConverters {
    AvailableConverters {
        n: 0,
        count: unsafe { versioned_function!(ucnv_countAvailable)() } as u32,
    }
}

/// See [available_converters()]
pub struct AvailableConverters {
    n: u32,
    count: u32,
}

impl AvailableConverters {
    #[inline(always)]
    fn elements_left(&self) -> usize {
        self.count.saturating_sub(self.n) as usize
    }
}

impl Iterator for AvailableConverters {
    type Item = String;

    fn next(&mut self) -> Option<Self::Item> {
        let name_c_str = unsafe { versioned_function!(ucnv_getAvailableName)(self.n as i32) };
        if name_c_str.is_null() {
            return None;
        }

        self.n += 1;
        unsafe {
            Some(
                CStr::from_ptr(name_c_str)
                    .to_str()
                    .expect("converter name should be UTF-8 compatible")
                    .to_string(),
            )
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let count = self.elements_left();
        (count, Some(count))
    }

    fn count(self) -> usize {
        self.elements_left()
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        if n >= self.elements_left() {
            self.n = self.count;
            None
        } else {
            self.n += n as u32;
            self.next()
        }
    }
}

impl ExactSizeIterator for AvailableConverters {}

/// Get an iterator over all aliases for the provided converter name (which may not necessarily be
/// the canonical converter name).
///
/// The [Aliases] iterator efficiently implements [Iterator::count] and [Iterator::nth] to avoid
/// calling `ucnv_getAlias` unnecessarily.
///
/// This interface wraps around `ucnv_countAliases` and `ucnv_getAlias`.
pub fn aliases(name: &str) -> Aliases {
    let name = CString::new(name).expect("converter name should not contain NUL");

    let mut status = sys::UErrorCode::U_ZERO_ERROR;
    let count = unsafe { versioned_function!(ucnv_countAliases)(name.as_ptr(), &mut status) };
    let is_ambiguous = status == sys::UErrorCode::U_AMBIGUOUS_ALIAS_WARNING;
    Aliases {
        n: 0,
        count,
        name,
        is_ambiguous,
    }
}

/// See [aliases()]
pub struct Aliases {
    n: u16,
    count: u16,
    name: CString,
    is_ambiguous: bool,
}

impl Aliases {
    #[inline(always)]
    fn elements_left(&self) -> usize {
        self.count.saturating_sub(self.n) as usize
    }

    /// Whether or not the converter name provided to [aliases()] is an ambiguous name.
    ///
    /// This value is the cached result of checking that the `status` of calling `ucnv_countAliases`
    /// was set to `U_AMBIGUOUS_ALIAS_WARNING`.
    pub fn is_ambiguous(&self) -> bool {
        self.is_ambiguous
    }
}

impl Iterator for Aliases {
    type Item = String;

    fn next(&mut self) -> Option<Self::Item> {
        let alias_c_str = unsafe {
            let mut status = sys::UErrorCode::U_ZERO_ERROR;
            versioned_function!(ucnv_getAlias)(self.name.as_ptr(), self.n, &mut status)
        };
        if alias_c_str.is_null() {
            return None;
        }

        self.n += 1;
        unsafe {
            Some(
                CStr::from_ptr(alias_c_str)
                    .to_str()
                    .expect("alias name should be UTF-8 compatible")
                    .to_string(),
            )
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let count = self.elements_left();
        (count, Some(count))
    }

    fn count(self) -> usize {
        self.elements_left()
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        if n >= self.elements_left() {
            self.n = self.count;
            None
        } else {
            self.n += n as u16;
            self.next()
        }
    }
}

impl ExactSizeIterator for Aliases {}

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

    #[test]
    fn test_available_converter_names() {
        let converters = available_converters();
        let converters_count = converters.len();

        let mut count = 0usize;
        for _ in converters {
            count += 1;
        }

        assert_eq!(converters_count, count);
    }

    #[test]
    fn test_converter_aliases() {
        let aliases = aliases("SHIFT_JIS");
        let aliases_count = aliases.len();

        let mut count = 0usize;
        for _ in aliases {
            count += 1;
        }

        assert_eq!(aliases_count, count);
    }
}
<|endoftext|>


<commit_before>extern crate itertools;

extern crate structopt;
#[macro_use]
extern crate structopt_derive;

use itertools::Itertools;
use structopt::StructOpt;
use std::fs::File;
use std::io::Read;

fn part1(input: &str) -> u32 {
    input
        .chars()
        .chain(input.chars().next())
        .filter_map(|c| c.to_digit(10))
        .tuple_windows()
        .map(|(x, y)| if x == y { x } else { 0 })
        .sum()
}

fn part2(input: &str) -> u32 {
    let size = input.chars().filter_map(|c| c.to_digit(10)).count();
    let rotated_iter = input.chars().filter_map(|c| c.to_digit(10)).cycle();
    input
        .chars()
        .chain(input.chars().next())
        .filter_map(|c| c.to_digit(10))
        .tuple_windows()
        .map(|(x, y)| if x == y { x } else { 0 })
        .sum()
}

fn main() {
    let opt = Opt::from_args();
    let mut contents = String::new();
    if opt.input == "-" {
        std::io::stdin()
            .read_to_string(&mut contents)
            .expect("could not read stdin");
    } else {
        let mut file = File::open(&opt.input)
            .expect(&format!("file {} not found", opt.input));
        file.read_to_string(&mut contents)
            .expect(&format!("could not read file {}", opt.input));
    }
    println!("Part 1: {}", part1(&contents));
    println!("Part 2: {}", part2(&contents));
}

#[derive(StructOpt, Debug)]
#[structopt(name = "day01", about = "Advent of code 2017 Day 01")]
struct Opt {
    #[structopt(help = "Input file")] input: String,
}

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

    #[test]
    fn part1_test() {
        assert_eq!(part1("1122"), 3);
        assert_eq!(part1("1111"), 4);
        assert_eq!(part1("1234"), 0);
        assert_eq!(part1("91212129"), 9);
    }
}
<commit_msg>2017 day 01 part 02<commit_after>extern crate itertools;

extern crate structopt;
#[macro_use]
extern crate structopt_derive;

use itertools::Itertools;
use structopt::StructOpt;
use std::fs::File;
use std::io::Read;

fn part1(input: &str) -> u32 {
    input
        .chars()
        .chain(input.chars().next())
        .filter_map(|c| c.to_digit(10))
        .tuple_windows()
        .map(|(x, y)| if x == y { x } else { 0 })
        .sum()
}

fn part2(input: &str) -> u32 {
    let size = input.chars().filter_map(|c| c.to_digit(10)).count();
    let rotated_iter = input
        .chars()
        .cycle()
        .filter_map(|c| c.to_digit(10))
        .skip(size / 2);
    input
        .chars()
        .filter_map(|c| c.to_digit(10))
        .zip(rotated_iter)
        .map(|(x, y)| if x == y { x } else { 0 })
        .sum()
}

fn main() {
    let opt = Opt::from_args();
    let mut contents = String::new();
    if opt.input == "-" {
        std::io::stdin()
            .read_to_string(&mut contents)
            .expect("could not read stdin");
    } else {
        let mut file = File::open(&opt.input)
            .expect(&format!("file {} not found", opt.input));
        file.read_to_string(&mut contents)
            .expect(&format!("could not read file {}", opt.input));
    }
    println!("Part 1: {}", part1(&contents));
    println!("Part 2: {}", part2(&contents));
}

#[derive(StructOpt, Debug)]
#[structopt(name = "day01", about = "Advent of code 2017 Day 01")]
struct Opt {
    #[structopt(help = "Input file")] input: String,
}

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

    #[test]
    fn part1_test() {
        assert_eq!(part1("1122"), 3);
        assert_eq!(part1("1111"), 4);
        assert_eq!(part1("1234"), 0);
        assert_eq!(part1("91212129"), 9);
    }

    #[test]
    fn part2_test() {
        assert_eq!(part2("1212"), 6);
        assert_eq!(part2("1221"), 0);
        assert_eq!(part2("123425"), 4);
        assert_eq!(part2("123123"), 12);
        assert_eq!(part2("12131415"), 4);
    }
}
<|endoftext|>


<commit_before>use super::ValidatorHarness;
use beacon_chain::{BeaconChain, BlockProcessingOutcome};
pub use beacon_chain::{BeaconChainError, CheckPoint};
use db::{
    stores::{BeaconBlockStore, BeaconStateStore},
    MemoryDB,
};
use fork_choice::BitwiseLMDGhost;
use log::debug;
use rayon::prelude::*;
use slot_clock::TestingSlotClock;
use ssz::TreeHash;
use std::sync::Arc;
use types::{test_utils::TestingBeaconStateBuilder, *};

type TestingBeaconChain = BeaconChain<MemoryDB, TestingSlotClock, BitwiseLMDGhost<MemoryDB>>;

/// The beacon chain harness simulates a single beacon node with `validator_count` validators connected
/// to it. Each validator is provided a borrow to the beacon chain, where it may read
/// information and submit blocks/attestations for processing.
///
/// This test harness is useful for testing validator and internal state transition logic. It
/// is not useful for testing that multiple beacon nodes can reach consensus.
pub struct BeaconChainHarness {
    pub db: Arc<MemoryDB>,
    pub beacon_chain: Arc<TestingBeaconChain>,
    pub block_store: Arc<BeaconBlockStore<MemoryDB>>,
    pub state_store: Arc<BeaconStateStore<MemoryDB>>,
    pub validators: Vec<ValidatorHarness>,
    pub spec: Arc<ChainSpec>,
}

impl BeaconChainHarness {
    /// Create a new harness with:
    ///
    /// - A keypair, `BlockProducer` and `Attester` for each validator.
    /// - A new BeaconChain struct where the given validators are in the genesis.
    pub fn new(spec: ChainSpec, validator_count: usize) -> Self {
        let state_builder =
            TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(validator_count, &spec);
        Self::from_beacon_state_builder(state_builder, spec)
    }

    pub fn from_beacon_state_builder(
        state_builder: TestingBeaconStateBuilder,
        spec: ChainSpec,
    ) -> Self {
        let db = Arc::new(MemoryDB::open());
        let block_store = Arc::new(BeaconBlockStore::new(db.clone()));
        let state_store = Arc::new(BeaconStateStore::new(db.clone()));
        let slot_clock = TestingSlotClock::new(spec.genesis_slot.as_u64());
        let fork_choice = BitwiseLMDGhost::new(block_store.clone(), state_store.clone());

        let (mut genesis_state, keypairs) = state_builder.build();

        let mut genesis_block = BeaconBlock::empty(&spec);
        genesis_block.state_root = Hash256::from_slice(&genesis_state.hash_tree_root());

        genesis_state
            .build_epoch_cache(RelativeEpoch::Previous, &spec)
            .unwrap();
        genesis_state
            .build_epoch_cache(RelativeEpoch::Current, &spec)
            .unwrap();
        genesis_state
            .build_epoch_cache(RelativeEpoch::NextWithoutRegistryChange, &spec)
            .unwrap();
        genesis_state
            .build_epoch_cache(RelativeEpoch::NextWithRegistryChange, &spec)
            .unwrap();

        // Create the Beacon Chain
        let beacon_chain = Arc::new(
            BeaconChain::from_genesis(
                state_store.clone(),
                block_store.clone(),
                slot_clock,
                genesis_state,
                genesis_block,
                spec.clone(),
                fork_choice,
            )
            .unwrap(),
        );

        let spec = Arc::new(spec);

        debug!("Creating validator producer and attester instances...");

        // Spawn the test validator instances.
        let validators: Vec<ValidatorHarness> = keypairs
            .iter()
            .map(|keypair| {
                ValidatorHarness::new(keypair.clone(), beacon_chain.clone(), spec.clone())
            })
            .collect();

        debug!("Created {} ValidatorHarnesss", validators.len());

        Self {
            db,
            beacon_chain,
            block_store,
            state_store,
            validators,
            spec,
        }
    }

    /// Move the `slot_clock` for the `BeaconChain` forward one slot.
    ///
    /// This is the equivalent of advancing a system clock forward one `SLOT_DURATION`.
    ///
    /// Returns the new slot.
    pub fn increment_beacon_chain_slot(&mut self) -> Slot {
        let slot = self.beacon_chain.present_slot() + 1;

        let nth_slot = slot
            - slot
                .epoch(self.spec.slots_per_epoch)
                .start_slot(self.spec.slots_per_epoch);
        let nth_epoch = slot.epoch(self.spec.slots_per_epoch) - self.spec.genesis_epoch;
        debug!(
            "Advancing BeaconChain to slot {}, epoch {} (epoch height: {}, slot {} in epoch.).",
            slot,
            slot.epoch(self.spec.slots_per_epoch),
            nth_epoch,
            nth_slot
        );

        self.beacon_chain.slot_clock.set_slot(slot.as_u64());
        self.beacon_chain
            .catchup_state()
            .expect("Failed to catch state");
        slot
    }

    pub fn gather_attesations(&mut self) -> Vec<Attestation> {
        let present_slot = self.beacon_chain.present_slot();
        let state = self.beacon_chain.state.read();

        let mut attestations = vec![];

        for committee in state
            .get_crosslink_committees_at_slot(present_slot, &self.spec)
            .unwrap()
        {
            for &validator in &committee.committee {
                let duties = state
                    .get_attestation_duties(validator, &self.spec)
                    .unwrap()
                    .expect("Attesting validators by definition have duties");

                // Obtain `AttestationData` from the beacon chain.
                let data = self
                    .beacon_chain
                    .produce_attestation_data(duties.shard)
                    .unwrap();

                // Produce an aggregate signature with a single signature.
                let aggregate_signature = {
                    let message = AttestationDataAndCustodyBit {
                        data: data.clone(),
                        custody_bit: false,
                    }
                    .hash_tree_root();
                    let domain = self.spec.get_domain(
                        state.slot.epoch(self.spec.slots_per_epoch),
                        Domain::Attestation,
                        &state.fork,
                    );
                    let sig =
                        Signature::new(&message, domain, &self.validators[validator].keypair.sk);

                    let mut agg_sig = AggregateSignature::new();
                    agg_sig.add(&sig);

                    agg_sig
                };

                let mut aggregation_bitfield = Bitfield::with_capacity(committee.committee.len());
                let custody_bitfield = Bitfield::with_capacity(committee.committee.len());

                aggregation_bitfield.set(duties.committee_index, true);

                attestations.push(Attestation {
                    aggregation_bitfield,
                    data,
                    custody_bitfield,
                    aggregate_signature,
                })
            }
        }

        attestations
    }

    /// Get the block from the proposer for the slot.
    ///
    /// Note: the validator will only produce it _once per slot_. So, if you call this twice you'll
    /// only get a block once.
    pub fn produce_block(&mut self) -> BeaconBlock {
        let present_slot = self.beacon_chain.present_slot();

        let proposer = self.beacon_chain.block_proposer(present_slot).unwrap();

        debug!(
            "Producing block from validator #{} for slot {}.",
            proposer, present_slot
        );

        // Ensure the validators slot clock is accurate.
        self.validators[proposer].set_slot(present_slot);
        let block = self.validators[proposer].produce_block().unwrap();

        block
    }

    /// Advances the chain with a BeaconBlock and attestations from all validators.
    ///
    /// This is the ideal scenario for the Beacon Chain, 100% honest participation from
    /// validators.
    pub fn advance_chain_with_block(&mut self) -> BeaconBlock {
        self.increment_beacon_chain_slot();

        // Produce a new block.
        let block = self.produce_block();
        debug!("Submitting block for processing...");
        match self.beacon_chain.process_block(block.clone()) {
            Ok(BlockProcessingOutcome::ValidBlock(_)) => {}
            other => panic!("block processing failed with {:?}", other),
        };
        debug!("...block processed by BeaconChain.");

        debug!("Producing attestations...");

        // Produce new attestations.
        let attestations = self.gather_attesations();

        debug!("Processing {} attestations...", attestations.len());

        attestations
            .par_iter()
            .enumerate()
            .for_each(|(i, attestation)| {
                self.beacon_chain
                    .process_attestation(attestation.clone())
                    .expect(&format!("Attestation {} invalid: {:?}", i, attestation));
            });

        debug!("Attestations processed.");

        block
    }

    /// Signs a message using some validators secret key with the `Fork` info from the latest state
    /// of the `BeaconChain`.
    ///
    /// Useful for producing slashable messages and other objects that `BeaconChainHarness` does
    /// not produce naturally.
    pub fn validator_sign(
        &self,
        validator_index: usize,
        message: &[u8],
        epoch: Epoch,
        domain_type: Domain,
    ) -> Option<Signature> {
        let validator = self.validators.get(validator_index)?;

        let domain = self
            .spec
            .get_domain(epoch, domain_type, &self.beacon_chain.state.read().fork);

        Some(Signature::new(message, domain, &validator.keypair.sk))
    }

    /// Returns the current `Fork` of the `beacon_chain`.
    pub fn fork(&self) -> Fork {
        self.beacon_chain.state.read().fork.clone()
    }

    /// Returns the current `epoch` of the `beacon_chain`.
    pub fn epoch(&self) -> Epoch {
        self.beacon_chain
            .state
            .read()
            .slot
            .epoch(self.spec.slots_per_epoch)
    }

    /// Returns the keypair for some validator index.
    pub fn validator_keypair(&self, validator_index: usize) -> Option<&Keypair> {
        self.validators
            .get(validator_index)
            .and_then(|v| Some(&v.keypair))
    }

    /// Submit a deposit to the `BeaconChain` and, if given a keypair, create a new
    /// `ValidatorHarness` instance for this validator.
    ///
    /// If a new `ValidatorHarness` was created, the validator should become fully operational as
    /// if the validator were created during `BeaconChainHarness` instantiation.
    pub fn add_deposit(&mut self, deposit: Deposit, keypair: Option<Keypair>) {
        self.beacon_chain.process_deposit(deposit).unwrap();

        // If a keypair is present, add a new `ValidatorHarness` to the rig.
        if let Some(keypair) = keypair {
            let validator =
                ValidatorHarness::new(keypair, self.beacon_chain.clone(), self.spec.clone());
            self.validators.push(validator);
        }
    }

    /// Submit an exit to the `BeaconChain` for inclusion in some block.
    ///
    /// Note: the `ValidatorHarness` for this validator continues to exist. Once it is exited it
    /// will stop receiving duties from the beacon chain and just do nothing when prompted to
    /// produce/attest.
    pub fn add_exit(&mut self, exit: VoluntaryExit) {
        self.beacon_chain.process_voluntary_exit(exit).unwrap();
    }

    /// Submit an transfer to the `BeaconChain` for inclusion in some block.
    pub fn add_transfer(&mut self, transfer: Transfer) {
        self.beacon_chain.process_transfer(transfer).unwrap();
    }

    /// Submit a proposer slashing to the `BeaconChain` for inclusion in some block.
    pub fn add_proposer_slashing(&mut self, proposer_slashing: ProposerSlashing) {
        self.beacon_chain
            .process_proposer_slashing(proposer_slashing)
            .unwrap();
    }

    /// Submit an attester slashing to the `BeaconChain` for inclusion in some block.
    pub fn add_attester_slashing(&mut self, attester_slashing: AttesterSlashing) {
        self.beacon_chain
            .process_attester_slashing(attester_slashing)
            .unwrap();
    }

    /// Executes the fork choice rule on the `BeaconChain`, selecting a new canonical head.
    pub fn run_fork_choice(&mut self) {
        self.beacon_chain.fork_choice().unwrap()
    }

    /// Dump all blocks and states from the canonical beacon chain.
    pub fn chain_dump(&self) -> Result<Vec<CheckPoint>, BeaconChainError> {
        self.beacon_chain.chain_dump()
    }
}
<commit_msg>Use committe_len in test_harness<commit_after>use super::ValidatorHarness;
use beacon_chain::{BeaconChain, BlockProcessingOutcome};
pub use beacon_chain::{BeaconChainError, CheckPoint};
use db::{
    stores::{BeaconBlockStore, BeaconStateStore},
    MemoryDB,
};
use fork_choice::BitwiseLMDGhost;
use log::debug;
use rayon::prelude::*;
use slot_clock::TestingSlotClock;
use ssz::TreeHash;
use std::sync::Arc;
use types::{test_utils::TestingBeaconStateBuilder, *};

type TestingBeaconChain = BeaconChain<MemoryDB, TestingSlotClock, BitwiseLMDGhost<MemoryDB>>;

/// The beacon chain harness simulates a single beacon node with `validator_count` validators connected
/// to it. Each validator is provided a borrow to the beacon chain, where it may read
/// information and submit blocks/attestations for processing.
///
/// This test harness is useful for testing validator and internal state transition logic. It
/// is not useful for testing that multiple beacon nodes can reach consensus.
pub struct BeaconChainHarness {
    pub db: Arc<MemoryDB>,
    pub beacon_chain: Arc<TestingBeaconChain>,
    pub block_store: Arc<BeaconBlockStore<MemoryDB>>,
    pub state_store: Arc<BeaconStateStore<MemoryDB>>,
    pub validators: Vec<ValidatorHarness>,
    pub spec: Arc<ChainSpec>,
}

impl BeaconChainHarness {
    /// Create a new harness with:
    ///
    /// - A keypair, `BlockProducer` and `Attester` for each validator.
    /// - A new BeaconChain struct where the given validators are in the genesis.
    pub fn new(spec: ChainSpec, validator_count: usize) -> Self {
        let state_builder =
            TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(validator_count, &spec);
        Self::from_beacon_state_builder(state_builder, spec)
    }

    pub fn from_beacon_state_builder(
        state_builder: TestingBeaconStateBuilder,
        spec: ChainSpec,
    ) -> Self {
        let db = Arc::new(MemoryDB::open());
        let block_store = Arc::new(BeaconBlockStore::new(db.clone()));
        let state_store = Arc::new(BeaconStateStore::new(db.clone()));
        let slot_clock = TestingSlotClock::new(spec.genesis_slot.as_u64());
        let fork_choice = BitwiseLMDGhost::new(block_store.clone(), state_store.clone());

        let (mut genesis_state, keypairs) = state_builder.build();

        let mut genesis_block = BeaconBlock::empty(&spec);
        genesis_block.state_root = Hash256::from_slice(&genesis_state.hash_tree_root());

        genesis_state
            .build_epoch_cache(RelativeEpoch::Previous, &spec)
            .unwrap();
        genesis_state
            .build_epoch_cache(RelativeEpoch::Current, &spec)
            .unwrap();
        genesis_state
            .build_epoch_cache(RelativeEpoch::NextWithoutRegistryChange, &spec)
            .unwrap();
        genesis_state
            .build_epoch_cache(RelativeEpoch::NextWithRegistryChange, &spec)
            .unwrap();

        // Create the Beacon Chain
        let beacon_chain = Arc::new(
            BeaconChain::from_genesis(
                state_store.clone(),
                block_store.clone(),
                slot_clock,
                genesis_state,
                genesis_block,
                spec.clone(),
                fork_choice,
            )
            .unwrap(),
        );

        let spec = Arc::new(spec);

        debug!("Creating validator producer and attester instances...");

        // Spawn the test validator instances.
        let validators: Vec<ValidatorHarness> = keypairs
            .iter()
            .map(|keypair| {
                ValidatorHarness::new(keypair.clone(), beacon_chain.clone(), spec.clone())
            })
            .collect();

        debug!("Created {} ValidatorHarnesss", validators.len());

        Self {
            db,
            beacon_chain,
            block_store,
            state_store,
            validators,
            spec,
        }
    }

    /// Move the `slot_clock` for the `BeaconChain` forward one slot.
    ///
    /// This is the equivalent of advancing a system clock forward one `SLOT_DURATION`.
    ///
    /// Returns the new slot.
    pub fn increment_beacon_chain_slot(&mut self) -> Slot {
        let slot = self.beacon_chain.present_slot() + 1;

        let nth_slot = slot
            - slot
                .epoch(self.spec.slots_per_epoch)
                .start_slot(self.spec.slots_per_epoch);
        let nth_epoch = slot.epoch(self.spec.slots_per_epoch) - self.spec.genesis_epoch;
        debug!(
            "Advancing BeaconChain to slot {}, epoch {} (epoch height: {}, slot {} in epoch.).",
            slot,
            slot.epoch(self.spec.slots_per_epoch),
            nth_epoch,
            nth_slot
        );

        self.beacon_chain.slot_clock.set_slot(slot.as_u64());
        self.beacon_chain
            .catchup_state()
            .expect("Failed to catch state");
        slot
    }

    pub fn gather_attesations(&mut self) -> Vec<Attestation> {
        let present_slot = self.beacon_chain.present_slot();
        let state = self.beacon_chain.state.read();

        let mut attestations = vec![];

        for committee in state
            .get_crosslink_committees_at_slot(present_slot, &self.spec)
            .unwrap()
        {
            for &validator in &committee.committee {
                let duties = state
                    .get_attestation_duties(validator, &self.spec)
                    .unwrap()
                    .expect("Attesting validators by definition have duties");

                // Obtain `AttestationData` from the beacon chain.
                let data = self
                    .beacon_chain
                    .produce_attestation_data(duties.shard)
                    .unwrap();

                // Produce an aggregate signature with a single signature.
                let aggregate_signature = {
                    let message = AttestationDataAndCustodyBit {
                        data: data.clone(),
                        custody_bit: false,
                    }
                    .hash_tree_root();
                    let domain = self.spec.get_domain(
                        state.slot.epoch(self.spec.slots_per_epoch),
                        Domain::Attestation,
                        &state.fork,
                    );
                    let sig =
                        Signature::new(&message, domain, &self.validators[validator].keypair.sk);

                    let mut agg_sig = AggregateSignature::new();
                    agg_sig.add(&sig);

                    agg_sig
                };

                let mut aggregation_bitfield = Bitfield::with_capacity(duties.committee_len);
                let custody_bitfield = Bitfield::with_capacity(duties.committee_len);

                aggregation_bitfield.set(duties.committee_index, true);

                attestations.push(Attestation {
                    aggregation_bitfield,
                    data,
                    custody_bitfield,
                    aggregate_signature,
                })
            }
        }

        attestations
    }

    /// Get the block from the proposer for the slot.
    ///
    /// Note: the validator will only produce it _once per slot_. So, if you call this twice you'll
    /// only get a block once.
    pub fn produce_block(&mut self) -> BeaconBlock {
        let present_slot = self.beacon_chain.present_slot();

        let proposer = self.beacon_chain.block_proposer(present_slot).unwrap();

        debug!(
            "Producing block from validator #{} for slot {}.",
            proposer, present_slot
        );

        // Ensure the validators slot clock is accurate.
        self.validators[proposer].set_slot(present_slot);
        let block = self.validators[proposer].produce_block().unwrap();

        block
    }

    /// Advances the chain with a BeaconBlock and attestations from all validators.
    ///
    /// This is the ideal scenario for the Beacon Chain, 100% honest participation from
    /// validators.
    pub fn advance_chain_with_block(&mut self) -> BeaconBlock {
        self.increment_beacon_chain_slot();

        // Produce a new block.
        let block = self.produce_block();
        debug!("Submitting block for processing...");
        match self.beacon_chain.process_block(block.clone()) {
            Ok(BlockProcessingOutcome::ValidBlock(_)) => {}
            other => panic!("block processing failed with {:?}", other),
        };
        debug!("...block processed by BeaconChain.");

        debug!("Producing attestations...");

        // Produce new attestations.
        let attestations = self.gather_attesations();

        debug!("Processing {} attestations...", attestations.len());

        attestations
            .par_iter()
            .enumerate()
            .for_each(|(i, attestation)| {
                self.beacon_chain
                    .process_attestation(attestation.clone())
                    .expect(&format!("Attestation {} invalid: {:?}", i, attestation));
            });

        debug!("Attestations processed.");

        block
    }

    /// Signs a message using some validators secret key with the `Fork` info from the latest state
    /// of the `BeaconChain`.
    ///
    /// Useful for producing slashable messages and other objects that `BeaconChainHarness` does
    /// not produce naturally.
    pub fn validator_sign(
        &self,
        validator_index: usize,
        message: &[u8],
        epoch: Epoch,
        domain_type: Domain,
    ) -> Option<Signature> {
        let validator = self.validators.get(validator_index)?;

        let domain = self
            .spec
            .get_domain(epoch, domain_type, &self.beacon_chain.state.read().fork);

        Some(Signature::new(message, domain, &validator.keypair.sk))
    }

    /// Returns the current `Fork` of the `beacon_chain`.
    pub fn fork(&self) -> Fork {
        self.beacon_chain.state.read().fork.clone()
    }

    /// Returns the current `epoch` of the `beacon_chain`.
    pub fn epoch(&self) -> Epoch {
        self.beacon_chain
            .state
            .read()
            .slot
            .epoch(self.spec.slots_per_epoch)
    }

    /// Returns the keypair for some validator index.
    pub fn validator_keypair(&self, validator_index: usize) -> Option<&Keypair> {
        self.validators
            .get(validator_index)
            .and_then(|v| Some(&v.keypair))
    }

    /// Submit a deposit to the `BeaconChain` and, if given a keypair, create a new
    /// `ValidatorHarness` instance for this validator.
    ///
    /// If a new `ValidatorHarness` was created, the validator should become fully operational as
    /// if the validator were created during `BeaconChainHarness` instantiation.
    pub fn add_deposit(&mut self, deposit: Deposit, keypair: Option<Keypair>) {
        self.beacon_chain.process_deposit(deposit).unwrap();

        // If a keypair is present, add a new `ValidatorHarness` to the rig.
        if let Some(keypair) = keypair {
            let validator =
                ValidatorHarness::new(keypair, self.beacon_chain.clone(), self.spec.clone());
            self.validators.push(validator);
        }
    }

    /// Submit an exit to the `BeaconChain` for inclusion in some block.
    ///
    /// Note: the `ValidatorHarness` for this validator continues to exist. Once it is exited it
    /// will stop receiving duties from the beacon chain and just do nothing when prompted to
    /// produce/attest.
    pub fn add_exit(&mut self, exit: VoluntaryExit) {
        self.beacon_chain.process_voluntary_exit(exit).unwrap();
    }

    /// Submit an transfer to the `BeaconChain` for inclusion in some block.
    pub fn add_transfer(&mut self, transfer: Transfer) {
        self.beacon_chain.process_transfer(transfer).unwrap();
    }

    /// Submit a proposer slashing to the `BeaconChain` for inclusion in some block.
    pub fn add_proposer_slashing(&mut self, proposer_slashing: ProposerSlashing) {
        self.beacon_chain
            .process_proposer_slashing(proposer_slashing)
            .unwrap();
    }

    /// Submit an attester slashing to the `BeaconChain` for inclusion in some block.
    pub fn add_attester_slashing(&mut self, attester_slashing: AttesterSlashing) {
        self.beacon_chain
            .process_attester_slashing(attester_slashing)
            .unwrap();
    }

    /// Executes the fork choice rule on the `BeaconChain`, selecting a new canonical head.
    pub fn run_fork_choice(&mut self) {
        self.beacon_chain.fork_choice().unwrap()
    }

    /// Dump all blocks and states from the canonical beacon chain.
    pub fn chain_dump(&self) -> Result<Vec<CheckPoint>, BeaconChainError> {
        self.beacon_chain.chain_dump()
    }
}
<|endoftext|>


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

#![feature(rustc_private, plugin_registrar)]

extern crate syntax;
extern crate rustc;

use syntax::ast::{MetaItem, Item, Expr};
use syntax::ast;
use syntax::codemap::Span;
use syntax::ext::base;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ext::deriving::generic::*;
use syntax::ext::deriving::generic::ty::*;
use syntax::parse::token;
use syntax::ptr::P;
use rustc::plugin::Registry;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(token::intern("derive_Rand"),
                                  base::Decorator(Box::new(expand_deriving_rand)));
}

pub fn expand_deriving_rand(cx: &mut ExtCtxt,
                            span: Span,
                            mitem: &MetaItem,
                            item: &Item,
                            mut push: Box<FnMut(P<Item>)>) {
    let trait_def = TraitDef {
        span: span,
        attributes: Vec::new(),
        path: Path::new(vec!("rand", "Rand")),
        additional_bounds: Vec::new(),
        generics: LifetimeBounds::empty(),
        methods: vec!(
            MethodDef {
                name: "rand",
                generics: LifetimeBounds {
                    lifetimes: Vec::new(),
                    bounds: vec!(("R",
                                  vec!( Path::new(vec!("rand", "Rng")) )))
                },
                explicit_self: None,
                args: vec!(
                    Ptr(Box::new(Literal(Path::new_local("R"))),
                        Borrowed(None, ast::MutMutable))
                ),
                ret_ty: Self_,
                attributes: Vec::new(),
                combine_substructure: combine_substructure(Box::new(|a, b, c| {
                    rand_substructure(a, b, c)
                }))
            }
        ),
        associated_types: Vec::new(),
    };
    trait_def.expand(cx, mitem, item, |i| push(i))
}

fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
    let rng = match substr.nonself_args {
        [ref rng] => rng,
        _ => cx.bug("Incorrect number of arguments to `rand` in `derive(Rand)`")
    };
    let rand_ident = vec!(
        cx.ident_of("rand"),
        cx.ident_of("Rand"),
        cx.ident_of("rand")
    );
    let rand_call = |cx: &mut ExtCtxt, span| {
        cx.expr_call_global(span,
                            rand_ident.clone(),
                            vec!(rng.clone()))
    };

    return match *substr.fields {
        StaticStruct(_, ref summary) => {
            let path = cx.path_ident(trait_span, substr.type_ident);
            rand_thing(cx, trait_span, path, summary, rand_call)
        }
        StaticEnum(_, ref variants) => {
            if variants.is_empty() {
                cx.span_err(trait_span, "`Rand` cannot be derived for enums with no variants");
                // let compilation continue
                return cx.expr_usize(trait_span, 0);
            }

            let variant_count = cx.expr_usize(trait_span, variants.len());

            let rand_name = cx.path_all(trait_span,
                                        true,
                                        rand_ident.clone(),
                                        Vec::new(),
                                        Vec::new(),
                                        Vec::new());
            let rand_name = cx.expr_path(rand_name);

            // ::rand::Rand::rand(rng)
            let rv_call = cx.expr_call(trait_span,
                                       rand_name,
                                       vec!(rng.clone()));

            // need to specify the usize-ness of the random number
            let usize_ty = cx.ty_ident(trait_span, cx.ident_of("usize"));
            let value_ident = cx.ident_of("__value");
            let let_statement = cx.stmt_let_typed(trait_span,
                                                  false,
                                                  value_ident,
                                                  usize_ty,
                                                  rv_call);

            // rand() % variants.len()
            let value_ref = cx.expr_ident(trait_span, value_ident);
            let rand_variant = cx.expr_binary(trait_span,
                                              ast::BiRem,
                                              value_ref,
                                              variant_count);

            let mut arms = variants.iter().enumerate().map(|(i, &(ident, v_span, ref summary))| {
                let i_expr = cx.expr_usize(v_span, i);
                let pat = cx.pat_lit(v_span, i_expr);

                let path = cx.path(v_span, vec![substr.type_ident, ident]);
                let thing = rand_thing(cx, v_span, path, summary, |cx, sp| rand_call(cx, sp));
                cx.arm(v_span, vec!( pat ), thing)
            }).collect::<Vec<ast::Arm> >();

            // _ => {} at the end. Should never occur
            arms.push(cx.arm_unreachable(trait_span));

            let match_expr = cx.expr_match(trait_span, rand_variant, arms);

            let block = cx.block(trait_span, vec!( let_statement ), Some(match_expr));
            cx.expr_block(block)
        }
        _ => cx.bug("Non-static method in `derive(Rand)`")
    };

    fn rand_thing<F>(cx: &mut ExtCtxt,
                     trait_span: Span,
                     ctor_path: ast::Path,
                     summary: &StaticFields,
                     mut rand_call: F)
                     -> P<Expr> where
        F: FnMut(&mut ExtCtxt, Span) -> P<Expr>,
    {
        let path = cx.expr_path(ctor_path.clone());
        match *summary {
            Unnamed(ref fields) => {
                if fields.is_empty() {
                    path
                } else {
                    let exprs = fields.iter().map(|span| rand_call(cx, *span)).collect();
                    cx.expr_call(trait_span, path, exprs)
                }
            }
            Named(ref fields) => {
                let rand_fields = fields.iter().map(|&(ident, span)| {
                    let e = rand_call(cx, span);
                    cx.field_imm(span, ident, e)
                }).collect();
                cx.expr_struct(trait_span, ctor_path, rand_fields)
            }
        }
    }
}
<commit_msg>Fix syntax extension signature<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(rustc_private, plugin_registrar)]

extern crate syntax;
extern crate rustc;

use syntax::ast::{MetaItem, Item, Expr};
use syntax::ast;
use syntax::codemap::Span;
use syntax::ext::base;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ext::deriving::generic::*;
use syntax::ext::deriving::generic::ty::*;
use syntax::parse::token;
use syntax::ptr::P;
use rustc::plugin::Registry;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(token::intern("derive_Rand"),
                                  base::Decorator(Box::new(expand_deriving_rand)));
}

pub fn expand_deriving_rand(cx: &mut ExtCtxt,
                            span: Span,
                            mitem: &MetaItem,
                            item: &Item,
                            push: &mut FnMut(P<Item>)) {
    let trait_def = TraitDef {
        span: span,
        attributes: Vec::new(),
        path: Path::new(vec!("rand", "Rand")),
        additional_bounds: Vec::new(),
        generics: LifetimeBounds::empty(),
        methods: vec!(
            MethodDef {
                name: "rand",
                generics: LifetimeBounds {
                    lifetimes: Vec::new(),
                    bounds: vec!(("R",
                                  vec!( Path::new(vec!("rand", "Rng")) )))
                },
                explicit_self: None,
                args: vec!(
                    Ptr(Box::new(Literal(Path::new_local("R"))),
                        Borrowed(None, ast::MutMutable))
                ),
                ret_ty: Self_,
                attributes: Vec::new(),
                combine_substructure: combine_substructure(Box::new(|a, b, c| {
                    rand_substructure(a, b, c)
                }))
            }
        ),
        associated_types: Vec::new(),
    };
    trait_def.expand(cx, mitem, item, |i| push(i))
}

fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
    let rng = match substr.nonself_args {
        [ref rng] => rng,
        _ => cx.bug("Incorrect number of arguments to `rand` in `derive(Rand)`")
    };
    let rand_ident = vec!(
        cx.ident_of("rand"),
        cx.ident_of("Rand"),
        cx.ident_of("rand")
    );
    let rand_call = |cx: &mut ExtCtxt, span| {
        cx.expr_call_global(span,
                            rand_ident.clone(),
                            vec!(rng.clone()))
    };

    return match *substr.fields {
        StaticStruct(_, ref summary) => {
            let path = cx.path_ident(trait_span, substr.type_ident);
            rand_thing(cx, trait_span, path, summary, rand_call)
        }
        StaticEnum(_, ref variants) => {
            if variants.is_empty() {
                cx.span_err(trait_span, "`Rand` cannot be derived for enums with no variants");
                // let compilation continue
                return cx.expr_usize(trait_span, 0);
            }

            let variant_count = cx.expr_usize(trait_span, variants.len());

            let rand_name = cx.path_all(trait_span,
                                        true,
                                        rand_ident.clone(),
                                        Vec::new(),
                                        Vec::new(),
                                        Vec::new());
            let rand_name = cx.expr_path(rand_name);

            // ::rand::Rand::rand(rng)
            let rv_call = cx.expr_call(trait_span,
                                       rand_name,
                                       vec!(rng.clone()));

            // need to specify the usize-ness of the random number
            let usize_ty = cx.ty_ident(trait_span, cx.ident_of("usize"));
            let value_ident = cx.ident_of("__value");
            let let_statement = cx.stmt_let_typed(trait_span,
                                                  false,
                                                  value_ident,
                                                  usize_ty,
                                                  rv_call);

            // rand() % variants.len()
            let value_ref = cx.expr_ident(trait_span, value_ident);
            let rand_variant = cx.expr_binary(trait_span,
                                              ast::BiRem,
                                              value_ref,
                                              variant_count);

            let mut arms = variants.iter().enumerate().map(|(i, &(ident, v_span, ref summary))| {
                let i_expr = cx.expr_usize(v_span, i);
                let pat = cx.pat_lit(v_span, i_expr);

                let path = cx.path(v_span, vec![substr.type_ident, ident]);
                let thing = rand_thing(cx, v_span, path, summary, |cx, sp| rand_call(cx, sp));
                cx.arm(v_span, vec!( pat ), thing)
            }).collect::<Vec<ast::Arm> >();

            // _ => {} at the end. Should never occur
            arms.push(cx.arm_unreachable(trait_span));

            let match_expr = cx.expr_match(trait_span, rand_variant, arms);

            let block = cx.block(trait_span, vec!( let_statement ), Some(match_expr));
            cx.expr_block(block)
        }
        _ => cx.bug("Non-static method in `derive(Rand)`")
    };

    fn rand_thing<F>(cx: &mut ExtCtxt,
                     trait_span: Span,
                     ctor_path: ast::Path,
                     summary: &StaticFields,
                     mut rand_call: F)
                     -> P<Expr> where
        F: FnMut(&mut ExtCtxt, Span) -> P<Expr>,
    {
        let path = cx.expr_path(ctor_path.clone());
        match *summary {
            Unnamed(ref fields) => {
                if fields.is_empty() {
                    path
                } else {
                    let exprs = fields.iter().map(|span| rand_call(cx, *span)).collect();
                    cx.expr_call(trait_span, path, exprs)
                }
            }
            Named(ref fields) => {
                let rand_fields = fields.iter().map(|&(ident, span)| {
                    let e = rand_call(cx, span);
                    cx.field_imm(span, ident, e)
                }).collect();
                cx.expr_struct(trait_span, ctor_path, rand_fields)
            }
        }
    }
}
<|endoftext|>


<commit_before>use super::cpu::interrupt;
use super::io;
use core::option::{Option, None};

pub unsafe fn init(table: interrupt::table) {
    table.enable(6, keypress as u32);
}

pub static mut keydown: Option<extern fn(char)> = None;

#[no_mangle]
pub unsafe fn keypress() {
    keydown.map(|f| {
        let x = *io::UART0 as u8 as char;
	if(x != '\r') {f(x);}
	else {f('\n');}
    });

    asm!("pop {r11, lr}
          subs pc, lr, #4");
}
<commit_msg>added another line. char 22 (fake backspace) maps to char 8 (real backspace)<commit_after>use super::cpu::interrupt;
use super::io;
use core::option::{Option, None};

pub unsafe fn init(table: interrupt::table) {
    table.enable(6, keypress as u32);
}

pub static mut keydown: Option<extern fn(char)> = None;

#[no_mangle]
pub unsafe fn keypress() {
    keydown.map(|f| {
        let x = *io::UART0 as u8 as char;
	if(x != '\r' && x != 22 as u8 as char) {f(x);}
	else if (x == 22 as u8 as char) { f(8 as u8 as char); }
	else {f('\n');}
    });

    asm!("pop {r11, lr}
          subs pc, lr, #4");
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    smoke_test_environment::SmokeTestEnvironment,
    test_utils::diem_swarm_utils::{
        get_op_tool, insert_waypoint, load_diem_root_storage, load_node_config, save_node_config,
    },
    workspace_builder,
    workspace_builder::workspace_root,
};
use anyhow::anyhow;
use diem_temppath::TempPath;
use diem_types::{
    account_config::{diem_root_address, treasury_compliance_account_address},
    transaction::{Transaction, WriteSetPayload},
    waypoint::Waypoint,
};
use regex::Regex;
use std::{
    fs, fs::File, io::Write, path::PathBuf, process::Command, str::FromStr, thread::sleep,
    time::Duration,
};
use transaction_builder::encode_remove_validator_and_reconfigure_script;

#[test]
/// This test verifies the flow of a genesis transaction after the chain starts.
/// 1. Test the consensus sync_only mode, every node should stop at the same version.
/// 2. Test the db-bootstrapper applying a manual genesis transaction (remove validator 0) on diemdb directly
/// 3. Test the nodes and clients resume working after updating waypoint
/// 4. Test a node lagging behind can sync to the waypoint
fn test_genesis_transaction_flow() {
    let db_bootstrapper = workspace_builder::get_bin("db-bootstrapper");

    let num_nodes = 4;
    let mut env = SmokeTestEnvironment::new(num_nodes);

    println!("1. Set sync_only = true for the first node and check it can sync to others");
    let (mut node_config, _) = load_node_config(&env.validator_swarm, 0);
    node_config.consensus.sync_only = true;
    save_node_config(&mut node_config, &env.validator_swarm, 0);

    env.validator_swarm.launch();
    let mut client_0 = env.get_validator_client(0, None);
    client_0.create_next_account(false).unwrap();
    client_0
        .mint_coins(&["mintb", "0", "10", "XUS"], true)
        .unwrap();

    println!("2. Set sync_only = true for all nodes and restart");
    for i in 0..num_nodes {
        let (mut node_config, _) = load_node_config(&env.validator_swarm, i);
        node_config.consensus.sync_only = true;
        save_node_config(&mut node_config, &env.validator_swarm, i);
        env.validator_swarm.kill_node(i);
        env.validator_swarm.add_node(i).unwrap();
    }

    println!("3. delete one node's db and test they can still sync when sync_only is true for every nodes");
    env.validator_swarm.kill_node(0);
    fs::remove_dir_all(node_config.storage.dir()).unwrap();
    env.validator_swarm.add_node(0).unwrap();

    println!("4. verify all nodes are at the same round and no progress being made in 5 sec");
    env.validator_swarm.wait_for_all_nodes_to_catchup();
    let mut known_round = None;
    for i in 0..5 {
        let last_committed_round_str = "diem_consensus_last_committed_round{}";
        for (index, node) in &mut env.validator_swarm.nodes {
            if let Some(round) = node.get_metric(last_committed_round_str) {
                match known_round {
                    Some(r) if r != round => panic!(
                        "round not equal, last known: {}, node {} is {}",
                        r, index, round
                    ),
                    None => known_round = Some(round),
                    _ => continue,
                }
            } else {
                panic!("unable to get round from node {}", index);
            }
        }
        println!(
            "The last know round after {} sec is {}",
            i,
            known_round.unwrap()
        );
        sleep(Duration::from_secs(1));
    }

    println!("5. kill all nodes and prepare a genesis txn to remove validator 0");
    let validator_address = node_config.validator_network.as_ref().unwrap().peer_id();
    let op_tool = get_op_tool(&env.validator_swarm, 0);
    let diem_root = load_diem_root_storage(&env.validator_swarm, 0);
    let config = op_tool
        .validator_config(validator_address, &diem_root)
        .unwrap();
    let name = config.name.as_bytes().to_vec();

    for index in 0..env.validator_swarm.nodes.len() {
        env.validator_swarm.kill_node(index);
    }
    let genesis_transaction = Transaction::GenesisTransaction(WriteSetPayload::Script {
        execute_as: diem_root_address(),
        script: encode_remove_validator_and_reconfigure_script(0, name, validator_address),
    });
    let genesis_path = TempPath::new();
    genesis_path.create_as_file().unwrap();
    let mut file = File::create(genesis_path.path()).unwrap();
    file.write_all(&bcs::to_bytes(&genesis_transaction).unwrap())
        .unwrap();

    println!("6. prepare the waypoint with the transaction");
    let waypoint_command = Command::new(db_bootstrapper.as_path())
        .current_dir(workspace_root())
        .args(&vec![
            node_config.storage.dir().to_str().unwrap(),
            "--genesis-txn-file",
            genesis_path.path().to_str().unwrap(),
        ])
        .output()
        .unwrap();
    let output = std::str::from_utf8(&waypoint_command.stdout).unwrap();
    let waypoint = parse_waypoint(output);

    println!("7. apply genesis transaction for nodes 1, 2, 3");
    for i in 1..num_nodes {
        let (mut node_config, _) = load_node_config(&env.validator_swarm, i);
        insert_waypoint(&mut node_config, waypoint);
        node_config.execution.genesis = Some(genesis_transaction.clone());
        // reset the sync_only flag to false
        node_config.consensus.sync_only = false;
        save_node_config(&mut node_config, &env.validator_swarm, i);
    }

    for i in 1..4 {
        env.validator_swarm.add_node(i).unwrap();
    }

    println!("8. verify it's able to mint after the waypoint");
    let mut client_proxy_1 = env.get_validator_client(1, Some(waypoint));
    client_proxy_1.set_accounts(client_0.copy_all_accounts());
    client_proxy_1.create_next_account(false).unwrap();
    client_proxy_1
        .mint_coins(&["mintb", "1", "10", "XUS"], true)
        .unwrap();
    client_proxy_1
        .wait_for_transaction(treasury_compliance_account_address(), 0)
        .unwrap();

    println!("9. add node 0 back and test if it can sync to the waypoint via state synchronizer");
    let op_tool = get_op_tool(&env.validator_swarm, 1);
    let _ = op_tool
        .add_validator(
            validator_address,
            &load_diem_root_storage(&env.validator_swarm, 0),
            false,
        )
        .unwrap();
    // setup the waypoint for node 0
    node_config.execution.genesis = None;
    node_config.execution.genesis_file_location = PathBuf::from("");
    insert_waypoint(&mut node_config, waypoint);
    save_node_config(&mut node_config, &env.validator_swarm, 0);
    env.validator_swarm.add_node(0).unwrap();
    let mut client_proxy_0 = env.get_validator_client(0, Some(waypoint));
    client_proxy_0.set_accounts(client_proxy_1.copy_all_accounts());
    client_proxy_0.create_next_account(false).unwrap();
    client_proxy_1
        .mint_coins(&["mintb", "1", "10", "XUS"], true)
        .unwrap();
}

fn parse_waypoint(db_bootstrapper_output: &str) -> Waypoint {
    let waypoint = Regex::new(r"Got waypoint: (\d+:\w+)")
        .unwrap()
        .captures(db_bootstrapper_output)
        .ok_or_else(|| anyhow!("Failed to parse db-bootstrapper output."));
    Waypoint::from_str(waypoint.unwrap()[1].into()).unwrap()
}
<commit_msg>fix new genesis smoke test<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    smoke_test_environment::SmokeTestEnvironment,
    test_utils::diem_swarm_utils::{
        get_op_tool, insert_waypoint, load_diem_root_storage, load_node_config, save_node_config,
    },
    workspace_builder,
    workspace_builder::workspace_root,
};
use anyhow::anyhow;
use diem_temppath::TempPath;
use diem_types::{
    account_config::{diem_root_address, treasury_compliance_account_address},
    transaction::{Transaction, WriteSetPayload},
    waypoint::Waypoint,
};
use regex::Regex;
use std::{
    fs, fs::File, io::Write, path::PathBuf, process::Command, str::FromStr, thread::sleep,
    time::Duration,
};
use transaction_builder::encode_remove_validator_and_reconfigure_script;

#[test]
/// This test verifies the flow of a genesis transaction after the chain starts.
/// 1. Test the consensus sync_only mode, every node should stop at the same version.
/// 2. Test the db-bootstrapper applying a manual genesis transaction (remove validator 0) on diemdb directly
/// 3. Test the nodes and clients resume working after updating waypoint
/// 4. Test a node lagging behind can sync to the waypoint
fn test_genesis_transaction_flow() {
    let db_bootstrapper = workspace_builder::get_bin("db-bootstrapper");

    let num_nodes = 4;
    let mut env = SmokeTestEnvironment::new(num_nodes);

    println!("1. Set sync_only = true for the first node and check it can sync to others");
    let (mut node_config, _) = load_node_config(&env.validator_swarm, 0);
    node_config.consensus.sync_only = true;
    save_node_config(&mut node_config, &env.validator_swarm, 0);

    env.validator_swarm.launch();
    let mut client_0 = env.get_validator_client(0, None);
    client_0.create_next_account(false).unwrap();
    client_0
        .mint_coins(&["mintb", "0", "10", "XUS"], true)
        .unwrap();

    println!("2. Set sync_only = true for all nodes and restart");
    for i in 0..num_nodes {
        let (mut node_config, _) = load_node_config(&env.validator_swarm, i);
        node_config.consensus.sync_only = true;
        save_node_config(&mut node_config, &env.validator_swarm, i);
        env.validator_swarm.kill_node(i);
        env.validator_swarm.add_node(i).unwrap();
    }

    println!("3. delete one node's db and test they can still sync when sync_only is true for every nodes");
    env.validator_swarm.kill_node(0);
    fs::remove_dir_all(node_config.storage.dir()).unwrap();
    env.validator_swarm.add_node(0).unwrap();

    println!("4. verify all nodes are at the same round and no progress being made in 5 sec");
    env.validator_swarm.wait_for_all_nodes_to_catchup();
    let mut known_round = None;
    for i in 0..5 {
        let last_committed_round_str = "diem_consensus_last_committed_round{}";
        for (index, node) in &mut env.validator_swarm.nodes {
            if let Some(round) = node.get_metric(last_committed_round_str) {
                match known_round {
                    Some(r) if r != round => panic!(
                        "round not equal, last known: {}, node {} is {}",
                        r, index, round
                    ),
                    None => known_round = Some(round),
                    _ => continue,
                }
            } else {
                panic!("unable to get round from node {}", index);
            }
        }
        println!(
            "The last know round after {} sec is {}",
            i,
            known_round.unwrap()
        );
        sleep(Duration::from_secs(1));
    }

    println!("5. kill all nodes and prepare a genesis txn to remove validator 0");
    let validator_address = node_config.validator_network.as_ref().unwrap().peer_id();
    let op_tool = get_op_tool(&env.validator_swarm, 0);
    let diem_root = load_diem_root_storage(&env.validator_swarm, 0);
    let config = op_tool
        .validator_config(validator_address, &diem_root)
        .unwrap();
    let name = config.name.as_bytes().to_vec();

    for index in 0..env.validator_swarm.nodes.len() {
        env.validator_swarm.kill_node(index);
    }
    let genesis_transaction = Transaction::GenesisTransaction(WriteSetPayload::Script {
        execute_as: diem_root_address(),
        script: encode_remove_validator_and_reconfigure_script(0, name, validator_address),
    });
    let genesis_path = TempPath::new();
    genesis_path.create_as_file().unwrap();
    let mut file = File::create(genesis_path.path()).unwrap();
    file.write_all(&bcs::to_bytes(&genesis_transaction).unwrap())
        .unwrap();

    println!("6. prepare the waypoint with the transaction");
    let waypoint_command = Command::new(db_bootstrapper.as_path())
        .current_dir(workspace_root())
        .args(&vec![
            node_config.storage.dir().to_str().unwrap(),
            "--genesis-txn-file",
            genesis_path.path().to_str().unwrap(),
        ])
        .output()
        .unwrap();
    let output = std::str::from_utf8(&waypoint_command.stdout).unwrap();
    let waypoint = parse_waypoint(output);

    println!("7. apply genesis transaction for nodes 1, 2, 3");
    for i in 1..num_nodes {
        let (mut node_config, _) = load_node_config(&env.validator_swarm, i);
        insert_waypoint(&mut node_config, waypoint);
        node_config.execution.genesis = Some(genesis_transaction.clone());
        // reset the sync_only flag to false
        node_config.consensus.sync_only = false;
        save_node_config(&mut node_config, &env.validator_swarm, i);
    }

    for i in 1..4 {
        env.validator_swarm.add_node(i).unwrap();
    }

    println!("8. verify it's able to mint after the waypoint");
    let mut client_proxy_1 = env.get_validator_client(1, Some(waypoint));
    client_proxy_1.set_accounts(client_0.copy_all_accounts());
    client_proxy_1.create_next_account(false).unwrap();
    client_proxy_1
        .mint_coins(&["mintb", "1", "10", "XUS"], true)
        .unwrap();
    client_proxy_1
        .wait_for_transaction(treasury_compliance_account_address(), 0)
        .unwrap();

    println!("9. add node 0 back and test if it can sync to the waypoint via state synchronizer");
    let op_tool = get_op_tool(&env.validator_swarm, 1);
    let _ = op_tool
        .add_validator(
            validator_address,
            &load_diem_root_storage(&env.validator_swarm, 0),
            false,
        )
        .unwrap();
    // setup the waypoint for node 0
    node_config.execution.genesis = None;
    node_config.execution.genesis_file_location = PathBuf::from("");
    insert_waypoint(&mut node_config, waypoint);
    save_node_config(&mut node_config, &env.validator_swarm, 0);
    env.validator_swarm.add_node(0).unwrap();
    assert!(env.validator_swarm.wait_for_all_nodes_to_catchup());
    let mut client_proxy_0 = env.get_validator_client(0, Some(waypoint));
    client_proxy_0.set_accounts(client_proxy_1.copy_all_accounts());
    client_proxy_0
        .mint_coins(&["mintb", "1", "10", "XUS"], true)
        .unwrap();
}

fn parse_waypoint(db_bootstrapper_output: &str) -> Waypoint {
    let waypoint = Regex::new(r"Got waypoint: (\d+:\w+)")
        .unwrap()
        .captures(db_bootstrapper_output)
        .ok_or_else(|| anyhow!("Failed to parse db-bootstrapper output."));
    Waypoint::from_str(waypoint.unwrap()[1].into()).unwrap()
}
<|endoftext|>