<commit_before>// Copyright 2017 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 std::cmp::min;

use crypto::{Hash, PublicKey, HASH_SIZE};
use super::super::StorageKey;

pub const BRANCH_KEY_PREFIX: u8 = 00;
pub const LEAF_KEY_PREFIX: u8 = 01;

/// Size in bytes of the `ProofMapKey`.
pub const KEY_SIZE: usize = HASH_SIZE;
pub const DB_KEY_SIZE: usize = KEY_SIZE + 2;

/// A trait that defines a subset of storage key types which are suitable for use with
/// `ProofMapIndex`.
///
/// The size of the keys must be exactly 32 bytes and the keys must have a uniform distribution.
pub trait ProofMapKey: StorageKey {}

impl ProofMapKey for Hash {}
impl ProofMapKey for PublicKey {}
impl ProofMapKey for [u8; KEY_SIZE] {}

impl StorageKey for [u8; KEY_SIZE] {
    fn size(&self) -> usize {
        KEY_SIZE
    }

    fn write(&self, buffer: &mut [u8]) {
        buffer.copy_from_slice(self.as_ref())
    }

    fn read(buffer: &[u8]) -> Self {
        let mut value = [0; KEY_SIZE];
        value.copy_from_slice(buffer);
        value
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ChildKind {
    Left,
    Right,
}

/// A struct that represents a bit slices of the proof map keys.
#[derive(Clone)]
pub struct DBKey {
    data: [u8; KEY_SIZE],
    from: u16,
    to: u16,
}

impl ::std::ops::Not for ChildKind {
    type Output = ChildKind;

    fn not(self) -> ChildKind {
        match self {
            ChildKind::Left => ChildKind::Right,
            ChildKind::Right => ChildKind::Left,
        }
    }
}

impl DBKey {
    /// Create a new bit slice from the given binary data.
    pub fn leaf<K: ProofMapKey>(key: &K) -> DBKey {
        debug_assert_eq!(key.size(), KEY_SIZE);

        let mut data = [0; KEY_SIZE];
        key.write(&mut data);
        DBKey {
            data: data,
            from: 0,
            to: (KEY_SIZE * 8) as u16,
        }
    }

    #[doc(hidden)]
    pub fn from(&self) -> u16 {
        self.from
    }

    // TODO: terrible hack, try to remove this (ECR-22)
    #[doc(hidden)]
    pub fn set_from(&mut self, from: u16) {
        self.from = from
    }

    #[doc(hidden)]
    pub fn to(&self) -> u16 {
        self.to
    }

    /// Returns length of the `DBKey`.
    pub fn len(&self) -> u16 {
        self.to - self.from
    }

    /// Returns true if `DBKey` has zero length.
    pub fn is_empty(&self) -> bool {
        self.to == self.from
    }

    /// Get bit at position `idx`.
    pub fn get(&self, idx: u16) -> ChildKind {
        debug_assert!(self.from + idx < self.to);

        let pos = self.from + idx;
        let chunk = self.data[(pos / 8) as usize];
        let bit = 7 - pos % 8;
        let value = (1 << bit) & chunk;
        if value != 0 {
            ChildKind::Right
        } else {
            ChildKind::Left
        }
    }

    /// Shortens this DBKey to the specified length.
    pub fn prefix(&self, suffix: u16) -> DBKey {
        debug_assert!(self.to + suffix <= self.data.len() as u16 * 8);

        DBKey {
            data: self.data,
            from: self.from,
            to: self.from + suffix,
        }
    }

    /// Return object which represents a view on to this slice (further) offset by `i` bits.
    pub fn suffix(&self, suffix: u16) -> DBKey {
        debug_assert!(self.from + suffix <= self.to);

        DBKey {
            data: self.data,
            from: self.from + suffix,
            to: self.to,
        }
    }

    /// Shortens this DBKey to the specified length.
    pub fn truncate(&self, size: u16) -> DBKey {
        debug_assert!(self.from + size <= self.to);

        DBKey {
            data: self.data,
            from: self.from,
            to: self.from + size,
        }
    }

    /// Returns how many bits at the beginning matches with `other`
    pub fn common_prefix(&self, other: &Self) -> u16 {
        // We assume that all slices created from byte arrays with the same length
        if self.from != other.from {
            0
        } else {
            let from = self.from / 8;
            let to = min((self.to + 7) / 8, (other.to + 7) / 8);
            let max_len = min(self.len(), other.len());

            for i in from..to {
                let x = self.data[i as usize] ^ other.data[i as usize];
                if x != 0 {
                    let tail = x.leading_zeros() as u16;
                    return min(i * 8 + tail - self.from, max_len);
                }
            }
            max_len
        }
    }

    /// Returns true if we starts with the same prefix at the whole of `Other`
    pub fn starts_with(&self, other: &Self) -> bool {
        self.common_prefix(other) == other.len()
    }

    /// Returns true if self.to not changed
    pub fn is_leaf(&self) -> bool {
        self.to == (KEY_SIZE * 8) as u16
    }

    // TODO: terrible hack, try to remove this (ECR-22)
    /// Represents `DBKey` as byte array and returns it
    pub fn as_bytes(&self) -> Box<[u8]> {
        let mut buffer = Box::new([0u8; DB_KEY_SIZE as usize]);
        self.write(buffer.as_mut());
        buffer
    }
}

impl AsRef<[u8]> for DBKey {
    fn as_ref(&self) -> &[u8] {
        &self.data
    }
}

impl StorageKey for DBKey {
    fn size(&self) -> usize {
        DB_KEY_SIZE
    }

    fn write(&self, buffer: &mut [u8]) {
        if self.is_leaf() {
            buffer[0] = LEAF_KEY_PREFIX;
            buffer[1..KEY_SIZE + 1].copy_from_slice(&self.data);
            buffer[KEY_SIZE + 1] = 0;
        } else {
            buffer[0] = BRANCH_KEY_PREFIX;
            let right = (self.to as usize + 7) / 8;
            buffer[1..right + 1].copy_from_slice(&self.data[0..right]);
            if self.to % 8 != 0 {
                buffer[right] &= !(255u8 >> (self.to % 8));
            }
            for i in buffer.iter_mut().take(KEY_SIZE + 1).skip(right + 1) {
                *i = 0
            }
            buffer[KEY_SIZE + 1] = self.to as u8;
        }
    }

    fn read(buffer: &[u8]) -> Self {
        debug_assert_eq!(buffer.len(), DB_KEY_SIZE);
        let mut data = [0; KEY_SIZE];
        data[..].copy_from_slice(&buffer[1..KEY_SIZE + 1]);
        let to = match buffer[0] {
            LEAF_KEY_PREFIX => KEY_SIZE as u16 * 8,
            BRANCH_KEY_PREFIX => u16::from(buffer[DB_KEY_SIZE - 1]),
            _ => unreachable!("wrong key prefix"),
        };
        DBKey {
            data: data,
            from: 0,
            to: to,
        }
    }
}

impl PartialEq for DBKey {
    fn eq(&self, other: &Self) -> bool {
        self.len() == other.len() && self.starts_with(other)
    }
}

impl ::std::fmt::Debug for DBKey {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "DBKey(")?;
        for i in 0..self.len() {
            write!(
                f,
                "{}",
                match self.get(i) {
                    ChildKind::Left => '0',
                    ChildKind::Right => '1',
                }
            )?;
        }
        write!(f, ")")
    }
}

#[test]
fn test_dbkey_suffix() {
    let b = DBKey::read(b"\x00\x01\x02\xFF\x0C0000000000000000000000000000\x20");
    assert_eq!(b.len(), 32);
    assert_eq!(b.get(0), ChildKind::Left);
    assert_eq!(b.get(7), ChildKind::Right);
    assert_eq!(b.get(8), ChildKind::Left);
    assert_eq!(b.get(14), ChildKind::Right);
    assert_eq!(b.get(15), ChildKind::Left);
    assert_eq!(b.get(16), ChildKind::Right);
    assert_eq!(b.get(20), ChildKind::Right);
    assert_eq!(b.get(23), ChildKind::Right);
    assert_eq!(b.get(31), ChildKind::Left);
    let b2 = b.suffix(8);
    assert_eq!(b2.len(), 24);
    assert_eq!(b2.get(0), ChildKind::Left);
    assert_eq!(b2.get(6), ChildKind::Right);
    assert_eq!(b2.get(7), ChildKind::Left);
    assert_eq!(b2.get(12), ChildKind::Right);
    assert_eq!(b2.get(15), ChildKind::Right);
    let b3 = b2.suffix(24);
    assert_eq!(b3.len(), 0);
    let b4 = b.suffix(1);
    assert_eq!(b4.get(6), ChildKind::Right);
    assert_eq!(b4.get(7), ChildKind::Left);
    assert_eq!(b4.get(13), ChildKind::Right);
}

#[test]
fn test_dbkey_truncate() {
    let b = DBKey::read(b"\x00\x80wertyuiopasdfghjklzxcvbnm123456\x08");
    assert_eq!(b.len(), 8);
    assert_eq!(b.truncate(1).get(0), ChildKind::Right);
    assert_eq!(b.truncate(1).len(), 1);
}

#[test]
fn test_dbkey_len() {
    let b = DBKey::read(b"\x01qwertyuiopasdfghjklzxcvbnm123456\x00");
    assert_eq!(b.len(), 256);
}

#[test]
#[should_panic(expected = "self.from + idx < self.to")]
fn test_dbkey_at_overflow() {
    let b = DBKey::read(b"\x00qwertyuiopasdfghjklzxcvbnm123456\x0F");
    b.get(32);
}

#[test]
#[should_panic(expected = "self.from + suffix <= self.to")]
fn test_dbkey_suffix_overflow() {
    let b = DBKey::read(b"\x00qwertyuiopasdfghjklzxcvbnm123456\xFF");
    assert_eq!(b"\x01qwertyuiopasdfghjklzxcvbnm123456\x00".len(), 34);
    b.suffix(255).suffix(2);
}

#[test]
#[should_panic(expected = "self.from + idx < self.to")]
fn test_dbkey_suffix_at_overflow() {
    let b = DBKey::read(b"\x00qwertyuiopasdfghjklzxcvbnm123456\xFF");
    b.suffix(1).get(255);
}

#[test]
fn test_dbkey_common_prefix() {
    let b1 = DBKey::read(b"\x01abcd0000000000000000000000000000\x00");
    let b2 = DBKey::read(b"\x01abde0000000000000000000000000000\x00");
    assert_eq!(b1.common_prefix(&b1), 256);
    let c = b1.common_prefix(&b2);
    assert_eq!(c, 21);
    let c = b2.common_prefix(&b1);
    assert_eq!(c, 21);
    let b1 = b1.suffix(9);
    let b2 = b2.suffix(9);
    let c = b1.common_prefix(&b2);
    assert_eq!(c, 12);
    let b3 = DBKey::read(b"\x01\xFF0000000000000000000000000000000\x00");
    let b4 = DBKey::read(b"\x01\xFE0000000000000000000000000000000\x00");
    assert_eq!(b3.common_prefix(&b4), 7);
    assert_eq!(b4.common_prefix(&b3), 7);
    assert_eq!(b3.common_prefix(&b3), 256);
    let b3 = b3.suffix(30);
    assert_eq!(b3.common_prefix(&b3), 226);
    let b3 = b3.truncate(200);
    assert_eq!(b3.common_prefix(&b3), 200);
    let b5 = DBKey::read(b"\x01\xFF0000000000000000000000000000000\x00");
    assert_eq!(b5.truncate(0).common_prefix(&b3), 0);
}

#[test]
fn test_dbkey_is_leaf() {
    let b = DBKey::read(b"\x01qwertyuiopasdfghjklzxcvbnm123456\x00");
    assert_eq!(b.len(), 256);
    assert_eq!(b.suffix(4).is_leaf(), true);
    assert_eq!(b.suffix(8).is_leaf(), true);
    assert_eq!(b.suffix(250).is_leaf(), true);
    assert_eq!(b.truncate(16).is_leaf(), false);
}

#[test]
fn test_dbkey_is_branch() {
    let b = DBKey::read(b"\x00qwertyuiopasdfghjklzxcvbnm123456\xFF");
    assert_eq!(b.len(), 255);
    assert_eq!(b.is_leaf(), false);
}
<commit_msg>Fix assertion<commit_after>// Copyright 2017 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 std::cmp::min;

use crypto::{Hash, PublicKey, HASH_SIZE};
use super::super::StorageKey;

pub const BRANCH_KEY_PREFIX: u8 = 00;
pub const LEAF_KEY_PREFIX: u8 = 01;

/// Size in bytes of the `ProofMapKey`.
pub const KEY_SIZE: usize = HASH_SIZE;
pub const DB_KEY_SIZE: usize = KEY_SIZE + 2;

/// A trait that defines a subset of storage key types which are suitable for use with
/// `ProofMapIndex`.
///
/// The size of the keys must be exactly 32 bytes and the keys must have a uniform distribution.
pub trait ProofMapKey: StorageKey {}

impl ProofMapKey for Hash {}
impl ProofMapKey for PublicKey {}
impl ProofMapKey for [u8; KEY_SIZE] {}

impl StorageKey for [u8; KEY_SIZE] {
    fn size(&self) -> usize {
        KEY_SIZE
    }

    fn write(&self, buffer: &mut [u8]) {
        buffer.copy_from_slice(self.as_ref())
    }

    fn read(buffer: &[u8]) -> Self {
        let mut value = [0; KEY_SIZE];
        value.copy_from_slice(buffer);
        value
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ChildKind {
    Left,
    Right,
}

/// A struct that represents a bit slices of the proof map keys.
#[derive(Clone)]
pub struct DBKey {
    data: [u8; KEY_SIZE],
    from: u16,
    to: u16,
}

impl ::std::ops::Not for ChildKind {
    type Output = ChildKind;

    fn not(self) -> ChildKind {
        match self {
            ChildKind::Left => ChildKind::Right,
            ChildKind::Right => ChildKind::Left,
        }
    }
}

impl DBKey {
    /// Create a new bit slice from the given binary data.
    pub fn leaf<K: ProofMapKey>(key: &K) -> DBKey {
        debug_assert_eq!(key.size(), KEY_SIZE);

        let mut data = [0; KEY_SIZE];
        key.write(&mut data);
        DBKey {
            data: data,
            from: 0,
            to: (KEY_SIZE * 8) as u16,
        }
    }

    #[doc(hidden)]
    pub fn from(&self) -> u16 {
        self.from
    }

    // TODO: terrible hack, try to remove this (ECR-22)
    #[doc(hidden)]
    pub fn set_from(&mut self, from: u16) {
        self.from = from
    }

    #[doc(hidden)]
    pub fn to(&self) -> u16 {
        self.to
    }

    /// Returns length of the `DBKey`.
    pub fn len(&self) -> u16 {
        self.to - self.from
    }

    /// Returns true if `DBKey` has zero length.
    pub fn is_empty(&self) -> bool {
        self.to == self.from
    }

    /// Get bit at position `idx`.
    pub fn get(&self, idx: u16) -> ChildKind {
        debug_assert!(self.from + idx < self.to);

        let pos = self.from + idx;
        let chunk = self.data[(pos / 8) as usize];
        let bit = 7 - pos % 8;
        let value = (1 << bit) & chunk;
        if value != 0 {
            ChildKind::Right
        } else {
            ChildKind::Left
        }
    }

    /// Shortens this DBKey to the specified length.
    pub fn prefix(&self, suffix: u16) -> DBKey {
        debug_assert!(self.from + suffix <= self.data.len() as u16 * 8);

        DBKey {
            data: self.data,
            from: self.from,
            to: self.from + suffix,
        }
    }

    /// Return object which represents a view on to this slice (further) offset by `i` bits.
    pub fn suffix(&self, suffix: u16) -> DBKey {
        debug_assert!(self.from + suffix <= self.to);

        DBKey {
            data: self.data,
            from: self.from + suffix,
            to: self.to,
        }
    }

    /// Shortens this DBKey to the specified length.
    pub fn truncate(&self, size: u16) -> DBKey {
        debug_assert!(self.from + size <= self.to);

        DBKey {
            data: self.data,
            from: self.from,
            to: self.from + size,
        }
    }

    /// Returns how many bits at the beginning matches with `other`
    pub fn common_prefix(&self, other: &Self) -> u16 {
        // We assume that all slices created from byte arrays with the same length
        if self.from != other.from {
            0
        } else {
            let from = self.from / 8;
            let to = min((self.to + 7) / 8, (other.to + 7) / 8);
            let max_len = min(self.len(), other.len());

            for i in from..to {
                let x = self.data[i as usize] ^ other.data[i as usize];
                if x != 0 {
                    let tail = x.leading_zeros() as u16;
                    return min(i * 8 + tail - self.from, max_len);
                }
            }
            max_len
        }
    }

    /// Returns true if we starts with the same prefix at the whole of `Other`
    pub fn starts_with(&self, other: &Self) -> bool {
        self.common_prefix(other) == other.len()
    }

    /// Returns true if self.to not changed
    pub fn is_leaf(&self) -> bool {
        self.to == (KEY_SIZE * 8) as u16
    }

    // TODO: terrible hack, try to remove this (ECR-22)
    /// Represents `DBKey` as byte array and returns it
    pub fn as_bytes(&self) -> Box<[u8]> {
        let mut buffer = Box::new([0u8; DB_KEY_SIZE as usize]);
        self.write(buffer.as_mut());
        buffer
    }
}

impl AsRef<[u8]> for DBKey {
    fn as_ref(&self) -> &[u8] {
        &self.data
    }
}

impl StorageKey for DBKey {
    fn size(&self) -> usize {
        DB_KEY_SIZE
    }

    fn write(&self, buffer: &mut [u8]) {
        if self.is_leaf() {
            buffer[0] = LEAF_KEY_PREFIX;
            buffer[1..KEY_SIZE + 1].copy_from_slice(&self.data);
            buffer[KEY_SIZE + 1] = 0;
        } else {
            buffer[0] = BRANCH_KEY_PREFIX;
            let right = (self.to as usize + 7) / 8;
            buffer[1..right + 1].copy_from_slice(&self.data[0..right]);
            if self.to % 8 != 0 {
                buffer[right] &= !(255u8 >> (self.to % 8));
            }
            for i in buffer.iter_mut().take(KEY_SIZE + 1).skip(right + 1) {
                *i = 0
            }
            buffer[KEY_SIZE + 1] = self.to as u8;
        }
    }

    fn read(buffer: &[u8]) -> Self {
        debug_assert_eq!(buffer.len(), DB_KEY_SIZE);
        let mut data = [0; KEY_SIZE];
        data[..].copy_from_slice(&buffer[1..KEY_SIZE + 1]);
        let to = match buffer[0] {
            LEAF_KEY_PREFIX => KEY_SIZE as u16 * 8,
            BRANCH_KEY_PREFIX => u16::from(buffer[DB_KEY_SIZE - 1]),
            _ => unreachable!("wrong key prefix"),
        };
        DBKey {
            data: data,
            from: 0,
            to: to,
        }
    }
}

impl PartialEq for DBKey {
    fn eq(&self, other: &Self) -> bool {
        self.len() == other.len() && self.starts_with(other)
    }
}

impl ::std::fmt::Debug for DBKey {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "DBKey(")?;
        for i in 0..self.len() {
            write!(
                f,
                "{}",
                match self.get(i) {
                    ChildKind::Left => '0',
                    ChildKind::Right => '1',
                }
            )?;
        }
        write!(f, ")")
    }
}

#[test]
fn test_dbkey_suffix() {
    let b = DBKey::read(b"\x00\x01\x02\xFF\x0C0000000000000000000000000000\x20");
    assert_eq!(b.len(), 32);
    assert_eq!(b.get(0), ChildKind::Left);
    assert_eq!(b.get(7), ChildKind::Right);
    assert_eq!(b.get(8), ChildKind::Left);
    assert_eq!(b.get(14), ChildKind::Right);
    assert_eq!(b.get(15), ChildKind::Left);
    assert_eq!(b.get(16), ChildKind::Right);
    assert_eq!(b.get(20), ChildKind::Right);
    assert_eq!(b.get(23), ChildKind::Right);
    assert_eq!(b.get(31), ChildKind::Left);
    let b2 = b.suffix(8);
    assert_eq!(b2.len(), 24);
    assert_eq!(b2.get(0), ChildKind::Left);
    assert_eq!(b2.get(6), ChildKind::Right);
    assert_eq!(b2.get(7), ChildKind::Left);
    assert_eq!(b2.get(12), ChildKind::Right);
    assert_eq!(b2.get(15), ChildKind::Right);
    let b3 = b2.suffix(24);
    assert_eq!(b3.len(), 0);
    let b4 = b.suffix(1);
    assert_eq!(b4.get(6), ChildKind::Right);
    assert_eq!(b4.get(7), ChildKind::Left);
    assert_eq!(b4.get(13), ChildKind::Right);
}

#[test]
fn test_dbkey_truncate() {
    let b = DBKey::read(b"\x00\x80wertyuiopasdfghjklzxcvbnm123456\x08");
    assert_eq!(b.len(), 8);
    assert_eq!(b.truncate(1).get(0), ChildKind::Right);
    assert_eq!(b.truncate(1).len(), 1);
}

#[test]
fn test_dbkey_len() {
    let b = DBKey::read(b"\x01qwertyuiopasdfghjklzxcvbnm123456\x00");
    assert_eq!(b.len(), 256);
}

#[test]
#[should_panic(expected = "self.from + idx < self.to")]
fn test_dbkey_at_overflow() {
    let b = DBKey::read(b"\x00qwertyuiopasdfghjklzxcvbnm123456\x0F");
    b.get(32);
}

#[test]
#[should_panic(expected = "self.from + suffix <= self.to")]
fn test_dbkey_suffix_overflow() {
    let b = DBKey::read(b"\x00qwertyuiopasdfghjklzxcvbnm123456\xFF");
    assert_eq!(b"\x01qwertyuiopasdfghjklzxcvbnm123456\x00".len(), 34);
    b.suffix(255).suffix(2);
}

#[test]
#[should_panic(expected = "self.from + idx < self.to")]
fn test_dbkey_suffix_at_overflow() {
    let b = DBKey::read(b"\x00qwertyuiopasdfghjklzxcvbnm123456\xFF");
    b.suffix(1).get(255);
}

#[test]
fn test_dbkey_common_prefix() {
    let b1 = DBKey::read(b"\x01abcd0000000000000000000000000000\x00");
    let b2 = DBKey::read(b"\x01abde0000000000000000000000000000\x00");
    assert_eq!(b1.common_prefix(&b1), 256);
    let c = b1.common_prefix(&b2);
    assert_eq!(c, 21);
    let c = b2.common_prefix(&b1);
    assert_eq!(c, 21);
    let b1 = b1.suffix(9);
    let b2 = b2.suffix(9);
    let c = b1.common_prefix(&b2);
    assert_eq!(c, 12);
    let b3 = DBKey::read(b"\x01\xFF0000000000000000000000000000000\x00");
    let b4 = DBKey::read(b"\x01\xFE0000000000000000000000000000000\x00");
    assert_eq!(b3.common_prefix(&b4), 7);
    assert_eq!(b4.common_prefix(&b3), 7);
    assert_eq!(b3.common_prefix(&b3), 256);
    let b3 = b3.suffix(30);
    assert_eq!(b3.common_prefix(&b3), 226);
    let b3 = b3.truncate(200);
    assert_eq!(b3.common_prefix(&b3), 200);
    let b5 = DBKey::read(b"\x01\xFF0000000000000000000000000000000\x00");
    assert_eq!(b5.truncate(0).common_prefix(&b3), 0);
}

#[test]
fn test_dbkey_is_leaf() {
    let b = DBKey::read(b"\x01qwertyuiopasdfghjklzxcvbnm123456\x00");
    assert_eq!(b.len(), 256);
    assert_eq!(b.suffix(4).is_leaf(), true);
    assert_eq!(b.suffix(8).is_leaf(), true);
    assert_eq!(b.suffix(250).is_leaf(), true);
    assert_eq!(b.truncate(16).is_leaf(), false);
}

#[test]
fn test_dbkey_is_branch() {
    let b = DBKey::read(b"\x00qwertyuiopasdfghjklzxcvbnm123456\xFF");
    assert_eq!(b.len(), 255);
    assert_eq!(b.is_leaf(), false);
}
<|endoftext|>


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

#[path="../src/lib.rs"]
mod event;

#[test]
fn must_register_an_event_and_call_callback_passing_data() {
    let mut emitter = event::Emitter::new();
    let test = String::from_str("TEST");
    let data_inside = String::from_str("DATA INSIDE");
    let callback = & mut |&mut:event:& mut HashMap<String, String>| {

        match event.get(&test) {
          Some(thing) => {
            if *thing != data_inside {
              panic!("the data inside the event is not what is expected, expected {}, get {}", data_inside, *thing);
            }
          },
          None => {
            panic!("the data expected wasn't found")
          },
        }
    };
    emitter.on(test.clone(), callback);

    let mut data : HashMap<String, String> = HashMap::new();
    data.insert(test.clone(), data_inside.clone());
    emitter.emit(test.clone(), & mut data);
}

#[test]
fn must_register_multiple_events_and_call_all_the_callback_passing_a_copy_of_the_same_data() {
    let mut emitter = event::Emitter::new();
    let test = String::from_str("TEST");
    let data_inside = String::from_str("DATA INSIDE");
    let callback = & mut |&mut:event:& mut HashMap<String, String>|{
        match event.get(&test) {
          Some(thing) => {
            if *thing != data_inside {
              panic!("the data inside the event is not what is expected, expected {}, get {}", data_inside, *thing);
            }
          },
          None => {
            panic!("the data expected wasn't found")
          },
        }
    };

    emitter.on(test.clone(), callback);
    let second_callback = & mut |&mut:event:& mut HashMap<String, String>|{
        match event.get(&test) {
          Some(thing) => {
            if *thing != data_inside {
              panic!("the data inside the event is not what is expected, expected {}, get {}", data_inside, *thing);
            }
          },
          None => {
            panic!("the data expected wasn't found")
          },
        }
    };
    emitter.on(test.clone(), second_callback);

    let mut data : HashMap<String, String> = HashMap::new();
    data.insert(test.clone(), data_inside.clone());
    emitter.emit(test.clone(), & mut data);
}

#[test]
fn must_unregister_an_event() {
    let mut emitter = event::Emitter::new();
    let test = String::from_str("TEST");
    let data_inside = String::from_str("DATA INSIDE");
    let callback = & mut |&mut:event: & mut HashMap<String, String>|{
        panic!("the emitter must never be called instead has been called with {} parameters", event.capacity());
    };
    emitter.on(test.clone(), callback);

    let mut data : HashMap<String, String> = HashMap::new();
    data.insert(test.clone(), data_inside.clone());
    emitter.off(test.clone());
    emitter.emit(test.clone(), & mut data);

}

#[test]
fn must_work_with_a_custom_event_data_and_allow_the_callback_to_modified_it(){
    struct Foo {
      bar : String
    };

    let mut emitter = event::Emitter::new();
    let test = String::from_str("TEST");
    let data_inside = String::from_str("DATA INSIDE");
    let callback = & mut |&mut:event:& mut HashMap<String, Foo>|{
        match event.get(&test) {
          Some(thing) => {
            if (*thing).bar != data_inside {
              panic!("the data inside the event is not what is expected, expected {}, get {}", data_inside, (*thing).bar);
            }
          },
          None => {
            panic!("the data expected wasn't found")
          },
        }
        event.insert(String::from_str("Result"), Foo {bar: String::from_str("HAHAHA")});
    };
    emitter.on(test.clone(), callback);

    let mut data : HashMap<String, Foo> = HashMap::new();
    data.insert(test.clone(), Foo {bar: data_inside.clone()});
    emitter.emit(test.clone(), & mut data);
    if data[String::from_str("Result")].bar != String::from_str("HAHAHA") { panic!("Doesn't pass back values") }
}
<commit_msg>Updating to rust 1.1.0<commit_after>use event::Events;
use std::collections::HashMap;

#[path="../src/lib.rs"]
mod event;

#[test]
fn must_register_an_event_and_call_callback_passing_data() {
    let (test, data_inside) = (
        "TEST".to_string(),
        "DATA INSIDE".to_string()
    );
    let (mut emitter, callback) = (
        event::Emitter::new(),
        & mut |event:& mut HashMap<String, String>| {
            match event.get(&test) {
              Some(thing) => {
                if *thing != data_inside {
                  panic!("the data inside the event is not what is expected, expected {}, get {}", data_inside, *thing);
                }
              },
              None => {
                panic!("the data expected wasn't found")
              },
            }
        }
    );

    emitter.on(test.clone(), callback);

    let mut data : HashMap<String, String> = HashMap::new();
    data.insert(test.clone(), data_inside.clone());
    emitter.emit(test.clone(), & mut data);
}

#[test]
fn must_register_multiple_events_and_call_all_the_callback_passing_a_copy_of_the_same_data() {
    let (test, data_inside) = (
        "TEST".to_string(),
        "DATA INSIDE".to_string()
    );
    let (mut emitter, callback, second_callback) = (event::Emitter::new(),
    & mut |event:& mut HashMap<String, String>|{
        match event.get(&test) {
          Some(thing) => {
            if *thing != data_inside {
              panic!("the data inside the event is not what is expected, expected {}, get {}", data_inside, *thing);
            }
          },
          None => {
            panic!("the data expected wasn't found")
          },
        }
    },
    & mut |event:& mut HashMap<String, String>|{
        match event.get(&test) {
          Some(thing) => {
            if *thing != data_inside {
              panic!("the data inside the event is not what is expected, expected {}, get {}", data_inside, *thing);
            }
          },
          None => {
            panic!("the data expected wasn't found")
          },
        }
    });

    emitter.on(test.clone(), callback);

    emitter.on(test.clone(), second_callback);

    let mut data : HashMap<String, String> = HashMap::new();
    data.insert(test.clone(), data_inside.clone());
    emitter.emit(test.clone(), & mut data);
}

#[test]
fn must_unregister_an_event() {
    let (test, data_inside) = (
        "TEST".to_string(),
        "DATA INSIDE".to_string()
    );
    let (mut emitter, callback) = (event::Emitter::new(), & mut |event: & mut HashMap<String, String>|{
        panic!("the emitter must never be called instead has been called with {} parameters", event.capacity());
    });
    emitter.on(test.clone(), callback);

    let mut data : HashMap<String, String> = HashMap::new();
    data.insert(test.clone(), data_inside.clone());
    emitter.off(test.clone());
    emitter.emit(test.clone(), & mut data);

}

#[test]
fn must_work_with_a_custom_event_data_and_allow_the_callback_to_modified_it(){
    struct Foo {
      bar : String
    };
    let (test, data_inside) = (
        "TEST".to_string(),
        "DATA INSIDE".to_string()
    );
    let (mut emitter, callback) = (event::Emitter::new(), & mut |event:& mut HashMap<String, Foo>|{
        match event.get(&test) {
          Some(thing) => {
            if (*thing).bar != data_inside {
              panic!("the data inside the event is not what is expected, expected {}, get {}", data_inside, (*thing).bar);
            }
          },
          None => {
            panic!("the data expected wasn't found")
          },
        }
        event.insert("Result".to_string(), Foo {bar: "HAHAHA".to_string()});
    });

    emitter.on(test.clone(), callback);

    let mut data : HashMap<String, Foo> = HashMap::new();
    data.insert(test.clone(), Foo {bar: data_inside.clone()});
    emitter.emit(test.clone(), & mut data);
    match data.get(&"Result".to_string()) {
        Some(ref data) => {
            if data.bar != "HAHAHA".to_string() {
                panic!("Doesn't pass back values")
            }
        }
        _ => { panic!("Doesn't pass back values") }
    }
}
<|endoftext|>


<commit_before>//#![feature(trace_macros)]
#![allow(dead_code)]
#![cfg_attr(feature = "cargo-clippy", allow(redundant_closure))]

use nom::{error::ErrorKind, Err, IResult, Needed};

#[allow(dead_code)]
struct Range {
  start: char,
  end: char,
}

pub fn take_char(input: &[u8]) -> IResult<&[u8], char> {
  if !input.is_empty() {
    Ok((&input[1..], input[0] as char))
  } else {
    Err(Err::Incomplete(Needed::new(1)))
  }
}

#[cfg(feature = "std")]
mod parse_int {
  use nom::HexDisplay;
  use nom::{
    character::streaming::{digit1 as digit, space1 as space},
    IResult,
  };
  use std::str;

  named!(parse_ints<Vec<i32>>, many0!(spaces_or_int));

  fn spaces_or_int(input: &[u8]) -> IResult<&[u8], i32> {
    println!("{}", input.to_hex(8));
    do_parse!(
      input,
      opt!(complete!(space))
        >> res: map!(complete!(digit), |x| {
          println!("x: {:?}", x);
          let result = str::from_utf8(x).unwrap();
          println!("Result: {}", result);
          println!("int is empty?: {}", x.is_empty());
          match result.parse() {
            Ok(i) => i,
            Err(e) => panic!("UH OH! NOT A DIGIT! {:?}", e),
          }
        })
        >> (res)
    )
  }

  #[test]
  fn issue_142() {
    let subject = parse_ints(&b"12 34 5689a"[..]);
    let expected = Ok((&b"a"[..], vec![12, 34, 5689]));
    assert_eq!(subject, expected);

    let subject = parse_ints(&b"12 34 5689 "[..]);
    let expected = Ok((&b" "[..], vec![12, 34, 5689]));
    assert_eq!(subject, expected)
  }
}

#[test]
fn usize_length_bytes_issue() {
  use nom::number::streaming::be_u16;
  let _: IResult<&[u8], &[u8], (&[u8], ErrorKind)> = length_data!(b"012346", be_u16);
}

/*
 DOES NOT COMPILE
#[test]
fn issue_152() {
  named!(take4, take!(4));
  named!(xyz, tag!("XYZ"));
  named!(abc, tag!("abc"));

  named!(sw,
    switch!(take4,
      b"abcd" => xyz |
      b"efgh" => abc
    )
  );
}
*/

#[test]
fn take_till_issue() {
  named!(nothing, take_till!(call!(|_| true)));

  assert_eq!(nothing(b""), Err(Err::Incomplete(Needed::new(1))));
  assert_eq!(nothing(b"abc"), Ok((&b"abc"[..], &b""[..])));
}

#[test]
fn issue_655() {
  use nom::character::streaming::{line_ending, not_line_ending};
  named!(twolines(&str) -> (&str, &str),
    do_parse!(
      l1 : not_line_ending >>
           line_ending >>
      l2 : not_line_ending >>
           line_ending >>
      ((l1, l2))
    )
  );

  assert_eq!(twolines("foo\nbar\n"), Ok(("", ("foo", "bar"))));
  assert_eq!(twolines("féo\nbar\n"), Ok(("", ("féo", "bar"))));
  assert_eq!(twolines("foé\nbar\n"), Ok(("", ("foé", "bar"))));
  assert_eq!(twolines("foé\r\nbar\n"), Ok(("", ("foé", "bar"))));
}

#[cfg(feature = "alloc")]
named!(issue_717<&[u8], Vec<&[u8]> >,
  separated_list0!(tag!([0x0]), is_not!([0x0u8]))
);

mod issue_647 {
  use nom::{error::Error, number::streaming::be_f64, Err};
  pub type Input<'a> = &'a [u8];

  #[derive(PartialEq, Debug, Clone)]
  struct Data {
    c: f64,
    v: Vec<f64>,
  }

  fn list<'a, 'b>(
    input: Input<'a>,
    _cs: &'b f64,
  ) -> Result<(Input<'a>, Vec<f64>), Err<Error<&'a [u8]>>> {
    separated_list0!(input, complete!(tag!(",")), complete!(be_f64))
  }

  named!(data<Input,Data>, map!(
      do_parse!(
          c: be_f64 >>
          tag!("\n") >>
          v: call!(list,&c) >>
          (c,v)
      ), |(c,v)| {
          Data {
              c: c,
              v: v
          }
      }
  ));
}

#[test]
fn issue_848_overflow_incomplete_bits_to_bytes() {
  named!(take, take!(0x2000000000000000));
  named!(parser<&[u8], &[u8]>, bits!(bytes!(take)));
  assert_eq!(
    parser(&b""[..]),
    Err(Err::Failure(error_position!(&b""[..], ErrorKind::TooLarge)))
  );
}

#[test]
fn issue_942() {
  use nom::error::{ContextError, ParseError};
  pub fn parser<'a, E: ParseError<&'a str> + ContextError<&'a str>>(
    i: &'a str,
  ) -> IResult<&'a str, usize, E> {
    use nom::{character::complete::char, error::context, multi::many0_count};
    many0_count(context("char_a", char('a')))(i)
  }
  assert_eq!(parser::<()>("aaa"), Ok(("", 3)));
}

#[test]
fn issue_many_m_n_with_zeros() {
  use nom::character::complete::char;
  use nom::multi::many_m_n;
  let mut parser = many_m_n::<_, _, (), _>(0, 0, char('a'));
  assert_eq!(parser("aaa"), Ok(("aaa", vec!())));
}

#[test]
fn issue_1027_convert_error_panic_nonempty() {
  use nom::character::complete::char;
  use nom::error::{convert_error, VerboseError};
  use nom::sequence::pair;

  let input = "a";

  let result: IResult<_, _, VerboseError<&str>> = pair(char('a'), char('b'))(input);
  let err = match result.unwrap_err() {
    Err::Error(e) => e,
    _ => unreachable!(),
  };

  let msg = convert_error(input, err);
  assert_eq!(
    msg,
    "0: at line 1:\na\n ^\nexpected \'b\', got end of input\n\n"
  );
}

#[test]
fn issue_1231_bits_expect_fn_closure() {
  use nom::bits::{bits, complete::take};
  use nom::error::Error;
  use nom::sequence::tuple;
  pub fn example(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
    bits::<_, _, Error<_>, _, _>(tuple((take(1usize), take(1usize))))(input)
  }
  assert_eq!(example(&[0xff]), Ok((&b""[..], (1, 1))));
}
<commit_msg>remove macros from issue tests<commit_after>//#![feature(trace_macros)]
#![allow(dead_code)]
#![cfg_attr(feature = "cargo-clippy", allow(redundant_closure))]

use nom::{error::ErrorKind, Err, IResult, Needed};

#[allow(dead_code)]
struct Range {
  start: char,
  end: char,
}

pub fn take_char(input: &[u8]) -> IResult<&[u8], char> {
  if !input.is_empty() {
    Ok((&input[1..], input[0] as char))
  } else {
    Err(Err::Incomplete(Needed::new(1)))
  }
}

#[cfg(feature = "std")]
mod parse_int {
  use nom::HexDisplay;
  use nom::{
    character::streaming::{digit1 as digit, space1 as space},
    combinator::{complete, map, opt},
    multi::many0,
    IResult,
  };
  use std::str;

  fn parse_ints(input: &[u8]) -> IResult<&[u8], Vec<i32>> {
    many0(spaces_or_int)(input)
  }

  fn spaces_or_int(input: &[u8]) -> IResult<&[u8], i32> {
    println!("{}", input.to_hex(8));
    let (i, _) = opt(complete(space))(input)?;
    let (i, res) = map(complete(digit), |x| {
      println!("x: {:?}", x);
      let result = str::from_utf8(x).unwrap();
      println!("Result: {}", result);
      println!("int is empty?: {}", x.is_empty());
      match result.parse() {
        Ok(i) => i,
        Err(e) => panic!("UH OH! NOT A DIGIT! {:?}", e),
      }
    })(i)?;

    Ok((i, res))
  }

  #[test]
  fn issue_142() {
    let subject = parse_ints(&b"12 34 5689a"[..]);
    let expected = Ok((&b"a"[..], vec![12, 34, 5689]));
    assert_eq!(subject, expected);

    let subject = parse_ints(&b"12 34 5689 "[..]);
    let expected = Ok((&b" "[..], vec![12, 34, 5689]));
    assert_eq!(subject, expected)
  }
}

#[test]
fn usize_length_bytes_issue() {
  use nom::multi::length_data;
  use nom::number::streaming::be_u16;
  let _: IResult<&[u8], &[u8], (&[u8], ErrorKind)> = length_data(be_u16)(b"012346");
}

#[test]
fn take_till_issue() {
  use nom::bytes::streaming::take_till;

  fn nothing(i: &[u8]) -> IResult<&[u8], &[u8]> {
    take_till(|_| true)(i)
  }

  assert_eq!(nothing(b""), Err(Err::Incomplete(Needed::new(1))));
  assert_eq!(nothing(b"abc"), Ok((&b"abc"[..], &b""[..])));
}

#[test]
fn issue_655() {
  use nom::character::streaming::{line_ending, not_line_ending};
  fn twolines(i: &str) -> IResult<&str, (&str, &str)> {
    let (i, l1) = not_line_ending(i)?;
    let (i, _) = line_ending(i)?;
    let (i, l2) = not_line_ending(i)?;
    let (i, _) = line_ending(i)?;

    Ok((i, (l1, l2)))
  }

  assert_eq!(twolines("foo\nbar\n"), Ok(("", ("foo", "bar"))));
  assert_eq!(twolines("féo\nbar\n"), Ok(("", ("féo", "bar"))));
  assert_eq!(twolines("foé\nbar\n"), Ok(("", ("foé", "bar"))));
  assert_eq!(twolines("foé\r\nbar\n"), Ok(("", ("foé", "bar"))));
}

#[cfg(feature = "alloc")]
fn issue_717(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
  use nom::bytes::complete::{is_not, tag};
  use nom::multi::separated_list0;

  separated_list0(tag([0x0]), is_not([0x0u8]))(i)
}

mod issue_647 {
  use nom::bytes::streaming::tag;
  use nom::combinator::complete;
  use nom::multi::separated_list0;
  use nom::{error::Error, number::streaming::be_f64, Err, IResult};
  pub type Input<'a> = &'a [u8];

  #[derive(PartialEq, Debug, Clone)]
  struct Data {
    c: f64,
    v: Vec<f64>,
  }

  fn list<'a, 'b>(
    input: Input<'a>,
    _cs: &'b f64,
  ) -> Result<(Input<'a>, Vec<f64>), Err<Error<&'a [u8]>>> {
    separated_list0(complete(tag(",")), complete(be_f64))(input)
  }

  fn data(input: Input<'_>) -> IResult<Input<'_>, Data> {
    let (i, c) = be_f64(input)?;
    let (i, _) = tag("\n")(i)?;
    let (i, v) = list(i, &c)?;
    Ok((i, Data { c, v }))
  }
}

#[test]
fn issue_848_overflow_incomplete_bits_to_bytes() {
  fn take(i: &[u8]) -> IResult<&[u8], &[u8]> {
    use nom::bytes::streaming::take;
    take(0x2000000000000000_usize)(i)
  }
  fn parser(i: &[u8]) -> IResult<&[u8], &[u8]> {
    use nom::bits::{bits, bytes};

    bits(bytes(take))(i)
  }
  assert_eq!(
    parser(&b""[..]),
    Err(Err::Failure(nom::error_position!(&b""[..], ErrorKind::TooLarge)))
  );
}

#[test]
fn issue_942() {
  use nom::error::{ContextError, ParseError};
  pub fn parser<'a, E: ParseError<&'a str> + ContextError<&'a str>>(
    i: &'a str,
  ) -> IResult<&'a str, usize, E> {
    use nom::{character::complete::char, error::context, multi::many0_count};
    many0_count(context("char_a", char('a')))(i)
  }
  assert_eq!(parser::<()>("aaa"), Ok(("", 3)));
}

#[test]
fn issue_many_m_n_with_zeros() {
  use nom::character::complete::char;
  use nom::multi::many_m_n;
  let mut parser = many_m_n::<_, _, (), _>(0, 0, char('a'));
  assert_eq!(parser("aaa"), Ok(("aaa", vec!())));
}

#[test]
fn issue_1027_convert_error_panic_nonempty() {
  use nom::character::complete::char;
  use nom::error::{convert_error, VerboseError};
  use nom::sequence::pair;

  let input = "a";

  let result: IResult<_, _, VerboseError<&str>> = pair(char('a'), char('b'))(input);
  let err = match result.unwrap_err() {
    Err::Error(e) => e,
    _ => unreachable!(),
  };

  let msg = convert_error(input, err);
  assert_eq!(
    msg,
    "0: at line 1:\na\n ^\nexpected \'b\', got end of input\n\n"
  );
}

#[test]
fn issue_1231_bits_expect_fn_closure() {
  use nom::bits::{bits, complete::take};
  use nom::error::Error;
  use nom::sequence::tuple;
  pub fn example(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
    bits::<_, _, Error<_>, _, _>(tuple((take(1usize), take(1usize))))(input)
  }
  assert_eq!(example(&[0xff]), Ok((&b""[..], (1, 1))));
}
<|endoftext|>


<commit_before>use std::vec::FromVec;
use compiler::*;
use typecheck::*;
use vm::*;
use interner::*;
use core::translate::*;
use core::*;
use lambda_lift::*;
use parser::Parser;
use renamer::{Name, rename_expr};

///Returns whether the type in question is an IO action
fn is_io(typ: &Type) -> bool {
    match *typ {
        TypeApplication(ref lhs, _) =>
            match **lhs {
                TypeConstructor(ref op) => op.name.as_slice() == "IO",
                _ => false
            },
        _ => false
    }
}

///Compiles an expression into an assembly
fn compile_expr(prelude: &Assembly, expr_str: &str) -> Assembly {
    let mut parser = Parser::new(expr_str.chars());
    let mut expr = rename_expr(parser.expression_());

    let mut type_env = TypeEnvironment::new();
    type_env.add_types(prelude as &DataTypes);
    type_env.typecheck_expr(&mut expr);
    let temp_module = Module::from_expr(translate_expr(expr));
    let m = do_lambda_lift(temp_module);

    let mut compiler = Compiler::new();
    compiler.assemblies.push(prelude);
    compiler.compile_module(&m)
}

///Finds the main function and if it is an IO function, adds instructions to push the "RealWorld" argument
fn find_main(assembly: &Assembly) -> (~[Instruction], Qualified<Type>) {
    assembly.superCombinators.iter()
        .find(|sc| sc.name == Name { name: intern("main"), uid: 0 })
        .map(|sc| {
            if is_io(&sc.typ.value) {
                //If the expression we compiled is IO we need to add an extra argument
                //'RealWorld' which can be any dumb value (42 here), len - 3 is used because
                //it is currently 3 instructions Eval, Update(0), Unwind at the end of each instruction list
                //to finish the expression
                let mut vec: Vec<Instruction> = sc.instructions.iter().map(|x| x.clone()).collect();
                let len = vec.len();
                vec.insert(len - 3, Mkap);
                vec.insert(0, PushInt(42));//Realworld
                (FromVec::from_vec(vec), sc.typ.clone())
            }
            else {
                (sc.instructions.clone(), sc.typ.clone())
            }
        })
        .expect("Expected main function")
}

pub fn run_and_print_expr(expr_str: &str) {
    let prelude = compile_file("Prelude.hs");
    let mut vm = VM::new();
    vm.add_assembly(prelude);
    let assembly = compile_expr(vm.get_assembly(0), expr_str.as_slice());
    let (instructions, type_decl) = find_main(&assembly);
    let assembly_index = vm.add_assembly(assembly);
    let result = evaluate(&vm, instructions, assembly_index);//TODO 0 is not necessarily correct
    println!("{}  {}", result, type_decl);
}

///Starts the REPL
pub fn start() {
    let prelude = compile_file("Prelude.hs");
    let mut vm = VM::new();
    vm.add_assembly(prelude);
    for line in ::std::io::stdin().lines() {
        let expr_str = match line {
            Ok(l) => l,
            Err(e) => fail!("Reading line failed with '{}'", e)
        };
        let assembly = compile_expr(vm.get_assembly(0), expr_str.as_slice());
        let (instructions, typ) = find_main(&assembly);
        let assembly_index = vm.add_assembly(assembly);
        let result = evaluate(&vm, instructions, assembly_index);//TODO 0 is not necessarily correct
        println!("{}  {}", result, typ);
    }
}
<commit_msg>Fix Qualified<Type> -> Qualified<Type, Name><commit_after>use std::vec::FromVec;
use compiler::*;
use typecheck::*;
use vm::*;
use interner::*;
use core::translate::*;
use core::*;
use lambda_lift::*;
use parser::Parser;
use renamer::{Name, rename_expr};

///Returns whether the type in question is an IO action
fn is_io(typ: &Type) -> bool {
    match *typ {
        TypeApplication(ref lhs, _) =>
            match **lhs {
                TypeConstructor(ref op) => op.name.as_slice() == "IO",
                _ => false
            },
        _ => false
    }
}

///Compiles an expression into an assembly
fn compile_expr(prelude: &Assembly, expr_str: &str) -> Assembly {
    let mut parser = Parser::new(expr_str.chars());
    let mut expr = rename_expr(parser.expression_());

    let mut type_env = TypeEnvironment::new();
    type_env.add_types(prelude as &DataTypes);
    type_env.typecheck_expr(&mut expr);
    let temp_module = Module::from_expr(translate_expr(expr));
    let m = do_lambda_lift(temp_module);

    let mut compiler = Compiler::new();
    compiler.assemblies.push(prelude);
    compiler.compile_module(&m)
}

///Finds the main function and if it is an IO function, adds instructions to push the "RealWorld" argument
fn find_main(assembly: &Assembly) -> (~[Instruction], Qualified<Type, Name>) {
    assembly.superCombinators.iter()
        .find(|sc| sc.name == Name { name: intern("main"), uid: 0 })
        .map(|sc| {
            if is_io(&sc.typ.value) {
                //If the expression we compiled is IO we need to add an extra argument
                //'RealWorld' which can be any dumb value (42 here), len - 3 is used because
                //it is currently 3 instructions Eval, Update(0), Unwind at the end of each instruction list
                //to finish the expression
                let mut vec: Vec<Instruction> = sc.instructions.iter().map(|x| x.clone()).collect();
                let len = vec.len();
                vec.insert(len - 3, Mkap);
                vec.insert(0, PushInt(42));//Realworld
                (FromVec::from_vec(vec), sc.typ.clone())
            }
            else {
                (sc.instructions.clone(), sc.typ.clone())
            }
        })
        .expect("Expected main function")
}

pub fn run_and_print_expr(expr_str: &str) {
    let prelude = compile_file("Prelude.hs");
    let mut vm = VM::new();
    vm.add_assembly(prelude);
    let assembly = compile_expr(vm.get_assembly(0), expr_str.as_slice());
    let (instructions, type_decl) = find_main(&assembly);
    let assembly_index = vm.add_assembly(assembly);
    let result = evaluate(&vm, instructions, assembly_index);//TODO 0 is not necessarily correct
    println!("{}  {}", result, type_decl);
}

///Starts the REPL
pub fn start() {
    let prelude = compile_file("Prelude.hs");
    let mut vm = VM::new();
    vm.add_assembly(prelude);
    for line in ::std::io::stdin().lines() {
        let expr_str = match line {
            Ok(l) => l,
            Err(e) => fail!("Reading line failed with '{}'", e)
        };
        let assembly = compile_expr(vm.get_assembly(0), expr_str.as_slice());
        let (instructions, typ) = find_main(&assembly);
        let assembly_index = vm.add_assembly(assembly);
        let result = evaluate(&vm, instructions, assembly_index);//TODO 0 is not necessarily correct
        println!("{}  {}", result, typ);
    }
}
<|endoftext|>


<commit_before>#![cfg(target_os="macos")]
extern crate fsevent;
extern crate tempfile;
extern crate time;

use fsevent::*;
use std::fs;
use std::fs::read_link;
use std::fs::OpenOptions;
use std::io::Write;
use std::path::{Component, PathBuf};
use std::thread;
use std::time::{Duration, SystemTime};

use std::sync::mpsc::{channel, Receiver};

fn validate_recv(rx: Receiver<Event>, evs: Vec<(String, StreamFlags)>) {
    let timeout: Duration = Duration::new(5, 0);
    let deadline = SystemTime::now() + timeout;
    let mut evs = evs.clone();

    while SystemTime::now() < deadline {
        if let Ok(actual) = rx.try_recv() {
            let mut found: Option<usize> = None;
            for i in 0..evs.len() {
                let expected = evs.get(i).unwrap();
                if actual.path == expected.0 && actual.flag == expected.1 {
                    found = Some(i);
                    break;
                }
            }
            if let Some(i) = found {
                evs.remove(i);
            } else {
                assert!(
                    false,
                    format!("actual: {:?} not found in expected: {:?}", actual, evs)
                );
            }
        }
        if evs.is_empty() {
            break;
        }
    }
    assert!(
        evs.is_empty(),
        "Some expected events did not occur before the test timedout:\n\t\t{:?}",
        evs
    );
}

// TODO: replace with std::fs::canonicalize rust-lang/rust#27706.
fn resolve_path(path: &str) -> PathBuf {
    let mut out = PathBuf::new();
    let buf = PathBuf::from(path);
    for p in buf.components() {
        match p {
            Component::RootDir => out.push("/"),
            Component::Normal(osstr) => {
                out.push(osstr);
                if let Ok(real) = read_link(&out) {
                    if real.is_relative() {
                        out.pop();
                        out.push(real);
                    } else {
                        out = real;
                    }
                }
            }
            _ => (),
        }
    }
    out
}

#[test]
fn observe_folder_sync() {
    internal_observe_folder(false);
}

#[test]
fn observe_folder_async() {
    internal_observe_folder(true);
}

fn internal_observe_folder(run_async: bool) {
    let dir = tempfile::Builder::new().prefix("dur").tempdir().unwrap();
    // Resolve path so we don't have to worry about affect of symlinks on the test.
    let dst = resolve_path(dir.path().to_str().unwrap());

    let mut dst1 = dst.clone();
    dst1.push("dest1");

    let ddst1 = dst1.clone();
    fs::create_dir(dst1.as_path().to_str().unwrap()).unwrap();

    let mut dst2 = dst.clone();

    dst2.push("dest2");
    let ddst2 = dst2.clone();
    fs::create_dir(dst2.as_path().to_str().unwrap()).unwrap();

    let mut dst3 = dst.clone();

    dst3.push("dest3");
    let ddst3 = dst3.clone();
    fs::create_dir(dst3.as_path().to_str().unwrap()).unwrap();

    let (sender, receiver) = channel();

    let mut async_fsevent = fsevent::FsEvent::new(vec![]);
    let fsevent_ref_wrapper = if run_async {
        async_fsevent
            .append_path(dst1.as_path().to_str().unwrap())
            .unwrap();
        async_fsevent
            .append_path(dst2.as_path().to_str().unwrap())
            .unwrap();
        async_fsevent
            .append_path(dst3.as_path().to_str().unwrap())
            .unwrap();
        Some(async_fsevent.observe_async(sender).unwrap())
    } else {
        let _t = thread::spawn(move || {
            let mut fsevent = fsevent::FsEvent::new(vec![]);
            fsevent
                .append_path(dst1.as_path().to_str().unwrap())
                .unwrap();
            fsevent
                .append_path(dst2.as_path().to_str().unwrap())
                .unwrap();
            fsevent
                .append_path(dst3.as_path().to_str().unwrap())
                .unwrap();
            fsevent.observe(sender);
        });
        None
    };

    validate_recv(
        receiver,
        vec![
            (
                ddst1.to_str().unwrap().to_string(),
                StreamFlags::ITEM_CREATED | StreamFlags::IS_DIR,
            ),
            (
                ddst2.to_str().unwrap().to_string(),
                StreamFlags::ITEM_CREATED | StreamFlags::IS_DIR,
            ),
            (
                ddst3.to_str().unwrap().to_string(),
                StreamFlags::ITEM_CREATED | StreamFlags::IS_DIR,
            ),
        ],
    );

    match fsevent_ref_wrapper {
        Some(r) => async_fsevent.shutdown_observe(r),
        None => {}
    }
}

#[test]
fn validate_watch_single_file_sync() {
    internal_validate_watch_single_file(false);
}

#[test]
fn validate_watch_single_file_async() {
    internal_validate_watch_single_file(true);
}

fn internal_validate_watch_single_file(run_async: bool) {
    let dir = tempfile::Builder::new().prefix("dur").tempdir().unwrap();
    // Resolve path so we don't have to worry about affect of symlinks on the test.
    let mut dst = resolve_path(dir.path().to_str().unwrap());
    dst.push("out.txt");
    let (sender, receiver) = channel();

    let mut file = OpenOptions::new()
        .write(true)
        .create(true)
        .open(dst.clone().as_path())
        .unwrap();
    file.write_all(b"create").unwrap();
    file.flush().unwrap();
    drop(file);

    let mut async_fsevent = fsevent::FsEvent::new(vec![]);
    let _fsevent_ref_wrapper = if run_async {
        let dst = dst.clone();
        async_fsevent
            .append_path(dst.as_path().to_str().unwrap())
            .unwrap();
        Some(async_fsevent.observe_async(sender).unwrap())
    } else {
        let dst = dst.clone();
        let _t = thread::spawn(move || {
            let mut fsevent = fsevent::FsEvent::new(vec![]);
            fsevent
                .append_path(dst.as_path().to_str().unwrap())
                .unwrap();
            fsevent.observe(sender);
        });
        None
    };

    {
        let dst = dst.clone();
        let t3 = thread::spawn(move || {
            thread::sleep(Duration::new(15, 0)); // Wait another 500ms after observe.
            let mut file = OpenOptions::new()
                .write(true)
                .append(true)
                .open(dst.as_path())
                .unwrap();
            file.write_all(b"foo").unwrap();
            file.flush().unwrap();
        });
        t3.join().unwrap();
    }

    validate_recv(
        receiver,
        vec![(
            dst.to_str().unwrap().to_string(),
            StreamFlags::ITEM_MODIFIED | StreamFlags::ITEM_CREATED | StreamFlags::IS_FILE,
        )],
    );

    match _fsevent_ref_wrapper {
        Some(r) => async_fsevent.shutdown_observe(r),
        None => {}
    }
}
<commit_msg>Fix a rust-2021 warning<commit_after>#![cfg(target_os="macos")]
extern crate fsevent;
extern crate tempfile;
extern crate time;

use fsevent::*;
use std::fs;
use std::fs::read_link;
use std::fs::OpenOptions;
use std::io::Write;
use std::path::{Component, PathBuf};
use std::thread;
use std::time::{Duration, SystemTime};

use std::sync::mpsc::{channel, Receiver};

fn validate_recv(rx: Receiver<Event>, evs: Vec<(String, StreamFlags)>) {
    let timeout: Duration = Duration::new(5, 0);
    let deadline = SystemTime::now() + timeout;
    let mut evs = evs.clone();

    while SystemTime::now() < deadline {
        if let Ok(actual) = rx.try_recv() {
            let mut found: Option<usize> = None;
            for i in 0..evs.len() {
                let expected = evs.get(i).unwrap();
                if actual.path == expected.0 && actual.flag == expected.1 {
                    found = Some(i);
                    break;
                }
            }
            if let Some(i) = found {
                evs.remove(i);
            } else {
                panic!("actual: {:?} not found in expected: {:?}", actual, evs);
            }
        }
        if evs.is_empty() {
            break;
        }
    }
    assert!(
        evs.is_empty(),
        "Some expected events did not occur before the test timedout:\n\t\t{:?}",
        evs
    );
}

// TODO: replace with std::fs::canonicalize rust-lang/rust#27706.
fn resolve_path(path: &str) -> PathBuf {
    let mut out = PathBuf::new();
    let buf = PathBuf::from(path);
    for p in buf.components() {
        match p {
            Component::RootDir => out.push("/"),
            Component::Normal(osstr) => {
                out.push(osstr);
                if let Ok(real) = read_link(&out) {
                    if real.is_relative() {
                        out.pop();
                        out.push(real);
                    } else {
                        out = real;
                    }
                }
            }
            _ => (),
        }
    }
    out
}

#[test]
fn observe_folder_sync() {
    internal_observe_folder(false);
}

#[test]
fn observe_folder_async() {
    internal_observe_folder(true);
}

fn internal_observe_folder(run_async: bool) {
    let dir = tempfile::Builder::new().prefix("dur").tempdir().unwrap();
    // Resolve path so we don't have to worry about affect of symlinks on the test.
    let dst = resolve_path(dir.path().to_str().unwrap());

    let mut dst1 = dst.clone();
    dst1.push("dest1");

    let ddst1 = dst1.clone();
    fs::create_dir(dst1.as_path().to_str().unwrap()).unwrap();

    let mut dst2 = dst.clone();

    dst2.push("dest2");
    let ddst2 = dst2.clone();
    fs::create_dir(dst2.as_path().to_str().unwrap()).unwrap();

    let mut dst3 = dst.clone();

    dst3.push("dest3");
    let ddst3 = dst3.clone();
    fs::create_dir(dst3.as_path().to_str().unwrap()).unwrap();

    let (sender, receiver) = channel();

    let mut async_fsevent = fsevent::FsEvent::new(vec![]);
    let fsevent_ref_wrapper = if run_async {
        async_fsevent
            .append_path(dst1.as_path().to_str().unwrap())
            .unwrap();
        async_fsevent
            .append_path(dst2.as_path().to_str().unwrap())
            .unwrap();
        async_fsevent
            .append_path(dst3.as_path().to_str().unwrap())
            .unwrap();
        Some(async_fsevent.observe_async(sender).unwrap())
    } else {
        let _t = thread::spawn(move || {
            let mut fsevent = fsevent::FsEvent::new(vec![]);
            fsevent
                .append_path(dst1.as_path().to_str().unwrap())
                .unwrap();
            fsevent
                .append_path(dst2.as_path().to_str().unwrap())
                .unwrap();
            fsevent
                .append_path(dst3.as_path().to_str().unwrap())
                .unwrap();
            fsevent.observe(sender);
        });
        None
    };

    validate_recv(
        receiver,
        vec![
            (
                ddst1.to_str().unwrap().to_string(),
                StreamFlags::ITEM_CREATED | StreamFlags::IS_DIR,
            ),
            (
                ddst2.to_str().unwrap().to_string(),
                StreamFlags::ITEM_CREATED | StreamFlags::IS_DIR,
            ),
            (
                ddst3.to_str().unwrap().to_string(),
                StreamFlags::ITEM_CREATED | StreamFlags::IS_DIR,
            ),
        ],
    );

    match fsevent_ref_wrapper {
        Some(r) => async_fsevent.shutdown_observe(r),
        None => {}
    }
}

#[test]
fn validate_watch_single_file_sync() {
    internal_validate_watch_single_file(false);
}

#[test]
fn validate_watch_single_file_async() {
    internal_validate_watch_single_file(true);
}

fn internal_validate_watch_single_file(run_async: bool) {
    let dir = tempfile::Builder::new().prefix("dur").tempdir().unwrap();
    // Resolve path so we don't have to worry about affect of symlinks on the test.
    let mut dst = resolve_path(dir.path().to_str().unwrap());
    dst.push("out.txt");
    let (sender, receiver) = channel();

    let mut file = OpenOptions::new()
        .write(true)
        .create(true)
        .open(dst.clone().as_path())
        .unwrap();
    file.write_all(b"create").unwrap();
    file.flush().unwrap();
    drop(file);

    let mut async_fsevent = fsevent::FsEvent::new(vec![]);
    let _fsevent_ref_wrapper = if run_async {
        let dst = dst.clone();
        async_fsevent
            .append_path(dst.as_path().to_str().unwrap())
            .unwrap();
        Some(async_fsevent.observe_async(sender).unwrap())
    } else {
        let dst = dst.clone();
        let _t = thread::spawn(move || {
            let mut fsevent = fsevent::FsEvent::new(vec![]);
            fsevent
                .append_path(dst.as_path().to_str().unwrap())
                .unwrap();
            fsevent.observe(sender);
        });
        None
    };

    {
        let dst = dst.clone();
        let t3 = thread::spawn(move || {
            thread::sleep(Duration::new(15, 0)); // Wait another 500ms after observe.
            let mut file = OpenOptions::new()
                .write(true)
                .append(true)
                .open(dst.as_path())
                .unwrap();
            file.write_all(b"foo").unwrap();
            file.flush().unwrap();
        });
        t3.join().unwrap();
    }

    validate_recv(
        receiver,
        vec![(
            dst.to_str().unwrap().to_string(),
            StreamFlags::ITEM_MODIFIED | StreamFlags::ITEM_CREATED | StreamFlags::IS_FILE,
        )],
    );

    match _fsevent_ref_wrapper {
        Some(r) => async_fsevent.shutdown_observe(r),
        None => {}
    }
}
<|endoftext|>


<commit_before>extern crate rsoundio;
extern crate rci;

use rci::Ci;

use std::thread;
use std::time::Duration;

#[test]
fn test_outstream() {
    if Ci::new().is_some() {
        return
    }
    let sio = rsoundio::SoundIo::new();
    sio.connect_backend(rsoundio::SioBackend::Dummy).unwrap();
    let current_backend = sio.current_backend().unwrap();
    assert_eq!(current_backend, rsoundio::SioBackend::Dummy);
    sio.flush_events();
    let dev_idx = sio.default_output_device_index().unwrap();
    let dev = sio.output_device(dev_idx).unwrap();
    let mut stream = dev.create_outstream().unwrap();
    stream.open().unwrap();
    assert!(stream.sample_rate() > 0);
    let layout = stream.layout();
    assert_eq!(layout.channel_count(), 2);
    let cb = |out: rsoundio::OutStream, min_frame_count: u32, max_frame_count: u32| {
        let l: Vec<f32> = (0..max_frame_count as usize)
                              .map(|i| {
                                  match i % 2 == 0 {
                                      true => -1.0,
                                      false => 1.0,
                                  }
                              })
                              .collect();
        let r = l.clone();
        let frames = vec![l, r];
        let frames_written = out.write_stream_f32(min_frame_count, &frames).unwrap();
        assert!(frames_written > 0);
    };
    stream.register_write_callback(cb);
    let ucb = |_: rsoundio::OutStream| println!("Underflow!");
    stream.register_underflow_callback(ucb);
    let ecb = |_: rsoundio::OutStream, err: rsoundio::SioError| println!("Error: {}", err);
    stream.register_error_callback(ecb);
    stream.start().unwrap();
    thread::sleep(Duration::new(1, 0));
    assert!(stream.pause().is_none());
    thread::sleep(Duration::new(1, 0));
    assert!(stream.unpause().is_none());
    assert!(stream.latency().is_ok());
    assert!(stream.clear_buffer().is_none());
    thread::sleep(Duration::new(1, 0));
}
<commit_msg>Explicitly exit if stream test is run in a CI environment<commit_after>extern crate rsoundio;
extern crate rci;

use rci::Ci;

use std::thread;
use std::time::Duration;

#[test]
fn test_outstream() {
    if Ci::new().is_some() {
        ::std::process::exit(0)
    }
    let sio = rsoundio::SoundIo::new();
    sio.connect_backend(rsoundio::SioBackend::Dummy).unwrap();
    let current_backend = sio.current_backend().unwrap();
    assert_eq!(current_backend, rsoundio::SioBackend::Dummy);
    sio.flush_events();
    let dev_idx = sio.default_output_device_index().unwrap();
    let dev = sio.output_device(dev_idx).unwrap();
    let mut stream = dev.create_outstream().unwrap();
    stream.open().unwrap();
    assert!(stream.sample_rate() > 0);
    let layout = stream.layout();
    assert_eq!(layout.channel_count(), 2);
    let cb = |out: rsoundio::OutStream, min_frame_count: u32, max_frame_count: u32| {
        let l: Vec<f32> = (0..max_frame_count as usize)
                              .map(|i| {
                                  match i % 2 == 0 {
                                      true => -1.0,
                                      false => 1.0,
                                  }
                              })
                              .collect();
        let r = l.clone();
        let frames = vec![l, r];
        let frames_written = out.write_stream_f32(min_frame_count, &frames).unwrap();
        assert!(frames_written > 0);
    };
    stream.register_write_callback(cb);
    let ucb = |_: rsoundio::OutStream| println!("Underflow!");
    stream.register_underflow_callback(ucb);
    let ecb = |_: rsoundio::OutStream, err: rsoundio::SioError| println!("Error: {}", err);
    stream.register_error_callback(ecb);
    stream.start().unwrap();
    thread::sleep(Duration::new(1, 0));
    assert!(stream.pause().is_none());
    thread::sleep(Duration::new(1, 0));
    assert!(stream.unpause().is_none());
    assert!(stream.latency().is_ok());
    assert!(stream.clear_buffer().is_none());
    thread::sleep(Duration::new(1, 0));
}
<|endoftext|>


<commit_before>use stm32f0x2::{TIM2, TIM3, GPIOA, GPIOB, GPIOC, RCC};

use cortex_m;

static mut FREQ: u32 = 0;
static mut DUTY: f64 = 0.0;
const FREQUENCY: u32 = 48_000_000;

// PWM channels : Pins available
pub enum Pin {
    PA0,
    PB3,
    PB4,
    PB5,
    PB10,
    PB11,
    PC6,
    PC7,
    PC8,
    PC9,
}

pub struct Pwm {
    pin: Pin,
}

impl Pwm {
    pub fn init(pin: Pin) -> Pwm {
        cortex_m::interrupt::free(|cs| {
            let rcc = RCC.borrow(cs);
            let tim2 = TIM2.borrow(cs);
            let tim3 = TIM3.borrow(cs);

            let gpioa = GPIOA.borrow(cs);
            let gpiob = GPIOB.borrow(cs);
            let gpioc = GPIOC.borrow(cs);

            // GPIOA, GPIOB and GPIOC Clock Activated
            rcc.ahbenr
                .modify(|_, w| w.iopaen().enabled().iopben().enabled().iopcen().enabled());
            // TIMER Clock Activated
            rcc.apb1enr.modify(|_, w| w.tim2en().enabled());
            rcc.apb1enr.modify(|_, w| w.tim3en().enabled());

            match pin {
                Pin::PA0 => {
                    gpioa.moder.modify(|_, w| w.moder0().alternate());
                    gpioa.afrl.modify(|_, w| w.afrl0().af2());
                    gpioa.otyper.modify(|_, w| w.ot0().push_pull());
                    tim2.ccmr1_output
                        .modify(|_, w| w.oc1m().pwmmode1().oc1pe().enabled());
                    tim2.ccer.modify(|_, w| w.cc1p().clear_bit());
                    tim2.ccer.modify(|_, w| w.cc1e().active());
                }
                Pin::PB3 => {
                    gpiob.moder.modify(|_, w| w.moder3().alternate());
                    gpiob.afrl.modify(|_, w| w.afrl3().af2());
                    gpiob.otyper.modify(|_, w| w.ot3().push_pull());
                    tim2.ccmr1_output
                        .modify(|_, w| w.oc2m().pwmmode1().oc2pe().enabled());
                    tim2.ccer.modify(|_, w| w.cc2p().clear_bit());
                    tim2.ccer.modify(|_, w| w.cc2e().active());
                }
                Pin::PB10 => {
                    gpiob.moder.modify(|_, w| w.moder10().alternate());
                    gpiob.afrh.modify(|_, w| w.afrh10().af2());
                    gpiob.otyper.modify(|_, w| w.ot10().push_pull());
                    tim2.ccmr2_output
                        .modify(|_, w| w.oc3m().pwmmode1().oc3pe().enabled());
                    tim2.ccer.modify(|_, w| w.cc3p().clear_bit());
                    tim2.ccer.modify(|_, w| w.cc3e().active());
                }
                Pin::PB11 => {
                    gpiob.moder.modify(|_, w| w.moder11().alternate());
                    gpiob.afrh.modify(|_, w| w.afrh11().af2());
                    gpiob.otyper.modify(|_, w| w.ot11().push_pull());
                    tim2.ccmr2_output
                        .modify(|_, w| w.oc4m().pwmmode1().oc4pe().enabled());
                    tim2.ccer.modify(|_, w| w.cc4p().clear_bit());
                    tim2.ccer.modify(|_, w| w.cc4e().active());
                }
                Pin::PB4 => {
                    gpiob.moder.modify(|_, w| w.moder4().alternate());
                    gpiob.afrl.modify(|_, w| w.afrl4().af1());
                    gpiob.otyper.modify(|_, w| w.ot4().push_pull());
                    tim3.ccmr1_output
                        .modify(|_, w| w.oc1m().pwmmode1().oc1pe().enabled());
                    tim3.ccer.modify(|_, w| w.cc1p().clear_bit());
                    tim3.ccer.modify(|_, w| w.cc1e().active());
                }
                Pin::PB5 => {
                    gpiob.moder.modify(|_, w| w.moder5().alternate());
                    gpiob.afrl.modify(|_, w| w.afrl5().af1());
                    gpiob.otyper.modify(|_, w| w.ot5().push_pull());
                    tim3.ccmr1_output
                        .modify(|_, w| w.oc2m().pwmmode1().oc2pe().enabled());
                    tim3.ccer.modify(|_, w| w.cc2p().clear_bit());
                    tim3.ccer.modify(|_, w| w.cc2e().active());
                }
                Pin::PC6 => {
                    gpioc.moder.modify(|_, w| w.moder6().alternate());
                    gpioc.afrl.modify(|_, w| w.afrl6().af0());
                    gpioc.otyper.modify(|_, w| w.ot6().push_pull());
                    tim3.ccmr1_output
                        .modify(|_, w| w.oc1m().pwmmode1().oc1pe().enabled());
                    tim3.ccer.modify(|_, w| w.cc1p().clear_bit());
                    tim3.ccer.modify(|_, w| w.cc1e().active());
                }
                Pin::PC7 => {
                    gpioc.moder.modify(|_, w| w.moder7().alternate());
                    gpioc.afrl.modify(|_, w| w.afrl7().af0());
                    gpioc.otyper.modify(|_, w| w.ot7().push_pull());
                    tim3.ccmr1_output
                        .modify(|_, w| w.oc2m().pwmmode1().oc2pe().enabled());
                    tim3.ccer.modify(|_, w| w.cc2p().clear_bit());
                    tim3.ccer.modify(|_, w| w.cc2e().active());
                }
                Pin::PC8 => {
                    gpioc.moder.modify(|_, w| w.moder8().alternate());
                    gpioc.afrh.modify(|_, w| w.afrh8().af0());
                    gpioc.otyper.modify(|_, w| w.ot8().push_pull());
                    tim3.ccmr2_output
                        .modify(|_, w| w.oc3m().pwmmode1().oc3pe().enabled());
                    tim3.ccer.modify(|_, w| w.cc3p().clear_bit());
                    tim3.ccer.modify(|_, w| w.cc3e().active());
                }
                Pin::PC9 => {
                    gpioc.moder.modify(|_, w| w.moder9().alternate());
                    gpioc.afrh.modify(|_, w| w.afrh9().af0());
                    gpioc.otyper.modify(|_, w| w.ot9().push_pull());
                    tim3.ccmr2_output
                        .modify(|_, w| w.oc4m().pwmmode1().oc4pe().enabled());
                    tim3.ccer.modify(|_, w| w.cc4p().clear_bit());
                    tim3.ccer.modify(|_, w| w.cc4e().active());
                }
            }

            tim2.cr1.write(|w| {
                w.cms()
                    .center_align_mode1()
                    .dir()
                    .up()
                    .opm()
                    .continuous()
                    .cen()
                    .enabled()
            });
            tim2.egr.write(|w| w.ug().set_bit());

            tim3.cr1.write(|w| {
                w.cms()
                    .center_align_mode1()
                    .dir()
                    .up()
                    .opm()
                    .continuous()
                    .cen()
                    .enabled()
            });
            tim3.egr.write(|w| w.ug().set_bit());
        });
        Pwm { pin }
    }

    // Be careful, after you have set frequency, it will be necessary to set all duty cycles of others PWMs
    pub fn set_frequency(&self, frequency: u32) {
        cortex_m::interrupt::free(|cs| {
            let tim2 = TIM2.borrow(cs);
            let tim3 = TIM3.borrow(cs);

            // Set Prescaler Register - 16 bits
            const PRE_SCALER: u16 = ((FREQUENCY / (1_000_000 * 2)) - 1) as u16;
            tim2.psc.write(|w| w.psc().bits(PRE_SCALER));
            tim3.psc.write(|w| w.psc().bits(PRE_SCALER)); // Counter clock Frequency = (fCK_PSC / (PSC[15:0] + 1)

            // Set Auto-Reload register - 16 bits
            let arr = 1000000 / frequency; //1000000
            tim3.arr.write(|w| w.arr_h().bits((arr >> 16) as u16));
            tim3.arr.write(|w| w.arr_l().bits(arr as u16));
            tim2.arr.write(|w| w.arr_h().bits((arr >> 16) as u16));
            tim2.arr.write(|w| w.arr_l().bits(arr as u16));

            unsafe {
                FREQ = frequency;
            }
            unsafe {
                self.set_duty(DUTY);
            }

            // Reset counter
            tim2.cnt.write(|w| w.cnt_h().bits(0));
            tim2.cnt.write(|w| w.cnt_l().bits(0));
            tim3.cnt.write(|w| w.cnt_h().bits(0));
            tim3.cnt.write(|w| w.cnt_l().bits(0));
        });
    }

    pub fn enable(&self) {
        cortex_m::interrupt::free(|cs| {
            let tim2 = TIM2.borrow(cs);
            let tim3 = TIM3.borrow(cs);
            match self.pin {
                Pin::PA0 => tim2.ccer.modify(|_, w| w.cc1e().set_bit()),
                Pin::PB3 => tim2.ccer.modify(|_, w| w.cc2e().set_bit()),
                Pin::PB10 => tim2.ccer.modify(|_, w| w.cc3e().set_bit()),
                Pin::PB11 => tim2.ccer.modify(|_, w| w.cc4e().set_bit()),
                Pin::PB4 => tim3.ccer.modify(|_, w| w.cc1e().set_bit()),
                Pin::PB5 => tim3.ccer.modify(|_, w| w.cc2e().set_bit()),
                Pin::PC6 => tim3.ccer.modify(|_, w| w.cc1e().set_bit()),
                Pin::PC7 => tim3.ccer.modify(|_, w| w.cc2e().set_bit()),
                Pin::PC8 => tim3.ccer.modify(|_, w| w.cc3e().set_bit()),
                Pin::PC9 => tim3.ccer.modify(|_, w| w.cc4e().set_bit()),
            }
        });
    }

    pub fn set_duty(&self, duty: f64) {
        cortex_m::interrupt::free(|cs| {
            let tim2 = TIM2.borrow(cs);
            let tim3 = TIM3.borrow(cs);
            unsafe {
                let ccr_value = (((1000000.0 / FREQ as f64) / 100.0) * duty) as u32;
                DUTY = duty;
                match self.pin {
                    Pin::PA0 => tim2.ccr1.write(|w| {
                        w.ccr1_l()
                            .bits((ccr_value) as u16)
                            .ccr1_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PB3 => tim2.ccr2.write(|w| {
                        w.ccr2_l()
                            .bits((ccr_value) as u16)
                            .ccr2_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PB10 => tim2.ccr3.write(|w| {
                        w.ccr3_l()
                            .bits((ccr_value) as u16)
                            .ccr3_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PB11 => tim2.ccr4.write(|w| {
                        w.ccr4_l()
                            .bits((ccr_value) as u16)
                            .ccr4_h()
                            .bits((ccr_value >> 16) as u16)
                    }),

                    Pin::PB4 => tim3.ccr1.write(|w| {
                        w.ccr1_l()
                            .bits((ccr_value) as u16)
                            .ccr1_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PB5 => tim3.ccr2.write(|w| {
                        w.ccr2_l()
                            .bits((ccr_value) as u16)
                            .ccr2_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PC6 => tim3.ccr1.write(|w| {
                        w.ccr1_l()
                            .bits((ccr_value) as u16)
                            .ccr1_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PC7 => tim3.ccr2.write(|w| {
                        w.ccr2_l()
                            .bits((ccr_value) as u16)
                            .ccr2_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PC8 => tim3.ccr3.write(|w| {
                        w.ccr3_l()
                            .bits((ccr_value) as u16)
                            .ccr3_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PC9 => tim3.ccr4.write(|w| {
                        w.ccr4_l()
                            .bits((ccr_value) as u16)
                            .ccr4_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                }
            }
        });
    }
}
<commit_msg>Add some frequency check in pwm.<commit_after>use stm32f0x2::{TIM2, TIM3, GPIOA, GPIOB, GPIOC, RCC};

use cortex_m;

static mut FREQ: u32 = 0;
static mut DUTY: f64 = 0.0;
const FREQUENCY: u32 = 48_000_000;

// PWM channels : Pins available
pub enum Pin {
    PA0,
    PB3,
    PB4,
    PB5,
    PB10,
    PB11,
    PC6,
    PC7,
    PC8,
    PC9,
}

pub struct Pwm {
    pin: Pin,
}

impl Pwm {
    pub fn init(pin: Pin) -> Pwm {
        cortex_m::interrupt::free(|cs| {
            let rcc = RCC.borrow(cs);
            let tim2 = TIM2.borrow(cs);
            let tim3 = TIM3.borrow(cs);

            let gpioa = GPIOA.borrow(cs);
            let gpiob = GPIOB.borrow(cs);
            let gpioc = GPIOC.borrow(cs);

            // GPIOA, GPIOB and GPIOC Clock Activated
            rcc.ahbenr
                .modify(|_, w| w.iopaen().enabled().iopben().enabled().iopcen().enabled());
            // TIMER Clock Activated
            rcc.apb1enr.modify(|_, w| w.tim2en().enabled());
            rcc.apb1enr.modify(|_, w| w.tim3en().enabled());

            match pin {
                Pin::PA0 => {
                    gpioa.moder.modify(|_, w| w.moder0().alternate());
                    gpioa.afrl.modify(|_, w| w.afrl0().af2());
                    gpioa.otyper.modify(|_, w| w.ot0().push_pull());
                    tim2.ccmr1_output
                        .modify(|_, w| w.oc1m().pwmmode1().oc1pe().enabled());
                    tim2.ccer.modify(|_, w| w.cc1p().clear_bit());
                    tim2.ccer.modify(|_, w| w.cc1e().active());
                }
                Pin::PB3 => {
                    gpiob.moder.modify(|_, w| w.moder3().alternate());
                    gpiob.afrl.modify(|_, w| w.afrl3().af2());
                    gpiob.otyper.modify(|_, w| w.ot3().push_pull());
                    tim2.ccmr1_output
                        .modify(|_, w| w.oc2m().pwmmode1().oc2pe().enabled());
                    tim2.ccer.modify(|_, w| w.cc2p().clear_bit());
                    tim2.ccer.modify(|_, w| w.cc2e().active());
                }
                Pin::PB10 => {
                    gpiob.moder.modify(|_, w| w.moder10().alternate());
                    gpiob.afrh.modify(|_, w| w.afrh10().af2());
                    gpiob.otyper.modify(|_, w| w.ot10().push_pull());
                    tim2.ccmr2_output
                        .modify(|_, w| w.oc3m().pwmmode1().oc3pe().enabled());
                    tim2.ccer.modify(|_, w| w.cc3p().clear_bit());
                    tim2.ccer.modify(|_, w| w.cc3e().active());
                }
                Pin::PB11 => {
                    gpiob.moder.modify(|_, w| w.moder11().alternate());
                    gpiob.afrh.modify(|_, w| w.afrh11().af2());
                    gpiob.otyper.modify(|_, w| w.ot11().push_pull());
                    tim2.ccmr2_output
                        .modify(|_, w| w.oc4m().pwmmode1().oc4pe().enabled());
                    tim2.ccer.modify(|_, w| w.cc4p().clear_bit());
                    tim2.ccer.modify(|_, w| w.cc4e().active());
                }
                Pin::PB4 => {
                    gpiob.moder.modify(|_, w| w.moder4().alternate());
                    gpiob.afrl.modify(|_, w| w.afrl4().af1());
                    gpiob.otyper.modify(|_, w| w.ot4().push_pull());
                    tim3.ccmr1_output
                        .modify(|_, w| w.oc1m().pwmmode1().oc1pe().enabled());
                    tim3.ccer.modify(|_, w| w.cc1p().clear_bit());
                    tim3.ccer.modify(|_, w| w.cc1e().active());
                }
                Pin::PB5 => {
                    gpiob.moder.modify(|_, w| w.moder5().alternate());
                    gpiob.afrl.modify(|_, w| w.afrl5().af1());
                    gpiob.otyper.modify(|_, w| w.ot5().push_pull());
                    tim3.ccmr1_output
                        .modify(|_, w| w.oc2m().pwmmode1().oc2pe().enabled());
                    tim3.ccer.modify(|_, w| w.cc2p().clear_bit());
                    tim3.ccer.modify(|_, w| w.cc2e().active());
                }
                Pin::PC6 => {
                    gpioc.moder.modify(|_, w| w.moder6().alternate());
                    gpioc.afrl.modify(|_, w| w.afrl6().af0());
                    gpioc.otyper.modify(|_, w| w.ot6().push_pull());
                    tim3.ccmr1_output
                        .modify(|_, w| w.oc1m().pwmmode1().oc1pe().enabled());
                    tim3.ccer.modify(|_, w| w.cc1p().clear_bit());
                    tim3.ccer.modify(|_, w| w.cc1e().active());
                }
                Pin::PC7 => {
                    gpioc.moder.modify(|_, w| w.moder7().alternate());
                    gpioc.afrl.modify(|_, w| w.afrl7().af0());
                    gpioc.otyper.modify(|_, w| w.ot7().push_pull());
                    tim3.ccmr1_output
                        .modify(|_, w| w.oc2m().pwmmode1().oc2pe().enabled());
                    tim3.ccer.modify(|_, w| w.cc2p().clear_bit());
                    tim3.ccer.modify(|_, w| w.cc2e().active());
                }
                Pin::PC8 => {
                    gpioc.moder.modify(|_, w| w.moder8().alternate());
                    gpioc.afrh.modify(|_, w| w.afrh8().af0());
                    gpioc.otyper.modify(|_, w| w.ot8().push_pull());
                    tim3.ccmr2_output
                        .modify(|_, w| w.oc3m().pwmmode1().oc3pe().enabled());
                    tim3.ccer.modify(|_, w| w.cc3p().clear_bit());
                    tim3.ccer.modify(|_, w| w.cc3e().active());
                }
                Pin::PC9 => {
                    gpioc.moder.modify(|_, w| w.moder9().alternate());
                    gpioc.afrh.modify(|_, w| w.afrh9().af0());
                    gpioc.otyper.modify(|_, w| w.ot9().push_pull());
                    tim3.ccmr2_output
                        .modify(|_, w| w.oc4m().pwmmode1().oc4pe().enabled());
                    tim3.ccer.modify(|_, w| w.cc4p().clear_bit());
                    tim3.ccer.modify(|_, w| w.cc4e().active());
                }
            }

            tim2.cr1.write(|w| {
                w.cms()
                    .center_align_mode1()
                    .dir()
                    .up()
                    .opm()
                    .continuous()
                    .cen()
                    .enabled()
            });
            tim2.egr.write(|w| w.ug().set_bit());

            tim3.cr1.write(|w| {
                w.cms()
                    .center_align_mode1()
                    .dir()
                    .up()
                    .opm()
                    .continuous()
                    .cen()
                    .enabled()
            });
            tim3.egr.write(|w| w.ug().set_bit());
        });
        Pwm { pin }
    }

    // Be careful, after you have set frequency, it will be necessary to set all duty cycles of others PWMs
    pub fn set_frequency(&self, frequency: u32) {
        assert!(frequency >= 50, "frequency too low!");
        assert!(frequency <= 100_000, "frequency too high!");

        cortex_m::interrupt::free(|cs| {
            let tim2 = TIM2.borrow(cs);
            let tim3 = TIM3.borrow(cs);

            // Set Prescaler Register - 16 bits
            const PRE_SCALER: u16 = ((FREQUENCY / (1_000_000 * 2)) - 1) as u16;
            tim2.psc.write(|w| w.psc().bits(PRE_SCALER));
            tim3.psc.write(|w| w.psc().bits(PRE_SCALER)); // Counter clock Frequency = (fCK_PSC / (PSC[15:0] + 1)

            // Set Auto-Reload register - 16 bits
            let arr = 1_000_000 / frequency; //1000000
            tim3.arr.write(|w| w.arr_h().bits((arr >> 16) as u16));
            tim3.arr.write(|w| w.arr_l().bits(arr as u16));
            tim2.arr.write(|w| w.arr_h().bits((arr >> 16) as u16));
            tim2.arr.write(|w| w.arr_l().bits(arr as u16));

            unsafe {
                FREQ = frequency;
            }
            unsafe {
                self.set_duty(DUTY);
            }

            // Reset counter
            tim2.cnt.write(|w| w.cnt_h().bits(0));
            tim2.cnt.write(|w| w.cnt_l().bits(0));
            tim3.cnt.write(|w| w.cnt_h().bits(0));
            tim3.cnt.write(|w| w.cnt_l().bits(0));
        });
    }

    pub fn enable(&self) {
        cortex_m::interrupt::free(|cs| {
            let tim2 = TIM2.borrow(cs);
            let tim3 = TIM3.borrow(cs);
            match self.pin {
                Pin::PA0 => tim2.ccer.modify(|_, w| w.cc1e().set_bit()),
                Pin::PB3 => tim2.ccer.modify(|_, w| w.cc2e().set_bit()),
                Pin::PB10 => tim2.ccer.modify(|_, w| w.cc3e().set_bit()),
                Pin::PB11 => tim2.ccer.modify(|_, w| w.cc4e().set_bit()),
                Pin::PB4 => tim3.ccer.modify(|_, w| w.cc1e().set_bit()),
                Pin::PB5 => tim3.ccer.modify(|_, w| w.cc2e().set_bit()),
                Pin::PC6 => tim3.ccer.modify(|_, w| w.cc1e().set_bit()),
                Pin::PC7 => tim3.ccer.modify(|_, w| w.cc2e().set_bit()),
                Pin::PC8 => tim3.ccer.modify(|_, w| w.cc3e().set_bit()),
                Pin::PC9 => tim3.ccer.modify(|_, w| w.cc4e().set_bit()),
            }
        });
    }

    pub fn set_duty(&self, duty: f64) {
        cortex_m::interrupt::free(|cs| {
            let tim2 = TIM2.borrow(cs);
            let tim3 = TIM3.borrow(cs);
            unsafe {
                let ccr_value = (((1000000.0 / FREQ as f64) / 100.0) * duty) as u32;
                DUTY = duty;
                match self.pin {
                    Pin::PA0 => tim2.ccr1.write(|w| {
                        w.ccr1_l()
                            .bits((ccr_value) as u16)
                            .ccr1_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PB3 => tim2.ccr2.write(|w| {
                        w.ccr2_l()
                            .bits((ccr_value) as u16)
                            .ccr2_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PB10 => tim2.ccr3.write(|w| {
                        w.ccr3_l()
                            .bits((ccr_value) as u16)
                            .ccr3_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PB11 => tim2.ccr4.write(|w| {
                        w.ccr4_l()
                            .bits((ccr_value) as u16)
                            .ccr4_h()
                            .bits((ccr_value >> 16) as u16)
                    }),

                    Pin::PB4 => tim3.ccr1.write(|w| {
                        w.ccr1_l()
                            .bits((ccr_value) as u16)
                            .ccr1_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PB5 => tim3.ccr2.write(|w| {
                        w.ccr2_l()
                            .bits((ccr_value) as u16)
                            .ccr2_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PC6 => tim3.ccr1.write(|w| {
                        w.ccr1_l()
                            .bits((ccr_value) as u16)
                            .ccr1_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PC7 => tim3.ccr2.write(|w| {
                        w.ccr2_l()
                            .bits((ccr_value) as u16)
                            .ccr2_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PC8 => tim3.ccr3.write(|w| {
                        w.ccr3_l()
                            .bits((ccr_value) as u16)
                            .ccr3_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                    Pin::PC9 => tim3.ccr4.write(|w| {
                        w.ccr4_l()
                            .bits((ccr_value) as u16)
                            .ccr4_h()
                            .bits((ccr_value >> 16) as u16)
                    }),
                }
            }
        });
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate crossbeam;
extern crate ipc_channel;
extern crate test;

use ipc_channel::platform;

use std::sync::{mpsc, Mutex};

/// Allows doing multiple inner iterations per bench.iter() run.
///
/// This is mostly to amortise the overhead of spawning a thread in the benchmark
/// when sending larger messages (that might be fragmented).
///
/// Note that you need to compensate the displayed results
/// for the proportionally longer runs yourself,
/// as the benchmark framework doesn't know about the inner iterations...
const ITERATIONS: usize = 1;

#[bench]
fn create_channel(b: &mut test::Bencher) {
    b.iter(|| {
        for _ in 0..ITERATIONS {
            platform::channel().unwrap();
        }
    });
}

fn bench_size(b: &mut test::Bencher, size: usize) {
    let data: Vec<u8> = (0..size).map(|i| (i % 251) as u8).collect();
    let (tx, rx) = platform::channel().unwrap();

    let (wait_tx, wait_rx) = mpsc::channel();
    let wait_rx = Mutex::new(wait_rx);

    if size > platform::OsIpcSender::get_max_fragment_size() {
        b.iter(|| {
            crossbeam::scope(|scope| {
                scope.spawn(|| {
                    let wait_rx = wait_rx.lock().unwrap();
                    for _ in 0..ITERATIONS {
                        tx.send(&data, vec![], vec![]).unwrap();
                        if ITERATIONS > 1 {
                            // Prevent beginning of the next send
                            // from overlapping with receive of last fragment,
                            // as otherwise results of runs with a large tail fragment
                            // are significantly skewed.
                            wait_rx.recv().unwrap();
                        }
                    }
                });
                for _ in 0..ITERATIONS {
                    rx.recv().unwrap();
                    if ITERATIONS > 1 {
                        wait_tx.send(()).unwrap();
                    }
                }
                // For reasons mysterious to me,
                // not returning a value *from every branch*
                // adds some 100 ns or so of overhead to all results --
                // which is quite significant for very short tests...
                0
            })
        });
    } else {
        b.iter(|| {
            for _ in 0..ITERATIONS {
                tx.send(&data, vec![], vec![]).unwrap();
                rx.recv().unwrap();
            }
            0
        });
    }
}

#[bench]
fn size_00_1(b: &mut test::Bencher) {
    bench_size(b, 1);
}
#[bench]
fn size_01_2(b: &mut test::Bencher) {
    bench_size(b, 2);
}
#[bench]
fn size_02_4(b: &mut test::Bencher) {
    bench_size(b, 4);
}
#[bench]
fn size_03_8(b: &mut test::Bencher) {
    bench_size(b, 8);
}
#[bench]
fn size_04_16(b: &mut test::Bencher) {
    bench_size(b, 16);
}
#[bench]
fn size_05_32(b: &mut test::Bencher) {
    bench_size(b, 32);
}
#[bench]
fn size_06_64(b: &mut test::Bencher) {
    bench_size(b, 64);
}
#[bench]
fn size_07_128(b: &mut test::Bencher) {
    bench_size(b, 128);
}
#[bench]
fn size_08_256(b: &mut test::Bencher) {
    bench_size(b, 256);
}
#[bench]
fn size_09_512(b: &mut test::Bencher) {
    bench_size(b, 512);
}
#[bench]
fn size_10_1k(b: &mut test::Bencher) {
    bench_size(b, 1 * 1024);
}
#[bench]
fn size_11_2k(b: &mut test::Bencher) {
    bench_size(b, 2 * 1024);
}
#[bench]
fn size_12_4k(b: &mut test::Bencher) {
    bench_size(b, 4 * 1024);
}
#[bench]
fn size_13_8k(b: &mut test::Bencher) {
    bench_size(b, 8 * 1024);
}
#[bench]
fn size_14_16k(b: &mut test::Bencher) {
    bench_size(b, 16 * 1024);
}
#[bench]
fn size_15_32k(b: &mut test::Bencher) {
    bench_size(b, 32 * 1024);
}
#[bench]
fn size_16_64k(b: &mut test::Bencher) {
    bench_size(b, 64 * 1024);
}
#[bench]
fn size_17_128k(b: &mut test::Bencher) {
    bench_size(b, 128 * 1024);
}
#[bench]
fn size_18_256k(b: &mut test::Bencher) {
    bench_size(b, 256 * 1024);
}
#[bench]
fn size_19_512k(b: &mut test::Bencher) {
    bench_size(b, 512 * 1024);
}
#[bench]
fn size_20_1m(b: &mut test::Bencher) {
    bench_size(b, 1 * 1024 * 1024);
}
#[bench]
fn size_21_2m(b: &mut test::Bencher) {
    bench_size(b, 2 * 1024 * 1024);
}
#[bench]
fn size_22_4m(b: &mut test::Bencher) {
    bench_size(b, 4 * 1024 * 1024);
}
#[bench]
fn size_23_8m(b: &mut test::Bencher) {
    bench_size(b, 8 * 1024 * 1024);
}
<commit_msg>Fix benchmarks with `OsIpcReceiver` not being `Sync` anymore<commit_after>#![feature(test)]

extern crate crossbeam;
extern crate ipc_channel;
extern crate test;

use ipc_channel::platform;

use std::sync::{mpsc, Mutex};

/// Allows doing multiple inner iterations per bench.iter() run.
///
/// This is mostly to amortise the overhead of spawning a thread in the benchmark
/// when sending larger messages (that might be fragmented).
///
/// Note that you need to compensate the displayed results
/// for the proportionally longer runs yourself,
/// as the benchmark framework doesn't know about the inner iterations...
const ITERATIONS: usize = 1;

#[bench]
fn create_channel(b: &mut test::Bencher) {
    b.iter(|| {
        for _ in 0..ITERATIONS {
            platform::channel().unwrap();
        }
    });
}

fn bench_size(b: &mut test::Bencher, size: usize) {
    let data: Vec<u8> = (0..size).map(|i| (i % 251) as u8).collect();
    let (tx, rx) = platform::channel().unwrap();

    let (wait_tx, wait_rx) = mpsc::channel();
    let wait_rx = Mutex::new(wait_rx);

    if size > platform::OsIpcSender::get_max_fragment_size() {
        b.iter(|| {
            crossbeam::scope(|scope| {
                let tx = tx.clone();
                scope.spawn(|| {
                    let wait_rx = wait_rx.lock().unwrap();
                    let tx = tx;
                    for _ in 0..ITERATIONS {
                        tx.send(&data, vec![], vec![]).unwrap();
                        if ITERATIONS > 1 {
                            // Prevent beginning of the next send
                            // from overlapping with receive of last fragment,
                            // as otherwise results of runs with a large tail fragment
                            // are significantly skewed.
                            wait_rx.recv().unwrap();
                        }
                    }
                });
                for _ in 0..ITERATIONS {
                    rx.recv().unwrap();
                    if ITERATIONS > 1 {
                        wait_tx.send(()).unwrap();
                    }
                }
                // For reasons mysterious to me,
                // not returning a value *from every branch*
                // adds some 100 ns or so of overhead to all results --
                // which is quite significant for very short tests...
                0
            })
        });
    } else {
        b.iter(|| {
            for _ in 0..ITERATIONS {
                tx.send(&data, vec![], vec![]).unwrap();
                rx.recv().unwrap();
            }
            0
        });
    }
}

#[bench]
fn size_00_1(b: &mut test::Bencher) {
    bench_size(b, 1);
}
#[bench]
fn size_01_2(b: &mut test::Bencher) {
    bench_size(b, 2);
}
#[bench]
fn size_02_4(b: &mut test::Bencher) {
    bench_size(b, 4);
}
#[bench]
fn size_03_8(b: &mut test::Bencher) {
    bench_size(b, 8);
}
#[bench]
fn size_04_16(b: &mut test::Bencher) {
    bench_size(b, 16);
}
#[bench]
fn size_05_32(b: &mut test::Bencher) {
    bench_size(b, 32);
}
#[bench]
fn size_06_64(b: &mut test::Bencher) {
    bench_size(b, 64);
}
#[bench]
fn size_07_128(b: &mut test::Bencher) {
    bench_size(b, 128);
}
#[bench]
fn size_08_256(b: &mut test::Bencher) {
    bench_size(b, 256);
}
#[bench]
fn size_09_512(b: &mut test::Bencher) {
    bench_size(b, 512);
}
#[bench]
fn size_10_1k(b: &mut test::Bencher) {
    bench_size(b, 1 * 1024);
}
#[bench]
fn size_11_2k(b: &mut test::Bencher) {
    bench_size(b, 2 * 1024);
}
#[bench]
fn size_12_4k(b: &mut test::Bencher) {
    bench_size(b, 4 * 1024);
}
#[bench]
fn size_13_8k(b: &mut test::Bencher) {
    bench_size(b, 8 * 1024);
}
#[bench]
fn size_14_16k(b: &mut test::Bencher) {
    bench_size(b, 16 * 1024);
}
#[bench]
fn size_15_32k(b: &mut test::Bencher) {
    bench_size(b, 32 * 1024);
}
#[bench]
fn size_16_64k(b: &mut test::Bencher) {
    bench_size(b, 64 * 1024);
}
#[bench]
fn size_17_128k(b: &mut test::Bencher) {
    bench_size(b, 128 * 1024);
}
#[bench]
fn size_18_256k(b: &mut test::Bencher) {
    bench_size(b, 256 * 1024);
}
#[bench]
fn size_19_512k(b: &mut test::Bencher) {
    bench_size(b, 512 * 1024);
}
#[bench]
fn size_20_1m(b: &mut test::Bencher) {
    bench_size(b, 1 * 1024 * 1024);
}
#[bench]
fn size_21_2m(b: &mut test::Bencher) {
    bench_size(b, 2 * 1024 * 1024);
}
#[bench]
fn size_22_4m(b: &mut test::Bencher) {
    bench_size(b, 4 * 1024 * 1024);
}
#[bench]
fn size_23_8m(b: &mut test::Bencher) {
    bench_size(b, 8 * 1024 * 1024);
}
<|endoftext|>