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

//! Texture creation and modification.
//!
//! "Texture" is an overloaded term. In gfx-rs, a texture consists of two
//! separate pieces of information: image storage description (which is
//! immutable for a single texture object), and image data. To actually use a
//! texture, a "sampler" is needed, which provides a way of accessing the
//! image data.  Image data consists of an array of "texture elements", or
//! texels.

use attrib::IntSubType;
use std::default::Default;
use std::fmt;

use state;

/// Surface creation/update error.
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum SurfaceError {
    /// Failed to map a given format to the device
    UnsupportedSurfaceFormat,
}

/// Texture creation/update error.
#[derive(Copy, Clone, PartialEq)]
pub enum TextureError {
    /// Failed to map a given format to the device.
    UnsupportedTextureFormat,
    /// Failed to map a given multisampled kind to the device.
    UnsupportedTextureSampling,
    /// The given TextureInfo contains invalid values.
    InvalidTextureInfo(TextureInfo),
    /// The given data has a different size than the target texture slice.
    IncorrectTextureSize(usize),
}

impl fmt::Debug for TextureError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &TextureError::UnsupportedTextureFormat =>
                write!(f, "Failed to map a given format to the device"),

            &TextureError::UnsupportedTextureSampling =>
                write!(
                    f,
                    "Failed to map a given multisampled kind to the device"
                ),

            &TextureError::InvalidTextureInfo(info) =>
                write!(
                    f,
                    "Invalid TextureInfo (width, height, and levels must not \
                    be zero): {:?}\n",
                    info
                ),
            &TextureError::IncorrectTextureSize(expected) =>
                write!(
                    f,
                    "Invalid data size provided to update the texture, \
                    expected size {:?}",
                    expected
                ),
        }
    }
}

/// Number of bits per component
pub type Bits = u8;
/// Number of MSAA samples
pub type NumSamples = u8;
/// Number of EQAA fragments
pub type NumFragments = u8;

/// Describes the configuration of samples inside each texel.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum AaMode {
    /// MultiSampled Anti-Aliasing
    Msaa(NumSamples),
    /// Enhanced Quality Anti-Aliasing
    Eqaa(NumSamples, NumFragments),
}

/// Describes the color components of each texel.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
#[repr(u8)]
pub enum Components {
    /// Red only
    R,
    /// Red and green
    RG,
    /// Red, green, blue
    RGB,
    /// Red, green, blue, alpha
    RGBA,
}

/// Codec used to compress image data.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
#[allow(non_camel_case_types)]
pub enum Compression {
    /// Use the EXT2 algorithm on 3 components.
    ETC2_RGB,
    /// Use the EXT2 algorithm on 4 components (RGBA) in the sRGB color space.
    ETC2_SRGB,
    /// Use the EXT2 EAC algorithm on 4 components.
    ETC2_EAC_RGBA8,
}

/// Describes the layout of each texel within a surface/texture.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum Format {
    /// Floating point.
    Float(Components, ::attrib::FloatSize),
    /// Signed integer.
    Integer(Components, Bits, ::attrib::IntSubType),
    /// Unsigned integer.
    Unsigned(Components, Bits, ::attrib::IntSubType),
    /// Compressed data.
    Compressed(Compression),
    /// Normalized integer, with 3 bits for R and G, but only 2 for B.
    R3G3B2,
    /// 5 bits each for RGB, 1 for Alpha.
    RGB5A1,
    /// 10 bits each for RGB, 2 for Alpha.
    RGB10A2,
    /// 10 bits each for RGB, 2 for Alpha, as unsigned integers.
    RGB10A2UI,
    /// This uses special 11 and 10-bit floating-point values without sign bits.
    R11FG11FB10F,
    /// This s an RGB format of type floating-point. The 3 color values have
    /// 9 bits of precision, and they share a single exponent.
    RGB9E5,
    /// Swizzled RGBA color format, used for interaction with Windows DIBs
    BGRA8,
    /// 24 bits for depth, 8 for stencil
    DEPTH24STENCIL8,
    // TODO: sRGB
}

impl Format {
    /// Extract the components format
    pub fn get_components(&self) -> Option<Components> {
        Some(match *self {
            Format::Float(c, _)       => c,
            Format::Integer(c, _, _)  => c,
            Format::Unsigned(c, _, _) => c,
            Format::Compressed(_)   => panic!("Tried to get components of compressed texel!"),
            Format::R3G3B2          |
            Format::R11FG11FB10F    |
            Format::RGB9E5          => Components::RGB,
            Format::RGB5A1          |
            Format::RGB10A2         |
            Format::RGB10A2UI       |
            Format::BGRA8           => Components::RGBA,
            Format::DEPTH24STENCIL8 => return None,
        })
    }

    /// Check if it's a compressed format
    pub fn is_compressed(&self) -> bool {
        match *self {
            Format::Compressed(_) => true,
            _ => false
        }
    }
}

/// A commonly used RGBA8 format
pub static RGBA8: Format = Format::Unsigned(Components::RGBA, 8, IntSubType::Normalized);

/// Describes the storage of a surface
#[allow(missing_docs)]
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub struct SurfaceInfo {
    pub width: u16,
    pub height: u16,
    pub format: Format,
    pub aa_mode: Option<AaMode>,
}

/// How to [filter](https://en.wikipedia.org/wiki/Texture_filtering) the
/// texture when sampling. They correspond to increasing levels of quality,
/// but also cost. They "layer" on top of each other: it is not possible to
/// have bilinear filtering without mipmapping, for example.
///
/// These names are somewhat poor, in that "bilinear" is really just doing
/// linear filtering on each axis, and it is only bilinear in the case of 2D
/// textures. Similarly for trilinear, it is really Quadralinear(?) for 3D
/// textures. Alas, these names are simple, and match certain intuitions
/// ingrained by many years of public use of inaccurate terminology.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum FilterMethod {
    /// The dumbest filtering possible, nearest-neighbor interpolation.
    Scale,
    /// Add simple mipmapping.
    Mipmap,
    /// Sample multiple texels within a single mipmap level to increase
    /// quality.
    Bilinear,
    /// Sample multiple texels across two mipmap levels to increase quality.
    Trilinear,
    /// Anisotropic filtering with a given "max", must be between 1 and 16,
    /// inclusive.
    Anisotropic(u8)
}

/// Specifies how a given texture may be used. The available texture types are
/// restricted by what Metal exposes, though this could conceivably be
/// extended in the future. Note that a single texture can *only* ever be of
/// one kind. A texture created as `Texture2D` will forever be `Texture2D`.
// TODO: "Texture views" let you get around that limitation.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum TextureKind {
    /// A single row of texels.
    Texture1D,
    /// An array of rows of texels. Equivalent to Texture2D except that texels
    /// in a different row are not sampled.
    Texture1DArray,
    /// A traditional 2D texture, with rows arranged contiguously.
    Texture2D,
    /// An array of 2D textures. Equivalent to Texture3D except that texels in
    /// a different depth level are not sampled.
    Texture2DArray,
    /// A multi-sampled 2D texture. Each pixel may have more than one data value
    /// (sample) associated with it.
    Texture2DMultiSample(AaMode),
    /// A array of multi-sampled 2D textures.
    Texture2DMultiSampleArray(AaMode),
    /// A set of 6 2D textures, one for each face of a cube.
    ///
    /// When creating a cube texture, the face is ignored, and storage for all 6 faces is created.
    /// When updating, only the face specified is updated.
    TextureCube(CubeFace),
    /// A volume texture, with each 2D layer arranged contiguously.
    Texture3D,
}

/// The face of a cube texture to do an operation on.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
#[allow(missing_docs)]
pub enum CubeFace {
    PosZ,
    NegZ,
    PosX,
    NegX,
    PosY,
    NegY
}

impl TextureKind {
    /// Return the anti-aliasing mode of the texture
    pub fn get_aa_mode(&self) -> Option<AaMode> {
        match *self {
            TextureKind::Texture2DMultiSample(aa) => Some(aa),
            TextureKind::Texture2DMultiSampleArray(aa) => Some(aa),
            _ => None,
        }
    }
}

/// Describes the storage of a texture.
///
/// # Portability note
///
/// Textures larger than 1024px in any dimension are unlikely to be supported
/// by mobile platforms.
#[allow(missing_docs)]
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub struct TextureInfo {
    pub width: u16,
    pub height: u16,
    pub depth: u16,
    /// Number of mipmap levels. Defaults to -1, which stands for unlimited.
    /// Mipmap levels at equal or above `levels` can not be loaded or sampled
    /// by the shader. width and height of each consecutive mipmap level is
    /// halved, starting from level 0.
    pub levels: u8,
    pub kind: TextureKind,
    pub format: Format,
}

/// Describes a subvolume of a texture, which image data can be uploaded into.
#[allow(missing_docs)]
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub struct ImageInfo {
    pub xoffset: u16,
    pub yoffset: u16,
    pub zoffset: u16,
    pub width: u16,
    pub height: u16,
    pub depth: u16,
    /// Format of each texel.
    pub format: Format,
    /// Which mipmap to select.
    pub mipmap: u8,
}

impl Default for ImageInfo {
    fn default() -> ImageInfo {
        ImageInfo {
            xoffset: 0,
            yoffset: 0,
            zoffset: 0,
            width: 0,
            height: 1,
            depth: 1,
            format: RGBA8,
            mipmap: 0
        }
    }
}

impl Default for TextureInfo {
    fn default() -> TextureInfo {
        TextureInfo {
            width: 0,
            height: 1,
            depth: 1,
            levels: -1,
            kind: TextureKind::Texture2D,
            format: RGBA8,
        }
    }
}

impl TextureInfo {
    /// Create a new empty texture info.
    pub fn new() -> TextureInfo {
        Default::default()
    }

    /// Convert to a default ImageInfo that could be used
    /// to update the contents of the whole texture.
    pub fn to_image_info(&self) -> ImageInfo {
        ImageInfo {
            xoffset: 0,
            yoffset: 0,
            zoffset: 0,
            width: self.width,
            height: self.height,
            depth: self.depth,
            format: self.format,
            mipmap: 0,
        }
    }

    /// Convert to a `SurfaceInfo`, used as a common denominator between
    /// surfaces and textures.
    pub fn to_surface_info(&self) -> SurfaceInfo {
        SurfaceInfo {
            width: self.width,
            height: self.height,
            format: self.format,
            aa_mode: self.kind.get_aa_mode(),
        }
    }

    /// Check if given ImageInfo is a part of the texture.
    pub fn contains(&self, img: &ImageInfo) -> bool {
        self.width <= img.xoffset + img.width &&
        self.height <= img.yoffset + img.height &&
        self.depth <= img.zoffset + img.depth &&
        self.format == img.format &&
        img.mipmap < self.levels &&
        self.kind.get_aa_mode().is_none()
    }
}

impl ImageInfo {
    /// Create a new `ImageInfo`, using default values.
    pub fn new() -> ImageInfo { Default::default() }
}

/// Specifies how texture coordinates outside the range `[0, 1]` are handled.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum WrapMode {
    /// Tile the texture. That is, sample the coordinate modulo `1.0`. This is
    /// the default.
    Tile,
    /// Mirror the texture. Like tile, but uses abs(coord) before the modulo.
    Mirror,
    /// Clamp the texture to the value at `0.0` or `1.0` respectively.
    Clamp,
}

/// Specified how the Comparison operator should be used when sampling
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum ComparisonMode {
    /// the default, don't use this feature.
    NoComparison,
    /// Compare Reference to Texture
    CompareRefToTexture(state::Comparison)
}

/// Specifies how to sample from a texture.
// TODO: document the details of sampling.
#[derive(PartialEq, PartialOrd, Clone, Copy, Debug)]
pub struct SamplerInfo {
    /// Filter method to use.
    pub filtering: FilterMethod,
    /// Wrapping mode for each of the U, V, and W axis (S, T, and R in OpenGL
    /// speak)
    pub wrap_mode: (WrapMode, WrapMode, WrapMode),
    /// This bias is added to every computed mipmap level (N + lod_bias). For
    /// example, if it would select mipmap level 2 and lod_bias is 1, it will
    /// use mipmap level 3.
    pub lod_bias: f32,
    /// This range is used to clamp LOD level used for sampling
    pub lod_range: (f32, f32),
    /// comparison mode, used primary for a shadow map
    pub comparison: ComparisonMode
}

impl SamplerInfo {
    /// Create a new sampler description with a given filter method and wrapping mode, using no LOD
    /// modifications.
    pub fn new(filtering: FilterMethod, wrap: WrapMode) -> SamplerInfo {
        SamplerInfo {
            filtering: filtering,
            wrap_mode: (wrap, wrap, wrap),
            lod_bias: 0.0,
            lod_range: (-1000.0, 1000.0),
            comparison: ComparisonMode::NoComparison
        }
    }
}
<commit_msg>Change unsigned int initialization from -1 to !0<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Texture creation and modification.
//!
//! "Texture" is an overloaded term. In gfx-rs, a texture consists of two
//! separate pieces of information: image storage description (which is
//! immutable for a single texture object), and image data. To actually use a
//! texture, a "sampler" is needed, which provides a way of accessing the
//! image data.  Image data consists of an array of "texture elements", or
//! texels.

use attrib::IntSubType;
use std::default::Default;
use std::fmt;

use state;

/// Surface creation/update error.
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum SurfaceError {
    /// Failed to map a given format to the device
    UnsupportedSurfaceFormat,
}

/// Texture creation/update error.
#[derive(Copy, Clone, PartialEq)]
pub enum TextureError {
    /// Failed to map a given format to the device.
    UnsupportedTextureFormat,
    /// Failed to map a given multisampled kind to the device.
    UnsupportedTextureSampling,
    /// The given TextureInfo contains invalid values.
    InvalidTextureInfo(TextureInfo),
    /// The given data has a different size than the target texture slice.
    IncorrectTextureSize(usize),
}

impl fmt::Debug for TextureError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &TextureError::UnsupportedTextureFormat =>
                write!(f, "Failed to map a given format to the device"),

            &TextureError::UnsupportedTextureSampling =>
                write!(
                    f,
                    "Failed to map a given multisampled kind to the device"
                ),

            &TextureError::InvalidTextureInfo(info) =>
                write!(
                    f,
                    "Invalid TextureInfo (width, height, and levels must not \
                    be zero): {:?}\n",
                    info
                ),
            &TextureError::IncorrectTextureSize(expected) =>
                write!(
                    f,
                    "Invalid data size provided to update the texture, \
                    expected size {:?}",
                    expected
                ),
        }
    }
}

/// Number of bits per component
pub type Bits = u8;
/// Number of MSAA samples
pub type NumSamples = u8;
/// Number of EQAA fragments
pub type NumFragments = u8;

/// Describes the configuration of samples inside each texel.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum AaMode {
    /// MultiSampled Anti-Aliasing
    Msaa(NumSamples),
    /// Enhanced Quality Anti-Aliasing
    Eqaa(NumSamples, NumFragments),
}

/// Describes the color components of each texel.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
#[repr(u8)]
pub enum Components {
    /// Red only
    R,
    /// Red and green
    RG,
    /// Red, green, blue
    RGB,
    /// Red, green, blue, alpha
    RGBA,
}

/// Codec used to compress image data.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
#[allow(non_camel_case_types)]
pub enum Compression {
    /// Use the EXT2 algorithm on 3 components.
    ETC2_RGB,
    /// Use the EXT2 algorithm on 4 components (RGBA) in the sRGB color space.
    ETC2_SRGB,
    /// Use the EXT2 EAC algorithm on 4 components.
    ETC2_EAC_RGBA8,
}

/// Describes the layout of each texel within a surface/texture.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum Format {
    /// Floating point.
    Float(Components, ::attrib::FloatSize),
    /// Signed integer.
    Integer(Components, Bits, ::attrib::IntSubType),
    /// Unsigned integer.
    Unsigned(Components, Bits, ::attrib::IntSubType),
    /// Compressed data.
    Compressed(Compression),
    /// Normalized integer, with 3 bits for R and G, but only 2 for B.
    R3G3B2,
    /// 5 bits each for RGB, 1 for Alpha.
    RGB5A1,
    /// 10 bits each for RGB, 2 for Alpha.
    RGB10A2,
    /// 10 bits each for RGB, 2 for Alpha, as unsigned integers.
    RGB10A2UI,
    /// This uses special 11 and 10-bit floating-point values without sign bits.
    R11FG11FB10F,
    /// This s an RGB format of type floating-point. The 3 color values have
    /// 9 bits of precision, and they share a single exponent.
    RGB9E5,
    /// Swizzled RGBA color format, used for interaction with Windows DIBs
    BGRA8,
    /// 24 bits for depth, 8 for stencil
    DEPTH24STENCIL8,
    // TODO: sRGB
}

impl Format {
    /// Extract the components format
    pub fn get_components(&self) -> Option<Components> {
        Some(match *self {
            Format::Float(c, _)       => c,
            Format::Integer(c, _, _)  => c,
            Format::Unsigned(c, _, _) => c,
            Format::Compressed(_)   => panic!("Tried to get components of compressed texel!"),
            Format::R3G3B2          |
            Format::R11FG11FB10F    |
            Format::RGB9E5          => Components::RGB,
            Format::RGB5A1          |
            Format::RGB10A2         |
            Format::RGB10A2UI       |
            Format::BGRA8           => Components::RGBA,
            Format::DEPTH24STENCIL8 => return None,
        })
    }

    /// Check if it's a compressed format
    pub fn is_compressed(&self) -> bool {
        match *self {
            Format::Compressed(_) => true,
            _ => false
        }
    }
}

/// A commonly used RGBA8 format
pub static RGBA8: Format = Format::Unsigned(Components::RGBA, 8, IntSubType::Normalized);

/// Describes the storage of a surface
#[allow(missing_docs)]
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub struct SurfaceInfo {
    pub width: u16,
    pub height: u16,
    pub format: Format,
    pub aa_mode: Option<AaMode>,
}

/// How to [filter](https://en.wikipedia.org/wiki/Texture_filtering) the
/// texture when sampling. They correspond to increasing levels of quality,
/// but also cost. They "layer" on top of each other: it is not possible to
/// have bilinear filtering without mipmapping, for example.
///
/// These names are somewhat poor, in that "bilinear" is really just doing
/// linear filtering on each axis, and it is only bilinear in the case of 2D
/// textures. Similarly for trilinear, it is really Quadralinear(?) for 3D
/// textures. Alas, these names are simple, and match certain intuitions
/// ingrained by many years of public use of inaccurate terminology.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum FilterMethod {
    /// The dumbest filtering possible, nearest-neighbor interpolation.
    Scale,
    /// Add simple mipmapping.
    Mipmap,
    /// Sample multiple texels within a single mipmap level to increase
    /// quality.
    Bilinear,
    /// Sample multiple texels across two mipmap levels to increase quality.
    Trilinear,
    /// Anisotropic filtering with a given "max", must be between 1 and 16,
    /// inclusive.
    Anisotropic(u8)
}

/// Specifies how a given texture may be used. The available texture types are
/// restricted by what Metal exposes, though this could conceivably be
/// extended in the future. Note that a single texture can *only* ever be of
/// one kind. A texture created as `Texture2D` will forever be `Texture2D`.
// TODO: "Texture views" let you get around that limitation.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum TextureKind {
    /// A single row of texels.
    Texture1D,
    /// An array of rows of texels. Equivalent to Texture2D except that texels
    /// in a different row are not sampled.
    Texture1DArray,
    /// A traditional 2D texture, with rows arranged contiguously.
    Texture2D,
    /// An array of 2D textures. Equivalent to Texture3D except that texels in
    /// a different depth level are not sampled.
    Texture2DArray,
    /// A multi-sampled 2D texture. Each pixel may have more than one data value
    /// (sample) associated with it.
    Texture2DMultiSample(AaMode),
    /// A array of multi-sampled 2D textures.
    Texture2DMultiSampleArray(AaMode),
    /// A set of 6 2D textures, one for each face of a cube.
    ///
    /// When creating a cube texture, the face is ignored, and storage for all 6 faces is created.
    /// When updating, only the face specified is updated.
    TextureCube(CubeFace),
    /// A volume texture, with each 2D layer arranged contiguously.
    Texture3D,
}

/// The face of a cube texture to do an operation on.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
#[allow(missing_docs)]
pub enum CubeFace {
    PosZ,
    NegZ,
    PosX,
    NegX,
    PosY,
    NegY
}

impl TextureKind {
    /// Return the anti-aliasing mode of the texture
    pub fn get_aa_mode(&self) -> Option<AaMode> {
        match *self {
            TextureKind::Texture2DMultiSample(aa) => Some(aa),
            TextureKind::Texture2DMultiSampleArray(aa) => Some(aa),
            _ => None,
        }
    }
}

/// Describes the storage of a texture.
///
/// # Portability note
///
/// Textures larger than 1024px in any dimension are unlikely to be supported
/// by mobile platforms.
#[allow(missing_docs)]
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub struct TextureInfo {
    pub width: u16,
    pub height: u16,
    pub depth: u16,
    /// Number of mipmap levels. Defaults to -1, which stands for unlimited.
    /// Mipmap levels at equal or above `levels` can not be loaded or sampled
    /// by the shader. width and height of each consecutive mipmap level is
    /// halved, starting from level 0.
    pub levels: u8,
    pub kind: TextureKind,
    pub format: Format,
}

/// Describes a subvolume of a texture, which image data can be uploaded into.
#[allow(missing_docs)]
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub struct ImageInfo {
    pub xoffset: u16,
    pub yoffset: u16,
    pub zoffset: u16,
    pub width: u16,
    pub height: u16,
    pub depth: u16,
    /// Format of each texel.
    pub format: Format,
    /// Which mipmap to select.
    pub mipmap: u8,
}

impl Default for ImageInfo {
    fn default() -> ImageInfo {
        ImageInfo {
            xoffset: 0,
            yoffset: 0,
            zoffset: 0,
            width: 0,
            height: 1,
            depth: 1,
            format: RGBA8,
            mipmap: 0
        }
    }
}

impl Default for TextureInfo {
    fn default() -> TextureInfo {
        TextureInfo {
            width: 0,
            height: 1,
            depth: 1,
            levels: !0,
            kind: TextureKind::Texture2D,
            format: RGBA8,
        }
    }
}

impl TextureInfo {
    /// Create a new empty texture info.
    pub fn new() -> TextureInfo {
        Default::default()
    }

    /// Convert to a default ImageInfo that could be used
    /// to update the contents of the whole texture.
    pub fn to_image_info(&self) -> ImageInfo {
        ImageInfo {
            xoffset: 0,
            yoffset: 0,
            zoffset: 0,
            width: self.width,
            height: self.height,
            depth: self.depth,
            format: self.format,
            mipmap: 0,
        }
    }

    /// Convert to a `SurfaceInfo`, used as a common denominator between
    /// surfaces and textures.
    pub fn to_surface_info(&self) -> SurfaceInfo {
        SurfaceInfo {
            width: self.width,
            height: self.height,
            format: self.format,
            aa_mode: self.kind.get_aa_mode(),
        }
    }

    /// Check if given ImageInfo is a part of the texture.
    pub fn contains(&self, img: &ImageInfo) -> bool {
        self.width <= img.xoffset + img.width &&
        self.height <= img.yoffset + img.height &&
        self.depth <= img.zoffset + img.depth &&
        self.format == img.format &&
        img.mipmap < self.levels &&
        self.kind.get_aa_mode().is_none()
    }
}

impl ImageInfo {
    /// Create a new `ImageInfo`, using default values.
    pub fn new() -> ImageInfo { Default::default() }
}

/// Specifies how texture coordinates outside the range `[0, 1]` are handled.
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum WrapMode {
    /// Tile the texture. That is, sample the coordinate modulo `1.0`. This is
    /// the default.
    Tile,
    /// Mirror the texture. Like tile, but uses abs(coord) before the modulo.
    Mirror,
    /// Clamp the texture to the value at `0.0` or `1.0` respectively.
    Clamp,
}

/// Specified how the Comparison operator should be used when sampling
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum ComparisonMode {
    /// the default, don't use this feature.
    NoComparison,
    /// Compare Reference to Texture
    CompareRefToTexture(state::Comparison)
}

/// Specifies how to sample from a texture.
// TODO: document the details of sampling.
#[derive(PartialEq, PartialOrd, Clone, Copy, Debug)]
pub struct SamplerInfo {
    /// Filter method to use.
    pub filtering: FilterMethod,
    /// Wrapping mode for each of the U, V, and W axis (S, T, and R in OpenGL
    /// speak)
    pub wrap_mode: (WrapMode, WrapMode, WrapMode),
    /// This bias is added to every computed mipmap level (N + lod_bias). For
    /// example, if it would select mipmap level 2 and lod_bias is 1, it will
    /// use mipmap level 3.
    pub lod_bias: f32,
    /// This range is used to clamp LOD level used for sampling
    pub lod_range: (f32, f32),
    /// comparison mode, used primary for a shadow map
    pub comparison: ComparisonMode
}

impl SamplerInfo {
    /// Create a new sampler description with a given filter method and wrapping mode, using no LOD
    /// modifications.
    pub fn new(filtering: FilterMethod, wrap: WrapMode) -> SamplerInfo {
        SamplerInfo {
            filtering: filtering,
            wrap_mode: (wrap, wrap, wrap),
            lod_bias: 0.0,
            lod_range: (-1000.0, 1000.0),
            comparison: ComparisonMode::NoComparison
        }
    }
}
<|endoftext|>


<commit_before>extern crate cgmath;

use sdl2::video::Window;
use sdl2::render::Canvas;
use graphicsdevice::GraphicsDevice;
use renderstate::RenderState;
use spritebatcher::SpriteBatcher;
use rectangle::Rectangle;
use spritefont::SpriteFont;
use self::cgmath::Matrix4;
use self::cgmath::Vector2;
use self::cgmath::One;

pub enum SpriteSortMode
{
    /// <summary>
    /// All sprites are drawing when <see cref="SpriteBatch.End"/> invokes, in order of draw call sequence. Depth is ignored.
    /// </summary>
    SpriteSortModeDeferred,
    /// <summary>
    /// Each sprite is drawing at individual draw call, instead of <see cref="SpriteBatch.End"/>. Depth is ignored.
    /// </summary>
    SpriteSortModeImmediate,
    /// <summary>
    /// Same as <see cref="SpriteSortMode.Deferred"/>, except sprites are sorted by texture prior to drawing. Depth is ignored.
    /// </summary>
    SpriteSortModeTexture,
    /// <summary>
    /// Same as <see cref="SpriteSortMode.Deferred"/>, except sprites are sorted by depth in back-to-front order prior to drawing.
    /// </summary>
    SpriteSortModeBackToFront,
    /// <summary>
    /// Same as <see cref="SpriteSortMode.Deferred"/>, except sprites are sorted by depth in front-to-back order prior to drawing.
    /// </summary>
    SpriteSortModeFrontToBack
}

pub struct SpriteBatch<'a> {
    renderer: &'a Canvas<Window>,
    render_state: RenderState<'a>,
    graphics_device: GraphicsDevice,
    batcher: SpriteBatcher<'a>,
    begin_called: bool,
    matrix: Matrix4<f32>,
    temp_rect: Rectangle,
    texCoordTL: Vector2<f32>,
    texCoordBR: Vector2<f32>,
    scaled_origin: Vector2<f32>,
    origin_rect: Rectangle,
    sprite_font: SpriteFont,
    sort_mode: SpriteSortMode,
    // Culling stuff
    cull_rect: Rectangle,
    vertexToCullTL: Vector2<f32>,
    vertexToCullTR: Vector2<f32>,
    vertexToCullBL: Vector2<f32>,
    vertexToCullBR: Vector2<f32>,
}

impl <'a>SpriteBatch<'a> {
    pub fn new(renderer: &'a Canvas<Window>) -> SpriteBatch<'a> {
        let mut gd = GraphicsDevice::new();
        gd.initialize();
        SpriteBatch {
            renderer: renderer,
            render_state: RenderState::new(None, None),
            graphics_device: gd,
            batcher: SpriteBatcher::new(renderer),
            begin_called: false,
            matrix: Matrix4::one(),
            temp_rect: Rectangle::new(0.0, 0.0, 0, 0),
            texCoordTL: Vector2 {
                x: 0.0,
                y: 0.0,
            },
            texCoordBR: Vector2 {
                x: 0.0,
                y: 0.0,
            },
            scaled_origin: Vector2 {
                x: 0.0,
                y: 0.0,
            },
            origin_rect: Rectangle::new(0.0, 0.0, 0, 0),
            sprite_font: SpriteFont {

            },
            sort_mode: SpriteSortMode::SpriteSortModeImmediate,
            cull_rect: Rectangle::new(0.0, 0.0, 0, 0),
            vertexToCullTL: Vector2 {
                x: 0.0,
                y: 0.0,
            },
            vertexToCullTR: Vector2 {
                x: 0.0,
                y: 0.0,
            },
            vertexToCullBL: Vector2 {
                x: 0.0,
                y: 0.0,
            },
            vertexToCullBR: Vector2 {
                x: 0.0,
                y: 0.0,
            },
        }
    }
}<commit_msg>More work on the sprite batcher<commit_after>extern crate cgmath;

use sdl2::video::Window;
use sdl2::render::Canvas;
use sdl2::rect::Rect;
use graphicsdevice::GraphicsDevice;
use renderstate::RenderState;
use spritebatcher::SpriteBatcher;
use rectangle::Rectangle;
use spritefont::SpriteFont;
use shader::Shader;
use self::cgmath::Matrix4;
use self::cgmath::Vector2;
use self::cgmath::One;
use std::option::Option;

#[derive(Copy, Clone)]
pub enum SpriteSortMode
{
    /// <summary>
    /// All sprites are drawing when <see cref="SpriteBatch.End"/> invokes, in order of draw call sequence. Depth is ignored.
    /// </summary>
    SpriteSortModeDeferred,
    /// <summary>
    /// Each sprite is drawing at individual draw call, instead of <see cref="SpriteBatch.End"/>. Depth is ignored.
    /// </summary>
    SpriteSortModeImmediate,
    /// <summary>
    /// Same as <see cref="SpriteSortMode.Deferred"/>, except sprites are sorted by texture prior to drawing. Depth is ignored.
    /// </summary>
    SpriteSortModeTexture,
    /// <summary>
    /// Same as <see cref="SpriteSortMode.Deferred"/>, except sprites are sorted by depth in back-to-front order prior to drawing.
    /// </summary>
    SpriteSortModeBackToFront,
    /// <summary>
    /// Same as <see cref="SpriteSortMode.Deferred"/>, except sprites are sorted by depth in front-to-back order prior to drawing.
    /// </summary>
    SpriteSortModeFrontToBack
}

pub struct SpriteBatch<'a> {
    renderer: &'a Canvas<Window>,
    render_state: RenderState<'a>,
    graphics_device: GraphicsDevice,
    batcher: SpriteBatcher<'a>,
    begin_called: bool,
    matrix: Matrix4<f32>,
    temp_rect: Rectangle,
    texCoordTL: Vector2<f32>,
    texCoordBR: Vector2<f32>,
    scaled_origin: Vector2<f32>,
    origin_rect: Rectangle,
    sprite_font: SpriteFont,
    sort_mode: SpriteSortMode,
    // Culling stuff
    cull_rect: Rectangle,
    vertexToCullTL: Vector2<f32>,
    vertexToCullTR: Vector2<f32>,
    vertexToCullBL: Vector2<f32>,
    vertexToCullBR: Vector2<f32>,
}

impl <'a>SpriteBatch<'a> {
    pub fn new(renderer: &'a Canvas<Window>) -> SpriteBatch<'a> {
        let mut gd = GraphicsDevice::new();
        gd.initialize();
        SpriteBatch {
            renderer: renderer,
            render_state: RenderState::new(None, None),
            graphics_device: gd,
            batcher: SpriteBatcher::new(renderer),
            begin_called: false,
            matrix: Matrix4::one(),
            temp_rect: Rectangle::new(0.0, 0.0, 0, 0),
            texCoordTL: Vector2 {
                x: 0.0,
                y: 0.0,
            },
            texCoordBR: Vector2 {
                x: 0.0,
                y: 0.0,
            },
            scaled_origin: Vector2 {
                x: 0.0,
                y: 0.0,
            },
            origin_rect: Rectangle::new(0.0, 0.0, 0, 0),
            sprite_font: SpriteFont {

            },
            sort_mode: SpriteSortMode::SpriteSortModeImmediate,
            cull_rect: Rectangle::new(0.0, 0.0, 0, 0),
            vertexToCullTL: Vector2 {
                x: 0.0,
                y: 0.0,
            },
            vertexToCullTR: Vector2 {
                x: 0.0,
                y: 0.0,
            },
            vertexToCullBL: Vector2 {
                x: 0.0,
                y: 0.0,
            },
            vertexToCullBR: Vector2 {
                x: 0.0,
                y: 0.0,
            },
        }
    }

    pub fn compute_cull_rectangle(&mut self) {
        let vp = self.renderer.viewport();
        //SDL_Rect vp;
        //SDL_RenderGetViewport(renderer, &vp);

        self.cull_rect.x = vp.x as f32;
        self.cull_rect.y = vp.y as f32;
        self.cull_rect.w = vp.w;
        self.cull_rect.h = vp.h;
    }

    pub fn begin(&mut self, sortMode: SpriteSortMode/*, BlendState *blendState = NULL, SamplerState *samplerState = NULL, DepthStencilState *depthStencilState = NULL, RasterizerState *rasterizerState = NULL, Effect *effect = NULL*/, shader: Option<&'a Shader>, transformMatrix: Option<Matrix4<f32>>) {
        self.render_state.shader = shader;
        if transformMatrix.is_some() {
            self.matrix = transformMatrix.unwrap();
        } else {
            self.matrix = Matrix4::one();
        }
        self.render_state.transform = self.matrix;
        self.sort_mode = sortMode;
        self.compute_cull_rectangle();
        match self.sort_mode
        {
            SpriteSortMode::SpriteSortModeImmediate => {
                self.setup();
            },
            _ => {},
        }

        self.begin_called = true;
    }

    pub fn end(&'a mut self) {
        self.begin_called = false;
        match self.sort_mode {
            SpriteSortMode::SpriteSortModeImmediate => {},
            _ => {
                self.setup();
            },
        }
        self.batcher.draw_batch(self.sort_mode, &mut self.render_state, &mut self.graphics_device);
    }

    pub fn setup(&mut self) {

    }

}<|endoftext|>


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

//! The web dispatcher

#![allow(visible_private_types)]

use std::default::Default;
use std::collections::HashMap;

use method::{Method, Get};
use response::{Resp, RoutingError};
use tools::{RoutesFnType, UnusedProducer, Unused, Producer};

/// The web dispatcher
pub struct Dispatcher<T, P = UnusedProducer, U = Unused> {
    routes: HashMap<(Vec<String>, Method), RoutesFnType<T, U>>,
    producer: P
}

impl<T, P: Producer<U> + Default = UnusedProducer, U = Unused> Dispatcher<T, P, U> {
    pub fn new(routes: Vec<(RoutesFnType<T, U>, &str, &str)>) -> Dispatcher<T, P, U> {
        Dispatcher {
            routes: routes.move_iter().fold(HashMap::new(), |mut h, (f, r, m)| {
                let r_ = split_route(r);
                h.insert((r_, from_str(m).unwrap()), f); h
            }),
            producer: Default::default()
        }
    }

    pub fn set_producer(&mut self, param_producer: P) {
        self.producer = param_producer
    }

    pub fn run_with_method(&mut self,
                           route: &str,
                           web_params: HashMap<String, String>,
                           method: Method)
                           -> Resp<T> {
        match self.find_simple_hash_route(route, &web_params, method) {
            Some(r) => r,
            None    => {
                match self.find_complex_regex_route(route, &web_params, method) {
                    Some(r) => r,
                    None    => RoutingError(format!("route: {}, don't exist", route))
                }
            }
        }
    }

    pub fn run(&mut self,
               route: &str,
               web_params: HashMap<String, String>)
               -> Resp<T> {
        self.run_with_method(route, web_params, Get)
    }

    fn find_simple_hash_route(&mut self,
                             route: &str,
                             web_params: &HashMap<String, String>,
                             method: Method)
                             -> Option<Resp<T>> {
        let r_ = split_route(route);
        match self.routes.find(&(r_, method)) {
            Some(&f) => Some(f(web_params.clone(), self.producer.get_new())),
            None     => None
        }
    }

    fn find_complex_route(&mut self,
                          route: &str,
                          web_params: &HashMap<String, String>,
                          method: Method)
                          -> Option<Resp<T>> {
        let r_ = split_route(route);
        for (&(ref r, m), f) in self.routes.iter() {
            println!("{}", r);
        }
        None
    }
}

fn split_route(route: &str) -> Vec<String> {
    let r_: Vec<&str> = route.split('/').collect();
    let mut r_: Vec<String> = r_.iter().map(|r| r.to_string()).collect();
    if r_.last().is_some() && r_.last().unwrap() == &"".to_string() { r_.pop(); }
    r_
}

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

//! The web dispatcher

#![allow(visible_private_types)]

use std::default::Default;
use std::collections::HashMap;

use method::{Method, Get};
use response::{Resp, RoutingError};
use tools::{RoutesFnType, UnusedProducer, Unused, Producer};

/// The web dispatcher
pub struct Dispatcher<T, P = UnusedProducer, U = Unused> {
    routes: HashMap<(Vec<String>, Method), RoutesFnType<T, U>>,
    producer: P
}

impl<T, P: Producer<U> + Default = UnusedProducer, U = Unused> Dispatcher<T, P, U> {
    pub fn new(routes: Vec<(RoutesFnType<T, U>, &str, &str)>) -> Dispatcher<T, P, U> {
        Dispatcher {
            routes: routes.move_iter().fold(HashMap::new(), |mut h, (f, r, m)| {
                let r_ = split_route(r);
                h.insert((r_, from_str(m).unwrap()), f); h
            }),
            producer: Default::default()
        }
    }

    pub fn set_producer(&mut self, param_producer: P) {
        self.producer = param_producer
    }

    pub fn run_with_method(&mut self,
                           route: &str,
                           web_params: HashMap<String, String>,
                           method: Method)
                           -> Resp<T> {
        match self.find_simple_hash_route(route, &web_params, method) {
            Some(r) => r,
            None    => {
                match self.find_complex_route(route, &web_params, method) {
                    Some(r) => r,
                    None    => RoutingError(format!("route: {}, don't exist", route))
                }
            }
        }
    }

    pub fn run(&mut self,
               route: &str,
               web_params: HashMap<String, String>)
               -> Resp<T> {
        self.run_with_method(route, web_params, Get)
    }

    fn find_simple_hash_route(&mut self,
                             route: &str,
                             web_params: &HashMap<String, String>,
                             method: Method)
                             -> Option<Resp<T>> {
        let r_ = split_route(route);
        match self.routes.find(&(r_, method)) {
            Some(&f) => Some(f(web_params.clone(), self.producer.get_new())),
            None     => None
        }
    }

    fn find_complex_route(&mut self,
                          route: &str,
                          web_params: &HashMap<String, String>,
                          method: Method)
                          -> Option<Resp<T>> {
        let r_ = split_route(route);
        for (&(ref r, m), f) in self.routes.iter() {
            println!("{}", r);
        }
        None
    }
}

fn split_route(route: &str) -> Vec<String> {
    let r_: Vec<&str> = route.split('/').collect();
    let mut r_: Vec<String> = r_.iter().map(|r| r.to_string()).collect();
    if r_.last().is_some() && r_.last().unwrap() == &"".to_string() { r_.pop(); }
    r_
}

<|endoftext|>


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

extern crate serde_json;

use std::fs::File;
use std::io::{Write, BufWriter};

type CvName = String;

pub type MiscExtRange = String;

pub type GeneUniquename = String;
pub type GeneName = String;
pub type TypeName = String;
pub type GeneProduct = String;

pub type TermName = String;
pub type TermId = String;
pub type TermDef = String;

pub type Evidence = String;

pub type TypeFeatureAnnotationMap =
    HashMap<TypeName, Vec<FeatureAnnotation>>;
pub type TypeReferenceAnnotationMap =
    HashMap<TypeName, Vec<ReferenceAnnotation>>;
pub type TypeInteractionAnnotationMap =
    HashMap<TypeName, Vec<InteractionAnnotation>>;

pub type UniquenameGeneMap =
    HashMap<GeneUniquename, GeneDetails>;

pub type TranscriptUniquename = String;

pub type UniquenameTranscriptMap =
    HashMap<TranscriptUniquename, TranscriptDetails>;

pub type GenotypeUniquename = String;

pub type UniquenameGenotypeMap =
    HashMap<GenotypeUniquename, GenotypeDetails>;

pub type AlleleUniquename = String;

pub type UniquenameAlleleShortMap =
    HashMap<AlleleUniquename, AlleleShort>;

pub type IdGeneMap = HashMap<GeneUniquename, GeneDetails>;
pub type IdGeneShortMap = HashMap<GeneUniquename, GeneShort>;
pub type IdTermDetailsMap = HashMap<TermId, TermDetails>;
pub type IdReferenceMap = HashMap<TermId, ReferenceDetails>;

include!(concat!(env!("OUT_DIR"), "/data_serde.rs"));

impl WebData {
    fn get_genes(&self) -> &IdGeneMap {
        &self.genes
    }
    fn get_terms(&self) -> &IdTermDetailsMap {
        &self.terms
    }

    fn write_reference_details(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.references).unwrap();
        let file_name = String::new() + &output_dir + "/references.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");

        for (reference_uniquename, reference_details) in &self.references {
            let s = serde_json::to_string(&reference_details).unwrap();
            let file_name = String::new() + &output_dir + "/reference/" + &reference_uniquename + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write!");
        }
    }

    fn write_gene_details(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.genes).unwrap();
        let file_name = String::new() + &output_dir + "/genes.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");

        for (gene_uniquename, gene_details) in &self.genes {
            let s = serde_json::to_string(&gene_details).unwrap();
            let file_name = String::new() + &output_dir + "/gene/" + &gene_uniquename + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write!");
        }
    }

    fn write_gene_summary(&self, output_dir: &str, organism_genus_species: &str) {
        let gene_summaries =
            self.gene_summaries.values()
            .filter(|gene_short| {
                let gene_uniquename = &gene_short.uniquename;
                let gene_details = self.get_genes().get(gene_uniquename).unwrap();
                let feature_org_genus_species = String::new() +
                    &gene_details.organism.genus + "_" + &gene_details.organism.species;
                feature_org_genus_species == organism_genus_species
            })
            .map(|gene_short| gene_short.clone())
            .collect::<Vec<GeneShort>>();
        let s = serde_json::to_string(&gene_summaries).unwrap();
        let file_name = String::new() + &output_dir + "/gene_summaries.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");
    }

    fn write_terms(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.terms).unwrap();
        let file_name = String::new() + &output_dir + "/terms.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");

        for (termid, term_details) in &self.terms {
            let s = serde_json::to_string(&term_details).unwrap();
            let file_name = String::new() + &output_dir + "/term/" + &termid + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write!");
        }
    }

    fn write_metadata(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.metadata).unwrap();
        let file_name = String::new() + &output_dir + "/metadata.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");
    }

    pub fn write(&self, output_dir: &str, organism_genus_species: &str) {
        let s = serde_json::to_string(self).unwrap();
        let file_name = String::new() + output_dir + "/all.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");

        self.write_reference_details(output_dir);
        self.write_gene_details(output_dir);
        self.write_gene_summary(output_dir, organism_genus_species);
        self.write_terms(output_dir);
        self.write_metadata(output_dir);

        println!("wrote {} genes", self.get_genes().len());
        println!("wrote {} terms", self.get_terms().len());
    }
}
<commit_msg>Don't write the all.json file - it's too big<commit_after>use std::collections::HashMap;

extern crate serde_json;

use std::fs::File;
use std::io::{Write, BufWriter};

type CvName = String;

pub type MiscExtRange = String;

pub type GeneUniquename = String;
pub type GeneName = String;
pub type TypeName = String;
pub type GeneProduct = String;

pub type TermName = String;
pub type TermId = String;
pub type TermDef = String;

pub type Evidence = String;

pub type TypeFeatureAnnotationMap =
    HashMap<TypeName, Vec<FeatureAnnotation>>;
pub type TypeReferenceAnnotationMap =
    HashMap<TypeName, Vec<ReferenceAnnotation>>;
pub type TypeInteractionAnnotationMap =
    HashMap<TypeName, Vec<InteractionAnnotation>>;

pub type UniquenameGeneMap =
    HashMap<GeneUniquename, GeneDetails>;

pub type TranscriptUniquename = String;

pub type UniquenameTranscriptMap =
    HashMap<TranscriptUniquename, TranscriptDetails>;

pub type GenotypeUniquename = String;

pub type UniquenameGenotypeMap =
    HashMap<GenotypeUniquename, GenotypeDetails>;

pub type AlleleUniquename = String;

pub type UniquenameAlleleShortMap =
    HashMap<AlleleUniquename, AlleleShort>;

pub type IdGeneMap = HashMap<GeneUniquename, GeneDetails>;
pub type IdGeneShortMap = HashMap<GeneUniquename, GeneShort>;
pub type IdTermDetailsMap = HashMap<TermId, TermDetails>;
pub type IdReferenceMap = HashMap<TermId, ReferenceDetails>;

include!(concat!(env!("OUT_DIR"), "/data_serde.rs"));

impl WebData {
    fn get_genes(&self) -> &IdGeneMap {
        &self.genes
    }
    fn get_terms(&self) -> &IdTermDetailsMap {
        &self.terms
    }

    fn write_reference_details(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.references).unwrap();
        let file_name = String::new() + &output_dir + "/references.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");

        for (reference_uniquename, reference_details) in &self.references {
            let s = serde_json::to_string(&reference_details).unwrap();
            let file_name = String::new() + &output_dir + "/reference/" + &reference_uniquename + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write!");
        }
    }

    fn write_gene_details(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.genes).unwrap();
        let file_name = String::new() + &output_dir + "/genes.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");

        for (gene_uniquename, gene_details) in &self.genes {
            let s = serde_json::to_string(&gene_details).unwrap();
            let file_name = String::new() + &output_dir + "/gene/" + &gene_uniquename + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write!");
        }
    }

    fn write_gene_summary(&self, output_dir: &str, organism_genus_species: &str) {
        let gene_summaries =
            self.gene_summaries.values()
            .filter(|gene_short| {
                let gene_uniquename = &gene_short.uniquename;
                let gene_details = self.get_genes().get(gene_uniquename).unwrap();
                let feature_org_genus_species = String::new() +
                    &gene_details.organism.genus + "_" + &gene_details.organism.species;
                feature_org_genus_species == organism_genus_species
            })
            .map(|gene_short| gene_short.clone())
            .collect::<Vec<GeneShort>>();
        let s = serde_json::to_string(&gene_summaries).unwrap();
        let file_name = String::new() + &output_dir + "/gene_summaries.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");
    }

    fn write_terms(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.terms).unwrap();
        let file_name = String::new() + &output_dir + "/terms.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");

        for (termid, term_details) in &self.terms {
            let s = serde_json::to_string(&term_details).unwrap();
            let file_name = String::new() + &output_dir + "/term/" + &termid + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write!");
        }
    }

    fn write_metadata(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.metadata).unwrap();
        let file_name = String::new() + &output_dir + "/metadata.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");
    }

    pub fn write(&self, output_dir: &str, organism_genus_species: &str) {
        self.write_reference_details(output_dir);
        self.write_gene_details(output_dir);
        self.write_gene_summary(output_dir, organism_genus_species);
        self.write_terms(output_dir);
        self.write_metadata(output_dir);

        println!("wrote {} genes", self.get_genes().len());
        println!("wrote {} terms", self.get_terms().len());
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use rand::{Rng, thread_rng};

fn one_of_n<R: Rng>(rng: &mut R, n: usize) -> usize {
    (1..n).fold(0, |keep, cand| {
        if rng.next_f64() < (1.0 / (cand + 1) as f64) {
            cand
        } else {
            keep
        }
    })
}

fn main() {
    const LINES: usize = 10;

    let mut dist = [0; LINES];
    let mut rng = thread_rng();

    for _ in 0..1_000_000 {
        let num = one_of_n(&mut rng, LINES);
        dist[num] += 1;
    }

    println!("{:?}", dist);
}
<commit_msg>switch one-of-n to gen_weighted_bool<commit_after>extern crate rand;

use rand::{Rng, thread_rng};

fn one_of_n<R: Rng>(rng: &mut R, n: usize) -> usize {
    (1..n).fold(0, |keep, cand| {
        // Note that this will break if n is larger than u32::MAX
        if rng.gen_weighted_bool(cand as u32 + 1) {
            cand
        } else {
            keep
        }
    })
}

fn main() {
    const LINES: usize = 10;

    let mut dist = [0; LINES];
    let mut rng = thread_rng();

    for _ in 0..1_000_000 {
        let num = one_of_n(&mut rng, LINES);
        dist[num] += 1;
    }

    println!("{:?}", dist);
}
<|endoftext|>


<commit_before>use luminance::tess::{Mode, Tess, TessVertices};

// A unit cube.
//
//     ×-----×
//    /|    /|
//   ×-+---× |
//   | ×---+-×
//   |/    |/
//   ×-----×
pub fn new_cube(with_normals: bool) -> Tess {
  if with_normals {
    let vertices = [
      // front face
      ([ 1., -1.,  1.], [ 0.,  0.,  1.]), // 0
      ([ 1.,  1.,  1.], [ 0.,  0.,  1.]),
      ([-1., -1.,  1.], [ 0.,  0.,  1.]),
      ([-1.,  1.,  1.], [ 0.,  0.,  1.]),
      // back face
      ([ 1., -1., -1.], [ 0.,  0., -1.]), // 4
      ([ 1.,  1., -1.], [ 0.,  0., -1.]),
      ([-1., -1., -1.], [ 0.,  0., -1.]),
      ([-1.,  1., -1.], [ 0.,  0., -1.]),
      // left face
      ([-1., -1.,  1.], [-1.,  0.,  0.]), // 8
      ([-1.,  1.,  1.], [-1.,  0.,  0.]),
      ([-1., -1., -1.], [-1.,  0.,  0.]),
      ([-1.,  1., -1.], [-1.,  0.,  0.]),
      // right face
      ([ 1., -1., -1.], [ 1.,  0.,  0.]), // 12
      ([ 1.,  1., -1.], [ 1.,  0.,  0.]),
      ([ 1., -1.,  1.], [ 1.,  0.,  0.]),
      ([ 1.,  1.,  1.], [ 1.,  0.,  0.]),
      // top face
      ([ 1.,  1.,  1.], [ 0.,  1., 0.]), // 16
      ([ 1.,  1., -1.], [ 0.,  1., 0.]),
      ([-1.,  1.,  1.], [ 0.,  1., 0.]),
      ([-1.,  1., -1.], [ 0.,  1., 0.]),
      // bottom face
      ([ 1., -1., -1.], [ 0., -1., 0.]), // 20
      ([ 1., -1.,  1.], [ 0., -1., 0.]),
      ([-1., -1., -1.], [ 0., -1., 0.]),
      ([-1., -1.,  1.], [ 0., -1., 0.]),
    ];

    let indices: &[u32] = &[
      0, 1, 2, 2, 1, 3, // front face
      4, 5, 6, 6, 5, 7, // back face
      8, 9, 10, 10, 9, 11, // left face
      12, 13, 14, 14, 13, 15, // right face
      16, 17, 18, 18, 17, 19, // top face
      20, 21, 22, 22, 21, 23, // bottom face
    ];

    Tess::new(Mode::Triangle, TessVertices::Fill(&vertices), indices)
  } else {
    let vertices = [
      [ 1., -1.,  1.],
      [ 1.,  1.,  1.],
      [-1., -1.,  1.],
      [-1.,  1.,  1.],
      [ 1., -1., -1.],
      [ 1.,  1., -1.],
      [-1., -1., -1.],
      [-1.,  1., -1.],
    ];

    let indices: &[u32] = &[
      0, 1, 2, 2, 1, 3, // front face
      1, 5, 3, 3, 5, 7, // top face
      2, 3, 6, 6, 3, 7, // right face
      4, 5, 0, 0, 5, 1, // left face
      4, 0, 6, 6, 0, 2, // bottom face
      4, 5, 6, 6, 5, 7, // back face
    ];

    Tess::new(Mode::Triangle, TessVertices::Fill(&vertices), indices)
  }
}
<commit_msg>Fixed cube’s vertices type.<commit_after>use luminance::tess::{Mode, Tess, TessVertices};

// A unit cube.
//
//     ×-----×
//    /|    /|
//   ×-+---× |
//   | ×---+-×
//   |/    |/
//   ×-----×
pub fn new_cube(with_normals: bool) -> Tess {
  if with_normals {
    let vertices = [
      // front face
      ([ 1.0f32, -1.,  1.], [ 0.0f32,  0.,  1.]), // 0
      ([ 1.,  1.,  1.], [ 0.,  0.,  1.]),
      ([-1., -1.,  1.], [ 0.,  0.,  1.]),
      ([-1.,  1.,  1.], [ 0.,  0.,  1.]),
      // back face
      ([ 1., -1., -1.], [ 0.,  0., -1.]), // 4
      ([ 1.,  1., -1.], [ 0.,  0., -1.]),
      ([-1., -1., -1.], [ 0.,  0., -1.]),
      ([-1.,  1., -1.], [ 0.,  0., -1.]),
      // left face
      ([-1., -1.,  1.], [-1.,  0.,  0.]), // 8
      ([-1.,  1.,  1.], [-1.,  0.,  0.]),
      ([-1., -1., -1.], [-1.,  0.,  0.]),
      ([-1.,  1., -1.], [-1.,  0.,  0.]),
      // right face
      ([ 1., -1., -1.], [ 1.,  0.,  0.]), // 12
      ([ 1.,  1., -1.], [ 1.,  0.,  0.]),
      ([ 1., -1.,  1.], [ 1.,  0.,  0.]),
      ([ 1.,  1.,  1.], [ 1.,  0.,  0.]),
      // top face
      ([ 1.,  1.,  1.], [ 0.,  1., 0.]), // 16
      ([ 1.,  1., -1.], [ 0.,  1., 0.]),
      ([-1.,  1.,  1.], [ 0.,  1., 0.]),
      ([-1.,  1., -1.], [ 0.,  1., 0.]),
      // bottom face
      ([ 1., -1., -1.], [ 0., -1., 0.]), // 20
      ([ 1., -1.,  1.], [ 0., -1., 0.]),
      ([-1., -1., -1.], [ 0., -1., 0.]),
      ([-1., -1.,  1.], [ 0., -1., 0.]),
    ];

    let indices: &[u32] = &[
      0, 1, 2, 2, 1, 3, // front face
      4, 5, 6, 6, 5, 7, // back face
      8, 9, 10, 10, 9, 11, // left face
      12, 13, 14, 14, 13, 15, // right face
      16, 17, 18, 18, 17, 19, // top face
      20, 21, 22, 22, 21, 23, // bottom face
    ];

    Tess::new(Mode::Triangle, TessVertices::Fill(&vertices), indices)
  } else {
    let vertices = [
      [ 1.0f32, -1.,  1.],
      [ 1.,  1.,  1.],
      [-1., -1.,  1.],
      [-1.,  1.,  1.],
      [ 1., -1., -1.],
      [ 1.,  1., -1.],
      [-1., -1., -1.],
      [-1.,  1., -1.],
    ];

    let indices: &[u32] = &[
      0, 1, 2, 2, 1, 3, // front face
      1, 5, 3, 3, 5, 7, // top face
      2, 3, 6, 6, 3, 7, // right face
      4, 5, 0, 0, 5, 1, // left face
      4, 0, 6, 6, 0, 2, // bottom face
      4, 5, 6, 6, 5, 7, // back face
    ];

    Tess::new(Mode::Triangle, TessVertices::Fill(&vertices), indices)
  }
}
<|endoftext|>


<commit_before>extern crate sputnikvm;
extern crate serde_json;
extern crate hexutil;
extern crate bigint;

mod blockchain;

pub use self::blockchain::{JSONBlock, create_block, create_context};

use serde_json::Value;
use std::str::FromStr;
use bigint::{Gas, M256, U256, H256, Address};
use hexutil::*;
use sputnikvm::errors::RequireError;
use sputnikvm::{VM, SeqContextVM, AccountCommitment, Context, AccountChange, Storage, Patch, VMStatus, VMTEST_PATCH};

pub fn fire_with_block(machine: &mut SeqContextVM, block: &JSONBlock) {
    loop {
        match machine.fire() {
            Err(RequireError::Account(address)) => {
                let account = block.request_account(address);
                machine.commit_account(account);
            },
            Err(RequireError::AccountCode(address)) => {
                let account = block.request_account_code(address);
                machine.commit_account(account);
            },
            Err(RequireError::AccountStorage(address, index)) => {
                let account = block.request_account_storage(address, index);
                machine.commit_account(account);
            },
            Err(RequireError::Blockhash(number)) => {
                // The test JSON file doesn't expose any block
                // information. So those numbers are crafted by hand.
                let hash1 = H256::from_str("0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6").unwrap();
                let hash2 = H256::from_str("0xad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5").unwrap();
                let hash256 = H256::from_str("0x6ca54da2c4784ea43fd88b3402de07ae4bced597cbb19f323b7595857a6720ae").unwrap();

                let hash = if number == U256::from(1u64) {
                    hash1
                } else if number == U256::from(2u64) {
                    hash2
                } else if number == U256::from(256u64) {
                    hash256
                } else {
                    panic!();
                };

                machine.commit_blockhash(number, hash);
            },
            Ok(()) => return,
        }
    }
}

pub fn apply_to_block(machine: &SeqContextVM, block: &mut JSONBlock) {
    for account in machine.accounts() {
        let account = (*account).clone();
        block.apply_account(account);
    }
    for log in machine.logs() {
        let log = (*log).clone();
        block.apply_log(log);
    }
}

pub fn create_machine(v: &Value, block: &JSONBlock) -> SeqContextVM {
    let transaction = create_context(v);

    SeqContextVM::new(transaction, block.block_header(), &VMTEST_PATCH)
}

pub fn test_machine(v: &Value, machine: &SeqContextVM, block: &JSONBlock, debug: bool) -> bool {
    let ref callcreates = v["callcreates"];

    if callcreates.as_array().is_some() {
        let mut i = 0;
        for callcreate in callcreates.as_array().unwrap() {
            let data = read_hex(callcreate["data"].as_str().unwrap()).unwrap();
            let destination = {
                let destination = callcreate["destination"].as_str().unwrap();
                if destination == "" {
                    None
                } else {
                    Some(Address::from_str(destination).unwrap())
                }
            };
            let gas_limit = Gas::from_str(callcreate["gasLimit"].as_str().unwrap()).unwrap();
            let value = U256::from_str(callcreate["value"].as_str().unwrap()).unwrap();

            if i >= machine.history().len() {
                if debug {
                    print!("\n");
                    println!("Transaction check failed, expected more than {} items.", i);
                }
                return false;
            }
            let ref transaction = machine.history()[i];
            if destination.is_some() {
                if transaction.address != destination.unwrap() {
                    if debug {
                        print!("\n");
                        println!("Transaction address mismatch. 0x{:x} != 0x{:x}.", transaction.address, destination.unwrap());
                    }
                    return false;
                }
            }
            if transaction.gas_limit != gas_limit || transaction.value != value || if destination.is_some() { transaction.data != data } else { transaction.code != data } {
                if debug {
                    print!("\n");
                    println!("Transaction mismatch. gas limit 0x{:x} =?= 0x{:x}, value 0x{:x} =?= 0x{:x}, data {:?} =?= {:?}", transaction.gas_limit, gas_limit, transaction.value, value, transaction.data, data);
                }
                return false;
            }

            i = i + 1;
        }
    }

    let out = v["out"].as_str();
    let gas = v["gas"].as_str();

    if out.is_some() {
        let out = read_hex(out.unwrap()).unwrap();
        let out_ref: &[u8] = out.as_ref();
        if machine.out() != out_ref {
            if debug {
                print!("\n");
                println!("Return value check failed. {:?} != {:?}", machine.out(), out_ref);
            }

            return false;
        }
    }

    if gas.is_some() {
        let gas = Gas::from_str(gas.unwrap()).unwrap();
        if machine.available_gas() != gas {
            if debug {
                print!("\n");
                println!("Gas check failed, VM returned: 0x{:x}, expected: 0x{:x}",
                         machine.available_gas(), gas);
            }

            return false;
        }
    }

    let ref post_addresses = v["post"];

    for (address, data) in post_addresses.as_object().unwrap() {
        let address = Address::from_str(address.as_str()).unwrap();
        let balance = U256::from_str(data["balance"].as_str().unwrap()).unwrap();
        let code = read_hex(data["code"].as_str().unwrap()).unwrap();
        let code_ref: &[u8] = code.as_ref();

        if code_ref != block.account_code(address) {
            if debug {
                print!("\n");
                println!("Account code check failed for address 0x{:x}.", address);
            }

            return false;
        }
        if balance != block.balance(address) {
            if debug {
                print!("\n");
                println!("Balance check failed for address 0x{:x}.", address);
                println!("Expected: 0x{:x}", balance);
                println!("Actual:   0x{:x}", block.balance(address));
            }

            return false;
        }

        let storage = data["storage"].as_object().unwrap();
        for (index, value) in storage {
            let index = U256::from_str(index.as_str()).unwrap();
            let value = M256::from_str(value.as_str().unwrap()).unwrap();
            if value != block.account_storage(address, index) {
                if debug {
                    print!("\n");
                    println!("Storage check failed for address 0x{:x} in storage index 0x{:x}",
                             address, index);
                    println!("Expected: 0x{:x}", value);
                    println!("Actual:   0x{:x}", block.account_storage(address, index));
                }
                return false;
            }
        }
    }

    let ref expect = v["expect"];

    if expect.as_object().is_some() {
        for (address, data) in expect.as_object().unwrap() {
            let address = Address::from_str(address.as_str()).unwrap();

            let storage = data["storage"].as_object().unwrap();
            for (index, value) in storage {
                let index = U256::from_str(index.as_str()).unwrap();
                let value = M256::from_str(value.as_str().unwrap()).unwrap();
                if value != block.account_storage(address, index) {
                    if debug {
                        print!("\n");
                        println!("Storage check (expect) failed for address 0x{:x} in storage index 0x{:x}",
                                 address, index);
                        println!("Expected: 0x{:x}", value);
                        println!("Actual:   0x{:x}", block.account_storage(address, index));
                    }
                    return false;
                }
            }
        }
    }

    let ref logs = v["logs"].as_array();

    if logs.is_some() {
        let logs = logs.unwrap();

        for log in logs {
            let log = log.as_object().unwrap();

            let address = Address::from_str(log["address"].as_str().unwrap()).unwrap();
            let data = read_hex(log["data"].as_str().unwrap()).unwrap();
            let mut topics: Vec<H256> = Vec::new();

            for topic in log["topics"].as_array().unwrap() {
                topics.push(H256::from_str(topic.as_str().unwrap()).unwrap());
            }

            if !block.find_log(address, data.as_slice(), topics.as_slice()) {
                if debug {
                    print!("\n");
                    println!("Log match failed.");
                }
                return false;
            }
        }
    }

    return true;
}

fn is_ok(status: VMStatus) -> bool {
    match status {
        VMStatus::ExitedOk => true,
        _ => false,
    }
}

pub fn test_transaction(name: &str, v: &Value, debug: bool) -> bool {
    let mut block = create_block(v);
    let mut machine = create_machine(v, &block);
    fire_with_block(&mut machine, &block);
    apply_to_block(&machine, &mut block);

    if debug {
        println!("status: {:?}", machine.status());
    }
    let out = v["out"].as_str();

    if out.is_some() {
        if is_ok(machine.status()) {
            if test_machine(v, &machine, &block, debug) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    } else {
        if !is_ok(machine.status()) {
            return true;
        } else {
            return false;
        }
    }
}
<commit_msg>Fix Patch interface in jsontests crate<commit_after>extern crate sputnikvm;
extern crate serde_json;
extern crate hexutil;
extern crate bigint;

mod blockchain;

pub use self::blockchain::{JSONBlock, create_block, create_context};

use serde_json::Value;
use std::str::FromStr;
use bigint::{Gas, M256, U256, H256, Address};
use hexutil::*;
use sputnikvm::errors::RequireError;
use sputnikvm::{VM, SeqContextVM, AccountCommitment, Context, AccountChange, Storage, Patch, VMStatus, VMTestPatch};

pub fn fire_with_block(machine: &mut SeqContextVM<VMTestPatch>, block: &JSONBlock) {
    loop {
        match machine.fire() {
            Err(RequireError::Account(address)) => {
                let account = block.request_account(address);
                machine.commit_account(account);
            },
            Err(RequireError::AccountCode(address)) => {
                let account = block.request_account_code(address);
                machine.commit_account(account);
            },
            Err(RequireError::AccountStorage(address, index)) => {
                let account = block.request_account_storage(address, index);
                machine.commit_account(account);
            },
            Err(RequireError::Blockhash(number)) => {
                // The test JSON file doesn't expose any block
                // information. So those numbers are crafted by hand.
                let hash1 = H256::from_str("0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6").unwrap();
                let hash2 = H256::from_str("0xad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5").unwrap();
                let hash256 = H256::from_str("0x6ca54da2c4784ea43fd88b3402de07ae4bced597cbb19f323b7595857a6720ae").unwrap();

                let hash = if number == U256::from(1u64) {
                    hash1
                } else if number == U256::from(2u64) {
                    hash2
                } else if number == U256::from(256u64) {
                    hash256
                } else {
                    panic!();
                };

                machine.commit_blockhash(number, hash);
            },
            Ok(()) => return,
        }
    }
}

pub fn apply_to_block(machine: &SeqContextVM<VMTestPatch>, block: &mut JSONBlock) {
    for account in machine.accounts() {
        let account = (*account).clone();
        block.apply_account(account);
    }
    for log in machine.logs() {
        let log = (*log).clone();
        block.apply_log(log);
    }
}

pub fn create_machine(v: &Value, block: &JSONBlock) -> SeqContextVM<VMTestPatch> {
    let transaction = create_context(v);

    SeqContextVM::<VMTestPatch>::new(transaction, block.block_header())
}

pub fn test_machine(v: &Value, machine: &SeqContextVM<VMTestPatch>, block: &JSONBlock, debug: bool) -> bool {
    let ref callcreates = v["callcreates"];

    if callcreates.as_array().is_some() {
        let mut i = 0;
        for callcreate in callcreates.as_array().unwrap() {
            let data = read_hex(callcreate["data"].as_str().unwrap()).unwrap();
            let destination = {
                let destination = callcreate["destination"].as_str().unwrap();
                if destination == "" {
                    None
                } else {
                    Some(Address::from_str(destination).unwrap())
                }
            };
            let gas_limit = Gas::from_str(callcreate["gasLimit"].as_str().unwrap()).unwrap();
            let value = U256::from_str(callcreate["value"].as_str().unwrap()).unwrap();

            if i >= machine.history().len() {
                if debug {
                    print!("\n");
                    println!("Transaction check failed, expected more than {} items.", i);
                }
                return false;
            }
            let ref transaction = machine.history()[i];
            if destination.is_some() {
                if transaction.address != destination.unwrap() {
                    if debug {
                        print!("\n");
                        println!("Transaction address mismatch. 0x{:x} != 0x{:x}.", transaction.address, destination.unwrap());
                    }
                    return false;
                }
            }
            if transaction.gas_limit != gas_limit || transaction.value != value || if destination.is_some() { transaction.data != data } else { transaction.code != data } {
                if debug {
                    print!("\n");
                    println!("Transaction mismatch. gas limit 0x{:x} =?= 0x{:x}, value 0x{:x} =?= 0x{:x}, data {:?} =?= {:?}", transaction.gas_limit, gas_limit, transaction.value, value, transaction.data, data);
                }
                return false;
            }

            i = i + 1;
        }
    }

    let out = v["out"].as_str();
    let gas = v["gas"].as_str();

    if out.is_some() {
        let out = read_hex(out.unwrap()).unwrap();
        let out_ref: &[u8] = out.as_ref();
        if machine.out() != out_ref {
            if debug {
                print!("\n");
                println!("Return value check failed. {:?} != {:?}", machine.out(), out_ref);
            }

            return false;
        }
    }

    if gas.is_some() {
        let gas = Gas::from_str(gas.unwrap()).unwrap();
        if machine.available_gas() != gas {
            if debug {
                print!("\n");
                println!("Gas check failed, VM returned: 0x{:x}, expected: 0x{:x}",
                         machine.available_gas(), gas);
            }

            return false;
        }
    }

    let ref post_addresses = v["post"];

    for (address, data) in post_addresses.as_object().unwrap() {
        let address = Address::from_str(address.as_str()).unwrap();
        let balance = U256::from_str(data["balance"].as_str().unwrap()).unwrap();
        let code = read_hex(data["code"].as_str().unwrap()).unwrap();
        let code_ref: &[u8] = code.as_ref();

        if code_ref != block.account_code(address) {
            if debug {
                print!("\n");
                println!("Account code check failed for address 0x{:x}.", address);
            }

            return false;
        }
        if balance != block.balance(address) {
            if debug {
                print!("\n");
                println!("Balance check failed for address 0x{:x}.", address);
                println!("Expected: 0x{:x}", balance);
                println!("Actual:   0x{:x}", block.balance(address));
            }

            return false;
        }

        let storage = data["storage"].as_object().unwrap();
        for (index, value) in storage {
            let index = U256::from_str(index.as_str()).unwrap();
            let value = M256::from_str(value.as_str().unwrap()).unwrap();
            if value != block.account_storage(address, index) {
                if debug {
                    print!("\n");
                    println!("Storage check failed for address 0x{:x} in storage index 0x{:x}",
                             address, index);
                    println!("Expected: 0x{:x}", value);
                    println!("Actual:   0x{:x}", block.account_storage(address, index));
                }
                return false;
            }
        }
    }

    let ref expect = v["expect"];

    if expect.as_object().is_some() {
        for (address, data) in expect.as_object().unwrap() {
            let address = Address::from_str(address.as_str()).unwrap();

            let storage = data["storage"].as_object().unwrap();
            for (index, value) in storage {
                let index = U256::from_str(index.as_str()).unwrap();
                let value = M256::from_str(value.as_str().unwrap()).unwrap();
                if value != block.account_storage(address, index) {
                    if debug {
                        print!("\n");
                        println!("Storage check (expect) failed for address 0x{:x} in storage index 0x{:x}",
                                 address, index);
                        println!("Expected: 0x{:x}", value);
                        println!("Actual:   0x{:x}", block.account_storage(address, index));
                    }
                    return false;
                }
            }
        }
    }

    let ref logs = v["logs"].as_array();

    if logs.is_some() {
        let logs = logs.unwrap();

        for log in logs {
            let log = log.as_object().unwrap();

            let address = Address::from_str(log["address"].as_str().unwrap()).unwrap();
            let data = read_hex(log["data"].as_str().unwrap()).unwrap();
            let mut topics: Vec<H256> = Vec::new();

            for topic in log["topics"].as_array().unwrap() {
                topics.push(H256::from_str(topic.as_str().unwrap()).unwrap());
            }

            if !block.find_log(address, data.as_slice(), topics.as_slice()) {
                if debug {
                    print!("\n");
                    println!("Log match failed.");
                }
                return false;
            }
        }
    }

    return true;
}

fn is_ok(status: VMStatus) -> bool {
    match status {
        VMStatus::ExitedOk => true,
        _ => false,
    }
}

pub fn test_transaction(name: &str, v: &Value, debug: bool) -> bool {
    let mut block = create_block(v);
    let mut machine = create_machine(v, &block);
    fire_with_block(&mut machine, &block);
    apply_to_block(&machine, &mut block);

    if debug {
        println!("status: {:?}", machine.status());
    }
    let out = v["out"].as_str();

    if out.is_some() {
        if is_ok(machine.status()) {
            if test_machine(v, &machine, &block, debug) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    } else {
        if !is_ok(machine.status()) {
            return true;
        } else {
            return false;
        }
    }
}
<|endoftext|>


<commit_before>mod engine;
mod mvcc;

use std::fmt;
use std::boxed::FnBox;

use mio::{EventLoop, Handler, Sender};

pub use self::engine::Dsn;
use self::engine::Engine;
use self::mvcc::{MvccEngine, Result};

pub type Key = Vec<u8>;
pub type Value = Vec<u8>;

#[derive(Debug, Clone)]
pub struct KvPair {
    key: Key,
    value: Value,
}

pub struct Storage {
    event_loop: EventLoop<StorageHandler>,
    handler: StorageHandler,
}

impl Storage {
    pub fn new() -> Storage {
        Storage {
            event_loop: EventLoop::new().unwrap(),
            handler: StorageHandler,
        }
    }

    pub fn get_sender(&self) -> StorageSender {
        StorageSender { inner_sender: self.event_loop.channel() }
    }

    pub fn run(&mut self) {
        self.event_loop.run(&mut self.handler).unwrap();
    }
}

pub struct StorageSender {
    inner_sender: Sender<Message>,
}

impl StorageSender {
    pub fn async_get(&self,
                     key: Key,
                     version: u64,
                     callback: Box<FnBox(Result<Option<Value>>) + Send>) {
        self.inner_sender
            .send(Message::Get {
                key: key,
                version: version,
                callback: callback,
            })
            .unwrap();
    }

    pub fn async_scan(&self,
                      start_key: Key,
                      limit: usize,
                      version: u64,
                      callback: Box<FnBox(Result<Vec<KvPair>>) + Send>) {
        self.inner_sender
            .send(Message::Scan {
                start_key: start_key,
                limit: limit,
                version: version,
                callback: callback,
            })
            .unwrap();
    }

    pub fn async_commit(&self,
                        puts: Vec<KvPair>,
                        deletes: Vec<Key>,
                        locks: Vec<Key>,
                        version: u64,
                        callback: Box<FnBox(Result<()>) + Send>) {
        self.inner_sender
            .send(Message::Commit {
                puts: puts,
                deletes: deletes,
                locks: locks,
                version: version,
                callback: callback,
            })
            .unwrap();
    }

    pub fn close(&self) {
        self.inner_sender.send(Message::Close).unwrap();
    }
}

enum Message {
    Get {
        key: Key,
        version: u64,
        callback: Box<FnBox(Result<Option<Value>>) + Send>,
    },
    Scan {
        start_key: Key,
        limit: usize,
        version: u64,
        callback: Box<FnBox(Result<Vec<KvPair>>) + Send>,
    },
    Commit {
        puts: Vec<KvPair>,
        deletes: Vec<Key>,
        locks: Vec<Key>,
        version: u64,
        callback: Box<FnBox(Result<()>) + Send>,
    },
    Close,
}

impl fmt::Debug for Message {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Message::Get{ref key, version, ..} => {
                write!(f, "storage::message::get {:?} @ {}", key, version)
            }
            Message::Scan{ref start_key, limit, version, ..} => {
                write!(f,
                       "storage::message::scan {:?}({}) @ {}",
                       start_key,
                       limit,
                       version)
            }
            Message::Commit{ref puts, ref deletes, ref locks, version, ..} => {
                write!(f,
                       "storage::message::commit puts({}), deletes({}), locks({}) @ {}",
                       puts.len(),
                       deletes.len(),
                       locks.len(),
                       version)
            }
            Message::Close => write!(f, "storage::message::close"),
        }
    }
}

struct StorageHandler;

impl Handler for StorageHandler {
    type Timeout = ();
    type Message = Message;

    fn notify(&mut self, event_loop: &mut EventLoop<StorageHandler>, msg: Message) {
        debug!("recv message: {:?}", msg);
        match msg {
            Message::Get{callback, ..} => callback(Ok(None)),
            Message::Scan{callback, ..} => callback(Ok(vec![])),
            Message::Commit{callback, ..} => callback(Ok(())),
            Message::Close => event_loop.shutdown(),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::thread;
    use super::{Storage, Value};

    #[test]
    fn test_async_api() {
        let mut storage = Storage::new();
        let sender = storage.get_sender();
        let storage = thread::spawn(move || storage.run());

        sender.async_get(b"x".to_vec(), 0u64, Box::new(|x| println!("{:?}", x)));
        sender.close();

        storage.join();
    }
}
<commit_msg>storage: tiny simplify<commit_after>mod engine;
mod mvcc;

use std::fmt;
use std::boxed::FnBox;

use mio::{EventLoop, Handler, Sender};

pub use self::engine::Dsn;
use self::engine::Engine;
use self::mvcc::{MvccEngine, Result};

pub type Key = Vec<u8>;
pub type Value = Vec<u8>;

#[derive(Debug, Clone)]
pub struct KvPair {
    key: Key,
    value: Value,
}

pub struct Storage {
    event_loop: EventLoop<StorageHandler>,
    handler: StorageHandler,
}

impl Storage {
    pub fn new() -> Storage {
        Storage {
            event_loop: EventLoop::new().unwrap(),
            handler: StorageHandler,
        }
    }

    pub fn get_sender(&self) -> StorageSender {
        StorageSender { inner_sender: self.event_loop.channel() }
    }

    pub fn run(&mut self) {
        self.event_loop.run(&mut self.handler).unwrap();
    }
}

pub struct StorageSender {
    inner_sender: Sender<Message>,
}

impl StorageSender {
    pub fn async_get(&self,
                     key: Key,
                     version: u64,
                     callback: Box<FnBox(Result<Option<Value>>) + Send>) {
        self.inner_sender.send(Message::Get(Cmd((key, version), callback))).unwrap();
    }

    pub fn async_scan(&self,
                      start_key: Key,
                      limit: usize,
                      version: u64,
                      callback: Box<FnBox(Result<Vec<KvPair>>) + Send>) {
        self.inner_sender.send(Message::Scan(Cmd((start_key, limit, version), callback))).unwrap();
    }

    pub fn async_commit(&self,
                        puts: Vec<KvPair>,
                        deletes: Vec<Key>,
                        locks: Vec<Key>,
                        version: u64,
                        callback: Box<FnBox(Result<()>) + Send>) {
        self.inner_sender
            .send(Message::Commit(Cmd((puts, deletes, locks, version), callback)))
            .unwrap();
    }

    pub fn close(&self) {
        self.inner_sender.send(Message::Close).unwrap();
    }
}

type Version = u64;
type Limit = usize;
type Puts = Vec<KvPair>;
type Deletes = Vec<Key>;
type Locks = Vec<Key>;

struct Cmd<T, V>(T, Box<FnBox(Result<V>) + Send>);
enum Message {
    Get(Cmd<(Key, Version), Option<Value>>),
    Scan(Cmd<(Key, Limit, Version), Vec<KvPair>>),
    Commit(Cmd<(Puts, Deletes, Locks, Version), ()>),
    Close,
}

impl fmt::Debug for Message {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Message::Get(Cmd((ref key, version), _)) => {
                write!(f, "storage::message::get {:?} @ {}", key, version)
            }
            Message::Scan(Cmd((ref start_key, limit, version), _)) => {
                write!(f,
                       "storage::message::scan {:?}({}) @ {}",
                       start_key,
                       limit,
                       version)
            }
            Message::Commit(Cmd((ref puts, ref deletes, ref locks, version), _)) => {
                write!(f,
                       "storage::message::commit puts({}), deletes({}), locks({}) @ {}",
                       puts.len(),
                       deletes.len(),
                       locks.len(),
                       version)
            }
            Message::Close => write!(f, "storage::message::close"),
        }
    }
}

struct StorageHandler;

impl Handler for StorageHandler {
    type Timeout = ();
    type Message = Message;

    fn notify(&mut self, event_loop: &mut EventLoop<StorageHandler>, msg: Message) {
        debug!("recv message: {:?}", msg);
        match msg {
            Message::Get(Cmd(_, callback)) => callback(Ok(None)),
            Message::Scan(Cmd(_, callback)) => callback(Ok(vec![])),
            Message::Commit(Cmd(_, callback)) => callback(Ok(())),
            Message::Close => event_loop.shutdown(),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::thread;
    use super::{Storage, Value};

    #[test]
    fn test_async_api() {
        let mut storage = Storage::new();
        let sender = storage.get_sender();
        let storage = thread::spawn(move || storage.run());

        sender.async_get(b"x".to_vec(), 0u64, Box::new(|x| println!("{:?}", x)));
        sender.close();

        storage.join();
    }
}
<|endoftext|>


<commit_before><commit_msg>Adding start of abstract_factory.rs<commit_after>/*
 * Abstract Factory Design Pattern
 * http://joshldavis.com/rust-design-patterns/abstract-factory/
 */

/*
 * Core Trait that defines a Phone
 */
trait Phone {
    fn call(&self);
}

/*
 * Core Trait that defines a Tablet
 */
trait Tablet {
    fn play_games(&self);
}

/*
 * Core Trait that defines a Factory
 */
trait Factory {
    fn new_phone<T: Phone>(&self) -> T;
    fn new_tablet<T: Tablet>(&self) -> T;
}

/*
 * Define our Apple products. Normally these structs would contain a lot more
 * data.
 */
struct iPhone;

impl Phone for iPhone {
    fn call(&self) {
        println("Look! I'm calling on an iPhone!");
    }
}

struct iPad;

impl Tablet for iPad {
    fn play_games(&self) {
        println("Just playing some games on my iPad.");
    }
}

/*
 * This would contain all stuff required to make Apple devices.
 */
struct AppleFactory;

impl Factory for AppleFactory {
    fn new_phone<T: Phone>(&self) -> T {
        return iPhone;
    }

    fn new_tablet<T: Tablet>(&self) -> T {
        return iPad;
    }
}

/*
 * Define our Google products. Like with Apple's products, these are
 * simplified.
 */

struct Nexus4;

impl Phone for Nexus4 {
    fn call(&self) {
        println("Look! I'm calling on a Nexus 4!");
    }
}

struct Nexus10;

impl Tablet for Nexus10 {
    fn play_games(&self) {
        println("Just playing some games on my Nexus 10.");
    }
}

/*
 * This would contain all stuff required to make Google devices.
 */
struct GoogleFactory;

impl Factory for GoogleFactory {
    fn new_phone<T: Phone>(&self) -> T {
        return Nexus4;
    }

    fn new_tablet<T: Tablet>(&self) -> T {
        return Nexus10;
    }
}

fn main() {

}
<|endoftext|>