<commit_before>// copyright 2017 Kaz Wesley

//! Implemenation of the Groestl hash function optimized for x86-64 systems.
//! Makes use of sse2, ssse3, and aes extensions as available.

#![cfg_attr(not(feature = "std"), no_std)]

pub extern crate digest;
#[cfg(feature = "std")]
#[macro_use]
extern crate lazy_static;

use block_buffer::byteorder::{BigEndian, ByteOrder, LE};
use block_buffer::generic_array::typenum::{
    PartialDiv, Unsigned, U1024, U16, U28, U48, U512, U64, U8,
};
use block_buffer::generic_array::GenericArray as BBGenericArray;
use block_buffer::BlockBuffer;
use core::fmt::{Debug, Formatter, Result};
use core::mem;
use digest::generic_array::GenericArray as DGenericArray;
pub use digest::Digest;

mod sse2;
use sse2::{init1024, init512, of1024, of512, tf1024, tf512};

#[repr(C, align(16))]
struct Align16<T>(T);

macro_rules! impl_digest {
    ($groestl:ident, $state:ident, $init:ident, $tf:ident, $of:ident, $bits:ident) => {
        #[derive(Clone)]
        #[repr(C, align(16))]
        struct $state {
            chaining: [u64; $bits::USIZE / 64],
            block_counter: u64,
        }

        impl $state {
            fn new(bits: u32) -> Self {
                unsafe {
                    let mut iv = Align16([0u64; $bits::USIZE / 64]);
                    iv.0[iv.0.len() - 1] = u64::from(bits).to_be();
                    Self {
                        chaining: mem::transmute($init(mem::transmute(iv))),
                        block_counter: 0,
                    }
                }
            }
            fn input_block(
                &mut self,
                block: &BBGenericArray<u8, <$bits as PartialDiv<U8>>::Output>,
            ) {
                self.block_counter += 1;
                unsafe {
                    $tf(
                        mem::transmute(&mut self.chaining),
                        &*(block.as_ptr() as *const _),
                    );
                }
            }
            fn finalize(mut self) -> [u64; $bits::USIZE / 64] {
                unsafe {
                    $of(mem::transmute(&mut self.chaining));
                }
                self.chaining
            }
        }

        #[derive(Clone)]
        pub struct $groestl {
            buffer: BlockBuffer<<$bits as PartialDiv<U8>>::Output>,
            state: $state,
        }
        impl $groestl {
            fn new_truncated(bits: u32) -> Self {
                Self {
                    buffer: BlockBuffer::default(),
                    state: $state::new(bits),
                }
            }
            fn finalize(self) -> [u64; $bits::USIZE / 64] {
                let mut state = self.state;
                let mut buffer = self.buffer;
                let count = state.block_counter + 1 + (buffer.remaining() <= 8) as u64;
                buffer.len64_padding::<BigEndian, _>(count, |b| state.input_block(b));
                state.finalize()
            }
        }
        impl Default for $groestl {
            fn default() -> Self {
                Self::new_truncated($bits::U32 / 2)
            }
        }
        impl Debug for $groestl {
            fn fmt(&self, f: &mut Formatter) -> Result {
                f.write_str("<$groestl>")
            }
        }
        impl digest::BlockInput for $groestl {
            type BlockSize = <$bits as PartialDiv<U8>>::Output;
        }
        impl digest::Input for $groestl {
            fn input<T: AsRef<[u8]>>(&mut self, data: T) {
                let state = &mut self.state;
                self.buffer.input(data.as_ref(), |b| state.input_block(b));
            }
        }
        impl digest::FixedOutput for $groestl {
            type OutputSize = <$bits as PartialDiv<U16>>::Output;
            fn fixed_result(self) -> DGenericArray<u8, Self::OutputSize> {
                let result = self.finalize();
                let mut out: DGenericArray<u8, Self::OutputSize> = DGenericArray::default();
                for (out, &input) in out.chunks_exact_mut(8).zip(&result[$bits::USIZE / 128..]) {
                    LE::write_u64(out, input);
                }
                out
            }
        }
        impl digest::Reset for $groestl {
            fn reset(&mut self) {
                *self = $groestl::default();
            }
        }
    };
}

impl_digest!(Groestl256, State512, init512, tf512, of512, U512);
impl_digest!(Groestl512, State1024, init1024, tf1024, of1024, U1024);

#[derive(Clone, Debug)]
pub struct Groestl224(Groestl256);
impl Default for Groestl224 {
    fn default() -> Self {
        Groestl224(Groestl256::new_truncated(224))
    }
}
impl digest::BlockInput for Groestl224 {
    type BlockSize = U64;
}
impl digest::Input for Groestl224 {
    fn input<T: AsRef<[u8]>>(&mut self, data: T) {
        digest::Input::input(&mut self.0, data.as_ref());
    }
}
impl digest::FixedOutput for Groestl224 {
    type OutputSize = U28;
    fn fixed_result(self) -> DGenericArray<u8, U28> {
        let result = self.0.finalize();
        let mut out: DGenericArray<u8, U28> = DGenericArray::default();
        LE::write_u32(&mut out[..4], (result[4] >> 32) as u32);
        for (out, &input) in out[4..].chunks_exact_mut(8).zip(&result[5..8]) {
            LE::write_u64(out, input);
        }
        out
    }
}
impl digest::Reset for Groestl224 {
    fn reset(&mut self) {
        self.0 = Groestl256::new_truncated(224);
    }
}

#[derive(Clone, Debug)]
pub struct Groestl384(Groestl512);
impl Default for Groestl384 {
    fn default() -> Self {
        Groestl384(Groestl512::new_truncated(384))
    }
}
impl digest::BlockInput for Groestl384 {
    type BlockSize = <Groestl512 as digest::BlockInput>::BlockSize;
}
impl digest::Input for Groestl384 {
    fn input<T: AsRef<[u8]>>(&mut self, data: T) {
        digest::Input::input(&mut self.0, data.as_ref());
    }
}
impl digest::FixedOutput for Groestl384 {
    type OutputSize = U48;
    fn fixed_result(self) -> DGenericArray<u8, U48> {
        let result = self.0.finalize();
        let mut out: DGenericArray<u8, U48> = DGenericArray::default();
        for (out, &input) in out.chunks_exact_mut(8).zip(&result[10..]) {
            LE::write_u64(out, input);
        }
        out
    }
}
impl digest::Reset for Groestl384 {
    fn reset(&mut self) {
        *self = Groestl384::default();
    }
}
<commit_msg>define compressors outside macro<commit_after>// copyright 2017 Kaz Wesley

//! Implemenation of the Groestl hash function optimized for x86-64 systems.
//! Makes use of sse2, ssse3, and aes extensions as available.

#![cfg_attr(not(feature = "std"), no_std)]

pub extern crate digest;
#[cfg(feature = "std")]
#[macro_use]
extern crate lazy_static;

use block_buffer::byteorder::{BigEndian, ByteOrder, LE};
use block_buffer::generic_array::typenum::{
    PartialDiv, Unsigned, U1024, U16, U28, U48, U512, U64, U8,
};
use block_buffer::generic_array::GenericArray as BBGenericArray;
use block_buffer::BlockBuffer;
use core::fmt::{Debug, Formatter, Result};
use core::mem;
use digest::generic_array::GenericArray as DGenericArray;
pub use digest::Digest;

mod sse2;
use sse2::{init1024, init512, of1024, of512, tf1024, tf512};

#[repr(C, align(16))]
struct Align16<T>(T);

type Block512 = [u64; 512 / 64];
#[repr(C, align(16))]
#[derive(Clone)]
struct Compressor512 {
    cv: [u64; 512 / 64],
}
impl Compressor512 {
    fn new(block: Block512) -> Self {
        let cv = unsafe { mem::transmute(init512(mem::transmute(block))) };
        Compressor512 { cv }
    }
    fn input(&mut self, data: &Block512) {
        unsafe {
            tf512(mem::transmute(&mut self.cv), &*(data.as_ptr() as *const _));
        }
    }
    fn finalize(mut self) -> Block512 {
        unsafe {
            of512(mem::transmute(&mut self.cv));
        }
        self.cv
    }
}

type Block1024 = [u64; 1024 / 64];
#[repr(C, align(16))]
#[derive(Clone)]
struct Compressor1024 {
    cv: [u64; 1024 / 64],
}
impl Compressor1024 {
    fn new(block: Block1024) -> Self {
        let cv = unsafe { mem::transmute(init1024(mem::transmute(block))) };
        Compressor1024 { cv }
    }
    fn input(&mut self, data: &Block1024) {
        unsafe {
            tf1024(mem::transmute(&mut self.cv), &*(data.as_ptr() as *const _));
        }
    }
    fn finalize(mut self) -> Block1024 {
        unsafe {
            of1024(mem::transmute(&mut self.cv));
        }
        self.cv
    }
}

macro_rules! impl_digest {
    ($groestl:ident, $compressor:ident, $bits:ident) => {
        #[derive(Clone)]
        pub struct $groestl {
            buffer: BlockBuffer<<$bits as PartialDiv<U8>>::Output>,
            block_counter: u64,
            compressor: $compressor,
        }
        impl $groestl {
            fn new_truncated(bits: u32) -> Self {
                let mut iv = Align16([0u64; $bits::USIZE / 64]);
                iv.0[iv.0.len() - 1] = u64::from(bits).to_be();
                let compressor = $compressor::new(iv.0);
                Self {
                    buffer: BlockBuffer::default(),
                    compressor: compressor,
                    block_counter: 0,
                }
            }
            fn finalize(self) -> [u64; $bits::USIZE / 64] {
                let mut buffer = self.buffer;
                let mut compressor = self.compressor;
                let count = self.block_counter + 1 + (buffer.remaining() <= 8) as u64;
                buffer.len64_padding::<BigEndian, _>(count, |b| {
                    compressor.input(unsafe { mem::transmute(b) })
                });
                compressor.finalize()
            }
        }
        impl Default for $groestl {
            fn default() -> Self {
                Self::new_truncated($bits::U32 / 2)
            }
        }
        impl Debug for $groestl {
            fn fmt(&self, f: &mut Formatter) -> Result {
                f.write_str("<$groestl>")
            }
        }
        impl digest::BlockInput for $groestl {
            type BlockSize = <$bits as PartialDiv<U8>>::Output;
        }
        impl digest::Input for $groestl {
            fn input<T: AsRef<[u8]>>(&mut self, data: T) {
                let block_counter = &mut self.block_counter;
                let compressor = &mut self.compressor;
                self.buffer.input(data.as_ref(), |b| {
                    *block_counter += 1;
                    compressor.input(unsafe { mem::transmute(b) })
                });
            }
        }
        impl digest::FixedOutput for $groestl {
            type OutputSize = <$bits as PartialDiv<U16>>::Output;
            fn fixed_result(self) -> DGenericArray<u8, Self::OutputSize> {
                let result = self.finalize();
                let mut out: DGenericArray<u8, Self::OutputSize> = DGenericArray::default();
                for (out, &input) in out.chunks_exact_mut(8).zip(&result[$bits::USIZE / 128..]) {
                    LE::write_u64(out, input);
                }
                out
            }
        }
        impl digest::Reset for $groestl {
            fn reset(&mut self) {
                *self = $groestl::default();
            }
        }
    };
}

impl_digest!(Groestl256, Compressor512, U512);
impl_digest!(Groestl512, Compressor1024, U1024);

#[derive(Clone, Debug)]
pub struct Groestl224(Groestl256);
impl Default for Groestl224 {
    fn default() -> Self {
        Groestl224(Groestl256::new_truncated(224))
    }
}
impl digest::BlockInput for Groestl224 {
    type BlockSize = U64;
}
impl digest::Input for Groestl224 {
    fn input<T: AsRef<[u8]>>(&mut self, data: T) {
        digest::Input::input(&mut self.0, data.as_ref());
    }
}
impl digest::FixedOutput for Groestl224 {
    type OutputSize = U28;
    fn fixed_result(self) -> DGenericArray<u8, U28> {
        let result = self.0.finalize();
        let mut out: DGenericArray<u8, U28> = DGenericArray::default();
        LE::write_u32(&mut out[..4], (result[4] >> 32) as u32);
        for (out, &input) in out[4..].chunks_exact_mut(8).zip(&result[5..8]) {
            LE::write_u64(out, input);
        }
        out
    }
}
impl digest::Reset for Groestl224 {
    fn reset(&mut self) {
        self.0 = Groestl256::new_truncated(224);
    }
}

#[derive(Clone, Debug)]
pub struct Groestl384(Groestl512);
impl Default for Groestl384 {
    fn default() -> Self {
        Groestl384(Groestl512::new_truncated(384))
    }
}
impl digest::BlockInput for Groestl384 {
    type BlockSize = <Groestl512 as digest::BlockInput>::BlockSize;
}
impl digest::Input for Groestl384 {
    fn input<T: AsRef<[u8]>>(&mut self, data: T) {
        digest::Input::input(&mut self.0, data.as_ref());
    }
}
impl digest::FixedOutput for Groestl384 {
    type OutputSize = U48;
    fn fixed_result(self) -> DGenericArray<u8, U48> {
        let result = self.0.finalize();
        let mut out: DGenericArray<u8, U48> = DGenericArray::default();
        for (out, &input) in out.chunks_exact_mut(8).zip(&result[10..]) {
            LE::write_u64(out, input);
        }
        out
    }
}
impl digest::Reset for Groestl384 {
    fn reset(&mut self) {
        *self = Groestl384::default();
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use glib::translate::*;
use std::clone::Clone;
use std::cmp::PartialEq;
use std::ops::Drop;
use std::ptr;
use ffi;

pub use ffi::enums::{
    Antialias,
    SubpixelOrder,
    HintStyle,
    HintMetrics,

    FontType,
    FontWeight,
    FontSlant,
    TextClusterFlags,
};
use ::matrices::{
    Matrix,
    MatrixTrait
};
use ffi::{
    cairo_font_options_t,
    cairo_font_face_t,
    cairo_scaled_font_t
};

pub use ffi::{
    FontExtents,
    Glyph,
    TextCluster,
    TextExtents
};

/* TODO
 Allocates an array of cairo_glyph_t's. This function is only useful in
 implementations of cairo_user_scaled_font_text_to_glyphs_func_t where the user
 needs to allocate an array of glyphs that cairo will free. For all other uses,
 user can use their own allocation method for glyphs.

impl Glyph {

    //pub fn cairo_glyph_allocate(num_glyphs: c_int) -> *Glyph;

    //pub fn cairo_glyph_free(glyphs: *Glyph);
}

 Allocates an array of cairo_glyph_t's. This function is only useful in
 implementations of cairo_user_scaled_font_text_to_glyphs_func_t where the user
 needs to allocate an array of glyphs that cairo will free. For all other uses,
 user can use their own allocation method for glyphs.

impl TextCluster {
    //pub fn cairo_text_cluster_allocate(num_clusters: c_int) -> *TextCluster;

    //pub fn cairo_text_cluster_free(clusters: *TextCluster);
}
*/

pub struct FontOptions(*mut cairo_font_options_t);

impl FontOptions {
    pub fn new() -> FontOptions {
        let font_options = unsafe {
            FontOptions(ffi::cairo_font_options_create())
        };
        font_options.ensure_status();
        font_options
    }

    #[doc(hidden)]
    pub fn get_ptr(&self) -> *mut cairo_font_options_t {
        let FontOptions(ptr) = *self;
        ptr
    }

    pub fn ensure_status(&self) {
        let status = unsafe {
            ffi::cairo_font_options_status(self.get_ptr())
        };
        status.ensure_valid()
    }

    pub fn merge(&mut self, other: &mut FontOptions) {
        unsafe {
            ffi::cairo_font_options_merge(self.get_ptr(), other.get_ptr())
        }
    }

    pub fn hash(&self) -> u64{
        unsafe {
            ffi::cairo_font_options_hash(self.get_ptr()) as u64
        }
    }

    pub fn set_antialias(&self, antialias: Antialias) {
        unsafe {
            ffi::cairo_font_options_set_antialias(self.get_ptr(), antialias)
        }
    }

    pub fn get_antialias(&self) -> Antialias {
        unsafe {
            ffi::cairo_font_options_get_antialias(self.get_ptr())
        }
    }

    pub fn set_subpixel_order(&self, order: SubpixelOrder) {
        unsafe {
            ffi::cairo_font_options_set_subpixel_order(self.get_ptr(), order)
        }
    }

    pub fn get_subpixel_order(&self) -> SubpixelOrder {
        unsafe {
            ffi::cairo_font_options_get_subpixel_order(self.get_ptr())
        }
    }

    pub fn set_hint_style(&self, hint_style: HintStyle) {
        unsafe {
            ffi::cairo_font_options_set_hint_style(self.get_ptr(), hint_style)
        }
    }

    pub fn get_hint_style(&self) -> HintStyle {
        unsafe {
            ffi::cairo_font_options_get_hint_style(self.get_ptr())
        }
    }

    pub fn set_hint_metrics(&self, hint_metrics: HintMetrics) {
        unsafe {
            ffi::cairo_font_options_set_hint_metrics(self.get_ptr(), hint_metrics)
        }
    }

    pub fn get_hint_metrics(&self) -> HintMetrics {
        unsafe {
            ffi::cairo_font_options_get_hint_metrics(self.get_ptr())
        }
    }
}

impl<'a> ToGlibPtr<'a, *const cairo_font_options_t> for &'a FontOptions {
    type Storage = &'a FontOptions;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *const cairo_font_options_t, &'a FontOptions> {
        Stash(self.0, *self)
    }
}

impl FromGlibPtrNone<*const cairo_font_options_t> for FontOptions {
    #[inline]
    unsafe fn from_glib_none(ptr: *const cairo_font_options_t) -> Self {
        let tmp = ffi::cairo_font_options_copy(ptr);
        assert!(!tmp.is_null());
        FontOptions(tmp)
    }
}

impl PartialEq for FontOptions {
    fn eq(&self, other: &FontOptions) -> bool {
        unsafe {
            ffi::cairo_font_options_equal(self.get_ptr(), other.get_ptr()).as_bool()
        }
    }
}

impl Clone for FontOptions {
    fn clone(&self) -> FontOptions {
        unsafe {
            FontOptions(ffi::cairo_font_options_copy(self.get_ptr()))
        }
    }
}

impl Drop for FontOptions {
    fn drop(&mut self) {
        unsafe {
            ffi::cairo_font_options_destroy(self.get_ptr())
        }
    }
}

pub struct FontFace(*mut cairo_font_face_t);

impl FontFace {
    #[doc(hidden)]
    pub fn get_ptr(&self) -> *mut cairo_font_face_t {
        let FontFace(ptr) = *self;
        ptr
    }

    pub fn toy_create(family: &str, slant: FontSlant, weight: FontWeight) -> FontFace {
        let font_face = FontFace(
            unsafe {
                ffi::cairo_toy_font_face_create(family.to_glib_none().0, slant, weight)
            }
        );
        font_face.ensure_status();
        font_face
    }

    pub fn toy_get_family(&self) -> Option<String> {
        unsafe {
            from_glib_none(ffi::cairo_toy_font_face_get_family(self.get_ptr()))
        }
    }

    pub fn toy_get_slant(&self) -> FontSlant {
        unsafe {
            ffi::cairo_toy_font_face_get_slant(self.get_ptr())
        }
    }

    pub fn toy_get_weight(&self) -> FontWeight {
        unsafe {
            ffi::cairo_toy_font_face_get_weight(self.get_ptr())
        }
    }

    pub fn ensure_status(&self) {
        let status = unsafe {
            ffi::cairo_font_face_status(self.get_ptr())
        };
        status.ensure_valid()
    }

    pub fn get_type(&self) -> FontType {
        unsafe {
            ffi::cairo_font_face_get_type(self.get_ptr())
        }
    }

    pub fn get_reference_count(&self) -> usize {
        unsafe {
            ffi::cairo_font_face_get_reference_count(self.get_ptr()) as usize
        }
    }

    pub fn reference(&self) -> FontFace {
        unsafe {
            FontFace(ffi::cairo_font_face_reference(self.get_ptr()))
        }
    }
}

impl<'a> ToGlibPtr<'a, *mut cairo_font_face_t> for &'a FontFace {
    type Storage = &'a FontFace;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *mut cairo_font_face_t, &'a FontFace> {
        Stash(self.0, *self)
    }
}

impl FromGlibPtrNone<*mut cairo_font_face_t> for FontFace {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut cairo_font_face_t) -> Self {
        let tmp = ffi::cairo_font_face_reference(ptr);
        assert!(!tmp.is_null());
        FontFace(tmp)
    }
}

impl Drop for FontFace {
    fn drop(&mut self) {
        unsafe {
            ffi::cairo_font_face_destroy(self.get_ptr())
        }
    }
}

pub struct ScaledFont(pub *mut cairo_scaled_font_t);

impl ScaledFont {
    #[doc(hidden)]
    pub fn get_ptr(&self) -> *mut cairo_scaled_font_t {
        let ScaledFont(ptr) = *self;
        ptr
    }

    pub fn new(font_face: FontFace, font_matrix: &mut Matrix, ctm: &mut Matrix, options: FontOptions) -> ScaledFont {
        let scaled_font = unsafe {
            ScaledFont(ffi::cairo_scaled_font_create(font_face.get_ptr(), font_matrix, ctm, options.get_ptr()))
        };
        scaled_font.ensure_status();
        scaled_font
    }

    pub fn ensure_status(&self) {
        let status = unsafe {
            ffi::cairo_scaled_font_status(self.get_ptr())
        };
        status.ensure_valid()
    }

    pub fn get_type(&self) -> FontType {
        unsafe {
            ffi::cairo_scaled_font_get_type(self.get_ptr())
        }
    }

    pub fn get_reference_count(&self) -> usize {
        unsafe {
            ffi::cairo_scaled_font_get_reference_count(self.get_ptr()) as usize
        }
    }

    pub fn extents(&self) -> FontExtents {
        let mut extents = FontExtents {
            ascent: 0.0,
            descent: 0.0,
            height: 0.0,
            max_x_advance: 0.0,
            max_y_advance: 0.0,
        };

        unsafe {
            ffi::cairo_scaled_font_extents(self.get_ptr(), &mut extents)
        }

        extents
    }

    pub fn text_extents(&self, text: &str) -> TextExtents {
        let mut extents = TextExtents {
            x_bearing: 0.0,
            y_bearing: 0.0,
            width: 0.0,
            height: 0.0,
            x_advance: 0.0,
            y_advance: 0.0,
        };

        unsafe {
            ffi::cairo_scaled_font_text_extents(self.get_ptr(), text.to_glib_none().0, &mut extents)
        }

        extents
    }

    pub fn glyph_extents(&self, glyphs: &[Glyph]) -> TextExtents {
        let mut extents = TextExtents {
            x_bearing: 0.0,
            y_bearing: 0.0,
            width: 0.0,
            height: 0.0,
            x_advance: 0.0,
            y_advance: 0.0,
        };

        unsafe {
            ffi::cairo_scaled_font_glyph_extents(self.get_ptr(), glyphs.as_ptr(), glyphs.len() as i32, &mut extents)
        }

        extents
    }

    pub fn text_to_glyphs(&self, x: f64, y: f64, text: &str) -> (Vec<Glyph>, Vec<TextCluster>) {
        // This large unsafe block is due to the FFI function returning two specially allocated
        // (cairo_{glyph,text_cluster}_allocate) pointers that need to be copied into Vec<T>
        // types before they're of any use to Rust code.

        unsafe {
            let mut glyphs_ptr: *mut Glyph = ptr::null_mut();
            let mut glyph_count = 0i32;
            let mut clusters_ptr: *mut TextCluster = ptr::null_mut();
            let mut cluster_count = 0i32;
            let mut cluster_flags = TextClusterFlags::None;

            let status = ffi::cairo_scaled_font_text_to_glyphs(
                self.get_ptr(),
                x,
                y,
                text.to_glib_none().0,
                text.len() as i32,
                &mut glyphs_ptr,
                &mut glyph_count,
                &mut clusters_ptr,
                &mut cluster_count,
                &mut cluster_flags);

            status.ensure_valid();

            let glyph_count = glyph_count as usize;
            let glyphs: Vec<Glyph> = {
                let mut glyphs: Vec<Glyph> = Vec::with_capacity(glyph_count);

                glyphs.set_len(glyph_count);
                ptr::copy(glyphs_ptr, glyphs.as_mut_ptr(), glyph_count);

                glyphs
            };

            let cluster_count = cluster_count as usize;
            let clusters: Vec<TextCluster> = {
                let mut clusters = Vec::with_capacity(cluster_count);

                clusters.set_len(cluster_count);
                ptr::copy(clusters_ptr, clusters.as_mut_ptr(), cluster_count);

                clusters
            };

            ffi::cairo_glyph_free(glyphs_ptr);
            ffi::cairo_text_cluster_free(clusters_ptr);

            (glyphs, clusters)
        }
    }

    pub fn get_font_face(&self) -> FontFace {
        unsafe {
            FontFace(ffi::cairo_scaled_font_get_font_face(self.get_ptr()))
        }
    }

    pub fn get_font_options(&self) -> FontOptions {
        let options = FontOptions::new();

        unsafe {
            ffi::cairo_scaled_font_get_font_options(self.get_ptr(), options.get_ptr())
        }

        options
    }

    pub fn get_font_matrix(&self) -> Matrix {
        let mut matrix = Matrix::null();

        unsafe {
            ffi::cairo_scaled_font_get_font_matrix(self.get_ptr(), &mut matrix)
        }

        matrix
    }

    pub fn get_ctm(&self) -> Matrix {
        let mut matrix = Matrix::null();

        unsafe {
            ffi::cairo_scaled_font_get_ctm(self.get_ptr(), &mut matrix)
        }

        matrix
    }

    pub fn get_scale_matrix(&self) -> Matrix {
        let mut matrix = Matrix::null();

        unsafe {
            ffi::cairo_scaled_font_get_scale_matrix(self.get_ptr(), &mut matrix)
        }

        matrix
    }

    pub fn reference(&self) -> ScaledFont {
        unsafe {
            ScaledFont(ffi::cairo_scaled_font_reference(self.get_ptr()))
        }
    }
}

impl Drop for ScaledFont {
    fn drop(&mut self) {
        unsafe {
            ffi::cairo_scaled_font_destroy(self.get_ptr())
        }
    }
}
<commit_msg>use *const in ToGlibPtr<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use glib::translate::*;
use std::clone::Clone;
use std::cmp::PartialEq;
use std::ops::Drop;
use std::ptr;
use ffi;

pub use ffi::enums::{
    Antialias,
    SubpixelOrder,
    HintStyle,
    HintMetrics,

    FontType,
    FontWeight,
    FontSlant,
    TextClusterFlags,
};
use ::matrices::{
    Matrix,
    MatrixTrait
};
use ffi::{
    cairo_font_options_t,
    cairo_font_face_t,
    cairo_scaled_font_t
};

pub use ffi::{
    FontExtents,
    Glyph,
    TextCluster,
    TextExtents
};

/* TODO
 Allocates an array of cairo_glyph_t's. This function is only useful in
 implementations of cairo_user_scaled_font_text_to_glyphs_func_t where the user
 needs to allocate an array of glyphs that cairo will free. For all other uses,
 user can use their own allocation method for glyphs.

impl Glyph {

    //pub fn cairo_glyph_allocate(num_glyphs: c_int) -> *Glyph;

    //pub fn cairo_glyph_free(glyphs: *Glyph);
}

 Allocates an array of cairo_glyph_t's. This function is only useful in
 implementations of cairo_user_scaled_font_text_to_glyphs_func_t where the user
 needs to allocate an array of glyphs that cairo will free. For all other uses,
 user can use their own allocation method for glyphs.

impl TextCluster {
    //pub fn cairo_text_cluster_allocate(num_clusters: c_int) -> *TextCluster;

    //pub fn cairo_text_cluster_free(clusters: *TextCluster);
}
*/

pub struct FontOptions(*mut cairo_font_options_t);

impl FontOptions {
    pub fn new() -> FontOptions {
        let font_options = unsafe {
            FontOptions(ffi::cairo_font_options_create())
        };
        font_options.ensure_status();
        font_options
    }

    #[doc(hidden)]
    pub fn get_ptr(&self) -> *mut cairo_font_options_t {
        let FontOptions(ptr) = *self;
        ptr
    }

    pub fn ensure_status(&self) {
        let status = unsafe {
            ffi::cairo_font_options_status(self.get_ptr())
        };
        status.ensure_valid()
    }

    pub fn merge(&mut self, other: &mut FontOptions) {
        unsafe {
            ffi::cairo_font_options_merge(self.get_ptr(), other.get_ptr())
        }
    }

    pub fn hash(&self) -> u64{
        unsafe {
            ffi::cairo_font_options_hash(self.get_ptr()) as u64
        }
    }

    pub fn set_antialias(&self, antialias: Antialias) {
        unsafe {
            ffi::cairo_font_options_set_antialias(self.get_ptr(), antialias)
        }
    }

    pub fn get_antialias(&self) -> Antialias {
        unsafe {
            ffi::cairo_font_options_get_antialias(self.get_ptr())
        }
    }

    pub fn set_subpixel_order(&self, order: SubpixelOrder) {
        unsafe {
            ffi::cairo_font_options_set_subpixel_order(self.get_ptr(), order)
        }
    }

    pub fn get_subpixel_order(&self) -> SubpixelOrder {
        unsafe {
            ffi::cairo_font_options_get_subpixel_order(self.get_ptr())
        }
    }

    pub fn set_hint_style(&self, hint_style: HintStyle) {
        unsafe {
            ffi::cairo_font_options_set_hint_style(self.get_ptr(), hint_style)
        }
    }

    pub fn get_hint_style(&self) -> HintStyle {
        unsafe {
            ffi::cairo_font_options_get_hint_style(self.get_ptr())
        }
    }

    pub fn set_hint_metrics(&self, hint_metrics: HintMetrics) {
        unsafe {
            ffi::cairo_font_options_set_hint_metrics(self.get_ptr(), hint_metrics)
        }
    }

    pub fn get_hint_metrics(&self) -> HintMetrics {
        unsafe {
            ffi::cairo_font_options_get_hint_metrics(self.get_ptr())
        }
    }
}

impl<'a> ToGlibPtr<'a, *const cairo_font_options_t> for &'a FontOptions {
    type Storage = &'a FontOptions;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *const cairo_font_options_t, &'a FontOptions> {
        Stash(self.0, *self)
    }
}

impl FromGlibPtrNone<*const cairo_font_options_t> for FontOptions {
    #[inline]
    unsafe fn from_glib_none(ptr: *const cairo_font_options_t) -> Self {
        let tmp = ffi::cairo_font_options_copy(ptr);
        assert!(!tmp.is_null());
        FontOptions(tmp)
    }
}

impl PartialEq for FontOptions {
    fn eq(&self, other: &FontOptions) -> bool {
        unsafe {
            ffi::cairo_font_options_equal(self.get_ptr(), other.get_ptr()).as_bool()
        }
    }
}

impl Clone for FontOptions {
    fn clone(&self) -> FontOptions {
        unsafe {
            FontOptions(ffi::cairo_font_options_copy(self.get_ptr()))
        }
    }
}

impl Drop for FontOptions {
    fn drop(&mut self) {
        unsafe {
            ffi::cairo_font_options_destroy(self.get_ptr())
        }
    }
}

pub struct FontFace(*mut cairo_font_face_t);

impl FontFace {
    #[doc(hidden)]
    pub fn get_ptr(&self) -> *mut cairo_font_face_t {
        let FontFace(ptr) = *self;
        ptr
    }

    pub fn toy_create(family: &str, slant: FontSlant, weight: FontWeight) -> FontFace {
        let font_face = FontFace(
            unsafe {
                ffi::cairo_toy_font_face_create(family.to_glib_none().0, slant, weight)
            }
        );
        font_face.ensure_status();
        font_face
    }

    pub fn toy_get_family(&self) -> Option<String> {
        unsafe {
            from_glib_none(ffi::cairo_toy_font_face_get_family(self.get_ptr()))
        }
    }

    pub fn toy_get_slant(&self) -> FontSlant {
        unsafe {
            ffi::cairo_toy_font_face_get_slant(self.get_ptr())
        }
    }

    pub fn toy_get_weight(&self) -> FontWeight {
        unsafe {
            ffi::cairo_toy_font_face_get_weight(self.get_ptr())
        }
    }

    pub fn ensure_status(&self) {
        let status = unsafe {
            ffi::cairo_font_face_status(self.get_ptr())
        };
        status.ensure_valid()
    }

    pub fn get_type(&self) -> FontType {
        unsafe {
            ffi::cairo_font_face_get_type(self.get_ptr())
        }
    }

    pub fn get_reference_count(&self) -> usize {
        unsafe {
            ffi::cairo_font_face_get_reference_count(self.get_ptr()) as usize
        }
    }

    pub fn reference(&self) -> FontFace {
        unsafe {
            FontFace(ffi::cairo_font_face_reference(self.get_ptr()))
        }
    }
}

impl<'a> ToGlibPtr<'a, *const cairo_font_face_t> for &'a FontFace {
    type Storage = &'a FontFace;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *const cairo_font_face_t, &'a FontFace> {
        Stash(self.0, *self)
    }
}

impl FromGlibPtrNone<*mut cairo_font_face_t> for FontFace {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut cairo_font_face_t) -> Self {
        let tmp = ffi::cairo_font_face_reference(ptr);
        assert!(!tmp.is_null());
        FontFace(tmp)
    }
}

impl Drop for FontFace {
    fn drop(&mut self) {
        unsafe {
            ffi::cairo_font_face_destroy(self.get_ptr())
        }
    }
}

pub struct ScaledFont(pub *mut cairo_scaled_font_t);

impl ScaledFont {
    #[doc(hidden)]
    pub fn get_ptr(&self) -> *mut cairo_scaled_font_t {
        let ScaledFont(ptr) = *self;
        ptr
    }

    pub fn new(font_face: FontFace, font_matrix: &mut Matrix, ctm: &mut Matrix, options: FontOptions) -> ScaledFont {
        let scaled_font = unsafe {
            ScaledFont(ffi::cairo_scaled_font_create(font_face.get_ptr(), font_matrix, ctm, options.get_ptr()))
        };
        scaled_font.ensure_status();
        scaled_font
    }

    pub fn ensure_status(&self) {
        let status = unsafe {
            ffi::cairo_scaled_font_status(self.get_ptr())
        };
        status.ensure_valid()
    }

    pub fn get_type(&self) -> FontType {
        unsafe {
            ffi::cairo_scaled_font_get_type(self.get_ptr())
        }
    }

    pub fn get_reference_count(&self) -> usize {
        unsafe {
            ffi::cairo_scaled_font_get_reference_count(self.get_ptr()) as usize
        }
    }

    pub fn extents(&self) -> FontExtents {
        let mut extents = FontExtents {
            ascent: 0.0,
            descent: 0.0,
            height: 0.0,
            max_x_advance: 0.0,
            max_y_advance: 0.0,
        };

        unsafe {
            ffi::cairo_scaled_font_extents(self.get_ptr(), &mut extents)
        }

        extents
    }

    pub fn text_extents(&self, text: &str) -> TextExtents {
        let mut extents = TextExtents {
            x_bearing: 0.0,
            y_bearing: 0.0,
            width: 0.0,
            height: 0.0,
            x_advance: 0.0,
            y_advance: 0.0,
        };

        unsafe {
            ffi::cairo_scaled_font_text_extents(self.get_ptr(), text.to_glib_none().0, &mut extents)
        }

        extents
    }

    pub fn glyph_extents(&self, glyphs: &[Glyph]) -> TextExtents {
        let mut extents = TextExtents {
            x_bearing: 0.0,
            y_bearing: 0.0,
            width: 0.0,
            height: 0.0,
            x_advance: 0.0,
            y_advance: 0.0,
        };

        unsafe {
            ffi::cairo_scaled_font_glyph_extents(self.get_ptr(), glyphs.as_ptr(), glyphs.len() as i32, &mut extents)
        }

        extents
    }

    pub fn text_to_glyphs(&self, x: f64, y: f64, text: &str) -> (Vec<Glyph>, Vec<TextCluster>) {
        // This large unsafe block is due to the FFI function returning two specially allocated
        // (cairo_{glyph,text_cluster}_allocate) pointers that need to be copied into Vec<T>
        // types before they're of any use to Rust code.

        unsafe {
            let mut glyphs_ptr: *mut Glyph = ptr::null_mut();
            let mut glyph_count = 0i32;
            let mut clusters_ptr: *mut TextCluster = ptr::null_mut();
            let mut cluster_count = 0i32;
            let mut cluster_flags = TextClusterFlags::None;

            let status = ffi::cairo_scaled_font_text_to_glyphs(
                self.get_ptr(),
                x,
                y,
                text.to_glib_none().0,
                text.len() as i32,
                &mut glyphs_ptr,
                &mut glyph_count,
                &mut clusters_ptr,
                &mut cluster_count,
                &mut cluster_flags);

            status.ensure_valid();

            let glyph_count = glyph_count as usize;
            let glyphs: Vec<Glyph> = {
                let mut glyphs: Vec<Glyph> = Vec::with_capacity(glyph_count);

                glyphs.set_len(glyph_count);
                ptr::copy(glyphs_ptr, glyphs.as_mut_ptr(), glyph_count);

                glyphs
            };

            let cluster_count = cluster_count as usize;
            let clusters: Vec<TextCluster> = {
                let mut clusters = Vec::with_capacity(cluster_count);

                clusters.set_len(cluster_count);
                ptr::copy(clusters_ptr, clusters.as_mut_ptr(), cluster_count);

                clusters
            };

            ffi::cairo_glyph_free(glyphs_ptr);
            ffi::cairo_text_cluster_free(clusters_ptr);

            (glyphs, clusters)
        }
    }

    pub fn get_font_face(&self) -> FontFace {
        unsafe {
            FontFace(ffi::cairo_scaled_font_get_font_face(self.get_ptr()))
        }
    }

    pub fn get_font_options(&self) -> FontOptions {
        let options = FontOptions::new();

        unsafe {
            ffi::cairo_scaled_font_get_font_options(self.get_ptr(), options.get_ptr())
        }

        options
    }

    pub fn get_font_matrix(&self) -> Matrix {
        let mut matrix = Matrix::null();

        unsafe {
            ffi::cairo_scaled_font_get_font_matrix(self.get_ptr(), &mut matrix)
        }

        matrix
    }

    pub fn get_ctm(&self) -> Matrix {
        let mut matrix = Matrix::null();

        unsafe {
            ffi::cairo_scaled_font_get_ctm(self.get_ptr(), &mut matrix)
        }

        matrix
    }

    pub fn get_scale_matrix(&self) -> Matrix {
        let mut matrix = Matrix::null();

        unsafe {
            ffi::cairo_scaled_font_get_scale_matrix(self.get_ptr(), &mut matrix)
        }

        matrix
    }

    pub fn reference(&self) -> ScaledFont {
        unsafe {
            ScaledFont(ffi::cairo_scaled_font_reference(self.get_ptr()))
        }
    }
}

impl Drop for ScaledFont {
    fn drop(&mut self) {
        unsafe {
            ffi::cairo_scaled_font_destroy(self.get_ptr())
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::Result as IOResult;
use std::io::Read;
use std::error::Error;

use byteorder::{ReadBytesExt, BigEndian};

const FRAME_LEN_U16: u8 = 126;
const FRAME_LEN_U64: u8 = 127;

#[allow(dead_code)]
#[derive(Debug)]
pub struct WebSocketFrameHeader {
    fin: bool,
    rsv1: bool,
    rsv2: bool,
    rsv3: bool,
    masked: bool,
    opcode: u8,
    payload_length: u8
}

#[derive(Debug)]
pub struct WebSocketFrame {
    header: WebSocketFrameHeader,
    pub payload: Vec<u8>
}

impl WebSocketFrame {
    pub fn read<R: Read>(input: &mut R) -> IOResult<WebSocketFrame> {
        let mut buf = [0u8; 2];
        try!(input.read(&mut buf));
        let header = Self::parse_header(buf);

        let len = try!(Self::read_length(header.payload_length, input));
        let mask_key = if header.masked {
            let mask = try!(Self::read_mask(input));
            Some(mask)
        } else {
            None
        };
        let mut payload = try!(Self::read_payload(len, input));

        if let Some(mask) = mask_key {
            Self::apply_mask(mask, &mut payload);
        }

        Ok(WebSocketFrame {
            header: header,
            payload: payload
        })
    }

    fn parse_header(buf: [u8; 2]) -> WebSocketFrameHeader {
        WebSocketFrameHeader {
            fin: buf[0] & 0x80 == 0x80,
            rsv1: buf[0] & 0x40 == 0x40,
            rsv2: buf[0] & 0x20 == 0x20,
            rsv3: buf[0] & 0x10 == 0x10,
            opcode: buf[0] & 0x0F,
            masked: buf[1] & 0x80 == 0x80,
            payload_length: buf[1] & 0x7F,
        }
    }

    fn apply_mask(mask: [u8; 4], bytes: &mut Vec<u8>) {
        for (idx, c) in bytes.iter_mut().enumerate() {
            *c = mask[idx % 4];
        }
    }

    fn read_mask<R: Read>(input: &mut R) -> IOResult<[u8; 4]> {
        let mut buf = [0; 4];
        try!(input.read(&mut buf));
        Ok(buf)
    }

    fn read_payload<R: Read>(payload_len: usize, input: &mut R) -> IOResult<Vec<u8>> {
        let mut payload: Vec<u8> = Vec::with_capacity(payload_len);
        unsafe { payload.set_len(payload_len) };
        try!(input.read(&mut payload));
        Ok(payload)
    }

    fn read_length<R: Read>(payload_len: u8, input: &mut R) -> Result<usize, io::Error> {
        return match payload_len {
            FRAME_LEN_U64 => input.read_u64::<BigEndian>().map(|v| v as usize).map_err(|e| io::Error::from(e)),
            FRAME_LEN_U16 => input.read_u16::<BigEndian>().map(|v| v as usize).map_err(|e| io::Error::from(e)),
            _ => Ok(payload_len as usize) // payload_len < 127
        }
    }
}
<commit_msg>Remove redundant type specialization<commit_after>use std::io;
use std::io::Result as IOResult;
use std::io::Read;
use std::error::Error;

use byteorder::{ReadBytesExt, BigEndian};

const FRAME_LEN_U16: u8 = 126;
const FRAME_LEN_U64: u8 = 127;

#[allow(dead_code)]
#[derive(Debug)]
pub struct WebSocketFrameHeader {
    fin: bool,
    rsv1: bool,
    rsv2: bool,
    rsv3: bool,
    masked: bool,
    opcode: u8,
    payload_length: u8
}

#[derive(Debug)]
pub struct WebSocketFrame {
    header: WebSocketFrameHeader,
    pub payload: Vec<u8>
}

impl WebSocketFrame {
    pub fn read<R: Read>(input: &mut R) -> IOResult<WebSocketFrame> {
        let mut buf = [0u8; 2];
        try!(input.read(&mut buf));
        let header = Self::parse_header(buf);

        let len = try!(Self::read_length(header.payload_length, input));
        let mask_key = if header.masked {
            let mask = try!(Self::read_mask(input));
            Some(mask)
        } else {
            None
        };
        let mut payload = try!(Self::read_payload(len, input));

        if let Some(mask) = mask_key {
            Self::apply_mask(mask, &mut payload);
        }

        Ok(WebSocketFrame {
            header: header,
            payload: payload
        })
    }

    fn parse_header(buf: [u8; 2]) -> WebSocketFrameHeader {
        WebSocketFrameHeader {
            fin: buf[0] & 0x80 == 0x80,
            rsv1: buf[0] & 0x40 == 0x40,
            rsv2: buf[0] & 0x20 == 0x20,
            rsv3: buf[0] & 0x10 == 0x10,
            opcode: buf[0] & 0x0F,
            masked: buf[1] & 0x80 == 0x80,
            payload_length: buf[1] & 0x7F,
        }
    }

    fn apply_mask(mask: [u8; 4], bytes: &mut Vec<u8>) {
        for (idx, c) in bytes.iter_mut().enumerate() {
            *c = mask[idx % 4];
        }
    }

    fn read_mask<R: Read>(input: &mut R) -> IOResult<[u8; 4]> {
        let mut buf = [0; 4];
        try!(input.read(&mut buf));
        Ok(buf)
    }

    fn read_payload<R: Read>(payload_len: usize, input: &mut R) -> IOResult<Vec<u8>> {
        let mut payload: Vec<u8> = Vec::with_capacity(payload_len);
        unsafe { payload.set_len(payload_len) };
        try!(input.read(&mut payload));
        Ok(payload)
    }

    fn read_length<R: Read>(payload_len: u8, input: &mut R) -> IOResult<usize> {
        return match payload_len {
            FRAME_LEN_U64 => input.read_u64::<BigEndian>().map(|v| v as usize).map_err(|e| io::Error::from(e)),
            FRAME_LEN_U16 => input.read_u16::<BigEndian>().map(|v| v as usize).map_err(|e| io::Error::from(e)),
            _ => Ok(payload_len as usize) // payload_len < 127
        }
    }
}
<|endoftext|>


<commit_before>//! Implements basic arithmetic and polynomial operations in GF(2^8).

use rand::{CryptoRng, Rng};

macro_rules! bool_to_mask {
    ($e:expr) => {{
        ($e as u8) * 0xff
    }};
}

/// Multiply two elements of GF(2^8).
fn mul(lhs: u8, rhs: u8) -> u8 {
    // This algorithm is constant-time, allowing us to perform GF256 arithmetic over secret values
    // without leaking information about the values via timing.
    let mut aa = lhs;
    let mut bb = rhs;
    let mut r = 0;
    // Loop over all 8 bits, regardless of whether or not it's required. aa != 0 is the usual loop
    // condition, but here it's folded into the per-round bitmask.
    for _ in 0..8 {
        // Perform r ^= bb iff aa & 1 == 0 && aa != 0.
        let loop_live = bool_to_mask!(aa != 0);
        r ^= bb & bool_to_mask!(aa & 1 != 0) & loop_live;
        let t = bb & 0x80;
        bb <<= 1;
        // Perform bb ^= 0x1b iff t != 0 && aa != 0.
        bb ^= 0x1b & bool_to_mask!(t != 0) & loop_live;
        aa >>= 1;
    }
    r
}

/// Divide one element of GF(2^8) by another.
fn div(lhs: u8, rhs: u8) -> u8 {
    if rhs == 0 {
        panic!("Divide by zero: {} / {}", lhs, rhs)
    }

    // Again, this algorithm is constant-time. First, we find the multiplicative inverse of `a` by
    // iterating over all possible values, and using a bitmask to accumulate only that value which,
    // when multiplied by `a`, is `1`.
    let mut inv = 0;
    for i in 0x00..=0xff {
        inv += i & bool_to_mask!(mul(i, rhs) == 1);
    }

    // Finally, we multiply `e` by the multiplicative inverse of `a`.
    mul(inv, lhs)
}

/// Evaluate a polynomial, returning the Y value for the given X value.
pub fn eval(p: &[u8], x: u8) -> u8 {
    p.iter().rev().fold(0, |res, &v| mul(res, x) ^ v)
}

/// Generates a random polynomial of the Nth degree with a Y-intercept with the
/// given value.
pub fn generate<R>(n: usize, y: u8, rng: &mut R) -> Vec<u8>
where
    R: Rng + CryptoRng,
{
    // Allocate a vec of n+1 bytes.
    let mut p = vec![0; n + 1];

    // Set its Y-intercept to the given value.
    p[0] = y;

    // Generate random coefficients.
    rng.fill_bytes(&mut p[1..n]);

    // Ensure the Nth coefficient is non-zero, otherwise it's an (N-1)th-degree
    // polynomial.
    p[n] = rng.gen_range(1, 255);

    p
}

/// Interpolates a vector of (X, Y) points, returning the Y value at zero.
pub fn y_intercept(points: Vec<(u8, u8)>) -> u8 {
    let mut value = 0;
    for (i, &(ax, ay)) in points.iter().enumerate() {
        let mut weight = 1;
        for (j, &(bx, _)) in points.iter().enumerate() {
            if i != j {
                weight = mul(weight, div(bx, ax ^ bx));
            }
        }
        value ^= mul(weight, ay)
    }
    value
}

#[cfg(test)]
mod test {
    extern crate proptest;
    extern crate rand_chacha;

    use rand::SeedableRng;

    use super::*;

    use self::proptest::prelude::*;
    use self::rand_chacha::ChaChaRng;

    proptest! {
        #[test]
        fn test_div_is_inverse_of_mul(a in 0u8..=255, b in 1u8..=255) {
            assert_eq!(mul(div(a, b), b), a);
        }

        #[test]
        fn test_mul_is_inverse_of_div(a in 0u8..=255, b in 1u8..=255) {
            assert_eq!(div(mul(a, b), b), a);
        }

        #[test]
        fn test_mul_is_commutative(a in 0u8..=255, b in 0u8..=255) {
            assert_eq!(mul(a, b), mul(b, a));
        }
    }

    #[test]
    fn test_mul() {
        assert_eq!(mul(90, 21), 254);
        assert_eq!(mul(133, 5), 167);
        assert_eq!(mul(0, 21), 0);
    }

    #[test]
    fn test_div() {
        assert_eq!(div(90, 21), 189);
        assert_eq!(div(6, 55), 151);
        assert_eq!(div(22, 192), 138);
        assert_eq!(div(0, 21), 0);
    }

    #[test]
    fn test_eval() {
        assert_eq!(eval(&vec![1, 0, 2, 3], 2), 17);
    }

    proptest! {
        #[test]
        fn test_generate(seed: [u8; 32]) {
            let mut rng = ChaChaRng::from_seed(seed);
            let p = generate(20, 100, &mut rng);
            assert_eq!(p[0], 100);
            assert_ne!(p[20], 0);
        }
    }

    #[test]
    fn test_y_intercept() {
        assert_eq!(y_intercept(vec![(1, 1), (2, 2), (3, 3)]), 0);
        assert_eq!(y_intercept(vec![(1, 80), (2, 90), (3, 20)]), 30);
        assert_eq!(y_intercept(vec![(1, 43), (2, 22), (3, 86)]), 107);
    }
}
<commit_msg>Use fold.<commit_after>//! Implements basic arithmetic and polynomial operations in GF(2^8).

use rand::{CryptoRng, Rng};

macro_rules! bool_to_mask {
    ($e:expr) => {{
        ($e as u8) * 0xff
    }};
}

/// Multiply two elements of GF(2^8).
fn mul(lhs: u8, rhs: u8) -> u8 {
    // This algorithm is constant-time, allowing us to perform GF256 arithmetic over secret values
    // without leaking information about the values via timing.
    let mut aa = lhs;
    let mut bb = rhs;
    let mut r = 0;
    // Loop over all 8 bits, regardless of whether or not it's required. aa != 0 is the usual loop
    // condition, but here it's folded into the per-round bitmask.
    for _ in 0..8 {
        // Perform r ^= bb iff aa & 1 == 0 && aa != 0.
        let loop_live = bool_to_mask!(aa != 0);
        r ^= bb & bool_to_mask!(aa & 1 != 0) & loop_live;
        let t = bb & 0x80;
        bb <<= 1;
        // Perform bb ^= 0x1b iff t != 0 && aa != 0.
        bb ^= 0x1b & bool_to_mask!(t != 0) & loop_live;
        aa >>= 1;
    }
    r
}

/// Divide one element of GF(2^8) by another.
fn div(lhs: u8, rhs: u8) -> u8 {
    if rhs == 0 {
        panic!("Divide by zero: {} / {}", lhs, rhs)
    }

    // Again, this algorithm is constant-time. First, we find the multiplicative inverse of `a` by
    // iterating over all possible values, and using a bitmask to accumulate only that value which,
    // when multiplied by `a`, is `1`.
    let mut inv = 0;
    for i in 0x00..=0xff {
        inv += i & bool_to_mask!(mul(i, rhs) == 1);
    }

    // Finally, we multiply `e` by the multiplicative inverse of `a`.
    mul(inv, lhs)
}

/// Evaluate a polynomial, returning the Y value for the given X value.
pub fn eval(p: &[u8], x: u8) -> u8 {
    p.iter().rev().fold(0, |res, &v| mul(res, x) ^ v)
}

/// Generates a random polynomial of the Nth degree with a Y-intercept with the
/// given value.
pub fn generate<R>(n: usize, y: u8, rng: &mut R) -> Vec<u8>
where
    R: Rng + CryptoRng,
{
    // Allocate a vec of n+1 bytes.
    let mut p = vec![0; n + 1];

    // Set its Y-intercept to the given value.
    p[0] = y;

    // Generate random coefficients.
    rng.fill_bytes(&mut p[1..n]);

    // Ensure the Nth coefficient is non-zero, otherwise it's an (N-1)th-degree
    // polynomial.
    p[n] = rng.gen_range(1, 255);

    p
}

/// Interpolates a vector of (X, Y) points, returning the Y value at zero.
pub fn y_intercept(points: Vec<(u8, u8)>) -> u8 {
    points.iter().enumerate().fold(0, |value, (i, &(ax, ay))| {
        let weight = points
            .iter()
            .enumerate()
            .filter(|&(j, _)| i != j)
            .fold(1, |weight, (_, &(bx, _))| mul(weight, div(bx, ax ^ bx)));
        value ^ mul(weight, ay)
    })
}

#[cfg(test)]
mod test {
    extern crate proptest;
    extern crate rand_chacha;

    use rand::SeedableRng;

    use super::*;

    use self::proptest::prelude::*;
    use self::rand_chacha::ChaChaRng;

    proptest! {
        #[test]
        fn test_div_is_inverse_of_mul(a in 0u8..=255, b in 1u8..=255) {
            assert_eq!(mul(div(a, b), b), a);
        }

        #[test]
        fn test_mul_is_inverse_of_div(a in 0u8..=255, b in 1u8..=255) {
            assert_eq!(div(mul(a, b), b), a);
        }

        #[test]
        fn test_mul_is_commutative(a in 0u8..=255, b in 0u8..=255) {
            assert_eq!(mul(a, b), mul(b, a));
        }
    }

    #[test]
    fn test_mul() {
        assert_eq!(mul(90, 21), 254);
        assert_eq!(mul(133, 5), 167);
        assert_eq!(mul(0, 21), 0);
    }

    #[test]
    fn test_div() {
        assert_eq!(div(90, 21), 189);
        assert_eq!(div(6, 55), 151);
        assert_eq!(div(22, 192), 138);
        assert_eq!(div(0, 21), 0);
    }

    #[test]
    fn test_eval() {
        assert_eq!(eval(&vec![1, 0, 2, 3], 2), 17);
    }

    proptest! {
        #[test]
        fn test_generate(seed: [u8; 32]) {
            let mut rng = ChaChaRng::from_seed(seed);
            let p = generate(20, 100, &mut rng);
            assert_eq!(p[0], 100);
            assert_ne!(p[20], 0);
        }
    }

    #[test]
    fn test_y_intercept() {
        assert_eq!(y_intercept(vec![(1, 1), (2, 2), (3, 3)]), 0);
        assert_eq!(y_intercept(vec![(1, 80), (2, 90), (3, 20)]), 30);
        assert_eq!(y_intercept(vec![(1, 43), (2, 22), (3, 86)]), 107);
    }
}
<|endoftext|>


<commit_before>use nom::{IResult, is_space};
use std::collections::{HashMap, HashSet};
use std::collections::hash_map::Entry;
use std::fmt::Debug;
use std::hash::Hash;
use std::iter::FromIterator;
use std::str::FromStr;

use util::parsing::*;

/// Structure containing the elements of type `A` in a equivalence class of type `B`
#[derive(Debug, Eq, PartialEq)]
pub struct EquivalenceClass<A, B>
    where A: Eq + Hash,
{
    label: B,
    set: Option<HashSet<A>>,
}

impl<A, B> From<(B, Option<Vec<A>>)> for EquivalenceClass<A, B>
    where A: Eq + Hash,
{
    fn from((label, set): (B, Option<Vec<A>>)) -> EquivalenceClass<A, B> {
        EquivalenceClass {
            label,
            set: set.and_then(|elements| Some(HashSet::from_iter(elements))),
        }
    }
}

/// A struct containing a remapping of elements of type `A` into their respective equivalence classes of type `B`.
#[derive(Clone, Debug)]
pub struct EquivalenceRelation<A, B>
    where A: Eq + Hash,
{
    map: HashMap<A, B>,
    default: B,
}

impl<A, B> PartialEq for EquivalenceRelation<A, B>
    where A: Eq + Hash,
          B: PartialEq,
{
    fn eq(&self, other: &Self) -> bool {
        self.default == other.default && self.map == other.map
    }
}

impl<A, B> EquivalenceRelation<A, B>
    where A: Eq + Hash,
          B: Clone + Eq + Hash,
{
    pub fn new(map: HashMap<B, HashSet<A>>, default: B) -> Self {
        match Self::new_safe(map, default) {
            Ok(relation) => relation,
            Err(error) => panic!(error),
        }
    }

    pub fn new_safe(map: HashMap<B, HashSet<A>>, default: B) -> Result<Self, String> {
        let mut relation_map = HashMap::new();
        for (class_name, members) in map {
            if class_name == default {
                return Err(String::from(
                    "There can only be one default class in the equivalence relation!"
                ));
            }

            for value in members {
                match relation_map.entry(value) {
                    Entry::Vacant(v) => {
                        v.insert(class_name.clone());
                    },
                    Entry::Occupied(_) => {
                        return Err(String::from(
                            "All classes of the equivalence relation must be disjoint!"
                        ));
                    },
                }
            }
        }

        Ok(EquivalenceRelation { map: relation_map, default })
    }

    // returns the equivalence class of a given value
    pub fn project(&self, key: &A) -> B {
        match self.map.get(key) {
            None => self.default.clone(),
            Some(e) => e.clone(),
        }
    }
}

impl<A, B> From<Vec<EquivalenceClass<A, B>>> for EquivalenceRelation<A, B>
    where A: Eq + Hash,
          B: Clone + Eq + Hash,
{
    fn from(classes: Vec<EquivalenceClass<A, B>>) -> EquivalenceRelation<A, B> {
        let mut map = HashMap::new();
        let mut default = None;

        for EquivalenceClass { label, set } in classes {
            if let Some(elements) = set {
                for element in elements {
                    map.insert(element, label.clone());
                }
            } else {
                default = Some(label);
            }
        }

        EquivalenceRelation { map, default: default.unwrap() }
    }
}

impl<A, B> FromStr for EquivalenceRelation<A, B>
    where A: Clone + Eq + Hash + FromStr,
          A::Err: Debug,
          B: Clone + Eq + Hash + FromStr,
          B::Err: Debug,
{
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut map = HashMap::new();
        let mut default = None;

        for l in s.lines() {
            if !l.is_empty() {
                match l.trim().parse()? {
                    EquivalenceClass { label, set: Some(elements) } => {
                        map.insert(label, elements);
                    },
                    EquivalenceClass { label, set: None } => {
                        default = Some(label);
                    },
                }
            }
        }

        if let Some(label) = default {
            if let Ok(relation) = EquivalenceRelation::new_safe(map, label) {
                return Ok(relation);
            }
        }

        Err(format!("Could not parse {}", s))
    }
}

impl <A, B> FromStr for EquivalenceClass<A, B>
    where A: Eq + FromStr + Hash,
          A::Err: Debug,
          B: FromStr,
          B::Err: Debug,
{
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match parse_set(s.as_bytes()) {
            IResult::Done(_, result) => Ok(result),
            _                        => Err(format!("Could not parse {}", s))
        }
    }
}

fn parse_set<A, B>(input: &[u8]) -> IResult<&[u8], EquivalenceClass<A, B>>
    where A: Eq + FromStr + Hash,
          A::Err: Debug,
          B: FromStr,
          B::Err: Debug,
{
    do_parse!(
        input,
        label: parse_token >>
            take_while!(is_space) >>
            set: alt!(
                do_parse!(
                    tag!("*") >> (None)
                )
                    |
                do_parse!(
                    the_set: parse_heap >> (Some(the_set))
                )
            ) >>
            (EquivalenceClass {
                label,
                set,
            })
    )
}

fn parse_heap<A>(input: &[u8]) -> IResult<&[u8], HashSet<A>>
    where A: Eq + FromStr + Hash,
          A::Err: Debug,
{
    match parse_vec(input, parse_token, "[", "]", ",") {
        IResult::Done(rest, parsed) => IResult::Done(rest, HashSet::from_iter(parsed)),
        IResult::Incomplete(needed) => IResult::Incomplete(needed),
        IResult::Error(error) => IResult::Error(error),
    }
}

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

    #[test]
    fn test_equivalence_class_from_str_legal_input() {
        let legal_inputs = vec![
            ("0 [0, 1]", EquivalenceClass::from((0, Some(vec![0, 1])))),
            ("0  [1, 0]", EquivalenceClass::from((0, Some(vec![0, 1])))),
            ("0  [0, 1, 1]", EquivalenceClass::from((0, Some(vec![0, 1])))),
            ("0 *", EquivalenceClass::from((0, None))),
        ];

        for (legal_input, correct_class) in legal_inputs {
            assert_eq!(correct_class,
                       EquivalenceClass::from_str(legal_input).unwrap());
        }
    }

    #[test]
    fn test_equivalence_class_from_str_illegal_input() {
        let illegal_inputs = vec![
            " 0 [0, 1]",
            "[0, 1]",
            "*",
        ];

        for illegal_input in illegal_inputs {
            match EquivalenceClass::<u8, u8>::from_str(illegal_input) {
                Ok(parsed) =>
                    panic!("Was able to parse the illegal input \'{}\' as \'{:?}\'",
                           illegal_input, parsed),
                Err(_) => (),
            }
        }
    }

    #[test]
    fn test_equivalence_relation_project() {
        let rel: EquivalenceRelation<u8, u8> = String::from("0 [0, 1]\n1 [2, 4]\n2 *").parse().unwrap();
        assert_eq!(0, rel.project(&1));
        assert_eq!(1, rel.project(&2));
        assert_eq!(2, rel.project(&3));
        assert_eq!(1, rel.project(&4));
    }

    #[test]
    #[should_panic(
        expected="There can only be one default class in the equivalence relation!"
    )]
    fn test_equivalence_relation_new_colliding_default() {
        let mut map = HashMap::new();
        let classes = vec![
            (0, HashSet::from_iter(vec![0, 1])),
            (1, HashSet::from_iter(vec![2, 3])),
        ];

        for (label, elements) in classes {
            map.insert(label, elements);
        }

        EquivalenceRelation::new(map, 1);
    }

    #[test]
    #[should_panic(
        expected="All classes of the equivalence relation must be disjoint!"
    )]
    fn test_equivalence_relation_new_intersecting_classes() {
        let mut map = HashMap::new();
        let classes = vec![
            (0, HashSet::from_iter(vec![0, 1])),
            (1, HashSet::from_iter(vec![1, 2])),
        ];

        for (label, elements) in classes {
            map.insert(label, elements);
        }

        EquivalenceRelation::new(map, 2);
    }

    #[test]
    fn test_equivalence_relation_from_str_legal_input() {
        let legal_inputs = vec![
            ("0 [0, 1]\n1 [2, 3]\n2 *", EquivalenceRelation::from(vec![
                EquivalenceClass::from((0, Some(vec![0, 1]))),
                EquivalenceClass::from((1, Some(vec![2, 3]))),
                EquivalenceClass::from((2, None)),
            ])),
        ];

        for (legal_input, correct_relation) in legal_inputs {
            assert_eq!(correct_relation,
                       EquivalenceRelation::from_str(legal_input).unwrap());
        }
    }

    #[test]
    fn test_equivalence_relation_from_str_illegal_input() {
        let illegal_inputs = vec![
            " 0 [0, 1]\n1 [2, 3]\n2 *",
            "0 [0, 1]1 [2, 3]2 *",
            "0 [0, 1]\n1 [1, 2]\n2 *",
        ];

        for illegal_input in illegal_inputs {
            match EquivalenceRelation::<u8, u8>::from_str(illegal_input) {
                Ok(parsed) =>
                    panic!("Was able to parse the illegal input \'{}\' as \'{:?}\'",
                           illegal_input, parsed),
                Err(_) => (),
            }
        }
    }
}
<commit_msg>src/approximation/equivalence_classes.rs: fixed tests and added one FIXME<commit_after>use nom::{IResult, is_space};
use std::collections::{HashMap, HashSet};
use std::collections::hash_map::Entry;
use std::fmt::Debug;
use std::hash::Hash;
use std::iter::FromIterator;
use std::str::FromStr;

use util::parsing::*;

/// Structure containing the elements of type `A` in a equivalence class of type `B`
#[derive(Debug, Eq, PartialEq)]
pub struct EquivalenceClass<A, B>
    where A: Eq + Hash,
{
    label: B,
    set: Option<HashSet<A>>,
}

impl<A, B> From<(B, Option<Vec<A>>)> for EquivalenceClass<A, B>
    where A: Eq + Hash,
{
    fn from((label, set): (B, Option<Vec<A>>)) -> EquivalenceClass<A, B> {
        EquivalenceClass {
            label,
            set: set.and_then(|elements| Some(HashSet::from_iter(elements))),
        }
    }
}

/// A struct containing a remapping of elements of type `A` into their respective equivalence classes of type `B`.
#[derive(Clone, Debug)]
pub struct EquivalenceRelation<A, B>
    where A: Eq + Hash,
{
    map: HashMap<A, B>,
    default: B,
}

impl<A, B> PartialEq for EquivalenceRelation<A, B>
    where A: Eq + Hash,
          B: PartialEq,
{
    fn eq(&self, other: &Self) -> bool {
        self.default == other.default && self.map == other.map
    }
}

impl<A, B> EquivalenceRelation<A, B>
    where A: Eq + Hash,
          B: Clone + Eq + Hash,
{
    pub fn new(map: HashMap<B, HashSet<A>>, default: B) -> Self {
        match Self::new_safe(map, default) {
            Ok(relation) => relation,
            Err(error) => panic!(error),
        }
    }

    pub fn new_safe(map: HashMap<B, HashSet<A>>, default: B) -> Result<Self, String> {
        let mut relation_map = HashMap::new();
        for (class_name, members) in map {
            if class_name == default {
                return Err(String::from(
                    "There can only be one default class in the equivalence relation!"
                ));
            }

            for value in members {
                match relation_map.entry(value) {
                    Entry::Vacant(v) => {
                        v.insert(class_name.clone());
                    },
                    Entry::Occupied(_) => {
                        return Err(String::from(
                            "All classes of the equivalence relation must be disjoint!"
                        ));
                    },
                }
            }
        }

        Ok(EquivalenceRelation { map: relation_map, default })
    }

    // returns the equivalence class of a given value
    pub fn project(&self, key: &A) -> B {
        match self.map.get(key) {
            None => self.default.clone(),
            Some(e) => e.clone(),
        }
    }
}

impl<A, B> From<Vec<EquivalenceClass<A, B>>> for EquivalenceRelation<A, B>
    where A: Eq + Hash,
          B: Clone + Eq + Hash,
{
    fn from(classes: Vec<EquivalenceClass<A, B>>) -> EquivalenceRelation<A, B> {
        let mut map = HashMap::new();
        let mut default = None;

        for EquivalenceClass { label, set } in classes {
            if let Some(elements) = set {
                for element in elements {
                    map.insert(element, label.clone());
                }
            } else {
                default = Some(label);
            }
        }

        EquivalenceRelation { map, default: default.unwrap() }
    }
}

impl<A, B> FromStr for EquivalenceRelation<A, B>
    where A: Clone + Eq + Hash + FromStr,
          A::Err: Debug,
          B: Clone + Eq + Hash + FromStr,
          B::Err: Debug,
{
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut map = HashMap::new();
        let mut default = None;

        for l in s.lines() {
            if !l.is_empty() {
                match l.trim().parse()? {
                    EquivalenceClass { label, set: Some(elements) } => {
                        map.insert(label, elements);
                    },
                    EquivalenceClass { label, set: None } => {
                        default = Some(label);
                    },
                }
            }
        }

        if let Some(label) = default {
            if let Ok(relation) = EquivalenceRelation::new_safe(map, label) {
                return Ok(relation);
            }
        }

        Err(format!("Could not parse {}", s))
    }
}

impl <A, B> FromStr for EquivalenceClass<A, B>
    where A: Eq + FromStr + Hash,
          A::Err: Debug,
          B: FromStr,
          B::Err: Debug,
{
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match parse_set(s.as_bytes()) {
            IResult::Done(_, result) => Ok(result),
            _                        => Err(format!("Could not parse {}", s))
        }
    }
}

fn parse_set<A, B>(input: &[u8]) -> IResult<&[u8], EquivalenceClass<A, B>>
    where A: Eq + FromStr + Hash,
          A::Err: Debug,
          B: FromStr,
          B::Err: Debug,
{
    do_parse!(
        input,
        label: parse_token >>
            take_while!(is_space) >>
            set: alt!(
                do_parse!(
                    tag!("*") >> (None)
                )
                    |
                do_parse!(
                    the_set: parse_heap >> (Some(the_set))
                )
            ) >>
            (EquivalenceClass {
                label,
                set,
            })
    )
}

fn parse_heap<A>(input: &[u8]) -> IResult<&[u8], HashSet<A>>
    where A: Eq + FromStr + Hash,
          A::Err: Debug,
{
    match parse_vec(input, parse_token, "[", "]", ",") {
        IResult::Done(rest, parsed) => IResult::Done(rest, HashSet::from_iter(parsed)),
        IResult::Incomplete(needed) => IResult::Incomplete(needed),
        IResult::Error(error) => IResult::Error(error),
    }
}

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

    #[test]
    fn test_equivalence_class_from_str_legal_input() {
        let legal_inputs = vec![
            ("0 [0, 1]", EquivalenceClass::from((0, Some(vec![0, 1])))),
            ("0  [1, 0]", EquivalenceClass::from((0, Some(vec![0, 1])))),
            ("0  [0, 1, 1]", EquivalenceClass::from((0, Some(vec![0, 1])))),
            ("0 *", EquivalenceClass::from((0, None))),
        ];

        for (legal_input, correct_class) in legal_inputs {
            assert_eq!(correct_class,
                       EquivalenceClass::from_str(legal_input).unwrap());
        }
    }

    // FIXME: The parsing fails (as expected), but results in a panic rather than in an Err value!
    #[test]
    fn test_equivalence_class_from_str_illegal_input() {
        let illegal_inputs = vec![
            " 0 [0, 1]",
            "[0, 1]",
            "*",
        ];

        for illegal_input in illegal_inputs {
            match EquivalenceClass::<u8, u8>::from_str(illegal_input) {
                Ok(parsed) =>
                    panic!("Was able to parse the illegal input \'{}\' as \'{:?}\'",
                           illegal_input, parsed),
                Err(_) => (),
            }
        }
    }

    #[test]
    fn test_equivalence_relation_project() {
        let rel: EquivalenceRelation<u8, u8> = String::from("0 [0, 1]\n1 [2, 4]\n2 *").parse().unwrap();
        assert_eq!(0, rel.project(&1));
        assert_eq!(1, rel.project(&2));
        assert_eq!(2, rel.project(&3));
        assert_eq!(1, rel.project(&4));
    }

    #[test]
    #[should_panic(
        expected="There can only be one default class in the equivalence relation!"
    )]
    fn test_equivalence_relation_new_colliding_default() {
        let mut map = HashMap::new();
        let classes = vec![
            (0, HashSet::from_iter(vec![0, 1])),
            (1, HashSet::from_iter(vec![2, 3])),
        ];

        for (label, elements) in classes {
            map.insert(label, elements);
        }

        EquivalenceRelation::new(map, 1);
    }

    #[test]
    #[should_panic(
        expected="All classes of the equivalence relation must be disjoint!"
    )]
    fn test_equivalence_relation_new_intersecting_classes() {
        let mut map = HashMap::new();
        let classes = vec![
            (0, HashSet::from_iter(vec![0, 1])),
            (1, HashSet::from_iter(vec![1, 2])),
        ];

        for (label, elements) in classes {
            map.insert(label, elements);
        }

        EquivalenceRelation::new(map, 2);
    }

    #[test]
    fn test_equivalence_relation_from_str_legal_input() {
        let legal_inputs = vec![
            ("0 [0, 1]\n1 [2, 3]\n2 *", EquivalenceRelation::from(vec![
                EquivalenceClass::from((0, Some(vec![0, 1]))),
                EquivalenceClass::from((1, Some(vec![2, 3]))),
                EquivalenceClass::from((2, None)),
            ])),
            (" 0 [0, 1]\n 1 [2, 3]  \n2 *  ", EquivalenceRelation::from(vec![
                EquivalenceClass::from((0, Some(vec![0, 1]))),
                EquivalenceClass::from((1, Some(vec![2, 3]))),
                EquivalenceClass::from((2, None))
            ])),
        ];

        for (legal_input, correct_relation) in legal_inputs {
            assert_eq!(correct_relation,
                       EquivalenceRelation::from_str(legal_input).unwrap());
        }
    }

    #[test]
    fn test_equivalence_relation_from_str_illegal_input() {
        let illegal_inputs = vec![
            "0 [0, 1]1 [2, 3]2 *",
            "0 [0, 1]\n1 [1, 2]\n2 *",
            "0 [0, 1]\n1 [0, 1]\n2 *",
        ];

        for illegal_input in illegal_inputs {
            match EquivalenceRelation::<u8, u8>::from_str(illegal_input) {
                Ok(parsed) =>
                    panic!("Was able to parse the illegal input \'{}\' as \'{:?}\'",
                           illegal_input, parsed),
                Err(_) => (),
            }
        }
    }
}
<|endoftext|>


<commit_before>#[test] fn test_task_gate_32() { assert_eq!(super::TASK_GATE_32.bits, 5)}
#[test] fn test_int_gate_32() { assert_eq!(super:INT_GATE_32.bits, 14)}

#[test] fn test_trap_gate_32() { assert_eq!(super::TRAP_GATE_32.bits, 16)}
<commit_msg>[x86_all] fix typo in gate size test<commit_after>#[test] fn test_task_gate_32() { assert_eq!(super::TASK_GATE_32.bits, 5)}
#[test] fn test_int_gate_32() { assert_eq!(super::INT_GATE_32.bits, 14)}

#[test] fn test_trap_gate_32() { assert_eq!(super::TRAP_GATE_32.bits, 16)}
<|endoftext|>


<commit_before>use std::ops::Deref;

use super::super::crypto::{Hash, hash};
use messages::Message;
use ::storage::{Database, Error};
use storage::Map;
use ::blockchain::Blockchain;
use config::txs::{ConfigTx, TxConfigPropose, TxConfigVote };
use config::view::ConfigsView;
use config::height_to_slice;

use super::view::StoredConfiguration;

#[derive(Clone)]
pub struct ConfigsBlockchain<D: Database> {
    pub db: D,
    pub loaded_config: Option<StoredConfiguration>
}

impl<D: Database> Deref for ConfigsBlockchain<D> {
    type Target = D;
    fn deref(&self) -> &D {
        &self.db
    }
}

impl<D> ConfigsBlockchain<D> where D: Database {

    fn handle_config_propose(&self, config_propose: &TxConfigPropose) {

        let view = self.view();
        if let Some(ref config) = self.loaded_config {
            if !config.validators.contains(config_propose.from()){
                error!("ConfigPropose from unknown validator: {:?}", config_propose.from());
                return;
            }
        }

        if view.config_proposes().get(&config_propose.hash()).unwrap().is_some() {
            error!("Received config_propose has already been handled, msg={:?}", config_propose);
            return;
        }

        trace!("Handle ConfigPropose");
        let _ = view.config_proposes().put(&config_propose.hash(), config_propose.clone());

    }

    fn handle_config_vote(&self, config_vote: &TxConfigVote){

        let view = self.view();
        if let Some(ref config) = self.loaded_config {

            let validators = config.validators.clone();
            if !validators.contains(config_vote.from()){
                error!("ConfigVote from unknown validator: {:?}", config_vote.from());
                return;
            }

            if view.config_proposes().get(config_vote.hash_propose()).unwrap().is_some() {
                error!("Received config_vote for unknown transaciton, msg={:?}", config_vote);
                return;
            }

            if let Some(vote) = view.config_votes().get(config_vote.from()).unwrap() {
                if vote.seed() != config_vote.seed() -1 {
                    error!("Received config_vote with wrong seed, msg={:?}", config_vote);
                    return;
                }
            }

            let msg = config_vote.clone();
            let _ = view.config_votes().put(msg.from(), config_vote.clone());

            let validators = config.validators.clone();
            let mut votes_count = 0;
            for pub_key in validators {
                if let Some(vote) = view.config_votes().get(&pub_key).unwrap() {
                    if !vote.revoke() {
                        votes_count += 1;
                    }
                }
            }

            let validators = config.validators.clone();
            if votes_count >= 2/3 * validators.len(){
                if let Some(config_propose) = view.config_proposes().get(config_vote.hash_propose()).unwrap() {
                    view.configs().put(&height_to_slice(config_propose.actual_from_height()), config_propose.config().to_vec()).unwrap();
                    // TODO: clear storages
                }
            }
        }
    }
}

impl<D> Blockchain for ConfigsBlockchain<D> where D: Database
{
    type Database = D;
    type Transaction = ConfigTx;
    type View = ConfigsView<D::Fork>;

    fn verify_tx(tx: &Self::Transaction) -> bool {
        tx.verify(tx.pub_key())
    }

    fn state_hash(view: &Self::View) -> Result<Hash, Error> {
        let mut hashes = Vec::new();
        hashes.extend_from_slice(view.configs().root_hash()?.as_ref());
        Ok(hash(&hashes))
    }

    fn execute(&self, tx: &Self::Transaction) -> Result<(), Error> {
        match *tx {
            ConfigTx::ConfigPropose(ref tx) => {
                self.handle_config_propose(tx);
            }
            ConfigTx::ConfigVote(ref tx) => {
                self.handle_config_vote(tx);

            }
        }
        Ok(())
    }

    fn get_initial_configuration (&mut self) -> Option<StoredConfiguration> {
        let r = self.last_block().unwrap();
        let last_height = if let Some(last_block) = r {
            last_block.height() + 1
        } else {
            0
        };
        let mut h = last_height;

        while h > 0 {
            if let Some(configuration) = self.get_configuration_at_height(h){
                self.loaded_config = Some(configuration);
                return self.loaded_config.clone();
            }
            h -= 1;
        }
        None
    }

    fn get_configuration_at_height (&mut self, height: u64) -> Option<StoredConfiguration> {
        let view = self.view();
        let configs = view.configs();
        if let Ok(config) = configs.get(&height_to_slice(height)) {
            match StoredConfiguration::deserialize(&config.unwrap()) {
                Ok(configuration) => {
                    self.loaded_config = Some(configuration);
                    return self.loaded_config.clone();
                },
                Err(_) => {
                    error!("Can't parse found configuration at height: {}", height);
                }
            }
        }
        None
    }
}<commit_msg>Revert "Build fix"<commit_after>use std::ops::Deref;

use super::super::crypto::{Hash, hash};
use messages::Message;
use ::storage::{Database, Error};
use storage::Map;
use ::blockchain::Blockchain;
use config::txs::{ConfigTx, TxConfigPropose, TxConfigVote };
use config::view::ConfigsView;
use config::height_to_slice;

use super::view::StoredConfiguration;

#[derive(Clone)]
pub struct ConfigsBlockchain<D: Database> {
    pub db: D,
    pub loaded_config: Option<StoredConfiguration>
}

impl<D: Database> Deref for ConfigsBlockchain<D> {
    type Target = D;
    fn deref(&self) -> &D {
        &self.db
    }
}

impl<D> ConfigsBlockchain<D> where D: Database {

    fn handle_config_propose(&self, config_propose: &TxConfigPropose) {

        let view = self.view();
        if let Some(ref config) = self.loaded_config {
            if !config.validators.contains(config_propose.from()){
                error!("ConfigPropose from unknown validator: {:?}", config_propose.from());
                return;
            }
        }

        if view.config_proposes().get(&config_propose.hash()).unwrap().is_some() {
            error!("Received config_propose has already been handled, msg={:?}", config_propose);
            return;
        }

        trace!("Handle ConfigPropose");
        let _ = view.config_proposes().put(&config_propose.hash(), config_propose.clone());

    }

    fn handle_config_vote(&self, config_vote: &TxConfigVote){

        let view = self.view();
        if let Some(ref config) = self.loaded_config {

            let validators = config.validators.clone();
            if !validators.contains(config_vote.from()){
                error!("ConfigVote from unknown validator: {:?}", config_vote.from());
                return;
            }

            if view.config_proposes().get(config_vote.hash_propose()).unwrap().is_some() {
                error!("Received config_vote for unknown transaciton, msg={:?}", config_vote);
                return;
            }

            if let Some(vote) = view.config_votes().get(config_vote.from()).unwrap() {
                if vote.seed() != config_vote.seed() -1 {
                    error!("Received config_vote with wrong seed, msg={:?}", config_vote);
                    return;
                }
            }

            let msg = config_vote.clone();
            let _ = view.config_votes().put(msg.from(), config_vote.clone());

            let validators = config.validators.clone();
            let mut votes_count = 0;
            for pub_key in validators {
                if let Some(vote) = view.config_votes().get(&pub_key).unwrap() {
                    if !vote.revoke() {
                        votes_count += 1;
                    }
                }
            }

            let validators = config.validators.clone();
            if votes_count >= 2/3 * validators.len(){
                if let Some(config_propose) = view.config_proposes().get(config_vote.hash_propose()).unwrap() {
                    view.configs().put(&height_to_slice(config_propose.actual_from_height()), config_propose.config().to_vec()).unwrap();
                    // TODO: clear storages
                }
            }
        }
    }
}

impl<D> Blockchain for ConfigsBlockchain<D> where D: Database
{
    type Database = D;
    type Transaction = ConfigTx;
    type View = ConfigsView<D::Fork>;

    fn verify_tx(tx: &Self::Transaction) -> bool {
        tx.verify(tx.pub_key())
    }

    fn state_hash(view: &Self::View) -> Result<Hash, Error> {
        let mut hashes = Vec::new();
        hashes.extend_from_slice(view.configs().root_hash()?.as_ref());
        Ok(hash(&hashes))
    }

    fn execute(&self, tx: &Self::Transaction) -> Result<(), Error> {
        match *tx {
            ConfigTx::ConfigPropose(ref tx) => {
                self.handle_config_propose(tx);
                return Ok(());
            }
            ConfigTx::ConfigVote(ref tx) => {
                self.handle_config_vote(tx);
                return Ok(());
            }
        }
    }

    fn get_initial_configuration (&mut self) -> Option<StoredConfiguration> {
        let r = self.last_block().unwrap();
        let last_height = if let Some(last_block) = r {
            last_block.height() + 1
        } else {
            0
        };
        let mut h = last_height;

        while h > 0 {
            if let Some(configuration) = self.get_configuration_at_height(h){
                self.loaded_config = Some(configuration);
                return self.loaded_config.clone();
            }
            h -= 1;
        }
        None
    }

    fn get_configuration_at_height (&mut self, height: u64) -> Option<StoredConfiguration> {
        let view = self.view();
        let configs = view.configs();
        if let Ok(config) = configs.get(&height_to_slice(height)) {
            match StoredConfiguration::deserialize(&config.unwrap()) {
                Ok(configuration) => {
                    self.loaded_config = Some(configuration);
                    return self.loaded_config.clone();
                },
                Err(_) => {
                    error!("Can't parse found configuration at height: {}", height);
                }
            }
        }
        None
    }
}<|endoftext|>