<commit_before>// Copyright (c) 2016-2020 Fabian Schuiki

//! This crate implements SystemVerilog for the moore compiler.

#[macro_use]
extern crate moore_common;
#[macro_use]
extern crate log;

pub extern crate moore_svlog_syntax as syntax;
pub(crate) use moore_common as common;

// Inline the salsa crate as a module, since we use a very esoteric branch for
// now.
// TODO(fschuiki): Remove this once salsa is regular dep again
#[macro_use]
mod salsa;

/// Assert that a condition holds, or emit a bug diagnostic and panic.
#[macro_export]
macro_rules! assert_span {
    ($cond:expr, $span:expr, $emitter:expr) => ({
        $crate::assert_span!(@IMPL $cond, $span, $emitter, "assertion failed: {}", stringify!($cond))
    });
    ($cond:expr, $span:expr, $emitter:expr,) => ({
        $crate::assert_span!(@IMPL $cond, $span, $emitter, "assertion failed: {}", stringify!($cond))
    });
    ($cond:expr, $span:expr, $emitter:expr, $($arg:tt)+) => ({
        $crate::assert_span!(@IMPL $cond, $span, $emitter, $($arg)+)
    });
    (@IMPL $cond:expr, $span:expr, $emitter:expr, $($arg:tt)*) => ({
        if !$cond {
            let msg = format!($($arg)*);
            $emitter.emit(
                moore_common::errors::DiagBuilder2::bug(&msg)
                .span($span)
                .add_note(format!("Assertion failed: {}", stringify!($cond)))
                .add_note(format!("Encountered at {}:{}", file!(), line!()))
            );
            panic!("{}", msg);
        }
    });
}

/// Emit a bug diagnostic and panic.
#[macro_export]
macro_rules! bug_span {
    ($span:expr, $emitter:expr, $($arg:tt)+) => ({
        let msg = format!($($arg)*);
        $emitter.emit(
            moore_common::errors::DiagBuilder2::bug(&msg)
            .span($span)
            .add_note(format!("Encountered at {}:{}", file!(), line!()))
        );
        panic!("{}", msg);
    });
}

/// Assert that two types are identical, or emit a bug diagnostic and panic.
#[macro_export]
macro_rules! assert_type {
    ($lhs:expr, $rhs:expr, $span:expr, $emitter:expr) => ({
        $crate::assert_type!($lhs, $rhs, $span, $emitter,)
    });
    ($lhs:expr, $rhs:expr, $span:expr, $emitter:expr,) => ({
        $crate::assert_type!($lhs, $rhs, $span, $emitter, "type assertion failed: `{}` != `{}`", $lhs, $rhs)
    });
    ($lhs:expr, $rhs:expr, $span:expr, $emitter:expr, $($arg:tt)+) => ({
        if !$lhs.is_identical($rhs) {
            let msg = format!($($arg)*);
            $emitter.emit(
                moore_common::errors::DiagBuilder2::bug(&msg)
                .span($span)
                .add_note("Type mismatch:")
                .add_note(format!("    Left-hand side:  `{}`", $lhs))
                .add_note(format!("    Right-hand side: `{}`", $rhs))
                .add_note(format!("Encountered at {}:{}", file!(), line!()))
            );
            panic!("{}", msg);
        }
    });
}

mod ast_map;
mod codegen;
mod context;
pub mod hir;
mod inst_details;
pub mod mir;
mod param_env;
#[warn(missing_docs)]
pub mod pattern_mapping;
pub mod port_list;
mod port_mapping;
pub mod resolver;
pub mod rst;
#[warn(missing_docs)]
pub mod ty;
pub mod typeck;
pub mod value;

pub use moore_common::{
    name::Name,
    source::{Span, Spanned},
};

/// A general result returned by the queries.
pub type Result<T> = std::result::Result<T, ()>;

pub use crate::{
    codegen::CodeGenerator,
    context::*,
    inst_details::{InstDetails, InstTargetDetails, InstVerbosityVisitor},
    param_env::{
        IntoNodeEnvId, NodeEnvId, ParamEnv, ParamEnvBinding, ParamEnvData, ParamEnvSource,
    },
    port_mapping::{PortMapping, PortMappingSource},
    // resolver::*,
    syntax::*,
};

/// Items commonly used within the crate.
mod crate_prelude {
    #[allow(unused_imports)]
    pub(crate) use crate::{
        ast::{AnyNode, AnyNodeData},
        common::{
            errors::*,
            name::Name,
            score::Result,
            source::{Span, Spanned},
            util::{HasDesc, HasSpan},
            NodeId, SessionContext, Verbosity,
        },
        context::{BaseContext, Context, GlobalContext},
        hir, mir, param_env, port_mapping,
        resolver::{Rib, RibKind},
        ty, typeck, value, IntoNodeEnvId, NodeEnvId, Ref, *,
    };
}

/// A node reference.
///
/// This reference is useful when querying the compiler database for information
/// about a node. It compares the reference *by pointer address*, thus allowing
/// for pessimistic compiler queries.
pub struct Ref<'a, T: 'a + ?Sized>(&'a T);

impl<'a, T: ?Sized> Copy for Ref<'a, T> {}

impl<'a, T: ?Sized> Clone for Ref<'a, T> {
    fn clone(&self) -> Self {
        Ref(self.0)
    }
}

impl<'a, T: ?Sized> From<&'a T> for Ref<'a, T> {
    fn from(r: &'a T) -> Ref<'a, T> {
        Ref(r)
    }
}

impl<'a, T: ?Sized> std::ops::Deref for Ref<'a, T> {
    type Target = &'a T;

    fn deref(&self) -> &&'a T {
        &self.0
    }
}

impl<T: ?Sized> Eq for Ref<'_, T> {}

impl<T: ?Sized> PartialEq for Ref<'_, T> {
    fn eq(&self, other: &Self) -> bool {
        std::ptr::eq(self.0, other.0)
    }
}

impl<T: ?Sized> std::hash::Hash for Ref<'_, T> {
    fn hash<H: std::hash::Hasher>(&self, h: &mut H) {
        std::ptr::hash(self.0, h)
    }
}

impl<T: ?Sized> std::fmt::Debug for Ref<'_, T>
where
    T: std::fmt::Debug,
{
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        std::fmt::Debug::fmt(self.0, f)
    }
}

impl<T: ?Sized> std::fmt::Display for Ref<'_, T>
where
    T: std::fmt::Display,
{
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        std::fmt::Display::fmt(self.0, f)
    }
}

/// A few checks to ensure that `Ref` can be passed around properly.
#[allow(dead_code, unused_variables)]
mod checks {
    use super::*;

    trait Dummy {}
    struct Foo;
    impl Dummy for Foo {}

    fn checks1<'a>(x: Ref<'a, impl Dummy>) {}
    fn checks2<'a>(x: Ref<'a, dyn Dummy>) {}

    fn checks3() {
        let foo = Foo;
        checks1(Ref(&foo));
        checks2(Ref(&foo));
    }

    fn checks4<'a>(x: Ref<'a, impl Dummy>) {
        checks2(Ref(*x));
    }

    fn checks5<'a>(x: Ref<'a, dyn Dummy>) {
        checks2(Ref(*x));
    }
}

// Derive the database queries. We group this into a module such that we can
// selectively enable/disable trace messages using `moore_svlog::queries` in the
// `MOORE_LOG` env var.
mod queries {
    use crate::crate_prelude::*;
    #[allow(deprecated)]
    use crate::{
        hir::lowering::*,
        hir::{accessed_nodes, AccessTable},
        inst_details::*,
        param_env::*,
        pattern_mapping::*,
        port_list::{self, *},
        port_mapping::*,
        resolver::*,
        rst::*,
        ty::UnpackedType,
        typeck::*,
        value::*,
    };
    use std::{
        cell::RefCell,
        collections::{HashMap, HashSet},
        sync::Arc,
    };

    moore_derive::derive_query_db! {
        /// A collection of compiler queries.
    }
}
pub use crate::queries::*;
<commit_msg>svlog: Document IRs in crate doc<commit_after>// Copyright (c) 2016-2020 Fabian Schuiki

//! The SystemVerilog implementation of the moore compiler.
//!
//! This crate implements a query-based compiler for the SystemVerilog language.
//! It strives to be a complete implementation of IEEE 1800-2017, mapping any
//! input source text to the equivalent LLHD code.
//!
//! The implementation uses different representations of the source text for
//! different parts of the compilation. Such a scheme is necessary due to the
//! very messy nature of SystemVerilog, with its strange mixture of static and
//! dynamic typing. Although the compiler uses queries to be able to handle the
//! more involved and loopy dependencies, the representations form a rough chain
//! of processing that each construct flows through (albeit each at its own
//! pace):
//!
//! - **AST**: Abstract Syntax Tree emitted by the parser in the `syntax` crate.
//! - **RST**: Resolved Syntax Tree which has ambiguities in the grammar
//!   resolved. This is possible by building name resolution scopes and defs on
//!   the AST representation, and resolving names to disambiguate things in the
//!   grammar.
//! - **HIR**: The High-level Intermediate Representation, which does things
//!   like taking the list of constructs in a module body and separating them
//!   into lists of declarations, instances, parameters, etc. Also tries to get
//!   rid of syntactic sugar where appropriate. Type-checking is performed on
//!   this representation, and `ParamEnv` is used to represent different
//!   parametrizations of the same HIR module/interface.
//! - **MIR**: The Medium-level Intermediate Representation, which has all
//!   implicit casting operations and parametrizations made explicit and fully
//!   unrolled. At this point most SystemVerilog craziness has been resolved and
//!   the nodes are crisp and have a clean, fully checked type.
//! - **LLHD**: The Low-level Hardware Description, emitted as the final step
//!   during code generation.

#[macro_use]
extern crate moore_common;
#[macro_use]
extern crate log;

pub extern crate moore_svlog_syntax as syntax;
pub(crate) use moore_common as common;

// Inline the salsa crate as a module, since we use a very esoteric branch for
// now.
// TODO(fschuiki): Remove this once salsa is regular dep again
#[macro_use]
mod salsa;

/// Assert that a condition holds, or emit a bug diagnostic and panic.
#[macro_export]
macro_rules! assert_span {
    ($cond:expr, $span:expr, $emitter:expr) => ({
        $crate::assert_span!(@IMPL $cond, $span, $emitter, "assertion failed: {}", stringify!($cond))
    });
    ($cond:expr, $span:expr, $emitter:expr,) => ({
        $crate::assert_span!(@IMPL $cond, $span, $emitter, "assertion failed: {}", stringify!($cond))
    });
    ($cond:expr, $span:expr, $emitter:expr, $($arg:tt)+) => ({
        $crate::assert_span!(@IMPL $cond, $span, $emitter, $($arg)+)
    });
    (@IMPL $cond:expr, $span:expr, $emitter:expr, $($arg:tt)*) => ({
        if !$cond {
            let msg = format!($($arg)*);
            $emitter.emit(
                moore_common::errors::DiagBuilder2::bug(&msg)
                .span($span)
                .add_note(format!("Assertion failed: {}", stringify!($cond)))
                .add_note(format!("Encountered at {}:{}", file!(), line!()))
            );
            panic!("{}", msg);
        }
    });
}

/// Emit a bug diagnostic and panic.
#[macro_export]
macro_rules! bug_span {
    ($span:expr, $emitter:expr, $($arg:tt)+) => ({
        let msg = format!($($arg)*);
        $emitter.emit(
            moore_common::errors::DiagBuilder2::bug(&msg)
            .span($span)
            .add_note(format!("Encountered at {}:{}", file!(), line!()))
        );
        panic!("{}", msg);
    });
}

/// Assert that two types are identical, or emit a bug diagnostic and panic.
#[macro_export]
macro_rules! assert_type {
    ($lhs:expr, $rhs:expr, $span:expr, $emitter:expr) => ({
        $crate::assert_type!($lhs, $rhs, $span, $emitter,)
    });
    ($lhs:expr, $rhs:expr, $span:expr, $emitter:expr,) => ({
        $crate::assert_type!($lhs, $rhs, $span, $emitter, "type assertion failed: `{}` != `{}`", $lhs, $rhs)
    });
    ($lhs:expr, $rhs:expr, $span:expr, $emitter:expr, $($arg:tt)+) => ({
        if !$lhs.is_identical($rhs) {
            let msg = format!($($arg)*);
            $emitter.emit(
                moore_common::errors::DiagBuilder2::bug(&msg)
                .span($span)
                .add_note("Type mismatch:")
                .add_note(format!("    Left-hand side:  `{}`", $lhs))
                .add_note(format!("    Right-hand side: `{}`", $rhs))
                .add_note(format!("Encountered at {}:{}", file!(), line!()))
            );
            panic!("{}", msg);
        }
    });
}

mod ast_map;
mod codegen;
mod context;
pub mod hir;
mod inst_details;
pub mod mir;
mod param_env;
#[warn(missing_docs)]
pub mod pattern_mapping;
pub mod port_list;
mod port_mapping;
pub mod resolver;
pub mod rst;
#[warn(missing_docs)]
pub mod ty;
pub mod typeck;
pub mod value;

pub use moore_common::{
    name::Name,
    source::{Span, Spanned},
};

/// A general result returned by the queries.
pub type Result<T> = std::result::Result<T, ()>;

pub use crate::{
    codegen::CodeGenerator,
    context::*,
    inst_details::{InstDetails, InstTargetDetails, InstVerbosityVisitor},
    param_env::{
        IntoNodeEnvId, NodeEnvId, ParamEnv, ParamEnvBinding, ParamEnvData, ParamEnvSource,
    },
    port_mapping::{PortMapping, PortMappingSource},
    // resolver::*,
    syntax::*,
};

/// Items commonly used within the crate.
mod crate_prelude {
    #[allow(unused_imports)]
    pub(crate) use crate::{
        ast::{AnyNode, AnyNodeData},
        common::{
            errors::*,
            name::Name,
            score::Result,
            source::{Span, Spanned},
            util::{HasDesc, HasSpan},
            NodeId, SessionContext, Verbosity,
        },
        context::{BaseContext, Context, GlobalContext},
        hir, mir, param_env, port_mapping,
        resolver::{Rib, RibKind},
        ty, typeck, value, IntoNodeEnvId, NodeEnvId, Ref, *,
    };
}

/// A node reference.
///
/// This reference is useful when querying the compiler database for information
/// about a node. It compares the reference *by pointer address*, thus allowing
/// for pessimistic compiler queries.
pub struct Ref<'a, T: 'a + ?Sized>(&'a T);

impl<'a, T: ?Sized> Copy for Ref<'a, T> {}

impl<'a, T: ?Sized> Clone for Ref<'a, T> {
    fn clone(&self) -> Self {
        Ref(self.0)
    }
}

impl<'a, T: ?Sized> From<&'a T> for Ref<'a, T> {
    fn from(r: &'a T) -> Ref<'a, T> {
        Ref(r)
    }
}

impl<'a, T: ?Sized> std::ops::Deref for Ref<'a, T> {
    type Target = &'a T;

    fn deref(&self) -> &&'a T {
        &self.0
    }
}

impl<T: ?Sized> Eq for Ref<'_, T> {}

impl<T: ?Sized> PartialEq for Ref<'_, T> {
    fn eq(&self, other: &Self) -> bool {
        std::ptr::eq(self.0, other.0)
    }
}

impl<T: ?Sized> std::hash::Hash for Ref<'_, T> {
    fn hash<H: std::hash::Hasher>(&self, h: &mut H) {
        std::ptr::hash(self.0, h)
    }
}

impl<T: ?Sized> std::fmt::Debug for Ref<'_, T>
where
    T: std::fmt::Debug,
{
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        std::fmt::Debug::fmt(self.0, f)
    }
}

impl<T: ?Sized> std::fmt::Display for Ref<'_, T>
where
    T: std::fmt::Display,
{
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        std::fmt::Display::fmt(self.0, f)
    }
}

/// A few checks to ensure that `Ref` can be passed around properly.
#[allow(dead_code, unused_variables)]
mod checks {
    use super::*;

    trait Dummy {}
    struct Foo;
    impl Dummy for Foo {}

    fn checks1<'a>(x: Ref<'a, impl Dummy>) {}
    fn checks2<'a>(x: Ref<'a, dyn Dummy>) {}

    fn checks3() {
        let foo = Foo;
        checks1(Ref(&foo));
        checks2(Ref(&foo));
    }

    fn checks4<'a>(x: Ref<'a, impl Dummy>) {
        checks2(Ref(*x));
    }

    fn checks5<'a>(x: Ref<'a, dyn Dummy>) {
        checks2(Ref(*x));
    }
}

// Derive the database queries. We group this into a module such that we can
// selectively enable/disable trace messages using `moore_svlog::queries` in the
// `MOORE_LOG` env var.
mod queries {
    use crate::crate_prelude::*;
    #[allow(deprecated)]
    use crate::{
        hir::lowering::*,
        hir::{accessed_nodes, AccessTable},
        inst_details::*,
        param_env::*,
        pattern_mapping::*,
        port_list::{self, *},
        port_mapping::*,
        resolver::*,
        rst::*,
        ty::UnpackedType,
        typeck::*,
        value::*,
    };
    use std::{
        cell::RefCell,
        collections::{HashMap, HashSet},
        sync::Arc,
    };

    moore_derive::derive_query_db! {
        /// A collection of compiler queries.
    }
}
pub use crate::queries::*;
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

//! Implementation of cross-process surfaces for Android. This uses EGL surface.

use texturegl::Texture;

use geom::size::Size2D;
use gleam::gl::{egl_image_target_texture2d_oes, TEXTURE_2D, TexImage2D, BGRA, UNSIGNED_BYTE};
use egl::egl::EGLDisplay;
use egl::eglext::{EGLImageKHR, DestroyImageKHR};
use libc::c_void;
use skia::{SkiaSkNativeSharedGLContextRef, SkiaSkNativeSharedGLContextStealSurface};
use std::iter::repeat;
use std::mem;
use std::ptr;
use std::slice::bytes::copy_memory;
use std::vec::Vec;

/// FIXME(Aydin Kim) :Currently, native surface is consist of 2 types of hybrid image buffer. EGLImageKHR is used to GPU rendering and vector is used to CPU rendering. EGL extension seems not provide simple way to accessing its bitmap directly. In the future, we need to find out the way to integrate them.

#[derive(Clone, Copy)]
pub struct NativeGraphicsMetadata {
    pub display: EGLDisplay,
}
unsafe impl Send for NativeGraphicsMetadata {}

pub struct NativePaintingGraphicsContext{
    display : EGLDisplay,
}

impl NativePaintingGraphicsContext {
    pub fn from_metadata(metadata: &NativeGraphicsMetadata) -> NativePaintingGraphicsContext {
        NativePaintingGraphicsContext {
            display : metadata.display,
        }
    }
}

impl Drop for NativePaintingGraphicsContext {
    fn drop(&mut self) {}
}

#[derive(Copy)]
pub struct NativeCompositingGraphicsContext;

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

pub struct EGLImageNativeSurface {
    image: Option<EGLImageKHR>, // For GPU rendering
    bitmap: Option<Vec<u8>>, // For CPU rendering
    will_leak: bool,
}

unsafe impl Send for EGLImageNativeSurface {}

impl EGLImageNativeSurface {
    pub fn from_image_khr(image_khr: EGLImageKHR) -> EGLImageNativeSurface {
        let mut _image: Option<EGLImageKHR> = None;
        if image_khr != ptr::null_mut() {
            _image = Some(image_khr);
        }
        EGLImageNativeSurface {
            image : _image,
            bitmap: None,
            will_leak: true,
        }
    }

    pub fn from_skia_shared_gl_context(context: SkiaSkNativeSharedGLContextRef)
                                       -> EGLImageNativeSurface {
        unsafe {
            let surface = SkiaSkNativeSharedGLContextStealSurface(context);
            EGLImageNativeSurface::from_image_khr(mem::transmute(surface))
        }
    }

    /// This may only be called on the case of CPU rendering.
    pub fn new(_: &NativePaintingGraphicsContext, size: Size2D<i32>, _stride: i32) -> EGLImageNativeSurface {
        let len = size.width * size.height * 4;
        let bitmap: Vec<u8> = repeat(0).take(len as usize).collect();

        EGLImageNativeSurface {
            image: None,
            bitmap: Some(bitmap),
            will_leak : true,
        }
    }

    /// This may only be called on the compositor side.
    pub fn bind_to_texture(&self,
                           _: &NativeCompositingGraphicsContext,
                           texture: &Texture,
                           size: Size2D<isize>) {
        let _bound = texture.bind();
        match self.image {
            None => match self.bitmap {
                Some(ref bitmap) => {
                    let data = bitmap.as_ptr() as *const c_void;
                    unsafe {
                        TexImage2D(TEXTURE_2D, 0, BGRA as i32, size.width as i32, size.height as i32,
                                   0, BGRA as u32, UNSIGNED_BYTE, data);
                    }
                }
                None => {
                    debug!("Cannot bind the buffer(CPU rendering), there is no bitmap");
                }
            },
            Some(image_khr) => {
                egl_image_target_texture2d_oes(TEXTURE_2D, image_khr as *const c_void);
            }
        }
    }

    /// This may only be called on the painting side.
    pub fn upload(&mut self, _: &NativePaintingGraphicsContext, data: &[u8]) {
        match self.bitmap {
            Some(ref mut bitmap) => {
                copy_memory(bitmap.as_mut_slice(), data);
            }
            None => {
                debug!("Cannot upload the buffer(CPU rendering), there is no bitmap");
            }
        }
    }

    pub fn get_id(&self) -> int {
        match self.image {
            None => 0,
            Some(image_khr) => image_khr as int,
        }
    }

    pub fn destroy(&mut self, graphics_context: &NativePaintingGraphicsContext) {
        match self.image {
            None => {},
            Some(image_khr) => {
                DestroyImageKHR(graphics_context.display, image_khr);
                mem::replace(&mut self.image, None);
            }
        }
        self.mark_wont_leak()
    }

    pub fn mark_will_leak(&mut self) {
        self.will_leak = true
    }

    pub fn mark_wont_leak(&mut self) {
        self.will_leak = false
    }
}
<commit_msg>Use BGRA_EXT on Android<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

//! Implementation of cross-process surfaces for Android. This uses EGL surface.

use texturegl::Texture;

use geom::size::Size2D;
use gleam::gl::{egl_image_target_texture2d_oes, TEXTURE_2D, TexImage2D, BGRA_EXT, UNSIGNED_BYTE};
use egl::egl::EGLDisplay;
use egl::eglext::{EGLImageKHR, DestroyImageKHR};
use libc::c_void;
use skia::{SkiaSkNativeSharedGLContextRef, SkiaSkNativeSharedGLContextStealSurface};
use std::iter::repeat;
use std::mem;
use std::ptr;
use std::slice::bytes::copy_memory;
use std::vec::Vec;

/// FIXME(Aydin Kim) :Currently, native surface is consist of 2 types of hybrid image buffer. EGLImageKHR is used to GPU rendering and vector is used to CPU rendering. EGL extension seems not provide simple way to accessing its bitmap directly. In the future, we need to find out the way to integrate them.

#[derive(Clone, Copy)]
pub struct NativeGraphicsMetadata {
    pub display: EGLDisplay,
}
unsafe impl Send for NativeGraphicsMetadata {}

pub struct NativePaintingGraphicsContext{
    display : EGLDisplay,
}

impl NativePaintingGraphicsContext {
    pub fn from_metadata(metadata: &NativeGraphicsMetadata) -> NativePaintingGraphicsContext {
        NativePaintingGraphicsContext {
            display : metadata.display,
        }
    }
}

impl Drop for NativePaintingGraphicsContext {
    fn drop(&mut self) {}
}

#[derive(Copy)]
pub struct NativeCompositingGraphicsContext;

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

pub struct EGLImageNativeSurface {
    image: Option<EGLImageKHR>, // For GPU rendering
    bitmap: Option<Vec<u8>>, // For CPU rendering
    will_leak: bool,
}

unsafe impl Send for EGLImageNativeSurface {}

impl EGLImageNativeSurface {
    pub fn from_image_khr(image_khr: EGLImageKHR) -> EGLImageNativeSurface {
        let mut _image: Option<EGLImageKHR> = None;
        if image_khr != ptr::null_mut() {
            _image = Some(image_khr);
        }
        EGLImageNativeSurface {
            image : _image,
            bitmap: None,
            will_leak: true,
        }
    }

    pub fn from_skia_shared_gl_context(context: SkiaSkNativeSharedGLContextRef)
                                       -> EGLImageNativeSurface {
        unsafe {
            let surface = SkiaSkNativeSharedGLContextStealSurface(context);
            EGLImageNativeSurface::from_image_khr(mem::transmute(surface))
        }
    }

    /// This may only be called on the case of CPU rendering.
    pub fn new(_: &NativePaintingGraphicsContext, size: Size2D<i32>, _stride: i32) -> EGLImageNativeSurface {
        let len = size.width * size.height * 4;
        let bitmap: Vec<u8> = repeat(0).take(len as usize).collect();

        EGLImageNativeSurface {
            image: None,
            bitmap: Some(bitmap),
            will_leak : true,
        }
    }

    /// This may only be called on the compositor side.
    pub fn bind_to_texture(&self,
                           _: &NativeCompositingGraphicsContext,
                           texture: &Texture,
                           size: Size2D<isize>) {
        let _bound = texture.bind();
        match self.image {
            None => match self.bitmap {
                Some(ref bitmap) => {
                    let data = bitmap.as_ptr() as *const c_void;
                    unsafe {
                        TexImage2D(TEXTURE_2D, 0, BGRA_EXT as i32, size.width as i32, size.height as i32,
                                   0, BGRA_EXT as u32, UNSIGNED_BYTE, data);
                    }
                }
                None => {
                    debug!("Cannot bind the buffer(CPU rendering), there is no bitmap");
                }
            },
            Some(image_khr) => {
                egl_image_target_texture2d_oes(TEXTURE_2D, image_khr as *const c_void);
            }
        }
    }

    /// This may only be called on the painting side.
    pub fn upload(&mut self, _: &NativePaintingGraphicsContext, data: &[u8]) {
        match self.bitmap {
            Some(ref mut bitmap) => {
                copy_memory(bitmap.as_mut_slice(), data);
            }
            None => {
                debug!("Cannot upload the buffer(CPU rendering), there is no bitmap");
            }
        }
    }

    pub fn get_id(&self) -> int {
        match self.image {
            None => 0,
            Some(image_khr) => image_khr as int,
        }
    }

    pub fn destroy(&mut self, graphics_context: &NativePaintingGraphicsContext) {
        match self.image {
            None => {},
            Some(image_khr) => {
                DestroyImageKHR(graphics_context.display, image_khr);
                mem::replace(&mut self.image, None);
            }
        }
        self.mark_wont_leak()
    }

    pub fn mark_will_leak(&mut self) {
        self.will_leak = true
    }

    pub fn mark_wont_leak(&mut self) {
        self.will_leak = false
    }
}
<|endoftext|>


<commit_before>use LalafellBot;
use listeners::ReceivesEvents;
use commands::*;
use discord::model::{Event, Message, ReactionEmoji};

use std::sync::Arc;
use std::collections::HashMap;

pub struct CommandListener<'a> {
  bot: Arc<LalafellBot>,
  commands: HashMap<Vec<String>, Box<Command<'a> + Send + Sync>>
}

impl<'a> CommandListener<'a> {
  pub fn new(bot: Arc<LalafellBot>) -> CommandListener<'a> {
    CommandListener {
      bot: bot,
      commands: Default::default()
    }
  }

  pub fn add_command<T: AsRef<str>>(&mut self, names: &[T], command: Box<Command<'a> + Send + Sync>) {
    self.commands.insert(names.iter().map(|t| t.as_ref().to_string()).collect(), command);
  }

  fn check_command(&self, message: &Message) {
    let parts: Vec<&str> = message.content.split_whitespace().collect();
    if parts.is_empty() {
      return;
    }
    let first = parts[0];
    if !first.starts_with('!') {
      return;
    }
    let command_name = &first[1..].to_lowercase();
    let params = &parts[1..];
    let (_, command) = match self.commands.iter().find(|&(names, _)| names.contains(&command_name.to_lowercase())) {
      Some(c) => c,
      None => return
    };
    let run_result = command.run(message, params);
    let command_success = run_result.is_ok();
    match run_result {
      Ok(info) => {
        match info.message {
          Some(embed) => {
            let color = if command_success { 1663832 } else { 6494491 };
            self.bot.discord.send_embed(message.channel_id, "", |e| embed(e).color(color)).ok();
          },
          None => {
            let emoji = if command_success { "\u{2705}" } else { "\u{274c}" };
            self.bot.discord.add_reaction(message.channel_id, message.id, ReactionEmoji::Unicode(emoji.to_string())).ok();
          }
        }
      },
      Err(CommandFailure::Internal(info)) => {
        self.bot.discord.send_embed(message.channel_id, "",
                                    |e| e.description("An internal error happened while processing this command.")).ok();
        for err in info.error.iter() {
          error!("error: {:#?}", err);
        }
      },
      Err(CommandFailure::External(info)) => {
        if let Some(embed) = info.message {
          self.bot.discord.send_embed(message.channel_id, "", embed).ok();
        }
      }
    }
  }
}

impl<'a> ReceivesEvents for CommandListener<'a> {
  fn receive(&self, event: &Event) {
    let message = match *event {
      Event::MessageCreate(ref m) => m,
      _ => return
    };
    self.check_command(message);
  }
}
<commit_msg>refactor: represent colors as hex<commit_after>use LalafellBot;
use listeners::ReceivesEvents;
use commands::*;
use discord::model::{Event, Message, ReactionEmoji};

use std::sync::Arc;
use std::collections::HashMap;

pub struct CommandListener<'a> {
  bot: Arc<LalafellBot>,
  commands: HashMap<Vec<String>, Box<Command<'a> + Send + Sync>>
}

impl<'a> CommandListener<'a> {
  pub fn new(bot: Arc<LalafellBot>) -> CommandListener<'a> {
    CommandListener {
      bot: bot,
      commands: Default::default()
    }
  }

  pub fn add_command<T: AsRef<str>>(&mut self, names: &[T], command: Box<Command<'a> + Send + Sync>) {
    self.commands.insert(names.iter().map(|t| t.as_ref().to_string()).collect(), command);
  }

  fn check_command(&self, message: &Message) {
    let parts: Vec<&str> = message.content.split_whitespace().collect();
    if parts.is_empty() {
      return;
    }
    let first = parts[0];
    if !first.starts_with('!') {
      return;
    }
    let command_name = &first[1..].to_lowercase();
    let params = &parts[1..];
    let (_, command) = match self.commands.iter().find(|&(names, _)| names.contains(&command_name.to_lowercase())) {
      Some(c) => c,
      None => return
    };
    let run_result = command.run(message, params);
    let command_success = run_result.is_ok();
    match run_result {
      Ok(info) => {
        match info.message {
          Some(embed) => {
            let color = if command_success { 0x196358 } else { 0x63191b };
            self.bot.discord.send_embed(message.channel_id, "", |e| embed(e).color(color)).ok();
          },
          None => {
            let emoji = if command_success { "\u{2705}" } else { "\u{274c}" };
            self.bot.discord.add_reaction(message.channel_id, message.id, ReactionEmoji::Unicode(emoji.to_string())).ok();
          }
        }
      },
      Err(CommandFailure::Internal(info)) => {
        self.bot.discord.send_embed(message.channel_id, "",
                                    |e| e.description("An internal error happened while processing this command.")).ok();
        for err in info.error.iter() {
          error!("error: {:#?}", err);
        }
      },
      Err(CommandFailure::External(info)) => {
        if let Some(embed) = info.message {
          self.bot.discord.send_embed(message.channel_id, "", embed).ok();
        }
      }
    }
  }
}

impl<'a> ReceivesEvents for CommandListener<'a> {
  fn receive(&self, event: &Event) {
    let message = match *event {
      Event::MessageCreate(ref m) => m,
      _ => return
    };
    self.check_command(message);
  }
}
<|endoftext|>


<commit_before>#![recursion_limit = "256"]

#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

extern crate syn;
#[macro_use]
extern crate quote;
use syn::*;
extern crate glob;
use glob::glob;

use std::fs::{File, metadata};
use std::io::Read;
use std::io::Write;
use std::process::Command;

extern crate ordermap;
use ordermap::OrderMap;

mod generators;
mod parsers;
use parsers::parse;

pub fn scan_and_generate(src_prefix: &str) {
    for maybe_mod_path in glob(&format!("{}/**/mod.rs", src_prefix)).unwrap() {
        if let Ok(mod_path) = maybe_mod_path {
            //println!("cargo:warning={:?}", mod_path);
            let auto_path = mod_path
                .clone()
                .to_str()
                .unwrap()
                .replace("mod.rs", "kay_auto.rs");
            if let Ok(src_meta) = metadata(&mod_path) {
                let regenerate = match metadata(&auto_path) {
                    Ok(auto_meta) => src_meta.modified().unwrap() > auto_meta.modified().unwrap(),
                    _ => true,
                };

                if regenerate {
                    let auto_file = if let Ok(ref mut file) = File::open(&mod_path) {
                        let mut file_str = String::new();
                        file.read_to_string(&mut file_str).unwrap();
                        match parse(&file_str) {
                            Ok(model) => generate(&model),
                            Err(error) => panic!("PARSE ERROR:\n {:?}", error),
                        }
                    } else {
                        panic!("couldn't load");
                    };

                    if let Ok(ref mut file) = File::create(&auto_path) {
                        file.write_all(auto_file.as_bytes()).unwrap();
                    }

                    let _ = Command::new("rustfmt")
                        .arg(&auto_path)
                        .arg("--backup")
                        .spawn();
                }
            } else {
                panic!("couldn't load");
            };
        }
    }
}

type ActorName = Ty;
type TraitName = syn::Path;

#[derive(Default)]
pub struct Model {
    pub actors: OrderMap<ActorName, ActorDef>,
    pub traits: OrderMap<TraitName, TraitDef>,
}

#[derive(Default)]
pub struct ActorDef {
    pub handlers: Vec<Handler>,
    pub impls: Vec<TraitName>,
    pub defined_here: bool,
}

#[derive(Default)]
pub struct TraitDef {
    pub handlers: Vec<Handler>,
}

#[derive(Clone)]
pub struct Handler {
    name: Ident,
    arguments: Vec<FnArg>,
    scope: HandlerType,
    critical: bool,
    returns_fate: bool,
    from_trait: Option<TraitName>,
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum HandlerType {
    Handler,
    Init,
}

pub fn generate(model: &Model) -> String {
    let traits_msgs = model.generate_traits();
    let actors_msgs = model.generate_actor_ids_messages_and_conversions();
    let setup = model.generate_setups();

    quote!(
        //! This is all auto-generated. Do not touch.
        #[allow(unused_imports)]
        use kay::{ActorSystem, TypedID, RawID, Fate, Actor, TraitIDFrom};
        #[allow(unused_imports)]
        use super::*;

        #traits_msgs
        #actors_msgs

        #[allow(unused_variables)]
        #[allow(unused_mut)]
        pub fn auto_setup(system: &mut ActorSystem) {
            #setup
        }

    ).into_string()
}

#[test]
fn simple_actor() {
    let input = quote!(
        pub struct SomeActor {
            id: Option<SomeActorID>,
            field: usize
        }

        impl SomeActor {
            pub fn some_method(&mut self, some_param: &usize, world: &mut World) {
                self.id().some_method(42, world);
            }

            pub fn no_params_fate(&mut self, world: &mut World) -> Fate {
                Fate::Die
            }

            pub fn init_ish(id: SomeActorID, some_param: &usize, world: &mut World) -> SomeActor {
                SomeActor {
                    id: Some(id),
                    field: some_param
                }
            }
        }
    );
    let expected = quote!(
        //! This is all auto-generated. Do not touch.
        #[allow(unused_imports)]
        use kay::{ActorSystem, TypedID, RawID, Fate, Actor, TraitIDFrom};
        use super::*;

        impl Actor for SomeActor {
            type ID = SomeActorID;

            fn id(&self) -> Self::ID {
                self.id
            }
            unsafe fn set_id(&mut self, id: RawID) {
                self.id = Self::ID::from_raw(id);
            }
        }

        #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
        pub struct SomeActorID {
            _raw_id: RawID
        }

        impl TypedID for SomeActorID {
            unsafe fn from_raw(id: RawID) -> Self {
                SomeActorID { _raw_id: id }
            }

            fn as_raw(&self) -> RawID {
                self._raw_id
            }
        }

        impl SomeActorID {
            pub fn some_method(&self, some_param: usize, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeActor_some_method(some_param));
            }

            pub fn no_params_fate(&self, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeActor_no_params_fate());
            }

            pub fn init_ish(some_param: usize, world: &mut World) -> Self {
                let id = unsafe{
                    SomeActorID::from_raw(world.allocate_instance_id::<SomeActor>())
                };
                let swarm = world.local_broadcast::<SomeActor>();
                world.send(swarm, MSG_SomeActor_init_ish(id, some_param));
                id
            }
        }

        #[allow(non_camel_case_types)]
        #[derive(Compact, Clone)]
        struct MSG_SomeActor_some_method(pub usize);
        #[allow(non_camel_case_types)]
        #[derive(Copy, Clone)]
        struct MSG_SomeActor_no_params_fate();
        #[allow(non_camel_case_types)]
        #[derive(Compact, Clone)]
        struct MSG_SomeActor_init_ish(pub SomeActorID, pub usize);

        #[allow(unused_variables)]
        #[allow(unused_mut)]
        pub fn auto_setup(system: &mut ActorSystem) {
            system.add_handler::<SomeActor, _, _>(
                |&MSG_SomeActor_some_method(ref some_param), instance, world| {
                instance.some_method(some_param, world);
                Fate::Live
            }, false);

            system.add_handler::<SomeActor, _, _>(
                |&MSG_SomeActor_no_params_fate(), instance, world| {
                instance.no_params_fate(world)
            }, false);

            system.add_spawner::<SomeActor, _, _>(
                |&MSG_SomeActor_init_ish(id, ref some_param), world| {
                SomeActor::init_ish(id, some_param, world)
            }, false);
        }
    );

    assert_eq!(
        expected.into_string(),
        generate(&parse(&input.into_string()).unwrap())
    );
}

#[test]
fn trait_and_impl() {
    let input = quote!(
        pub struct SomeActor {
            _id: Option<SomeActorID>,
            field: usize
        }

        trait SomeTrait {
            fn some_method(&mut self, some_param: &usize, world: &mut World);
            fn no_params_fate(&mut self, world: &mut World) -> Fate;
            fn some_default_impl_method(&mut self, world: &mut World) {
                self.some_method(3, world);
            }
        }

        impl SomeTrait for SomeActor {
            fn some_method(&mut self, some_param: &usize, world: &mut World) {
                self.id().some_method(42, world);
            }

            fn no_params_fate(&mut self, world: &mut World) -> Fate {
                Fate::Die
            }
        }

        impl ForeignTrait for SomeActor {
            fn simple(&mut self, some_param: &usize, world: &mut World) {
                self.id().some_method(some_param, world);
            }
        }

        // This shouldn't generate any RawID
        impl Deref for SomeActor {
            type Target = usize;
            fn deref(&self) -> &usize {
                &self.field
            }
        }
    );
    let expected = quote!(
        //! This is all auto-generated. Do not touch.
        #[allow(unused_imports)]
        use kay::{ActorSystem, TypedID, RawID, Fate, Actor, TraitIDFrom};
        use super::*;

        #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
        pub struct SomeTraitID {
            _raw_id: RawID
        }

        impl TypedID for SomeTraitID {
            unsafe fn from_raw(id: RawID) -> Self {
                SomeTraitID { _raw_id: id }
            }

            fn as_raw(&self) -> RawID {
                self._raw_id
            }
        }

        impl<A: Actor + SomeTrait> TraitIDFrom<A> for SomeTraitID {}

        impl SomeTraitID {
            pub fn some_method(&self, some_param: usize, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeTrait_some_method(some_param));
            }

            pub fn no_params_fate(&self, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeTrait_no_params_fate());
            }

            pub fn some_default_impl_method(&self, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeTrait_some_default_impl_method());
            }

            pub fn register_handlers<A: Actor + SomeTrait>(system: &mut ActorSystem) {
                system.add_handler::<A, _, _>(
                    |&MSG_SomeTrait_some_method(ref some_param), instance, world| {
                    instance.some_method(some_param, world);
                    Fate::Live
                }, false);

                system.add_handler::<A, _, _>(
                    |&MSG_SomeTrait_no_params_fate(), instance, world| {
                    instance.no_params_fate(world)
                }, false);

                system.add_handler::<A, _, _>(
                    |&MSG_SomeTrait_some_default_impl_method(), instance, world| {
                    instance.some_default_impl_method(world);
                    Fate::Live
                }, false);
            }
        }

        #[allow(non_camel_case_types)]
        #[derive(Compact, Clone)]
        struct MSG_SomeTrait_some_method(pub usize);
        #[allow(non_camel_case_types)]
        #[derive(Copy, Clone)]
        struct MSG_SomeTrait_no_params_fate();
        #[allow(non_camel_case_types)]
        #[derive(Copy, Clone)]
        struct MSG_SomeTrait_some_default_impl_method();

        impl Actor for SomeActor {
            type ID = SomeActorID;

            fn id(&self) -> Self::ID {
                self.id
            }
            unsafe fn set_id(&mut self, id: RawID) {
                self.id = Self::ID::from_raw(id);
            }
        }

        #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
        pub struct SomeActorID {
            _raw_id: RawID
        }

        impl TypedID for SomeActorID {
            unsafe fn from_raw(id: RawID) -> Self {
                SomeActorID { _raw_id: id }
            }

            fn as_raw(&self) -> RawID {
                self._raw_id
            }
        }

        impl SomeActorID { }

        impl Into<SomeTraitID> for SomeActorID {
            fn into(self) -> SomeTraitID {
                unsafe {SomeTraitID::from_raw(self.as_raw())}
            }
        }

        impl Into<ForeignTraitID> for SomeActorID {
            fn into(self) -> ForeignTraitID {
                unsafe {ForeignTraitID::from_raw(self.as_raw())}
            }
        }

        #[allow(unused_variables)]
        #[allow(unused_mut)]
        pub fn auto_setup(system: &mut ActorSystem) {
            SomeTraitID::register_handlers::<SomeActor>(system);
            ForeignTraitID::register_handlers::<SomeActor>(system);
        }
    );

    assert_eq!(
        expected.into_string(),
        generate(&parse(&input.into_string()).unwrap())
    );
}
<commit_msg>Remove format backup for kay_auto.rs<commit_after>#![recursion_limit = "256"]

#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

extern crate syn;
#[macro_use]
extern crate quote;
use syn::*;
extern crate glob;
use glob::glob;

use std::fs::{File, metadata};
use std::io::Read;
use std::io::Write;
use std::process::Command;

extern crate ordermap;
use ordermap::OrderMap;

mod generators;
mod parsers;
use parsers::parse;

pub fn scan_and_generate(src_prefix: &str) {
    for maybe_mod_path in glob(&format!("{}/**/mod.rs", src_prefix)).unwrap() {
        if let Ok(mod_path) = maybe_mod_path {
            //println!("cargo:warning={:?}", mod_path);
            let auto_path = mod_path
                .clone()
                .to_str()
                .unwrap()
                .replace("mod.rs", "kay_auto.rs");
            if let Ok(src_meta) = metadata(&mod_path) {
                let regenerate = match metadata(&auto_path) {
                    Ok(auto_meta) => src_meta.modified().unwrap() > auto_meta.modified().unwrap(),
                    _ => true,
                };

                if regenerate {
                    let auto_file = if let Ok(ref mut file) = File::open(&mod_path) {
                        let mut file_str = String::new();
                        file.read_to_string(&mut file_str).unwrap();
                        match parse(&file_str) {
                            Ok(model) => generate(&model),
                            Err(error) => panic!("PARSE ERROR:\n {:?}", error),
                        }
                    } else {
                        panic!("couldn't load");
                    };

                    if let Ok(ref mut file) = File::create(&auto_path) {
                        file.write_all(auto_file.as_bytes()).unwrap();
                    }

                    let _ = Command::new("rustfmt")
                        .arg(&auto_path)
                        .spawn();
                }
            } else {
                panic!("couldn't load");
            };
        }
    }
}

type ActorName = Ty;
type TraitName = syn::Path;

#[derive(Default)]
pub struct Model {
    pub actors: OrderMap<ActorName, ActorDef>,
    pub traits: OrderMap<TraitName, TraitDef>,
}

#[derive(Default)]
pub struct ActorDef {
    pub handlers: Vec<Handler>,
    pub impls: Vec<TraitName>,
    pub defined_here: bool,
}

#[derive(Default)]
pub struct TraitDef {
    pub handlers: Vec<Handler>,
}

#[derive(Clone)]
pub struct Handler {
    name: Ident,
    arguments: Vec<FnArg>,
    scope: HandlerType,
    critical: bool,
    returns_fate: bool,
    from_trait: Option<TraitName>,
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum HandlerType {
    Handler,
    Init,
}

pub fn generate(model: &Model) -> String {
    let traits_msgs = model.generate_traits();
    let actors_msgs = model.generate_actor_ids_messages_and_conversions();
    let setup = model.generate_setups();

    quote!(
        //! This is all auto-generated. Do not touch.
        #[allow(unused_imports)]
        use kay::{ActorSystem, TypedID, RawID, Fate, Actor, TraitIDFrom};
        #[allow(unused_imports)]
        use super::*;

        #traits_msgs
        #actors_msgs

        #[allow(unused_variables)]
        #[allow(unused_mut)]
        pub fn auto_setup(system: &mut ActorSystem) {
            #setup
        }

    ).into_string()
}

#[test]
fn simple_actor() {
    let input = quote!(
        pub struct SomeActor {
            id: Option<SomeActorID>,
            field: usize
        }

        impl SomeActor {
            pub fn some_method(&mut self, some_param: &usize, world: &mut World) {
                self.id().some_method(42, world);
            }

            pub fn no_params_fate(&mut self, world: &mut World) -> Fate {
                Fate::Die
            }

            pub fn init_ish(id: SomeActorID, some_param: &usize, world: &mut World) -> SomeActor {
                SomeActor {
                    id: Some(id),
                    field: some_param
                }
            }
        }
    );
    let expected = quote!(
        //! This is all auto-generated. Do not touch.
        #[allow(unused_imports)]
        use kay::{ActorSystem, TypedID, RawID, Fate, Actor, TraitIDFrom};
        use super::*;

        impl Actor for SomeActor {
            type ID = SomeActorID;

            fn id(&self) -> Self::ID {
                self.id
            }
            unsafe fn set_id(&mut self, id: RawID) {
                self.id = Self::ID::from_raw(id);
            }
        }

        #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
        pub struct SomeActorID {
            _raw_id: RawID
        }

        impl TypedID for SomeActorID {
            unsafe fn from_raw(id: RawID) -> Self {
                SomeActorID { _raw_id: id }
            }

            fn as_raw(&self) -> RawID {
                self._raw_id
            }
        }

        impl SomeActorID {
            pub fn some_method(&self, some_param: usize, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeActor_some_method(some_param));
            }

            pub fn no_params_fate(&self, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeActor_no_params_fate());
            }

            pub fn init_ish(some_param: usize, world: &mut World) -> Self {
                let id = unsafe{
                    SomeActorID::from_raw(world.allocate_instance_id::<SomeActor>())
                };
                let swarm = world.local_broadcast::<SomeActor>();
                world.send(swarm, MSG_SomeActor_init_ish(id, some_param));
                id
            }
        }

        #[allow(non_camel_case_types)]
        #[derive(Compact, Clone)]
        struct MSG_SomeActor_some_method(pub usize);
        #[allow(non_camel_case_types)]
        #[derive(Copy, Clone)]
        struct MSG_SomeActor_no_params_fate();
        #[allow(non_camel_case_types)]
        #[derive(Compact, Clone)]
        struct MSG_SomeActor_init_ish(pub SomeActorID, pub usize);

        #[allow(unused_variables)]
        #[allow(unused_mut)]
        pub fn auto_setup(system: &mut ActorSystem) {
            system.add_handler::<SomeActor, _, _>(
                |&MSG_SomeActor_some_method(ref some_param), instance, world| {
                instance.some_method(some_param, world);
                Fate::Live
            }, false);

            system.add_handler::<SomeActor, _, _>(
                |&MSG_SomeActor_no_params_fate(), instance, world| {
                instance.no_params_fate(world)
            }, false);

            system.add_spawner::<SomeActor, _, _>(
                |&MSG_SomeActor_init_ish(id, ref some_param), world| {
                SomeActor::init_ish(id, some_param, world)
            }, false);
        }
    );

    assert_eq!(
        expected.into_string(),
        generate(&parse(&input.into_string()).unwrap())
    );
}

#[test]
fn trait_and_impl() {
    let input = quote!(
        pub struct SomeActor {
            _id: Option<SomeActorID>,
            field: usize
        }

        trait SomeTrait {
            fn some_method(&mut self, some_param: &usize, world: &mut World);
            fn no_params_fate(&mut self, world: &mut World) -> Fate;
            fn some_default_impl_method(&mut self, world: &mut World) {
                self.some_method(3, world);
            }
        }

        impl SomeTrait for SomeActor {
            fn some_method(&mut self, some_param: &usize, world: &mut World) {
                self.id().some_method(42, world);
            }

            fn no_params_fate(&mut self, world: &mut World) -> Fate {
                Fate::Die
            }
        }

        impl ForeignTrait for SomeActor {
            fn simple(&mut self, some_param: &usize, world: &mut World) {
                self.id().some_method(some_param, world);
            }
        }

        // This shouldn't generate any RawID
        impl Deref for SomeActor {
            type Target = usize;
            fn deref(&self) -> &usize {
                &self.field
            }
        }
    );
    let expected = quote!(
        //! This is all auto-generated. Do not touch.
        #[allow(unused_imports)]
        use kay::{ActorSystem, TypedID, RawID, Fate, Actor, TraitIDFrom};
        use super::*;

        #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
        pub struct SomeTraitID {
            _raw_id: RawID
        }

        impl TypedID for SomeTraitID {
            unsafe fn from_raw(id: RawID) -> Self {
                SomeTraitID { _raw_id: id }
            }

            fn as_raw(&self) -> RawID {
                self._raw_id
            }
        }

        impl<A: Actor + SomeTrait> TraitIDFrom<A> for SomeTraitID {}

        impl SomeTraitID {
            pub fn some_method(&self, some_param: usize, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeTrait_some_method(some_param));
            }

            pub fn no_params_fate(&self, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeTrait_no_params_fate());
            }

            pub fn some_default_impl_method(&self, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeTrait_some_default_impl_method());
            }

            pub fn register_handlers<A: Actor + SomeTrait>(system: &mut ActorSystem) {
                system.add_handler::<A, _, _>(
                    |&MSG_SomeTrait_some_method(ref some_param), instance, world| {
                    instance.some_method(some_param, world);
                    Fate::Live
                }, false);

                system.add_handler::<A, _, _>(
                    |&MSG_SomeTrait_no_params_fate(), instance, world| {
                    instance.no_params_fate(world)
                }, false);

                system.add_handler::<A, _, _>(
                    |&MSG_SomeTrait_some_default_impl_method(), instance, world| {
                    instance.some_default_impl_method(world);
                    Fate::Live
                }, false);
            }
        }

        #[allow(non_camel_case_types)]
        #[derive(Compact, Clone)]
        struct MSG_SomeTrait_some_method(pub usize);
        #[allow(non_camel_case_types)]
        #[derive(Copy, Clone)]
        struct MSG_SomeTrait_no_params_fate();
        #[allow(non_camel_case_types)]
        #[derive(Copy, Clone)]
        struct MSG_SomeTrait_some_default_impl_method();

        impl Actor for SomeActor {
            type ID = SomeActorID;

            fn id(&self) -> Self::ID {
                self.id
            }
            unsafe fn set_id(&mut self, id: RawID) {
                self.id = Self::ID::from_raw(id);
            }
        }

        #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
        pub struct SomeActorID {
            _raw_id: RawID
        }

        impl TypedID for SomeActorID {
            unsafe fn from_raw(id: RawID) -> Self {
                SomeActorID { _raw_id: id }
            }

            fn as_raw(&self) -> RawID {
                self._raw_id
            }
        }

        impl SomeActorID { }

        impl Into<SomeTraitID> for SomeActorID {
            fn into(self) -> SomeTraitID {
                unsafe {SomeTraitID::from_raw(self.as_raw())}
            }
        }

        impl Into<ForeignTraitID> for SomeActorID {
            fn into(self) -> ForeignTraitID {
                unsafe {ForeignTraitID::from_raw(self.as_raw())}
            }
        }

        #[allow(unused_variables)]
        #[allow(unused_mut)]
        pub fn auto_setup(system: &mut ActorSystem) {
            SomeTraitID::register_handlers::<SomeActor>(system);
            ForeignTraitID::register_handlers::<SomeActor>(system);
        }
    );

    assert_eq!(
        expected.into_string(),
        generate(&parse(&input.into_string()).unwrap())
    );
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate time;
extern crate columnar;
extern crate timely;
extern crate differential_dataflow;

extern crate docopt;
use docopt::Docopt;

use std::thread;
use std::fs::File;
use std::io::{BufRead, BufReader};

use timely::example_shared::*;
use timely::example_shared::operators::*;
use timely::communication::*;
use timely::networking::initialize_networking;
use timely::networking::initialize_networking_from_file;

use timely::drain::DrainExt;

// use differential_dataflow::collection_trace::lookup::UnsignedInt;
// use differential_dataflow::collection_trace::LeastUpperBound;

use differential_dataflow::operators::*;

// The typical differential dataflow vertex receives updates of the form (key, time, value, update),
// where the data are logically partitioned by key, and are then subject to various aggregations by time,
// accumulating for each value the update integers. The resulting multiset is the subjected to computation.

// The implementation I am currently most comfortable with is *conservative* in the sense that it will defer updates
// until it has received all updates for a time, at which point it commits these updates permanently. This is done
// to avoid issues with running logic on partially formed data, but should also simplify our data management story.
// Rather than requiring random access to diffs, we can store them as flat arrays (possibly sorted) and integrate
// them using merge techniques. Updating cached accumulations seems maybe harder w/o hashmaps, but we'll see...

static USAGE: &'static str = "
Usage: tpch17 [options] [<arguments>...] <parts> <items>

Options:
    -w <arg>, --workers <arg>    number of workers per process [default: 1]
    -p <arg>, --processid <arg>  identity of this process      [default: 0]
    -n <arg>, --processes <arg>  number of processes involved  [default: 1]
    -h <arg>, --hosts <arg>      list of host:port for workers
";

fn main() {

    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    let workers: u64 = if let Ok(threads) = args.get_str("-w").parse() { threads }
                       else { panic!("invalid setting for --workers: {}", args.get_str("-t")) };
    let process_id: u64 = if let Ok(proc_id) = args.get_str("-p").parse() { proc_id }
                          else { panic!("invalid setting for --processid: {}", args.get_str("-p")) };
    let processes: u64 = if let Ok(processes) = args.get_str("-n").parse() { processes }
                         else { panic!("invalid setting for --processes: {}", args.get_str("-n")) };

    println!("Starting timely with");
    println!("\tworkers:\t{}", workers);
    println!("\tprocesses:\t{}", processes);
    println!("\tprocessid:\t{}", process_id);

    let parts_file = args.get_str("<parts>").to_owned();
    let items_file = args.get_str("<items>").to_owned();

    // vector holding communicators to use; one per local worker.
    if processes > 1 {
        println!("Initializing BinaryCommunicator");

        let hosts = args.get_str("-h");
        let communicators = if hosts != "" {
            initialize_networking_from_file(hosts, process_id, workers).ok().expect("error initializing networking")
        }
        else {
            let addresses = (0..processes).map(|index| format!("localhost:{}", 2101 + index).to_string()).collect();
            initialize_networking(addresses, process_id, workers).ok().expect("error initializing networking")
        };

        start_main(communicators, parts_file, items_file);
    }
    else if workers > 1 {
        println!("Initializing ProcessCommunicator");
        start_main(ProcessCommunicator::new_vector(workers), parts_file, items_file);
    }
    else {
        println!("Initializing ThreadCommunicator");
        start_main(vec![ThreadCommunicator], parts_file, items_file);
    };
}

fn start_main<C: Communicator+Send>(communicators: Vec<C>, parts_pattern: String, items_pattern: String) {
    // let communicators = ProcessCommunicator::new_vector(1);
    let mut guards = Vec::new();
    for communicator in communicators.into_iter() {
        let parts = parts_pattern.clone();
        let items = items_pattern.clone();
        guards.push(thread::Builder::new().name(format!("worker thread {}", communicator.index()))
                                          .spawn(move || test_dataflow(communicator, parts, items))
                                          .unwrap());
    }

    for guard in guards { guard.join().unwrap(); }
}

fn test_dataflow<C: Communicator>(communicator: C, parts_pattern: String, items_pattern: String) {

    let start = time::precise_time_s();
    let mut computation = GraphRoot::new(communicator);

    let (mut parts, mut items) = computation.subcomputation(|builder| {

        let (part_input, parts) = builder.new_input::<((u32, String, String), i32)>();
        let (item_input, items) = builder.new_input::<((u32, u32, u64), i32)>();

        // compute the average quantities
        let average = items.group_by_u(|(x,y,_)| (x,y), |k,v| (*k,*v), |_,s,t| {
            let mut sum = 0;
            let mut cnt = 0;
            for &(val,wgt) in s.iter() {
                cnt += wgt;
                sum += val;
            }
            t.push((sum / cnt as u32, 1));
        });

        // filter parts by brand and container
        let parts = parts.filter(|x| (x.0).1 == "Brand#33" && (x.0).2 == "WRAP PACK")
                         .map(|((key, _, _), wgt)| (key, wgt));

        // join items against their averages, filter by quantity, remove filter coordinate
        let items = items.join_u(&average, |x| (x.0, (x.1, x.2)), |y| y, |k, x, f| (*k, x.0, x.1, *f))
                         .filter(|&((_, q, _, avg),_)| q < avg / 5)
                         .map(|((key,_,price,_), wgt)| ((key,price), wgt));

        // semi-join against the part keys we retained. think of a better way to produce sum ...
        parts.join_u(&items, |k| (k,()), |(k,p)| (k,p), |_,_,p| *p)
             .inspect_batch(|_t,x| println!("results: {:?}", x.len()));

        (part_input, item_input)
    });

    if let Ok(parts_file) = File::open(format!("{}-{}", parts_pattern, computation.index())) {

        let mut parts_buffer = Vec::new();
        let parts_reader = BufReader::new(parts_file);

        for line in parts_reader.lines() {
            let text = line.ok().expect("read error");
            let mut fields = text.split(" ");

            let part_id = fields.next().unwrap().parse::<u32>().unwrap();
            fields.next();
            fields.next();
            let brand = fields.next().unwrap().to_owned();
            fields.next();
            fields.next();
            let container = fields.next().unwrap().to_owned();

            parts_buffer.push(((part_id, brand, container), 1));
            if parts_buffer.len() == 1024 {
                parts.send_at(0u64, parts_buffer.drain_temp());
                computation.step();

            }
        }

        parts.send_at(0u64, parts_buffer.drain_temp());
        computation.step();
    }
    else { println!("worker {}: did not find input {}-{}", computation.index(), parts_pattern, computation.index()); }

    if let Ok(items_file) = File::open(format!("{}-{}", items_pattern, computation.index())) {
        let mut items_buffer = Vec::new();
        let items_reader =  BufReader::new(items_file);
        for line in items_reader.lines() {
            let text = line.ok().expect("read error");
            let mut fields = text.split(" ");

            fields.next();
            let item_id = fields.next().unwrap().parse::<u32>().unwrap();
            fields.next();
            fields.next();
            let quantity = fields.next().unwrap().parse::<u32>().unwrap();
            let extended_price = fields.next().unwrap().parse::<f64>().unwrap() as u64;

            items_buffer.push(((item_id, quantity, extended_price), 1));
            if items_buffer.len() == 1024 {
                items.send_at(0u64, items_buffer.drain_temp());
                computation.step();
            }
        }

        items.send_at(0u64, items_buffer.drain_temp());
        computation.step();
    }
    else { println!("worker {}: did not find input {}-{}", computation.index(), items_pattern, computation.index()); }

    println!("data loaded at {}", time::precise_time_s() - start);

    parts.close();
    items.close();

    while computation.step() { std::thread::yield_now(); }
    computation.step(); // shut down

    println!("computation finished at {}", time::precise_time_s() - start);
}
<commit_msg>updated query fields<commit_after>extern crate rand;
extern crate time;
extern crate columnar;
extern crate timely;
extern crate differential_dataflow;

extern crate docopt;
use docopt::Docopt;

use std::thread;
use std::fs::File;
use std::io::{BufRead, BufReader};

use timely::example_shared::*;
use timely::example_shared::operators::*;
use timely::communication::*;
use timely::networking::initialize_networking;
use timely::networking::initialize_networking_from_file;

use timely::drain::DrainExt;

// use differential_dataflow::collection_trace::lookup::UnsignedInt;
// use differential_dataflow::collection_trace::LeastUpperBound;

use differential_dataflow::operators::*;

// The typical differential dataflow vertex receives updates of the form (key, time, value, update),
// where the data are logically partitioned by key, and are then subject to various aggregations by time,
// accumulating for each value the update integers. The resulting multiset is the subjected to computation.

// The implementation I am currently most comfortable with is *conservative* in the sense that it will defer updates
// until it has received all updates for a time, at which point it commits these updates permanently. This is done
// to avoid issues with running logic on partially formed data, but should also simplify our data management story.
// Rather than requiring random access to diffs, we can store them as flat arrays (possibly sorted) and integrate
// them using merge techniques. Updating cached accumulations seems maybe harder w/o hashmaps, but we'll see...

static USAGE: &'static str = "
Usage: tpch17 [options] [<arguments>...] <parts> <items>

Options:
    -w <arg>, --workers <arg>    number of workers per process [default: 1]
    -p <arg>, --processid <arg>  identity of this process      [default: 0]
    -n <arg>, --processes <arg>  number of processes involved  [default: 1]
    -h <arg>, --hosts <arg>      list of host:port for workers
";

fn main() {

    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    let workers: u64 = if let Ok(threads) = args.get_str("-w").parse() { threads }
                       else { panic!("invalid setting for --workers: {}", args.get_str("-t")) };
    let process_id: u64 = if let Ok(proc_id) = args.get_str("-p").parse() { proc_id }
                          else { panic!("invalid setting for --processid: {}", args.get_str("-p")) };
    let processes: u64 = if let Ok(processes) = args.get_str("-n").parse() { processes }
                         else { panic!("invalid setting for --processes: {}", args.get_str("-n")) };

    println!("Starting timely with");
    println!("\tworkers:\t{}", workers);
    println!("\tprocesses:\t{}", processes);
    println!("\tprocessid:\t{}", process_id);

    let parts_file = args.get_str("<parts>").to_owned();
    let items_file = args.get_str("<items>").to_owned();

    // vector holding communicators to use; one per local worker.
    if processes > 1 {
        println!("Initializing BinaryCommunicator");

        let hosts = args.get_str("-h");
        let communicators = if hosts != "" {
            initialize_networking_from_file(hosts, process_id, workers).ok().expect("error initializing networking")
        }
        else {
            let addresses = (0..processes).map(|index| format!("localhost:{}", 2101 + index).to_string()).collect();
            initialize_networking(addresses, process_id, workers).ok().expect("error initializing networking")
        };

        start_main(communicators, parts_file, items_file);
    }
    else if workers > 1 {
        println!("Initializing ProcessCommunicator");
        start_main(ProcessCommunicator::new_vector(workers), parts_file, items_file);
    }
    else {
        println!("Initializing ThreadCommunicator");
        start_main(vec![ThreadCommunicator], parts_file, items_file);
    };
}

fn start_main<C: Communicator+Send>(communicators: Vec<C>, parts_pattern: String, items_pattern: String) {
    // let communicators = ProcessCommunicator::new_vector(1);
    let mut guards = Vec::new();
    for communicator in communicators.into_iter() {
        let parts = parts_pattern.clone();
        let items = items_pattern.clone();
        guards.push(thread::Builder::new().name(format!("worker thread {}", communicator.index()))
                                          .spawn(move || test_dataflow(communicator, parts, items))
                                          .unwrap());
    }

    for guard in guards { guard.join().unwrap(); }
}

fn test_dataflow<C: Communicator>(communicator: C, parts_pattern: String, items_pattern: String) {

    let start = time::precise_time_s();
    let mut computation = GraphRoot::new(communicator);

    let (mut parts, mut items) = computation.subcomputation(|builder| {

        let (part_input, parts) = builder.new_input::<((u32, String, String), i32)>();
        let (item_input, items) = builder.new_input::<((u32, u32, u64), i32)>();

        // compute the average quantities
        let average = items.group_by_u(|(x,y,_)| (x,y), |k,v| (*k,*v), |_,s,t| {
            let mut sum = 0;
            let mut cnt = 0;
            for &(val,wgt) in s.iter() {
                cnt += wgt;
                sum += val;
            }
            t.push((sum / cnt as u32, 1));
        });

        // filter parts by brand and container
        let parts = parts.filter(|x| (x.0).1 == "Brand#13" && (x.0).2 == "MEDBAG")
                         .map(|((key, _, _), wgt)| (key, wgt));

        // join items against their averages, filter by quantity, remove filter coordinate
        let items = items.join_u(&average, |x| (x.0, (x.1, x.2)), |y| y, |k, x, f| (*k, x.0, x.1, *f))
                         .filter(|&((_, q, _, avg),_)| q < avg / 5)
                         .map(|((key,_,price,_), wgt)| ((key,price), wgt));

        // semi-join against the part keys we retained. think of a better way to produce sum ...
        parts.join_u(&items, |k| (k,()), |(k,p)| (k,p), |_,_,p| *p)
             .inspect_batch(|_t,x| println!("results: {:?}", x.len()));

        (part_input, item_input)
    });

    if let Ok(parts_file) = File::open(format!("{}-{}", parts_pattern, computation.index())) {

        let mut parts_buffer = Vec::new();
        let parts_reader = BufReader::new(parts_file);

        for line in parts_reader.lines() {
            let text = line.ok().expect("read error");
            let mut fields = text.split(" ");

            let part_id = fields.next().unwrap().parse::<u32>().unwrap();
            fields.next();
            fields.next();
            let brand = fields.next().unwrap().to_owned();
            fields.next();
            fields.next();
            let container = fields.next().unwrap().to_owned();

            parts_buffer.push(((part_id, brand, container), 1));
            if parts_buffer.len() == 1024 {
                parts.send_at(0u64, parts_buffer.drain_temp());
                computation.step();

            }
        }

        parts.send_at(0u64, parts_buffer.drain_temp());
        computation.step();
    }
    else { println!("worker {}: did not find input {}-{}", computation.index(), parts_pattern, computation.index()); }

    if let Ok(items_file) = File::open(format!("{}-{}", items_pattern, computation.index())) {
        let mut items_buffer = Vec::new();
        let items_reader =  BufReader::new(items_file);
        for line in items_reader.lines() {
            let text = line.ok().expect("read error");
            let mut fields = text.split(" ");

            fields.next();
            let item_id = fields.next().unwrap().parse::<u32>().unwrap();
            fields.next();
            fields.next();
            let quantity = fields.next().unwrap().parse::<u32>().unwrap();
            let extended_price = fields.next().unwrap().parse::<f64>().unwrap() as u64;

            items_buffer.push(((item_id, quantity, extended_price), 1));
            if items_buffer.len() == 1024 {
                items.send_at(0u64, items_buffer.drain_temp());
                computation.step();
            }
        }

        items.send_at(0u64, items_buffer.drain_temp());
        computation.step();
    }
    else { println!("worker {}: did not find input {}-{}", computation.index(), items_pattern, computation.index()); }

    println!("data loaded at {}", time::precise_time_s() - start);

    parts.close();
    items.close();

    while computation.step() { std::thread::yield_now(); }
    computation.step(); // shut down

    println!("computation finished at {}", time::precise_time_s() - start);
}
<|endoftext|>


<commit_before>use super::STATES_DB_COLUMN as DB_COLUMN;
use super::{ClientDB, DBError};
use ssz::decode;
use std::sync::Arc;
use types::{BeaconState, Hash256};

pub struct BeaconStateStore<T>
where
    T: ClientDB,
{
    db: Arc<T>,
}

// Implements `put`, `get`, `exists` and `delete` for the store.
impl_crud_for_store!(BeaconStateStore, DB_COLUMN);

impl<T: ClientDB> BeaconStateStore<T> {
    pub fn new(db: Arc<T>) -> Self {
        Self { db }
    }

    pub fn get_deserialized(&self, hash: &Hash256) -> Result<Option<BeaconState>, DBError> {
        match self.get(&hash)? {
            None => Ok(None),
            Some(ssz) => {
                let state = decode::<BeaconState>(&ssz).map_err(|_| DBError {
                    message: "Bad State SSZ.".to_string(),
                })?;
                Ok(Some(state))
            }
        }
    }
}

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

    use ssz::ssz_encode;
    use std::sync::Arc;
    use types::test_utils::{SeedableRng, TestRandom, XorShiftRng};
    use types::Hash256;

    test_crud_for_store!(BeaconStateStore, DB_COLUMN);

    #[test]
    fn test_reader() {
        let db = Arc::new(MemoryDB::open());
        let store = BeaconStateStore::new(db.clone());

        let mut rng = XorShiftRng::from_seed([42; 16]);
        let state = BeaconState::random_for_test(&mut rng);
        let state_root = state.canonical_root();

        store.put(&state_root, &ssz_encode(&state)).unwrap();

        let decoded = store.get_deserialized(&state_root).unwrap().unwrap();

        assert_eq!(state, decoded);
    }
}
<commit_msg>Update `db` crate for new `BeaconStateTypes`<commit_after>use super::STATES_DB_COLUMN as DB_COLUMN;
use super::{ClientDB, DBError};
use ssz::decode;
use std::sync::Arc;
use types::{BeaconState, BeaconStateTypes, FoundationBeaconState, Hash256};

pub struct BeaconStateStore<T>
where
    T: ClientDB,
{
    db: Arc<T>,
}

// Implements `put`, `get`, `exists` and `delete` for the store.
impl_crud_for_store!(BeaconStateStore, DB_COLUMN);

impl<T: ClientDB> BeaconStateStore<T> {
    pub fn new(db: Arc<T>) -> Self {
        Self { db }
    }

    pub fn get_deserialized<B: BeaconStateTypes>(
        &self,
        hash: &Hash256,
    ) -> Result<Option<BeaconState<B>>, DBError> {
        match self.get(&hash)? {
            None => Ok(None),
            Some(ssz) => {
                let state = decode::<BeaconState<B>>(&ssz).map_err(|_| DBError {
                    message: "Bad State SSZ.".to_string(),
                })?;
                Ok(Some(state))
            }
        }
    }
}

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

    use ssz::ssz_encode;
    use std::sync::Arc;
    use types::test_utils::{SeedableRng, TestRandom, XorShiftRng};
    use types::Hash256;

    test_crud_for_store!(BeaconStateStore, DB_COLUMN);

    #[test]
    fn test_reader() {
        let db = Arc::new(MemoryDB::open());
        let store = BeaconStateStore::new(db.clone());

        let mut rng = XorShiftRng::from_seed([42; 16]);
        let state: FoundationBeaconState = BeaconState::random_for_test(&mut rng);
        let state_root = state.canonical_root();

        store.put(&state_root, &ssz_encode(&state)).unwrap();

        let decoded = store.get_deserialized(&state_root).unwrap().unwrap();

        assert_eq!(state, decoded);
    }
}
<|endoftext|>


<commit_before>/// The tokenizer for the query interpreter

use error::*;

#[derive(Debug, PartialEq, Eq)]
pub enum Token {
    Identifier {
        ident: String,
        next: Option<Box<Token>>
    },

    Index {
        idx: usize,
        next: Option<Box<Token>>
    }
}

impl Token {

    pub fn next(&self) -> Option<&Box<Token>> {
        match self {
            &Token::Identifier { ref next, .. } => next.as_ref(),
            &Token::Index { ref next, .. }      => next.as_ref(),
        }
    }

    pub fn set_next(&mut self, token: Token) {
        match self {
            &mut Token::Identifier { ref mut next, .. } => *next = Some(Box::new(token)),
            &mut Token::Index { ref mut next, .. }      => *next = Some(Box::new(token)),
        }
    }

    #[cfg(test)]
    pub fn identifier(&self) -> &String {
        match self {
            &Token::Identifier { ident: ref ident, .. } => &ident,
            _ => unreachable!(),
        }
    }

    #[cfg(test)]
    pub fn idx(&self) -> usize {
        match self {
            &Token::Index { idx: i, .. } => i,
            _ => unreachable!(),
        }
    }
}

pub fn tokenize_with_seperator(query: &String, seperator: char) -> Result<Token> {
    use std::str::Split;

    /// Creates a Token object from a string
    ///
    /// # Panics
    ///
    /// * If the internal regex does not compile (should never happen)
    /// * If the token is non-valid (that is, a array index with a non-i64)
    /// * If the regex does not find anything
    /// * If the integer in the brackets (`[]`) cannot be parsed to a valid i64
    ///
    /// # Incorrect behaviour
    ///
    /// * If the regex finds multiple captures
    ///
    /// # Returns
    ///
    /// The `Token` object with the correct identifier/index for this token and no next token.
    ///
    fn mk_token_object(s: &str) -> Result<Token> {
        use regex::Regex;
        use std::str::FromStr;

        lazy_static! {
            static ref RE: Regex = Regex::new(r"^\[\d+\]$").unwrap();
        }

        if !has_array_brackets(s) {
            return Ok(Token::Identifier { ident: String::from(s), next: None });
        }

        match RE.captures(s) {
            None => return Err(Error::from(ErrorKind::ArrayAccessWithoutIndex)),
            Some(captures) => {
                match captures.get(0) {
                    None => Ok(Token::Identifier { ident: String::from(s), next: None }),
                    Some(mtch) => {
                        let mtch = without_array_brackets(mtch.as_str());
                        let i : usize = FromStr::from_str(&mtch).unwrap(); // save because regex
                        Ok(Token::Index {
                            idx: i,
                            next: None,
                        })
                    }
                }
            }
        }
    }

    /// Check whether a str begins with '[' and ends with ']'
    fn has_array_brackets(s: &str) -> bool {
        s.as_bytes()[0] == b'[' && s.as_bytes()[s.len() - 1] == b']'
    }

    /// Remove '[' and ']' from a str
    fn without_array_brackets(s: &str) -> String {
        s.replace("[","").replace("]","")
    }

    fn build_token_tree(split: &mut Split<char>, last: &mut Token) -> Result<()> {
        match split.next() {
            None        => { /* No more tokens */ }
            Some(token) => {
                if token.len() == 0 {
                    return Err(Error::from(ErrorKind::EmptyIdentifier));
                }
                let mut token = try!(mk_token_object(token));
                try!(build_token_tree(split, &mut token));
                last.set_next(token);
            }
        }
        Ok(())
    }

    if query.is_empty() {
        return Err(Error::from(ErrorKind::EmptyQueryError));
    }

    let mut tokens = query.split(seperator);

    match tokens.next() {
        None        => Err(Error::from(ErrorKind::EmptyQueryError)),
        Some(token) => {
            if token.len() == 0 {
                return Err(Error::from(ErrorKind::EmptyIdentifier));
            }
            let mut tok = try!(mk_token_object(token));
            let _       = try!(build_token_tree(&mut tokens, &mut tok));
            Ok(tok)
        }
    }
}

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

    use std::ops::Deref;

    #[test]
    fn test_tokenize_empty_query_to_error() {
        let tokens = tokenize_with_seperator(&String::from(""), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyQueryError { .. }));
    }

    #[test]
    fn test_tokenize_seperator_only() {
        let tokens = tokenize_with_seperator(&String::from("."), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyIdentifier { .. }));
    }

    #[test]
    fn test_tokenize_array_brackets_only() {
        let tokens = tokenize_with_seperator(&String::from("[]"), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::ArrayAccessWithoutIndex { .. }));
    }

    #[test]
    fn test_tokenize_identifiers_with_array_brackets_only() {
        let tokens = tokenize_with_seperator(&String::from("a.b.c.[]"), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::ArrayAccessWithoutIndex { .. }));
    }

    #[test]
    fn test_tokenize_identifiers_in_array_brackets() {
        let tokens = tokenize_with_seperator(&String::from("[a]"), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::ArrayAccessWithoutIndex { .. }));
    }

    #[test]
    fn test_tokenize_single_token_query() {
        let tokens = tokenize_with_seperator(&String::from("example"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier {
                ident: ident,
                next: None
            } => {
                assert_eq!(String::from("example"), ident);
                true
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_double_token_query() {
        let tokens = tokenize_with_seperator(&String::from("a.b"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!("b", next.deref().identifier());
                match next.deref() {
                    &Token::Identifier { next: None, .. } => true,
                    _ => false
                }
            },
            _ => false,
        });
        assert_eq!("a", tokens.identifier());
    }

    #[test]
    fn test_tokenize_ident_then_array_query() {
        let tokens = tokenize_with_seperator(&String::from("a.[0]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());
        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                match next.deref() {
                    &Token::Index { idx: 0, next: None } => true,
                    _ => false
                }
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_many_idents_then_array_query() {
        use std::ops::Deref;

        let tokens = tokenize_with_seperator(&String::from("a.b.c.[1000]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());

        let expected =
            Token::Identifier {
                ident: String::from("a"),
                next: Some(Box::new(Token::Identifier {
                    ident: String::from("b"),
                    next: Some(Box::new(Token::Identifier {
                        ident: String::from("c"),
                        next: Some(Box::new(Token::Index {
                            idx: 1000,
                            next: None,
                        })),
                    })),
                })),
            };

        assert_eq!(expected, tokens);
    }

    #[test]
    fn test_tokenize_empty_token_after_good_token() {
        let tokens = tokenize_with_seperator(&String::from("a..b"), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyIdentifier { .. }));
    }

    quickcheck! {
        fn test_array_index(i: usize) -> bool {
            match tokenize_with_seperator(&format!("[{}]", i), '.') {
                Ok(Token::Index {
                    idx: i,
                    next: None,
                }) => true,
                _ => false,
            }
        }
    }

}
<commit_msg>Remove warnings from tests<commit_after>/// The tokenizer for the query interpreter

use error::*;

#[derive(Debug, PartialEq, Eq)]
pub enum Token {
    Identifier {
        ident: String,
        next: Option<Box<Token>>
    },

    Index {
        idx: usize,
        next: Option<Box<Token>>
    }
}

impl Token {

    pub fn next(&self) -> Option<&Box<Token>> {
        match self {
            &Token::Identifier { ref next, .. } => next.as_ref(),
            &Token::Index { ref next, .. }      => next.as_ref(),
        }
    }

    pub fn set_next(&mut self, token: Token) {
        match self {
            &mut Token::Identifier { ref mut next, .. } => *next = Some(Box::new(token)),
            &mut Token::Index { ref mut next, .. }      => *next = Some(Box::new(token)),
        }
    }

    #[cfg(test)]
    pub fn identifier(&self) -> &String {
        match self {
            &Token::Identifier { ref ident, .. } => &ident,
            _ => unreachable!(),
        }
    }

}

pub fn tokenize_with_seperator(query: &String, seperator: char) -> Result<Token> {
    use std::str::Split;

    /// Creates a Token object from a string
    ///
    /// # Panics
    ///
    /// * If the internal regex does not compile (should never happen)
    /// * If the token is non-valid (that is, a array index with a non-i64)
    /// * If the regex does not find anything
    /// * If the integer in the brackets (`[]`) cannot be parsed to a valid i64
    ///
    /// # Incorrect behaviour
    ///
    /// * If the regex finds multiple captures
    ///
    /// # Returns
    ///
    /// The `Token` object with the correct identifier/index for this token and no next token.
    ///
    fn mk_token_object(s: &str) -> Result<Token> {
        use regex::Regex;
        use std::str::FromStr;

        lazy_static! {
            static ref RE: Regex = Regex::new(r"^\[\d+\]$").unwrap();
        }

        if !has_array_brackets(s) {
            return Ok(Token::Identifier { ident: String::from(s), next: None });
        }

        match RE.captures(s) {
            None => return Err(Error::from(ErrorKind::ArrayAccessWithoutIndex)),
            Some(captures) => {
                match captures.get(0) {
                    None => Ok(Token::Identifier { ident: String::from(s), next: None }),
                    Some(mtch) => {
                        let mtch = without_array_brackets(mtch.as_str());
                        let i : usize = FromStr::from_str(&mtch).unwrap(); // save because regex
                        Ok(Token::Index {
                            idx: i,
                            next: None,
                        })
                    }
                }
            }
        }
    }

    /// Check whether a str begins with '[' and ends with ']'
    fn has_array_brackets(s: &str) -> bool {
        s.as_bytes()[0] == b'[' && s.as_bytes()[s.len() - 1] == b']'
    }

    /// Remove '[' and ']' from a str
    fn without_array_brackets(s: &str) -> String {
        s.replace("[","").replace("]","")
    }

    fn build_token_tree(split: &mut Split<char>, last: &mut Token) -> Result<()> {
        match split.next() {
            None        => { /* No more tokens */ }
            Some(token) => {
                if token.len() == 0 {
                    return Err(Error::from(ErrorKind::EmptyIdentifier));
                }
                let mut token = try!(mk_token_object(token));
                try!(build_token_tree(split, &mut token));
                last.set_next(token);
            }
        }
        Ok(())
    }

    if query.is_empty() {
        return Err(Error::from(ErrorKind::EmptyQueryError));
    }

    let mut tokens = query.split(seperator);

    match tokens.next() {
        None        => Err(Error::from(ErrorKind::EmptyQueryError)),
        Some(token) => {
            if token.len() == 0 {
                return Err(Error::from(ErrorKind::EmptyIdentifier));
            }
            let mut tok = try!(mk_token_object(token));
            let _       = try!(build_token_tree(&mut tokens, &mut tok));
            Ok(tok)
        }
    }
}

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

    use std::ops::Deref;

    #[test]
    fn test_tokenize_empty_query_to_error() {
        let tokens = tokenize_with_seperator(&String::from(""), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyQueryError { .. }));
    }

    #[test]
    fn test_tokenize_seperator_only() {
        let tokens = tokenize_with_seperator(&String::from("."), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyIdentifier { .. }));
    }

    #[test]
    fn test_tokenize_array_brackets_only() {
        let tokens = tokenize_with_seperator(&String::from("[]"), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::ArrayAccessWithoutIndex { .. }));
    }

    #[test]
    fn test_tokenize_identifiers_with_array_brackets_only() {
        let tokens = tokenize_with_seperator(&String::from("a.b.c.[]"), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::ArrayAccessWithoutIndex { .. }));
    }

    #[test]
    fn test_tokenize_identifiers_in_array_brackets() {
        let tokens = tokenize_with_seperator(&String::from("[a]"), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::ArrayAccessWithoutIndex { .. }));
    }

    #[test]
    fn test_tokenize_single_token_query() {
        let tokens = tokenize_with_seperator(&String::from("example"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier { ref ident, next: None } => {
                assert_eq!("example", ident);
                true
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_double_token_query() {
        let tokens = tokenize_with_seperator(&String::from("a.b"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!("b", next.deref().identifier());
                match next.deref() {
                    &Token::Identifier { next: None, .. } => true,
                    _ => false
                }
            },
            _ => false,
        });
        assert_eq!("a", tokens.identifier());
    }

    #[test]
    fn test_tokenize_ident_then_array_query() {
        let tokens = tokenize_with_seperator(&String::from("a.[0]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());
        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                match next.deref() {
                    &Token::Index { idx: 0, next: None } => true,
                    _ => false
                }
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_many_idents_then_array_query() {
        let tokens = tokenize_with_seperator(&String::from("a.b.c.[1000]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());

        let expected =
            Token::Identifier {
                ident: String::from("a"),
                next: Some(Box::new(Token::Identifier {
                    ident: String::from("b"),
                    next: Some(Box::new(Token::Identifier {
                        ident: String::from("c"),
                        next: Some(Box::new(Token::Index {
                            idx: 1000,
                            next: None,
                        })),
                    })),
                })),
            };

        assert_eq!(expected, tokens);
    }

    #[test]
    fn test_tokenize_empty_token_after_good_token() {
        let tokens = tokenize_with_seperator(&String::from("a..b"), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyIdentifier { .. }));
    }

    quickcheck! {
        fn test_array_index(i: usize) -> bool {
            match tokenize_with_seperator(&format!("[{}]", i), '.') {
                Ok(Token::Index { next: None, ..  }) => true,
                _                                    => false,
            }
        }
    }

}
<|endoftext|>