<commit_before>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2013, 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use glib as ffi;
use types::{gchar,gpointer};
use util::escape_bytestring;

use libc;
use std::error::Error;
use std::fmt;
use std::marker;
use std::mem;
use std::ops::Deref;
use std::slice;
use std::str;

const NUL: u8 = 0;

pub struct OwnedGStr {
    ptr: *const gchar,
}

pub unsafe fn parse_as_bytes<'a, T: ?Sized>(raw: *const gchar,
                                            life_anchor: &'a T)
                                           -> &'a [u8]
{
    assert!(!raw.is_null());
    let r = mem::copy_lifetime(life_anchor, &(raw as *const u8));
    slice::from_raw_buf(r, libc::strlen(raw) as usize)
}

#[inline]
pub unsafe fn parse_as_utf8<'a, T: ?Sized>(raw: *const gchar,
                                           life_anchor: &'a T)
                                          -> Result<&'a str, str::Utf8Error>
{
    str::from_utf8(parse_as_bytes(raw, life_anchor))
}

impl OwnedGStr {

    pub unsafe fn from_raw(ptr: *mut gchar) -> OwnedGStr {
        assert!(!ptr.is_null());
        OwnedGStr { ptr: ptr as *const gchar }
    }
}

impl Deref for OwnedGStr {

    type Target = GStr;

    fn deref(&self) -> &GStr {
        unsafe { g_str_from_ptr_internal(self.ptr as *const u8, self) }
    }
}

impl Drop for OwnedGStr {
    fn drop(&mut self) {
        unsafe { ffi::g_free(self.ptr as gpointer) }
    }
}

impl Clone for OwnedGStr {
    fn clone(&self) -> OwnedGStr {
        unsafe {
            OwnedGStr::from_raw(ffi::g_strdup(self.ptr))
        }
    }
}

impl PartialEq for OwnedGStr {
    fn eq(&self, other: &OwnedGStr) -> bool {
        unsafe { libc::strcmp(self.ptr, other.ptr) == 0 }
    }
}

impl Eq for OwnedGStr { }

#[derive(Copy)]
pub struct NulError {
    pub position: usize
}

impl Error for NulError {

    fn description(&self) -> &str {
        "invalid data for C string: contains a NUL byte"
    }
}

impl fmt::Display for NulError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "invalid data for C string: NUL at position {}",
               self.position)
    }
}

pub struct IntoGStrError {
    cause: NulError,
    bytes: Vec<u8>
}

impl IntoGStrError {

    pub fn nul_error(&self) -> &NulError {
        &self.cause
    }

    pub fn into_bytes(self) -> Vec<u8> {
        self.bytes
    }
}

impl Error for IntoGStrError {

    fn description(&self) -> &str {
        self.cause.description()
    }
}

impl fmt::Display for IntoGStrError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.cause)
    }
}

#[repr(C)]
pub struct GStr {
    head: gchar,
    marker: marker::NoCopy
}

#[repr(C)]
pub struct Utf8 {
    gstr: GStr
}

impl GStr {
    #[inline]
    pub fn as_ptr(&self) -> *const gchar {
        &self.head as *const gchar
    }

    pub fn parse_as_bytes(&self) -> &[u8] {
        unsafe {
            let r = mem::copy_lifetime(self, &(self.as_ptr() as *const u8));
            slice::from_raw_buf(r, libc::strlen(self.as_ptr()) as usize)
        }
    }

    #[inline]
    pub fn parse_as_utf8(&self) -> Result<&str, str::Utf8Error> {
        str::from_utf8(self.parse_as_bytes())
    }

    #[inline]
    pub unsafe fn parse_as_utf8_unchecked(&self) -> &str {
        str::from_utf8_unchecked(self.parse_as_bytes())
    }

    pub fn from_static_bytes(bytes: &'static [u8]) -> &'static GStr {
        assert!(bytes.last() == Some(&NUL),
                "static byte string is not null-terminated: \"{}\"",
                escape_bytestring(bytes));
        unsafe { g_str_from_ptr_internal(bytes.as_ptr(), bytes) }
    }

    pub unsafe fn from_raw<'a, T: ?Sized>(ptr: *const gchar,
                                          life_anchor: &'a T)
                                         -> &'a GStr
    {
        assert!(!ptr.is_null());
        g_str_from_ptr_internal(ptr as *const u8, life_anchor)
    }
}

impl Utf8 {

    #[inline]
    pub fn as_ptr(&self) -> *const gchar {
        self.gstr.as_ptr()
    }

    #[inline]
    pub fn as_g_str(&self) -> &GStr {
        &self.gstr
    }

    #[inline]
    pub fn parse_as_str(&self) -> &str {
        unsafe { str::from_utf8_unchecked(self.gstr.parse_as_bytes()) }
    }

    pub fn from_static_str(s: &'static str) -> &'static Utf8 {
        assert!(s.ends_with("\0"),
                "static string is not null-terminated: \"{}\"", s);
        unsafe { utf8_from_ptr_internal(s.as_ptr(), s) }
    }

    pub unsafe fn from_raw<'a, T: ?Sized>(ptr: *const gchar,
                                          life_anchor: &'a T)
                                         -> &'a Utf8
    {
        assert!(!ptr.is_null());
        utf8_from_ptr_internal(ptr as *const u8, life_anchor)
    }
}

unsafe fn g_str_from_ptr_internal<'a, T: ?Sized>(ptr: *const u8,
                                                 life_anchor: &'a T)
                                                -> &'a GStr
{
    mem::copy_lifetime(life_anchor, &*(ptr as *const GStr))
}

unsafe fn utf8_from_ptr_internal<'a, T: ?Sized>(ptr: *const u8,
                                                life_anchor: &'a T)
                                               -> &'a Utf8
{
    mem::copy_lifetime(life_anchor, &*(ptr as *const Utf8))
}

fn vec_into_g_str_buf(mut v: Vec<u8>) -> GStrBuf {
    v.push(NUL);
    GStrBuf { data: v }
}

pub struct GStrBuf {
    data: Vec<u8>
}

impl Deref for GStrBuf {

    type Target = GStr;

    fn deref(&self) -> &GStr {
        unsafe { g_str_from_ptr_internal(self.data.as_ptr(), self) }
    }
}

impl GStrBuf {

    #[inline]
    pub fn from_str(s: &str) -> Result<GStrBuf, NulError> {
        GStrBuf::from_bytes(s.as_bytes())
    }

    pub fn from_bytes(bytes: &[u8]) -> Result<GStrBuf, NulError> {
        if let Some(pos) = bytes.position_elem(&NUL) {
            return Err(NulError { position: pos });
        }
        Ok(vec_into_g_str_buf(bytes.to_vec()))
    }

    pub fn from_vec(vec: Vec<u8>) -> Result<GStrBuf, IntoGStrError> {
        if let Some(pos) = vec.position_elem(&NUL) {
            return Err(IntoGStrError {
                cause: NulError { position: pos },
                bytes: vec
            });
        }
        Ok(vec_into_g_str_buf(vec))
    }
}

pub struct Utf8Buf {
    inner: GStrBuf
}

impl Deref for Utf8Buf {

    type Target = Utf8;

    fn deref(&self) -> &Utf8 {
        unsafe { utf8_from_ptr_internal(self.inner.data.as_ptr(), self) }
    }
}

fn utf8_wrap_g_str_result<E>(res: Result<GStrBuf, E>) -> Result<Utf8Buf, E> {
    res.map(|buf| {
        Utf8Buf { inner: buf }
    })
}

impl Utf8Buf {

    pub fn from_str(s: &str) -> Result<Utf8Buf, NulError> {
        utf8_wrap_g_str_result(GStrBuf::from_bytes(s.as_bytes()))
    }

    pub fn from_string(s: String) -> Result<Utf8Buf, IntoGStrError> {
        utf8_wrap_g_str_result(GStrBuf::from_vec(s.into_bytes()))
    }
}
<commit_msg>gstr: implement std::fmt::Debug for errors<commit_after>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2013, 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use glib as ffi;
use types::{gchar,gpointer};
use util::escape_bytestring;

use libc;
use std::error::Error;
use std::fmt;
use std::marker;
use std::mem;
use std::ops::Deref;
use std::slice;
use std::str;

const NUL: u8 = 0;

pub struct OwnedGStr {
    ptr: *const gchar,
}

pub unsafe fn parse_as_bytes<'a, T: ?Sized>(raw: *const gchar,
                                            life_anchor: &'a T)
                                           -> &'a [u8]
{
    assert!(!raw.is_null());
    let r = mem::copy_lifetime(life_anchor, &(raw as *const u8));
    slice::from_raw_buf(r, libc::strlen(raw) as usize)
}

#[inline]
pub unsafe fn parse_as_utf8<'a, T: ?Sized>(raw: *const gchar,
                                           life_anchor: &'a T)
                                          -> Result<&'a str, str::Utf8Error>
{
    str::from_utf8(parse_as_bytes(raw, life_anchor))
}

impl OwnedGStr {

    pub unsafe fn from_raw(ptr: *mut gchar) -> OwnedGStr {
        assert!(!ptr.is_null());
        OwnedGStr { ptr: ptr as *const gchar }
    }
}

impl Deref for OwnedGStr {

    type Target = GStr;

    fn deref(&self) -> &GStr {
        unsafe { g_str_from_ptr_internal(self.ptr as *const u8, self) }
    }
}

impl Drop for OwnedGStr {
    fn drop(&mut self) {
        unsafe { ffi::g_free(self.ptr as gpointer) }
    }
}

impl Clone for OwnedGStr {
    fn clone(&self) -> OwnedGStr {
        unsafe {
            OwnedGStr::from_raw(ffi::g_strdup(self.ptr))
        }
    }
}

impl PartialEq for OwnedGStr {
    fn eq(&self, other: &OwnedGStr) -> bool {
        unsafe { libc::strcmp(self.ptr, other.ptr) == 0 }
    }
}

impl Eq for OwnedGStr { }

#[derive(Copy)]
pub struct NulError {
    pub position: usize
}

impl Error for NulError {

    fn description(&self) -> &str {
        "invalid data for C string: contains a NUL byte"
    }
}

impl fmt::Display for NulError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "invalid data for C string: NUL at position {}",
               self.position)
    }
}

impl fmt::Debug for NulError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self)
    }
}

pub struct IntoGStrError {
    cause: NulError,
    bytes: Vec<u8>
}

impl IntoGStrError {

    pub fn nul_error(&self) -> &NulError {
        &self.cause
    }

    pub fn into_bytes(self) -> Vec<u8> {
        self.bytes
    }
}

impl Error for IntoGStrError {

    fn description(&self) -> &str {
        self.cause.description()
    }
}

impl fmt::Display for IntoGStrError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.cause)
    }
}

impl fmt::Debug for IntoGStrError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.cause)
    }
}

#[repr(C)]
pub struct GStr {
    head: gchar,
    marker: marker::NoCopy
}

#[repr(C)]
pub struct Utf8 {
    gstr: GStr
}

impl GStr {
    #[inline]
    pub fn as_ptr(&self) -> *const gchar {
        &self.head as *const gchar
    }

    pub fn parse_as_bytes(&self) -> &[u8] {
        unsafe {
            let r = mem::copy_lifetime(self, &(self.as_ptr() as *const u8));
            slice::from_raw_buf(r, libc::strlen(self.as_ptr()) as usize)
        }
    }

    #[inline]
    pub fn parse_as_utf8(&self) -> Result<&str, str::Utf8Error> {
        str::from_utf8(self.parse_as_bytes())
    }

    #[inline]
    pub unsafe fn parse_as_utf8_unchecked(&self) -> &str {
        str::from_utf8_unchecked(self.parse_as_bytes())
    }

    pub fn from_static_bytes(bytes: &'static [u8]) -> &'static GStr {
        assert!(bytes.last() == Some(&NUL),
                "static byte string is not null-terminated: \"{}\"",
                escape_bytestring(bytes));
        unsafe { g_str_from_ptr_internal(bytes.as_ptr(), bytes) }
    }

    pub unsafe fn from_raw<'a, T: ?Sized>(ptr: *const gchar,
                                          life_anchor: &'a T)
                                         -> &'a GStr
    {
        assert!(!ptr.is_null());
        g_str_from_ptr_internal(ptr as *const u8, life_anchor)
    }
}

impl Utf8 {

    #[inline]
    pub fn as_ptr(&self) -> *const gchar {
        self.gstr.as_ptr()
    }

    #[inline]
    pub fn as_g_str(&self) -> &GStr {
        &self.gstr
    }

    #[inline]
    pub fn parse_as_str(&self) -> &str {
        unsafe { str::from_utf8_unchecked(self.gstr.parse_as_bytes()) }
    }

    pub fn from_static_str(s: &'static str) -> &'static Utf8 {
        assert!(s.ends_with("\0"),
                "static string is not null-terminated: \"{}\"", s);
        unsafe { utf8_from_ptr_internal(s.as_ptr(), s) }
    }

    pub unsafe fn from_raw<'a, T: ?Sized>(ptr: *const gchar,
                                          life_anchor: &'a T)
                                         -> &'a Utf8
    {
        assert!(!ptr.is_null());
        utf8_from_ptr_internal(ptr as *const u8, life_anchor)
    }
}

unsafe fn g_str_from_ptr_internal<'a, T: ?Sized>(ptr: *const u8,
                                                 life_anchor: &'a T)
                                                -> &'a GStr
{
    mem::copy_lifetime(life_anchor, &*(ptr as *const GStr))
}

unsafe fn utf8_from_ptr_internal<'a, T: ?Sized>(ptr: *const u8,
                                                life_anchor: &'a T)
                                               -> &'a Utf8
{
    mem::copy_lifetime(life_anchor, &*(ptr as *const Utf8))
}

fn vec_into_g_str_buf(mut v: Vec<u8>) -> GStrBuf {
    v.push(NUL);
    GStrBuf { data: v }
}

pub struct GStrBuf {
    data: Vec<u8>
}

impl Deref for GStrBuf {

    type Target = GStr;

    fn deref(&self) -> &GStr {
        unsafe { g_str_from_ptr_internal(self.data.as_ptr(), self) }
    }
}

impl GStrBuf {

    #[inline]
    pub fn from_str(s: &str) -> Result<GStrBuf, NulError> {
        GStrBuf::from_bytes(s.as_bytes())
    }

    pub fn from_bytes(bytes: &[u8]) -> Result<GStrBuf, NulError> {
        if let Some(pos) = bytes.position_elem(&NUL) {
            return Err(NulError { position: pos });
        }
        Ok(vec_into_g_str_buf(bytes.to_vec()))
    }

    pub fn from_vec(vec: Vec<u8>) -> Result<GStrBuf, IntoGStrError> {
        if let Some(pos) = vec.position_elem(&NUL) {
            return Err(IntoGStrError {
                cause: NulError { position: pos },
                bytes: vec
            });
        }
        Ok(vec_into_g_str_buf(vec))
    }
}

pub struct Utf8Buf {
    inner: GStrBuf
}

impl Deref for Utf8Buf {

    type Target = Utf8;

    fn deref(&self) -> &Utf8 {
        unsafe { utf8_from_ptr_internal(self.inner.data.as_ptr(), self) }
    }
}

fn utf8_wrap_g_str_result<E>(res: Result<GStrBuf, E>) -> Result<Utf8Buf, E> {
    res.map(|buf| {
        Utf8Buf { inner: buf }
    })
}

impl Utf8Buf {

    pub fn from_str(s: &str) -> Result<Utf8Buf, NulError> {
        utf8_wrap_g_str_result(GStrBuf::from_bytes(s.as_bytes()))
    }

    pub fn from_string(s: String) -> Result<Utf8Buf, IntoGStrError> {
        utf8_wrap_g_str_result(GStrBuf::from_vec(s.into_bytes()))
    }
}
<|endoftext|>


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

use crate::BinaryValue;
use exonum_crypto::{Hash, HashStream};

#[repr(u8)]
#[derive(Copy, Clone, Debug)]
/// `MerkleDB` hash prefixes.
pub enum HashTag {
    /// Hash prefix of a leaf node of the merkle tree.
    Leaf = 0,
    /// Hash prefix of a branch node of the merkle tree.
    Node = 1,
    /// Hash prefix of the list object.
    ListNode = 2,
}

/// Calculate hash value with the specified prefix.
///
/// Different hashes for leaf and branch nodes are used to secure merkle tree from
/// the pre-image attack.
///
/// See more information [here][1].
///
/// [1]: https://tools.ietf.org/html/rfc6962#section-2.1
impl HashTag {
    ///`HashStream` object with the corresponding hash prefix.
    pub(crate) fn hash_stream(self) -> HashStream {
        HashStream::new().update(&[self as u8])
    }

    /// Convenience method to obtain hashed value of the merkle tree node.
    pub fn hash_node(left_hash: &Hash, right_hash: &Hash) -> Hash {
        HashTag::Node
            .hash_stream()
            .update(left_hash.as_ref())
            .update(right_hash.as_ref())
            .hash()
    }

    /// Convenience method to obtain a hashed value of the merkle tree node with one child.
    pub fn hash_single_node(hash: &Hash) -> Hash {
        HashTag::Node.hash_stream().update(hash.as_ref()).hash()
    }

    /// Convenience method to obtain a hashed value of the merkle tree leaf.
    pub fn hash_leaf(value: &[u8]) -> Hash {
        HashTag::Leaf.hash_stream().update(value).hash()
    }

    /// Hash of the list object.
    ///
    /// ```text
    /// h = sha-256( HashTag::List || len as u64 || merkle_root )
    /// ```
    pub fn hash_list_node(len: u64, root: Hash) -> Hash {
        let mut len_bytes = [0; 8];
        LittleEndian::write_u64(&mut len_bytes, len);

        HashStream::new()
            .update(&[HashTag::ListNode as u8])
            .update(&len_bytes)
            .update(root.as_ref())
            .hash()
    }

    /// Hash of the empty list object.
    ///
    /// Empty list hash:
    /// ```text
    /// h = sha-256( HashTag::List || 0 || Hash::default() )
    /// ```
    pub fn empty_list_hash() -> Hash {
        Hash::from_hex("c6c0aa07f27493d2f2e5cff56c890a353a20086d6c25ec825128e12ae752b2d9").unwrap()
    }

    /// Computes a list hash for the given list of hashes.
    pub fn hash_list(hashes: &[Hash]) -> Hash {
        Self::hash_list_node(hashes.len() as u64, root_hash(hashes))
    }
}

/// Computes a Merkle root hash for a the given list of hashes.
///
/// If `hashes` are empty then `Hash::zero()` value is returned.
fn root_hash(hashes: &[Hash]) -> Hash {
    match hashes.len() {
        0 => Hash::zero(),
        1 => HashTag::hash_leaf(&hashes[0].to_bytes()),
        _ => {
            let hashes: Vec<Hash> = hashes
                .iter()
                .map(|h| HashTag::hash_leaf(&h.to_bytes()))
                .collect();

            let mut current_hashes = combine_hash_list(&hashes);

            while current_hashes.len() > 1 {
                current_hashes = combine_hash_list(&current_hashes);
            }
            current_hashes[0]
        }
    }
}

fn combine_hash_list(hashes: &[Hash]) -> Vec<Hash> {
    hashes
        .chunks(2)
        .map(|pair| match pair {
            [first, second] => HashTag::hash_node(first, second),
            [single] => HashTag::hash_single_node(single),
            _ => unreachable!(),
        })
        .collect()
}

/// A common trait for the ability to compute a unique hash.
///
/// Unlike `CryptoHash`, the hash value returned by the `UniqueHash::hash()`
/// method isn't always irreversible. This hash is used, for example, in the
/// storage as a key, as uniqueness is important in this case.
pub trait UniqueHash: BinaryValue {
    /// Returns a hash of the value.
    ///
    /// Hash must be unique, but not necessary cryptographic.
    fn hash(&self) -> Hash {
        exonum_crypto::hash(&self.to_bytes())
    }
}

/// Just returns the origin hash.
impl UniqueHash for Hash {
    fn hash(&self) -> Hash {
        *self
    }
}
<commit_msg>Fix fmt.<commit_after>// Copyright 2018 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use byteorder::{ByteOrder, LittleEndian};
use hex::FromHex;

use crate::BinaryValue;
use exonum_crypto::{Hash, HashStream};

#[repr(u8)]
#[derive(Copy, Clone, Debug)]
/// `MerkleDB` hash prefixes.
pub enum HashTag {
    /// Hash prefix of a leaf node of the merkle tree.
    Leaf = 0,
    /// Hash prefix of a branch node of the merkle tree.
    Node = 1,
    /// Hash prefix of the list object.
    ListNode = 2,
}

/// Calculate hash value with the specified prefix.
///
/// Different hashes for leaf and branch nodes are used to secure merkle tree from
/// the pre-image attack.
///
/// See more information [here][1].
///
/// [1]: https://tools.ietf.org/html/rfc6962#section-2.1
impl HashTag {
    ///`HashStream` object with the corresponding hash prefix.
    pub(crate) fn hash_stream(self) -> HashStream {
        HashStream::new().update(&[self as u8])
    }

    /// Convenience method to obtain hashed value of the merkle tree node.
    pub fn hash_node(left_hash: &Hash, right_hash: &Hash) -> Hash {
        HashTag::Node
            .hash_stream()
            .update(left_hash.as_ref())
            .update(right_hash.as_ref())
            .hash()
    }

    /// Convenience method to obtain a hashed value of the merkle tree node with one child.
    pub fn hash_single_node(hash: &Hash) -> Hash {
        HashTag::Node.hash_stream().update(hash.as_ref()).hash()
    }

    /// Convenience method to obtain a hashed value of the merkle tree leaf.
    pub fn hash_leaf(value: &[u8]) -> Hash {
        HashTag::Leaf.hash_stream().update(value).hash()
    }

    /// Hash of the list object.
    ///
    /// ```text
    /// h = sha-256( HashTag::List || len as u64 || merkle_root )
    /// ```
    pub fn hash_list_node(len: u64, root: Hash) -> Hash {
        let mut len_bytes = [0; 8];
        LittleEndian::write_u64(&mut len_bytes, len);

        HashStream::new()
            .update(&[HashTag::ListNode as u8])
            .update(&len_bytes)
            .update(root.as_ref())
            .hash()
    }

    /// Hash of the empty list object.
    ///
    /// Empty list hash:
    /// ```text
    /// h = sha-256( HashTag::List || 0 || Hash::default() )
    /// ```
    pub fn empty_list_hash() -> Hash {
        Hash::from_hex("c6c0aa07f27493d2f2e5cff56c890a353a20086d6c25ec825128e12ae752b2d9").unwrap()
    }

    /// Computes a list hash for the given list of hashes.
    pub fn hash_list(hashes: &[Hash]) -> Hash {
        Self::hash_list_node(hashes.len() as u64, root_hash(hashes))
    }
}

/// Computes a Merkle root hash for a the given list of hashes.
///
/// If `hashes` are empty then `Hash::zero()` value is returned.
fn root_hash(hashes: &[Hash]) -> Hash {
    match hashes.len() {
        0 => Hash::zero(),
        1 => HashTag::hash_leaf(&hashes[0].to_bytes()),
        _ => {
            let hashes: Vec<Hash> = hashes
                .iter()
                .map(|h| HashTag::hash_leaf(&h.to_bytes()))
                .collect();

            let mut current_hashes = combine_hash_list(&hashes);

            while current_hashes.len() > 1 {
                current_hashes = combine_hash_list(&current_hashes);
            }
            current_hashes[0]
        }
    }
}

fn combine_hash_list(hashes: &[Hash]) -> Vec<Hash> {
    hashes
        .chunks(2)
        .map(|pair| match pair {
            [first, second] => HashTag::hash_node(first, second),
            [single] => HashTag::hash_single_node(single),
            _ => unreachable!(),
        })
        .collect()
}

/// A common trait for the ability to compute a unique hash.
///
/// Unlike `CryptoHash`, the hash value returned by the `UniqueHash::hash()`
/// method isn't always irreversible. This hash is used, for example, in the
/// storage as a key, as uniqueness is important in this case.
pub trait UniqueHash: BinaryValue {
    /// Returns a hash of the value.
    ///
    /// Hash must be unique, but not necessary cryptographic.
    fn hash(&self) -> Hash {
        exonum_crypto::hash(&self.to_bytes())
    }
}

/// Just returns the origin hash.
impl UniqueHash for Hash {
    fn hash(&self) -> Hash {
        *self
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The gl-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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.

//! # gl_generator
//!
//! `gl_generator` is an OpenGL bindings generator plugin. It defines a macro named
//!  `generate_gl_bindings!` which can be used to generate all constants and functions of a
//!  given OpenGL version.
//!
//! ## Example
//!
//! ```rust
//! #[phase(plugin)]
//! extern crate gl_generator;
//! extern crate libc;
//!
//! use std::mem;
//! use self::types::*;
//!
//! generate_gl_bindings!("gl", "core", "4.5", "global", [ "GL_EXT_texture_filter_anisotropic" ])
//! ```
//!
//! ## Parameters
//!
//! * API: Can be `gl`, `gles1`, `gles2`, `wgl`, `glx`, `egl`.
//! * Profile: Can be `core` or `compatibility`. `core` will only include all functions supported
//!    by the requested version it self, while `compatibility` will include all the functions from
//!    previous versions as well.
//! * Version: The requested version of OpenGL, WGL, GLX or EGL in the format `x.x`.
//! * Generator: Can be `static`, `global` or `struct`.
//! * Extensions (optional): An array of extensions to include in the bindings.
//!
//! ## About EGL
//!
//! When you generate bindings for EGL, the following platform-specific types must be declared
//!  *at the same level where you call `generate_gl_bindings`*:
//!
//! - khronos_utime_nanoseconds_t
//! - khronos_uint64_t
//! - khronos_ssize_t
//! - EGLNativeDisplayType
//! - EGLNativePixmapType
//! - EGLNativeWindowType
//! - EGLint
//! - NativeDisplayType
//! - NativePixmapType
//! - NativeWindowType
//!

#![crate_name = "gl_generator"]
#![comment = "OpenGL function loader generator."]
#![license = "ASL2"]
#![crate_type = "dylib"]

#![feature(phase)]
#![feature(macro_rules)]
#![feature(plugin_registrar)]
#![feature(quote)]

#[phase(plugin, link)]
extern crate log;

#[phase(plugin)]
extern crate regex_macros;

extern crate khronos_api;
extern crate regex;
extern crate rustc;
extern crate syntax;

use registry::{Registry, Filter};
use registry::{Gl, Gles1, Gles2, Wgl, Glx, Egl};
use syntax::ast::{ Item, TokenTree };
use syntax::ext::base::{expr_to_string, get_exprs_from_tts, DummyResult, ExtCtxt, MacResult};
use syntax::codemap::Span;
use syntax::ptr::P;

mod generators;

#[allow(dead_code)]
mod registry;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut ::rustc::plugin::Registry) {
    reg.register_macro("generate_gl_bindings", macro_handler);
}

// this is the object that we will return from the "generate_gl_bindings" macro expansion
struct MacroResult {
    content: Vec<P<Item>>
}
impl MacResult for MacroResult {
    fn make_def(&mut self) -> Option<::syntax::ext::base::MacroDef> { None }
    fn make_expr(self: Box<MacroResult>) -> Option<P<::syntax::ast::Expr>> { None }
    fn make_pat(self: Box<MacroResult>) -> Option<P<::syntax::ast::Pat>> { None }
    fn make_stmt(self: Box<MacroResult>) -> Option<P<::syntax::ast::Stmt>> { None }

    fn make_items(self: Box<MacroResult>) -> Option<::syntax::util::small_vector::SmallVector<P<Item>>> {
        Some(::syntax::util::small_vector::SmallVector::many(self.content.clone()))
    }
}

// handler for generate_gl_bindings!
fn macro_handler(ecx: &mut ExtCtxt, span: Span, token_tree: &[TokenTree]) -> Box<MacResult+'static> {
    // getting the arguments from the macro
    let (api, profile, version, generator, extensions) = match parse_macro_arguments(ecx, span.clone(), token_tree) {
        Some(t) => t,
        None => return DummyResult::any(span)
    };

    let (ns, source) = match api.as_slice() {
        "gl"  => (Gl, khronos_api::GL_XML),
        "glx" => (Glx, khronos_api::GLX_XML),
        "wgl" => (Wgl, khronos_api::WGL_XML),
        "egl" => (Egl, khronos_api::EGL_XML),
        "gles1"  => (Gles1, khronos_api::GL_XML),
        "gles2"  => (Gles2, khronos_api::GL_XML),
        ns => {
            ecx.span_err(span, format!("Unexpected opengl namespace '{}'", ns).as_slice());
            return DummyResult::any(span)
        }
    };

    let filter = Some(Filter {
        extensions: extensions,
        profile: profile,
        version: version,
        api: api,
    });

    // generating the registry of all bindings
    let reg = {
        use std::io::BufReader;
        use std::task;

        let result = task::try(proc() {
            let reader = BufReader::new(source.as_bytes());
            Registry::from_xml(reader, ns, filter)
        });

        match result {
            Ok(reg) => reg,
            Err(err) => {
                use std::any::{Any, AnyRefExt};
                let err: &Any = &*err;

                match err {
                    err if err.is::<String>() => {
                        ecx.span_err(span, "error while parsing the registry");
                        ecx.span_err(span, err.downcast_ref::<String>().unwrap().as_slice());
                    },
                    err if err.is::<&'static str>() => {
                        ecx.span_err(span, "error while parsing the registry");
                        ecx.span_err(span, err.downcast_ref::<&'static str>().unwrap().as_slice());
                    },
                    _ => {
                        ecx.span_err(span, "unknown error while parsing the registry");
                    }
                }

                return DummyResult::any(span);
            }
        }
    };

    // generating the Rust bindings as a source code into "buffer"
    let items = {
        use generators::Generator;

        // calling the generator
        match generator.as_slice() {
            "global" => (generators::global_gen::GlobalGenerator).write(ecx, &reg, ns),
            "struct" => (generators::struct_gen::StructGenerator).write(ecx, &reg, ns),
            "static" => (generators::static_gen::StaticGenerator).write(ecx, &reg, ns),

            generator => {
                ecx.span_err(span, format!("unknown generator type: {}", generator).as_slice());
                return DummyResult::any(span);
            },
        }
    };

    box MacroResult { content: items } as Box<MacResult>
}

fn parse_macro_arguments(ecx: &mut ExtCtxt, span: Span, tts: &[syntax::ast::TokenTree])
                        -> Option<(String, String, String, String, Vec<String>)>
{
    // getting parameters list
    let values = match get_exprs_from_tts(ecx, span, tts) {
        Some(v) => v,
        None => return None
    };

    if values.len() != 4 && values.len() != 5 {
        ecx.span_err(span, format!("expected 4 or 5 arguments but got {}", values.len())
            .as_slice());
        return None;
    }

    // computing the extensions (last parameter)
    let extensions: Vec<String> = match values.as_slice().get(4) {
        None => Vec::new(),
        Some(vector) => {
            use syntax::ast::ExprVec;

            match vector.node {
                // only [ ... ] is accepted
                ExprVec(ref list) => {
                    // turning each element into a string
                    let mut result = Vec::new();
                    for element in list.iter() {
                        match expr_to_string(ecx, element.clone(), "expected string literal") {
                            Some((s, _)) => result.push(s.get().to_string()),
                            None => return None
                        }
                    }
                    result
                },
                _ => {
                    ecx.span_err(span, format!("last argument must be a vector").as_slice());
                    return None;
                }
            }
        }
    };

    // computing other parameters
    match (
        expr_to_string(ecx, values.as_slice().get(0).unwrap().clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() }),
        expr_to_string(ecx, values.as_slice().get(1).unwrap().clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() }),
        expr_to_string(ecx, values.as_slice().get(2).unwrap().clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() }),
        expr_to_string(ecx, values.as_slice().get(3).unwrap().clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() })
    ) {
        (Some(a), Some(b), Some(c), Some(d)) => Some((a, b, c, d, extensions)),
        _ => None
    }
}
<commit_msg>Use MacItems instead of a custom MacResult impl<commit_after>// Copyright 2013-2014 The gl-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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.

//! # gl_generator
//!
//! `gl_generator` is an OpenGL bindings generator plugin. It defines a macro named
//!  `generate_gl_bindings!` which can be used to generate all constants and functions of a
//!  given OpenGL version.
//!
//! ## Example
//!
//! ```rust
//! #[phase(plugin)]
//! extern crate gl_generator;
//! extern crate libc;
//!
//! use std::mem;
//! use self::types::*;
//!
//! generate_gl_bindings!("gl", "core", "4.5", "global", [ "GL_EXT_texture_filter_anisotropic" ])
//! ```
//!
//! ## Parameters
//!
//! * API: Can be `gl`, `gles1`, `gles2`, `wgl`, `glx`, `egl`.
//! * Profile: Can be `core` or `compatibility`. `core` will only include all functions supported
//!    by the requested version it self, while `compatibility` will include all the functions from
//!    previous versions as well.
//! * Version: The requested version of OpenGL, WGL, GLX or EGL in the format `x.x`.
//! * Generator: Can be `static`, `global` or `struct`.
//! * Extensions (optional): An array of extensions to include in the bindings.
//!
//! ## About EGL
//!
//! When you generate bindings for EGL, the following platform-specific types must be declared
//!  *at the same level where you call `generate_gl_bindings`*:
//!
//! - khronos_utime_nanoseconds_t
//! - khronos_uint64_t
//! - khronos_ssize_t
//! - EGLNativeDisplayType
//! - EGLNativePixmapType
//! - EGLNativeWindowType
//! - EGLint
//! - NativeDisplayType
//! - NativePixmapType
//! - NativeWindowType
//!

#![crate_name = "gl_generator"]
#![comment = "OpenGL function loader generator."]
#![license = "ASL2"]
#![crate_type = "dylib"]

#![feature(phase)]
#![feature(macro_rules)]
#![feature(plugin_registrar)]
#![feature(quote)]

#[phase(plugin, link)]
extern crate log;

#[phase(plugin)]
extern crate regex_macros;

extern crate khronos_api;
extern crate regex;
extern crate rustc;
extern crate syntax;

use registry::{Registry, Filter};
use registry::{Gl, Gles1, Gles2, Wgl, Glx, Egl};
use syntax::ast::TokenTree;
use syntax::ext::base::{expr_to_string, get_exprs_from_tts, DummyResult, ExtCtxt, MacResult, MacItems};
use syntax::codemap::Span;

mod generators;

#[allow(dead_code)]
mod registry;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut ::rustc::plugin::Registry) {
    reg.register_macro("generate_gl_bindings", macro_handler);
}

// handler for generate_gl_bindings!
fn macro_handler(ecx: &mut ExtCtxt, span: Span, token_tree: &[TokenTree]) -> Box<MacResult+'static> {
    // getting the arguments from the macro
    let (api, profile, version, generator, extensions) = match parse_macro_arguments(ecx, span.clone(), token_tree) {
        Some(t) => t,
        None => return DummyResult::any(span)
    };

    let (ns, source) = match api.as_slice() {
        "gl"  => (Gl, khronos_api::GL_XML),
        "glx" => (Glx, khronos_api::GLX_XML),
        "wgl" => (Wgl, khronos_api::WGL_XML),
        "egl" => (Egl, khronos_api::EGL_XML),
        "gles1"  => (Gles1, khronos_api::GL_XML),
        "gles2"  => (Gles2, khronos_api::GL_XML),
        ns => {
            ecx.span_err(span, format!("Unexpected opengl namespace '{}'", ns).as_slice());
            return DummyResult::any(span)
        }
    };

    let filter = Some(Filter {
        extensions: extensions,
        profile: profile,
        version: version,
        api: api,
    });

    // generating the registry of all bindings
    let reg = {
        use std::io::BufReader;
        use std::task;

        let result = task::try(proc() {
            let reader = BufReader::new(source.as_bytes());
            Registry::from_xml(reader, ns, filter)
        });

        match result {
            Ok(reg) => reg,
            Err(err) => {
                use std::any::{Any, AnyRefExt};
                let err: &Any = &*err;

                match err {
                    err if err.is::<String>() => {
                        ecx.span_err(span, "error while parsing the registry");
                        ecx.span_err(span, err.downcast_ref::<String>().unwrap().as_slice());
                    },
                    err if err.is::<&'static str>() => {
                        ecx.span_err(span, "error while parsing the registry");
                        ecx.span_err(span, err.downcast_ref::<&'static str>().unwrap().as_slice());
                    },
                    _ => {
                        ecx.span_err(span, "unknown error while parsing the registry");
                    }
                }

                return DummyResult::any(span);
            }
        }
    };

    // generating the Rust bindings as a source code into "buffer"
    let items = {
        use generators::Generator;

        // calling the generator
        match generator.as_slice() {
            "global" => (generators::global_gen::GlobalGenerator).write(ecx, &reg, ns),
            "struct" => (generators::struct_gen::StructGenerator).write(ecx, &reg, ns),
            "static" => (generators::static_gen::StaticGenerator).write(ecx, &reg, ns),

            generator => {
                ecx.span_err(span, format!("unknown generator type: {}", generator).as_slice());
                return DummyResult::any(span);
            },
        }
    };

    MacItems::new(items.into_iter())
}

fn parse_macro_arguments(ecx: &mut ExtCtxt, span: Span, tts: &[syntax::ast::TokenTree])
                        -> Option<(String, String, String, String, Vec<String>)>
{
    // getting parameters list
    let values = match get_exprs_from_tts(ecx, span, tts) {
        Some(v) => v,
        None => return None
    };

    if values.len() != 4 && values.len() != 5 {
        ecx.span_err(span, format!("expected 4 or 5 arguments but got {}", values.len())
            .as_slice());
        return None;
    }

    // computing the extensions (last parameter)
    let extensions: Vec<String> = match values.as_slice().get(4) {
        None => Vec::new(),
        Some(vector) => {
            use syntax::ast::ExprVec;

            match vector.node {
                // only [ ... ] is accepted
                ExprVec(ref list) => {
                    // turning each element into a string
                    let mut result = Vec::new();
                    for element in list.iter() {
                        match expr_to_string(ecx, element.clone(), "expected string literal") {
                            Some((s, _)) => result.push(s.get().to_string()),
                            None => return None
                        }
                    }
                    result
                },
                _ => {
                    ecx.span_err(span, format!("last argument must be a vector").as_slice());
                    return None;
                }
            }
        }
    };

    // computing other parameters
    match (
        expr_to_string(ecx, values.as_slice().get(0).unwrap().clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() }),
        expr_to_string(ecx, values.as_slice().get(1).unwrap().clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() }),
        expr_to_string(ecx, values.as_slice().get(2).unwrap().clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() }),
        expr_to_string(ecx, values.as_slice().get(3).unwrap().clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() })
    ) {
        (Some(a), Some(b), Some(c), Some(d)) => Some((a, b, c, d, extensions)),
        _ => None
    }
}
<|endoftext|>


<commit_before>//! Thread pool for blocking operations

use tokio_sync::oneshot;

use lazy_static::lazy_static;
use std::collections::VecDeque;
use std::future::Future;
use std::pin::Pin;
use std::sync::{Condvar, Mutex};
use std::task::{Context, Poll};
use std::thread;
use std::time::Duration;

struct Pool {
    shared: Mutex<Shared>,
    condvar: Condvar,
}

struct Shared {
    queue: VecDeque<Box<dyn FnOnce() + Send>>,
    num_th: u32,
    num_idle: u32,
}

lazy_static! {
    static ref POOL: Pool = Pool::new();
}

const MAX_THREADS: u32 = 1_000;
const KEEP_ALIVE: Duration = Duration::from_secs(10);

/// Result of a blocking operation running on the blocking thread pool.
#[derive(Debug)]
pub struct Blocking<T> {
    rx: oneshot::Receiver<T>,
}

/// Run the provided function on a threadpool dedicated to blocking operations.
pub fn run<F, R>(f: F) -> Blocking<R>
where
    F: FnOnce() -> R + Send + 'static,
    R: Send + 'static,
{
    let (tx, rx) = oneshot::channel();

    let should_spawn = {
        let mut shared = POOL.shared.lock().unwrap();

        shared.queue.push_back(Box::new(move || {
            // The receiver may have dropped
            let _ = tx.send(f());
        }));

        if shared.num_idle == 0 {
            // No threads are able to process the task

            if shared.num_th == MAX_THREADS {
                // At max number of threads
                false
            } else {
                shared.num_th += 1;
                true
            }
        } else {
            shared.num_idle -= 1;
            POOL.condvar.notify_one();
            false
        }
    };

    if should_spawn {
        spawn_thread();
    }

    Blocking { rx }
}

impl<T> Future for Blocking<T> {
    type Output = T;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        use std::task::Poll::*;

        match Pin::new(&mut self.rx).poll(cx) {
            Ready(Ok(v)) => Ready(v),
            Ready(Err(_)) => panic!(
                "the blocking operation has been dropped before completing. \
                 This should not happen and is a bug."
            ),
            Pending => Pending,
        }
    }
}

fn spawn_thread() {
    thread::Builder::new()
        .name("tokio-blocking-driver".to_string())
        .spawn(|| {
            'outer: loop {
                let mut shared = POOL.shared.lock().unwrap();

                if let Some(task) = shared.queue.pop_front() {
                    drop(shared);
                    run_task(task);
                    continue;
                }

                // IDLE
                shared.num_idle += 1;

                loop {
                    shared = POOL.condvar.wait_timeout(shared, KEEP_ALIVE).unwrap().0;

                    if let Some(task) = shared.queue.pop_front() {
                        drop(shared);
                        run_task(task);
                        continue 'outer;
                    }
                }
            }
        })
        .unwrap();
}

fn run_task(f: Box<dyn FnOnce() + Send>) {
    use std::panic::{catch_unwind, AssertUnwindSafe};

    let _ = catch_unwind(AssertUnwindSafe(|| f()));
}

impl Pool {
    fn new() -> Pool {
        Pool {
            shared: Mutex::new(Shared {
                queue: VecDeque::new(),
                num_th: 0,
                num_idle: 0,
            }),
            condvar: Condvar::new(),
        }
    }
}
<commit_msg>executor: shut down idle threads in the blocking pool (#1514)<commit_after>//! Thread pool for blocking operations

use tokio_sync::oneshot;

use lazy_static::lazy_static;
use std::collections::VecDeque;
use std::future::Future;
use std::pin::Pin;
use std::sync::{Condvar, Mutex};
use std::task::{Context, Poll};
use std::thread;
use std::time::Duration;

struct Pool {
    shared: Mutex<Shared>,
    condvar: Condvar,
}

struct Shared {
    queue: VecDeque<Box<dyn FnOnce() + Send>>,
    num_th: u32,
    num_idle: u32,
}

lazy_static! {
    static ref POOL: Pool = Pool::new();
}

const MAX_THREADS: u32 = 1_000;
const KEEP_ALIVE: Duration = Duration::from_secs(10);

/// Result of a blocking operation running on the blocking thread pool.
#[derive(Debug)]
pub struct Blocking<T> {
    rx: oneshot::Receiver<T>,
}

/// Run the provided function on a threadpool dedicated to blocking operations.
pub fn run<F, R>(f: F) -> Blocking<R>
where
    F: FnOnce() -> R + Send + 'static,
    R: Send + 'static,
{
    let (tx, rx) = oneshot::channel();

    let should_spawn = {
        let mut shared = POOL.shared.lock().unwrap();

        shared.queue.push_back(Box::new(move || {
            // The receiver may have dropped
            let _ = tx.send(f());
        }));

        if shared.num_idle == 0 {
            // No threads are able to process the task

            if shared.num_th == MAX_THREADS {
                // At max number of threads
                false
            } else {
                shared.num_th += 1;
                true
            }
        } else {
            shared.num_idle -= 1;
            POOL.condvar.notify_one();
            false
        }
    };

    if should_spawn {
        spawn_thread();
    }

    Blocking { rx }
}

impl<T> Future for Blocking<T> {
    type Output = T;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        use std::task::Poll::*;

        match Pin::new(&mut self.rx).poll(cx) {
            Ready(Ok(v)) => Ready(v),
            Ready(Err(_)) => panic!(
                "the blocking operation has been dropped before completing. \
                 This should not happen and is a bug."
            ),
            Pending => Pending,
        }
    }
}

fn spawn_thread() {
    thread::Builder::new()
        .name("tokio-blocking-driver".to_string())
        .spawn(|| {
            'outer: loop {
                let mut shared = POOL.shared.lock().unwrap();

                if let Some(task) = shared.queue.pop_front() {
                    drop(shared);
                    run_task(task);
                    continue;
                }

                // IDLE
                shared.num_idle += 1;

                loop {
                    let lock_result = POOL.condvar.wait_timeout(shared, KEEP_ALIVE).unwrap();
                    shared = lock_result.0;
                    let timeout_result = lock_result.1;

                    if let Some(task) = shared.queue.pop_front() {
                        drop(shared);
                        run_task(task);
                        continue 'outer;
                    } else if timeout_result.timed_out() {
                        break 'outer;
                    }
                }
            }
        })
        .unwrap();
}

fn run_task(f: Box<dyn FnOnce() + Send>) {
    use std::panic::{catch_unwind, AssertUnwindSafe};

    let _ = catch_unwind(AssertUnwindSafe(|| f()));
}

impl Pool {
    fn new() -> Pool {
        Pool {
            shared: Mutex::new(Shared {
                queue: VecDeque::new(),
                num_th: 0,
                num_idle: 0,
            }),
            condvar: Condvar::new(),
        }
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![deny(missing_copy_implementations)]

//! Window abstraction

extern crate libc;
extern crate input;
extern crate shader_version;

use shader_version::OpenGL;
use input::Input;

/// The type of an OpenGL function address.
pub type ProcAddress = *const libc::c_void;

/// Size in pixels.
#[derive(Copy, Clone)]
pub struct Size {
    /// The width in pixels.
    pub width: u32,
    /// The height in pixels.
    pub height: u32,
}

impl From<[u32; 2]> for Size {
    #[inline(always)]
    fn from(value: [u32; 2]) -> Size {
        Size { width: value[0], height: value[1] }
    }
}

impl From<(u32, u32)> for Size {
    #[inline(always)]
    fn from(value: (u32, u32)) -> Size {
        Size { width: value.0, height: value.1 }
    }
}

/// Builds window from window settings.
pub trait BuildFromWindowSettings: Sized {
    /// Builds window from window settings.
    fn build_from_window_settings(settings: WindowSettings)
    -> Result<Self, String>;
}

/// Required to use the event loop.
pub trait Window {
    /// The event type emitted by `poll_event`
    type Event;

    /// Tells the window to close or stay open.
    fn set_should_close(&mut self, value: bool);

    /// Returns true if window should close.
    fn should_close(&self) -> bool;

    /// Gets the size of the window in user coordinates.
    fn size(&self) -> Size;

    /// Swaps render buffers.
    fn swap_buffers(&mut self);

    /// Polls event from window.
    fn poll_event(&mut self) -> Option<Self::Event>;

    /// Gets draw size of the window.
    /// This is equal to the size of the frame buffer of the inner window,
    /// excluding the title bar and borders.
    fn draw_size(&self) -> Size;
}

/// Implemented by fully supported window back-ends.
pub trait AdvancedWindow: Window + Sized {
    /// Gets a copy of the title of the window.
    fn get_title(&self) -> String;

    /// Sets the title of the window.
    fn set_title(&mut self, value: String);

    /// Sets title on window.
    fn title(mut self, value: String) -> Self {
        self.set_title(value);
        self
    }

    /// Gets whether to exit when pressing esc.
    fn get_exit_on_esc(&self) -> bool;

    /// Sets whether to exit when pressing esc.
    fn set_exit_on_esc(&mut self, value: bool);

    /// Sets whether to exit when pressing esc.
    fn exit_on_esc(mut self, value: bool) -> Self {
        self.set_exit_on_esc(value);
        self
    }

    /// Sets whether to capture/grab cursor.
    /// This is used to lock and hide cursor to the window,
    /// for example in a first-person shooter game.
    fn set_capture_cursor(&mut self, value: bool);

    /// Sets whether to capture/grab cursor (see `set_capture_cursor`).
    fn capture_cursor(mut self, value: bool) -> Self {
        self.set_capture_cursor(value);
        self
    }
}

/// Trait for OpenGL specific operations.
pub trait OpenGLWindow: Window {
    /// Returns the address of an OpenGL function if it exist, else returns null pointer.
    fn get_proc_address(&mut self, proc_name: &str) -> ProcAddress;

    /// Returns true if this context is the current context.
    fn is_current(&self) -> bool;

    /// Make this context current.
    fn make_current(&mut self);
}

/// Settings for window behavior.
pub struct WindowSettings {
    /// Title of the window.
    title: String,
    /// The size of the window.
    size: Size,
    /// Number samples per pixel (anti-aliasing).
    samples: u8,
    /// If true, the window is fullscreen.
    fullscreen: bool,
    /// If true, exit when pressing Esc.
    exit_on_esc: bool,
    /// If true, enable vsync.
    vsync: bool,
    /// An optional OpenGL version.
    opengl: Option<OpenGL>,
}

impl WindowSettings {
    /// Creates window settings with defaults.
    /// - samples: 0
    /// - fullscreen: false
    /// - exit_on_esc: false
    pub fn new<T: Into<String>, S: Into<Size>>(
        title: T, size: S) -> WindowSettings
    {
        WindowSettings {
            title: title.into(),
            size: size.into(),
            samples: 0,
            fullscreen: false,
            exit_on_esc: false,
            vsync: false,
            opengl: None,
        }
    }

    /// Builds window.
    pub fn build<W: BuildFromWindowSettings>(self) -> Result<W, String> {
        BuildFromWindowSettings::build_from_window_settings(self)
    }

    /// Gets title.
    pub fn get_title(&self) -> String { self.title.clone() }

    /// Sets title.
    pub fn title(mut self, value: String) -> Self {
        self.title = value;
        self
    }

    /// Gets size.
    pub fn get_size(&self) -> Size { self.size }

    /// Sets size.
    pub fn size(mut self, value: Size) -> Self {
        self.size = value;
        self
    }

    /// Gets fullscreen.
    pub fn get_fullscreen(&self) -> bool { self.fullscreen }

    /// Sets fullscreen.
    pub fn fullscreen(mut self, value: bool) -> Self {
        self.fullscreen = value;
        self
    }

    /// Gets exit on esc.
    pub fn get_exit_on_esc(&self) -> bool { self.exit_on_esc }

    /// Sets exit on esc.
    pub fn exit_on_esc(mut self, value: bool) -> Self {
        self.exit_on_esc = value;
        self
    }

    /// Gets samples.
    pub fn get_samples(&self) -> u8 { self.samples }

    /// Sets samples.
    pub fn samples(mut self, value: u8) -> Self {
        self.samples = value;
        self
    }

    /// Gets vsync.
    pub fn get_vsync(&self) -> bool { self.vsync }

    /// Sets vsync.
    pub fn vsync(mut self, value: bool) -> Self {
        self.vsync = value;
        self
    }

    /// Gets opengl.
    pub fn get_maybe_opengl(&self) -> Option<OpenGL> { self.opengl }

    /// Sets opengl.
    pub fn maybe_opengl(mut self, value: Option<OpenGL>) -> Self {
        self.opengl = value;
        self
    }

    /// Sets opengl.
    pub fn opengl(mut self, value: OpenGL) -> Self {
        self.opengl = Some(value);
        self
    }
}

/// An implementation of Window that runs without a window at all.
pub struct NoWindow {
    should_close: bool,
    title: String,
    size: Size
}

impl NoWindow {
    /// Returns a new `NoWindow`.
    pub fn new(settings: WindowSettings) -> NoWindow {
        NoWindow {
            should_close: false,
            title: settings.title,
            size: settings.size,
        }
    }
}

impl Window for NoWindow {
    type Event = Input;
    fn should_close(&self) -> bool { self.should_close }
    fn set_should_close(&mut self, value: bool) { self.should_close = value; }
    fn size(&self) -> Size { self.size }
    fn swap_buffers(&mut self) {}
    fn poll_event(&mut self) -> Option<Input> { None }
    fn draw_size(&self) -> Size { self.size() }
}

impl BuildFromWindowSettings for NoWindow {
    fn build_from_window_settings(settings: WindowSettings)
    -> Result<Self, String> {
        Ok(NoWindow::new(settings))
    }
}

impl AdvancedWindow for NoWindow {
    fn get_title(&self) -> String { self.title.clone() }
    fn set_title(&mut self, value: String) { self.title = value; }
    fn get_exit_on_esc(&self) -> bool { false }
    fn set_exit_on_esc(&mut self, _value: bool) {}
    fn set_capture_cursor(&mut self, _value: bool) {}
}
<commit_msg>insert  inside derive of Struct Size from window<commit_after>#![deny(missing_docs)]
#![deny(missing_copy_implementations)]

//! Window abstraction

extern crate libc;
extern crate input;
extern crate shader_version;

use shader_version::OpenGL;
use input::Input;

/// The type of an OpenGL function address.
pub type ProcAddress = *const libc::c_void;

/// Size in pixels.
#[derive(Debug, Copy, Clone)]
pub struct Size {
    /// The width in pixels.
    pub width: u32,
    /// The height in pixels.
    pub height: u32,
}

impl From<[u32; 2]> for Size {
    #[inline(always)]
    fn from(value: [u32; 2]) -> Size {
        Size { width: value[0], height: value[1] }
    }
}

impl From<(u32, u32)> for Size {
    #[inline(always)]
    fn from(value: (u32, u32)) -> Size {
        Size { width: value.0, height: value.1 }
    }
}

/// Builds window from window settings.
pub trait BuildFromWindowSettings: Sized {
    /// Builds window from window settings.
    fn build_from_window_settings(settings: WindowSettings)
    -> Result<Self, String>;
}

/// Required to use the event loop.
pub trait Window {
    /// The event type emitted by `poll_event`
    type Event;

    /// Tells the window to close or stay open.
    fn set_should_close(&mut self, value: bool);

    /// Returns true if window should close.
    fn should_close(&self) -> bool;

    /// Gets the size of the window in user coordinates.
    fn size(&self) -> Size;

    /// Swaps render buffers.
    fn swap_buffers(&mut self);

    /// Polls event from window.
    fn poll_event(&mut self) -> Option<Self::Event>;

    /// Gets draw size of the window.
    /// This is equal to the size of the frame buffer of the inner window,
    /// excluding the title bar and borders.
    fn draw_size(&self) -> Size;
}

/// Implemented by fully supported window back-ends.
pub trait AdvancedWindow: Window + Sized {
    /// Gets a copy of the title of the window.
    fn get_title(&self) -> String;

    /// Sets the title of the window.
    fn set_title(&mut self, value: String);

    /// Sets title on window.
    fn title(mut self, value: String) -> Self {
        self.set_title(value);
        self
    }

    /// Gets whether to exit when pressing esc.
    fn get_exit_on_esc(&self) -> bool;

    /// Sets whether to exit when pressing esc.
    fn set_exit_on_esc(&mut self, value: bool);

    /// Sets whether to exit when pressing esc.
    fn exit_on_esc(mut self, value: bool) -> Self {
        self.set_exit_on_esc(value);
        self
    }

    /// Sets whether to capture/grab cursor.
    /// This is used to lock and hide cursor to the window,
    /// for example in a first-person shooter game.
    fn set_capture_cursor(&mut self, value: bool);

    /// Sets whether to capture/grab cursor (see `set_capture_cursor`).
    fn capture_cursor(mut self, value: bool) -> Self {
        self.set_capture_cursor(value);
        self
    }
}

/// Trait for OpenGL specific operations.
pub trait OpenGLWindow: Window {
    /// Returns the address of an OpenGL function if it exist, else returns null pointer.
    fn get_proc_address(&mut self, proc_name: &str) -> ProcAddress;

    /// Returns true if this context is the current context.
    fn is_current(&self) -> bool;

    /// Make this context current.
    fn make_current(&mut self);
}

/// Settings for window behavior.
pub struct WindowSettings {
    /// Title of the window.
    title: String,
    /// The size of the window.
    size: Size,
    /// Number samples per pixel (anti-aliasing).
    samples: u8,
    /// If true, the window is fullscreen.
    fullscreen: bool,
    /// If true, exit when pressing Esc.
    exit_on_esc: bool,
    /// If true, enable vsync.
    vsync: bool,
    /// An optional OpenGL version.
    opengl: Option<OpenGL>,
}

impl WindowSettings {
    /// Creates window settings with defaults.
    /// - samples: 0
    /// - fullscreen: false
    /// - exit_on_esc: false
    pub fn new<T: Into<String>, S: Into<Size>>(
        title: T, size: S) -> WindowSettings
    {
        WindowSettings {
            title: title.into(),
            size: size.into(),
            samples: 0,
            fullscreen: false,
            exit_on_esc: false,
            vsync: false,
            opengl: None,
        }
    }

    /// Builds window.
    pub fn build<W: BuildFromWindowSettings>(self) -> Result<W, String> {
        BuildFromWindowSettings::build_from_window_settings(self)
    }

    /// Gets title.
    pub fn get_title(&self) -> String { self.title.clone() }

    /// Sets title.
    pub fn title(mut self, value: String) -> Self {
        self.title = value;
        self
    }

    /// Gets size.
    pub fn get_size(&self) -> Size { self.size }

    /// Sets size.
    pub fn size(mut self, value: Size) -> Self {
        self.size = value;
        self
    }

    /// Gets fullscreen.
    pub fn get_fullscreen(&self) -> bool { self.fullscreen }

    /// Sets fullscreen.
    pub fn fullscreen(mut self, value: bool) -> Self {
        self.fullscreen = value;
        self
    }

    /// Gets exit on esc.
    pub fn get_exit_on_esc(&self) -> bool { self.exit_on_esc }

    /// Sets exit on esc.
    pub fn exit_on_esc(mut self, value: bool) -> Self {
        self.exit_on_esc = value;
        self
    }

    /// Gets samples.
    pub fn get_samples(&self) -> u8 { self.samples }

    /// Sets samples.
    pub fn samples(mut self, value: u8) -> Self {
        self.samples = value;
        self
    }

    /// Gets vsync.
    pub fn get_vsync(&self) -> bool { self.vsync }

    /// Sets vsync.
    pub fn vsync(mut self, value: bool) -> Self {
        self.vsync = value;
        self
    }

    /// Gets opengl.
    pub fn get_maybe_opengl(&self) -> Option<OpenGL> { self.opengl }

    /// Sets opengl.
    pub fn maybe_opengl(mut self, value: Option<OpenGL>) -> Self {
        self.opengl = value;
        self
    }

    /// Sets opengl.
    pub fn opengl(mut self, value: OpenGL) -> Self {
        self.opengl = Some(value);
        self
    }
}

/// An implementation of Window that runs without a window at all.
pub struct NoWindow {
    should_close: bool,
    title: String,
    size: Size
}

impl NoWindow {
    /// Returns a new `NoWindow`.
    pub fn new(settings: WindowSettings) -> NoWindow {
        NoWindow {
            should_close: false,
            title: settings.title,
            size: settings.size,
        }
    }
}

impl Window for NoWindow {
    type Event = Input;
    fn should_close(&self) -> bool { self.should_close }
    fn set_should_close(&mut self, value: bool) { self.should_close = value; }
    fn size(&self) -> Size { self.size }
    fn swap_buffers(&mut self) {}
    fn poll_event(&mut self) -> Option<Input> { None }
    fn draw_size(&self) -> Size { self.size() }
}

impl BuildFromWindowSettings for NoWindow {
    fn build_from_window_settings(settings: WindowSettings)
    -> Result<Self, String> {
        Ok(NoWindow::new(settings))
    }
}

impl AdvancedWindow for NoWindow {
    fn get_title(&self) -> String { self.title.clone() }
    fn set_title(&mut self, value: String) { self.title = value; }
    fn get_exit_on_esc(&self) -> bool { false }
    fn set_exit_on_esc(&mut self, _value: bool) {}
    fn set_capture_cursor(&mut self, _value: bool) {}
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![deny(missing_copy_implementations)]

//! Window abstraction

extern crate input;
extern crate shader_version;

use shader_version::OpenGL;
use input::Input;

/// The type of an OpenGL function address.
pub type ProcAddress = *const ();

/// Size in pixels.
#[derive(Debug, Copy, Clone)]
pub struct Size {
    /// The width in pixels.
    pub width: u32,
    /// The height in pixels.
    pub height: u32,
}

impl From<[u32; 2]> for Size {
    #[inline(always)]
    fn from(value: [u32; 2]) -> Size {
        Size { width: value[0], height: value[1] }
    }
}

impl From<(u32, u32)> for Size {
    #[inline(always)]
    fn from(value: (u32, u32)) -> Size {
        Size { width: value.0, height: value.1 }
    }
}

/// Builds window from window settings.
pub trait BuildFromWindowSettings: Sized {
    /// Builds window from window settings.
    fn build_from_window_settings(settings: &WindowSettings)
    -> Result<Self, String>;
}

/// Required to use the event loop.
pub trait Window {
    /// The event type emitted by `poll_event`
    type Event;

    /// Tells the window to close or stay open.
    fn set_should_close(&mut self, value: bool);

    /// Returns true if window should close.
    fn should_close(&self) -> bool;

    /// Gets the size of the window in user coordinates.
    fn size(&self) -> Size;

    /// Swaps render buffers.
    fn swap_buffers(&mut self);

    /// Polls event from window.
    fn poll_event(&mut self) -> Option<Self::Event>;

    /// Gets draw size of the window.
    /// This is equal to the size of the frame buffer of the inner window,
    /// excluding the title bar and borders.
    fn draw_size(&self) -> Size;
}

/// Implemented by fully supported window back-ends.
pub trait AdvancedWindow: Window + Sized {
    /// Gets a copy of the title of the window.
    fn get_title(&self) -> String;

    /// Sets the title of the window.
    fn set_title(&mut self, value: String);

    /// Sets title on window.
    fn title(mut self, value: String) -> Self {
        self.set_title(value);
        self
    }

    /// Gets whether to exit when pressing esc.
    fn get_exit_on_esc(&self) -> bool;

    /// Sets whether to exit when pressing esc.
    fn set_exit_on_esc(&mut self, value: bool);

    /// Sets whether to exit when pressing esc.
    fn exit_on_esc(mut self, value: bool) -> Self {
        self.set_exit_on_esc(value);
        self
    }

    /// Sets whether to capture/grab cursor.
    /// This is used to lock and hide cursor to the window,
    /// for example in a first-person shooter game.
    fn set_capture_cursor(&mut self, value: bool);

    /// Sets whether to capture/grab cursor (see `set_capture_cursor`).
    fn capture_cursor(mut self, value: bool) -> Self {
        self.set_capture_cursor(value);
        self
    }
}

/// Trait for OpenGL specific operations.
pub trait OpenGLWindow: Window {
    /// Returns the address of an OpenGL function if it exist, else returns null pointer.
    fn get_proc_address(&mut self, proc_name: &str) -> ProcAddress;

    /// Returns true if this context is the current context.
    fn is_current(&self) -> bool;

    /// Make this context current.
    fn make_current(&mut self);
}

/// Settings for window behavior.
#[derive(Clone)]
pub struct WindowSettings {
    /// Title of the window.
    title: String,
    /// The size of the window.
    size: Size,
    /// Number samples per pixel (anti-aliasing).
    samples: u8,
    /// If true, the window is fullscreen.
    fullscreen: bool,
    /// If true, exit when pressing Esc.
    exit_on_esc: bool,
    /// If true, enable vsync.
    vsync: bool,
    /// An optional OpenGL version.
    opengl: Option<OpenGL>,
    /// Whether sRGB is enabled.
    srgb: bool,
}

impl WindowSettings {
    /// Creates window settings with defaults.
    ///
    /// - samples: 0
    /// - fullscreen: false
    /// - exit_on_esc: false
    /// - vsync: false
    /// - srgb: true
    pub fn new<T: Into<String>, S: Into<Size>>(
        title: T, size: S) -> WindowSettings
    {
        WindowSettings {
            title: title.into(),
            size: size.into(),
            samples: 0,
            fullscreen: false,
            exit_on_esc: false,
            vsync: false,
            opengl: None,
            srgb: true,
        }
    }

    /// Builds window.
    pub fn build<W: BuildFromWindowSettings>(&self) -> Result<W, String> {
        BuildFromWindowSettings::build_from_window_settings(self)
    }

    /// Gets title.
    pub fn get_title(&self) -> String { self.title.clone() }

    /// Sets title.
    pub fn title(mut self, value: String) -> Self {
        self.title = value;
        self
    }

    /// Gets size.
    pub fn get_size(&self) -> Size { self.size }

    /// Sets size.
    pub fn size(mut self, value: Size) -> Self {
        self.size = value;
        self
    }

    /// Gets fullscreen.
    pub fn get_fullscreen(&self) -> bool { self.fullscreen }

    /// Sets fullscreen.
    pub fn fullscreen(mut self, value: bool) -> Self {
        self.fullscreen = value;
        self
    }

    /// Gets exit on esc.
    pub fn get_exit_on_esc(&self) -> bool { self.exit_on_esc }

    /// Sets exit on esc.
    pub fn exit_on_esc(mut self, value: bool) -> Self {
        self.exit_on_esc = value;
        self
    }

    /// Gets samples.
    pub fn get_samples(&self) -> u8 { self.samples }

    /// Sets samples.
    ///
    /// See https://en.wikipedia.org/wiki/Multisample_anti-aliasing
    /// for more information.
    pub fn samples(mut self, value: u8) -> Self {
        self.samples = value;
        self
    }

    /// Gets vsync.
    ///
    /// See https://en.wikipedia.org/wiki/Screen_tearing for more information.
    pub fn get_vsync(&self) -> bool { self.vsync }

    /// Sets vsync.
    pub fn vsync(mut self, value: bool) -> Self {
        self.vsync = value;
        self
    }

    /// Gets opengl.
    pub fn get_maybe_opengl(&self) -> Option<OpenGL> { self.opengl }

    /// Sets opengl.
    pub fn maybe_opengl(mut self, value: Option<OpenGL>) -> Self {
        self.opengl = value;
        self
    }

    /// Sets opengl.
    pub fn opengl(mut self, value: OpenGL) -> Self {
        self.opengl = Some(value);
        self
    }

    /// Gets sRGB.
    pub fn get_srgb(&self) -> bool { self.srgb }

    /// Sets sRGB.
    ///
    /// See https://en.wikipedia.org/wiki/SRGB for more information.
    pub fn srgb(mut self, value: bool) -> Self {
        self.srgb = value;
        self
    }
}

/// An implementation of Window that runs without a window at all.
pub struct NoWindow {
    should_close: bool,
    title: String,
    size: Size
}

impl NoWindow {
    /// Returns a new `NoWindow`.
    pub fn new(settings: &WindowSettings) -> NoWindow {
        NoWindow {
            should_close: false,
            title: settings.get_title(),
            size: settings.get_size(),
        }
    }
}

impl Window for NoWindow {
    type Event = Input;
    fn should_close(&self) -> bool { self.should_close }
    fn set_should_close(&mut self, value: bool) { self.should_close = value; }
    fn size(&self) -> Size { self.size }
    fn swap_buffers(&mut self) {}
    fn poll_event(&mut self) -> Option<Input> { None }
    fn draw_size(&self) -> Size { self.size() }
}

impl BuildFromWindowSettings for NoWindow {
    fn build_from_window_settings(settings: &WindowSettings)
    -> Result<Self, String> {
        Ok(NoWindow::new(settings))
    }
}

impl AdvancedWindow for NoWindow {
    fn get_title(&self) -> String { self.title.clone() }
    fn set_title(&mut self, value: String) { self.title = value; }
    fn get_exit_on_esc(&self) -> bool { false }
    fn set_exit_on_esc(&mut self, _value: bool) {}
    fn set_capture_cursor(&mut self, _value: bool) {}
}
<commit_msg>Added missing methods on `WindowSettings`<commit_after>#![deny(missing_docs)]
#![deny(missing_copy_implementations)]

//! Window abstraction

extern crate input;
extern crate shader_version;

use shader_version::OpenGL;
use input::Input;

/// The type of an OpenGL function address.
pub type ProcAddress = *const ();

/// Size in pixels.
#[derive(Debug, Copy, Clone)]
pub struct Size {
    /// The width in pixels.
    pub width: u32,
    /// The height in pixels.
    pub height: u32,
}

impl From<[u32; 2]> for Size {
    #[inline(always)]
    fn from(value: [u32; 2]) -> Size {
        Size { width: value[0], height: value[1] }
    }
}

impl From<(u32, u32)> for Size {
    #[inline(always)]
    fn from(value: (u32, u32)) -> Size {
        Size { width: value.0, height: value.1 }
    }
}

/// Builds window from window settings.
pub trait BuildFromWindowSettings: Sized {
    /// Builds window from window settings.
    fn build_from_window_settings(settings: &WindowSettings)
    -> Result<Self, String>;
}

/// Required to use the event loop.
pub trait Window {
    /// The event type emitted by `poll_event`
    type Event;

    /// Tells the window to close or stay open.
    fn set_should_close(&mut self, value: bool);

    /// Returns true if window should close.
    fn should_close(&self) -> bool;

    /// Gets the size of the window in user coordinates.
    fn size(&self) -> Size;

    /// Swaps render buffers.
    fn swap_buffers(&mut self);

    /// Polls event from window.
    fn poll_event(&mut self) -> Option<Self::Event>;

    /// Gets draw size of the window.
    /// This is equal to the size of the frame buffer of the inner window,
    /// excluding the title bar and borders.
    fn draw_size(&self) -> Size;
}

/// Implemented by fully supported window back-ends.
pub trait AdvancedWindow: Window + Sized {
    /// Gets a copy of the title of the window.
    fn get_title(&self) -> String;

    /// Sets the title of the window.
    fn set_title(&mut self, value: String);

    /// Sets title on window.
    fn title(mut self, value: String) -> Self {
        self.set_title(value);
        self
    }

    /// Gets whether to exit when pressing esc.
    fn get_exit_on_esc(&self) -> bool;

    /// Sets whether to exit when pressing esc.
    fn set_exit_on_esc(&mut self, value: bool);

    /// Sets whether to exit when pressing esc.
    fn exit_on_esc(mut self, value: bool) -> Self {
        self.set_exit_on_esc(value);
        self
    }

    /// Sets whether to capture/grab cursor.
    /// This is used to lock and hide cursor to the window,
    /// for example in a first-person shooter game.
    fn set_capture_cursor(&mut self, value: bool);

    /// Sets whether to capture/grab cursor (see `set_capture_cursor`).
    fn capture_cursor(mut self, value: bool) -> Self {
        self.set_capture_cursor(value);
        self
    }
}

/// Trait for OpenGL specific operations.
pub trait OpenGLWindow: Window {
    /// Returns the address of an OpenGL function if it exist, else returns null pointer.
    fn get_proc_address(&mut self, proc_name: &str) -> ProcAddress;

    /// Returns true if this context is the current context.
    fn is_current(&self) -> bool;

    /// Make this context current.
    fn make_current(&mut self);
}

/// Settings for window behavior.
#[derive(Clone)]
pub struct WindowSettings {
    /// Title of the window.
    title: String,
    /// The size of the window.
    size: Size,
    /// Number samples per pixel (anti-aliasing).
    samples: u8,
    /// If true, the window is fullscreen.
    fullscreen: bool,
    /// If true, exit when pressing Esc.
    exit_on_esc: bool,
    /// If true, enable vsync.
    vsync: bool,
    /// An optional OpenGL version.
    opengl: Option<OpenGL>,
    /// Whether sRGB is enabled.
    srgb: bool,
}

impl WindowSettings {
    /// Creates window settings with defaults.
    ///
    /// - samples: 0
    /// - fullscreen: false
    /// - exit_on_esc: false
    /// - vsync: false
    /// - srgb: true
    pub fn new<T: Into<String>, S: Into<Size>>(
        title: T, size: S) -> WindowSettings
    {
        WindowSettings {
            title: title.into(),
            size: size.into(),
            samples: 0,
            fullscreen: false,
            exit_on_esc: false,
            vsync: false,
            opengl: None,
            srgb: true,
        }
    }

    /// Builds window.
    pub fn build<W: BuildFromWindowSettings>(&self) -> Result<W, String> {
        BuildFromWindowSettings::build_from_window_settings(self)
    }

    /// Gets title.
    pub fn get_title(&self) -> String { self.title.clone() }

    /// Sets title.
    pub fn set_title(&mut self, value: String) {
        self.title = value;
    }

    /// Sets title.
    pub fn title(mut self, value: String) -> Self {
        self.set_title(value);
        self
    }

    /// Gets size.
    pub fn get_size(&self) -> Size { self.size }

    /// Sets size.
    pub fn set_size(&mut self, value: Size) {
        self.size = value;
    }

    /// Sets size.
    pub fn size(mut self, value: Size) -> Self {
        self.set_size(value);
        self
    }

    /// Gets fullscreen.
    pub fn get_fullscreen(&self) -> bool { self.fullscreen }

    /// Sets fullscreen.
    pub fn set_fullscreen(&mut self, value: bool) {
        self.fullscreen = value;
    }

    /// Sets fullscreen.
    pub fn fullscreen(mut self, value: bool) -> Self {
        self.set_fullscreen(value);
        self
    }

    /// Gets exit on esc.
    pub fn get_exit_on_esc(&self) -> bool { self.exit_on_esc }

    /// Sets exit on esc.
    pub fn set_exit_on_esc(&mut self, value: bool) {
        self.exit_on_esc = value;
    }

    /// Sets exit on esc.
    pub fn exit_on_esc(mut self, value: bool) -> Self {
        self.set_exit_on_esc(value);
        self
    }

    /// Gets samples.
    ///
    /// See https://en.wikipedia.org/wiki/Multisample_anti-aliasing
    /// for more information.
    pub fn get_samples(&self) -> u8 { self.samples }

    /// Sets samples.
    pub fn set_samples(&mut self, value: u8) {
        self.samples = value;
    }

    /// Sets samples.
    pub fn samples(mut self, value: u8) -> Self {
        self.set_samples(value);
        self
    }

    /// Gets vsync.
    ///
    /// See https://en.wikipedia.org/wiki/Screen_tearing for more information.
    pub fn get_vsync(&self) -> bool { self.vsync }

    /// Sets vsync.
    pub fn set_vsync(&mut self, value: bool) {
        self.vsync = value;
    }

    /// Sets vsync.
    pub fn vsync(mut self, value: bool) -> Self {
        self.set_vsync(value);
        self
    }

    /// Gets OpenGL version.
    pub fn get_maybe_opengl(&self) -> Option<OpenGL> { self.opengl }

    /// Sets OpenGL version.
    pub fn set_maybe_opengl(&mut self, value: Option<OpenGL>) {
        self.opengl = value;
    }

    /// Sets OpenGL version.
    pub fn maybe_opengl(mut self, value: Option<OpenGL>) -> Self {
        self.set_maybe_opengl(value);
        self
    }

    /// Sets OpenGL version.
    pub fn set_opengl(&mut self, value: OpenGL) {
        self.opengl = Some(value);
    }

    /// Sets OpenGL version.
    pub fn opengl(mut self, value: OpenGL) -> Self {
        self.set_opengl(value);
        self
    }

    /// Gets sRGB.
    ///
    /// See https://en.wikipedia.org/wiki/SRGB for more information.
    pub fn get_srgb(&self) -> bool { self.srgb }

    /// Sets sRGB.
    pub fn set_srgb(&mut self, value: bool) {
        self.srgb = value;
    }

    /// Sets sRGB.
    pub fn srgb(mut self, value: bool) -> Self {
        self.set_srgb(value);
        self
    }
}

/// An implementation of Window that runs without a window at all.
pub struct NoWindow {
    should_close: bool,
    title: String,
    size: Size
}

impl NoWindow {
    /// Returns a new `NoWindow`.
    pub fn new(settings: &WindowSettings) -> NoWindow {
        NoWindow {
            should_close: false,
            title: settings.get_title(),
            size: settings.get_size(),
        }
    }
}

impl Window for NoWindow {
    type Event = Input;
    fn should_close(&self) -> bool { self.should_close }
    fn set_should_close(&mut self, value: bool) { self.should_close = value; }
    fn size(&self) -> Size { self.size }
    fn swap_buffers(&mut self) {}
    fn poll_event(&mut self) -> Option<Input> { None }
    fn draw_size(&self) -> Size { self.size() }
}

impl BuildFromWindowSettings for NoWindow {
    fn build_from_window_settings(settings: &WindowSettings)
    -> Result<Self, String> {
        Ok(NoWindow::new(settings))
    }
}

impl AdvancedWindow for NoWindow {
    fn get_title(&self) -> String { self.title.clone() }
    fn set_title(&mut self, value: String) { self.title = value; }
    fn get_exit_on_esc(&self) -> bool { false }
    fn set_exit_on_esc(&mut self, _value: bool) {}
    fn set_capture_cursor(&mut self, _value: bool) {}
}
<|endoftext|>


<commit_before>extern crate crypto;

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

use crypto::aessafe::{AesSafe128Decryptor, AesSafe128Encryptor};
use crypto::symmetriccipher::{BlockDecryptor, BlockEncryptor};

fn hex_to_u8(a: u8) -> u8 {
    match a {
        b'0'...b'9' => a - b'0',
        b'a'...b'h' => a - b'a' + 10,
        _           => 0
    }
}

fn vec_u8_from_hex_string(s: &String) -> Vec<u8> {
    s.as_bytes().chunks(2).map(|a| hex_to_u8(a[0]) * 16 + hex_to_u8(a[1])).collect()
}

fn vec_xor(v1: &Vec<u8>, v2: &Vec<u8>) -> Vec<u8> {
    let mut v = Vec::with_capacity(cmp::min(v1.len(), v2.len()));

    for (a, b) in v1.iter().zip(v2.iter()) {
        v.push(a ^ b);
    }

    v
}

fn cbc_decrypt(key: &Vec<u8>, msg: &Vec<u8>) -> Vec<u8> {
    let mut v = Vec::with_capacity(msg.len());
    let (iv, msg) = msg.split_at(16);
    let mut prev = &mut [0; 16];

    for i in 0..16 {
        prev[i] = iv[i];
    }

    let mut m_i = &mut [0; 16];
    let decryptor = AesSafe128Decryptor::new(&key[..]);

    for c_i in msg.chunks(16) {
        decryptor.decrypt_block(c_i, &mut m_i[..]);

        for i in 0..m_i.len() {
            v.push(m_i[i] ^ prev[i]);
        }

        for i in 0..prev.len() {
            prev[i] = c_i[i];
        }
    }

    let pad = v.pop().unwrap();

    for i in 1..pad {
        v.pop();
    }

    v
}

fn main() {
    let input_file = File::open("in.txt").unwrap();
    let input = BufReader::new(input_file);
    let input: Vec<_> = input.lines().filter_map(|res| res.ok())
        .filter(|s| s.len() > 0)
        .map(|s| vec_u8_from_hex_string(&s))
        .collect();
    let input: Vec<_> = input.chunks(2).collect();

    for v in input {
        println!("key: {:?}", v[0]);
        println!("cpt: {:?}", v[1]);

        let msg = cbc_decrypt(&v[0], &v[1]);
        println!("msg: {:?}", msg);

        let pt = String::from_utf8(msg).unwrap();
        println!("pt: {:?}", pt);

        println!("");
    }
}

<commit_msg>cbc decrypt cleanup<commit_after>extern crate crypto;

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

use crypto::aessafe::{AesSafe128Decryptor, AesSafe128Encryptor};
use crypto::symmetriccipher::{BlockDecryptor, BlockEncryptor};

fn hex_to_u8(a: u8) -> u8 {
    match a {
        b'0'...b'9' => a - b'0',
        b'a'...b'h' => a - b'a' + 10,
        _           => 0
    }
}

fn vec_u8_from_hex_string(s: &String) -> Vec<u8> {
    s.as_bytes().chunks(2).map(|a| hex_to_u8(a[0]) * 16 + hex_to_u8(a[1])).collect()
}

fn cbc_decrypt(key: &Vec<u8>, msg: &Vec<u8>) -> Vec<u8> {
    let mut v = Vec::with_capacity(msg.len());
    let (iv, msg) = msg.split_at(16);
    // TODO: find better way to copy arrays
    let mut prev = &mut [0; 16];

    for i in 0..16 {
        prev[i] = iv[i];
    }

    let mut m_i = &mut [0; 16];
    let decryptor = AesSafe128Decryptor::new(&key[..]);

    for c_i in msg.chunks(16) {
        decryptor.decrypt_block(c_i, &mut m_i[..]);

        for i in 0..m_i.len() {
            v.push(m_i[i] ^ prev[i]);
        }

        for i in 0..prev.len() {
            prev[i] = c_i[i];
        }
    }

    let pad = v.pop().unwrap();

    for _ in 1..pad {
        v.pop();
    }

    v
}

fn main() {
    let input_file = File::open("in.txt").unwrap();
    let input = BufReader::new(input_file);
    let input: Vec<_> = input.lines().filter_map(|res| res.ok())
        .filter(|s| s.len() > 0)
        .map(|s| vec_u8_from_hex_string(&s))
        .collect();
    let input: Vec<_> = input.chunks(2).collect();

    for v in input {
        println!("key: {:?}", v[0]);
        println!("cpt: {:?}", v[1]);

        let msg = cbc_decrypt(&v[0], &v[1]);
        println!("msg: {:?}", msg);

        let pt = String::from_utf8(msg).unwrap();
        println!("pt: {:?}", pt);

        println!("");
    }
}

<|endoftext|>