<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use consensus_types::block::block_test_utils;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use libra_crypto::{ed25519::Ed25519PrivateKey, Uniform};
use libra_secure_storage::{InMemoryStorage, OnDiskStorage, Storage};
use libra_types::validator_signer::ValidatorSigner;
use safety_rules::{
    test_utils, PersistentSafetyStorage,
    SafetyRulesManager, TSafetyRules,
};
use tempfile::NamedTempFile;

/// Execute an in order series of blocks (0 <- 1 <- 2 <- 3 and commit 0 and continue to rotate
/// left, appending new blocks on the right, committing the left most block
fn lsr(mut safety_rules: Box<dyn TSafetyRules>, signer: ValidatorSigner, n: u64) {
    let data = block_test_utils::random_payload(1);

    let (proof, genesis_qc) = test_utils::make_genesis(&signer);
    safety_rules.initialize(&proof).unwrap();

    let mut round = genesis_qc.certified_block().round();

    round += 1;
    let mut b0 = test_utils::make_proposal_with_qc(round, genesis_qc, &signer, None);
    safety_rules.construct_and_sign_vote(&b0).unwrap();

    round += 1;
    let mut b1 =
        test_utils::make_proposal_with_parent(data.clone(), round, &b0, None, &signer, None);
    safety_rules.construct_and_sign_vote(&b1).unwrap();

    round += 1;
    let mut b2 =
        test_utils::make_proposal_with_parent(data.clone(), round, &b1, None, &signer, None);
    safety_rules.construct_and_sign_vote(&b2).unwrap();

    for _i in 0..n {
        round += 1;
        let b3 = test_utils::make_proposal_with_parent(
            data.clone(),
            round,
            &b2,
            Some(&b0),
            &signer,
            None,
        );

        safety_rules.construct_and_sign_vote(&b3).unwrap();

        b0 = b1;
        b1 = b2;
        b2 = b3;
    }
}

fn in_memory(n: u64) {
    let signer = ValidatorSigner::from_int(0);
    let waypoint = test_utils::validator_signers_to_waypoint(&[&signer]);
    let storage = PersistentSafetyStorage::initialize(
        Storage::from(InMemoryStorage::new()),
        signer.author(),
        signer.private_key().clone(),
        Ed25519PrivateKey::generate_for_testing(),
        waypoint,
    );
    let safety_rules_manager = SafetyRulesManager::new_local(storage, false);
    lsr(safety_rules_manager.client(), signer, n);
}

fn on_disk(n: u64) {
    let signer = ValidatorSigner::from_int(0);
    let file_path = NamedTempFile::new().unwrap().into_temp_path().to_path_buf();
    let waypoint = test_utils::validator_signers_to_waypoint(&[&signer]);
    let storage = PersistentSafetyStorage::initialize(
        Storage::from(OnDiskStorage::new(file_path)),
        signer.author(),
        signer.private_key().clone(),
        Ed25519PrivateKey::generate_for_testing(),
        waypoint,
    );
    let safety_rules_manager = SafetyRulesManager::new_local(storage, false);
    lsr(safety_rules_manager.client(), signer, n);
}

fn serializer(n: u64) {
    let signer = ValidatorSigner::from_int(0);
    let file_path = NamedTempFile::new().unwrap().into_temp_path().to_path_buf();
    let waypoint = test_utils::validator_signers_to_waypoint(&[&signer]);
    let storage = PersistentSafetyStorage::initialize(
        Storage::from(OnDiskStorage::new(file_path)),
        signer.author(),
        signer.private_key().clone(),
        Ed25519PrivateKey::generate_for_testing(),
        waypoint,
    );
    let safety_rules_manager = SafetyRulesManager::new_serializer(storage, false);
    lsr(safety_rules_manager.client(), signer, n);
}

fn thread(n: u64) {
    let signer = ValidatorSigner::from_int(0);
    let file_path = NamedTempFile::new().unwrap().into_temp_path().to_path_buf();
    let waypoint = test_utils::validator_signers_to_waypoint(&[&signer]);
    let storage = PersistentSafetyStorage::initialize(
        Storage::from(OnDiskStorage::new(file_path)),
        signer.author(),
        signer.private_key().clone(),
        Ed25519PrivateKey::generate_for_testing(),
        waypoint,
    );
    let safety_rules_manager = SafetyRulesManager::new_thread(storage, false);
    lsr(safety_rules_manager.client(), signer, n);
}

pub fn benchmark(c: &mut Criterion) {
    let count = 100;
    let mut group = c.benchmark_group("SafetyRules");
    group.measurement_time(std::time::Duration::from_secs(5)).sample_size(10);
    group.bench_function("InMemory", |b| b.iter(|| in_memory(black_box(count))));
    group.bench_function("OnDisk", |b| b.iter(|| on_disk(black_box(count))));
    group.bench_function("Serializer", |b| b.iter(|| serializer(black_box(count))));
    group.bench_function("Thread", |b| b.iter(|| thread(black_box(count))));
}

criterion_group!(benches, benchmark);
criterion_main!(benches);
<commit_msg>[safety-rules] Benchmark for vault<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use consensus_types::block::block_test_utils;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use libra_crypto::{ed25519::Ed25519PrivateKey, Uniform};
use libra_secure_storage::{InMemoryStorage, KVStorage, OnDiskStorage, Storage, VaultStorage};
use libra_types::validator_signer::ValidatorSigner;
use safety_rules::{test_utils, PersistentSafetyStorage, SafetyRulesManager, TSafetyRules};
use tempfile::NamedTempFile;

const VAULT_HOST: &str = "http://localhost:8200";
const VAULT_TOKEN: &str = "root_token";

/// Execute an in order series of blocks (0 <- 1 <- 2 <- 3 and commit 0 and continue to rotate
/// left, appending new blocks on the right, committing the left most block
fn lsr(mut safety_rules: Box<dyn TSafetyRules>, signer: ValidatorSigner, n: u64) {
    let data = block_test_utils::random_payload(1);

    let (proof, genesis_qc) = test_utils::make_genesis(&signer);
    safety_rules.initialize(&proof).unwrap();

    let mut round = genesis_qc.certified_block().round();

    round += 1;
    let mut b0 = test_utils::make_proposal_with_qc(round, genesis_qc, &signer, None);
    safety_rules.construct_and_sign_vote(&b0).unwrap();

    round += 1;
    let mut b1 =
        test_utils::make_proposal_with_parent(data.clone(), round, &b0, None, &signer, None);
    safety_rules.construct_and_sign_vote(&b1).unwrap();

    round += 1;
    let mut b2 =
        test_utils::make_proposal_with_parent(data.clone(), round, &b1, None, &signer, None);
    safety_rules.construct_and_sign_vote(&b2).unwrap();

    for _i in 0..n {
        round += 1;
        let b3 = test_utils::make_proposal_with_parent(
            data.clone(),
            round,
            &b2,
            Some(&b0),
            &signer,
            None,
        );

        safety_rules.construct_and_sign_vote(&b3).unwrap();

        b0 = b1;
        b1 = b2;
        b2 = b3;
    }
}

fn in_memory(n: u64) {
    let signer = ValidatorSigner::from_int(0);
    let waypoint = test_utils::validator_signers_to_waypoint(&[&signer]);
    let storage = PersistentSafetyStorage::initialize(
        Storage::from(InMemoryStorage::new()),
        signer.author(),
        signer.private_key().clone(),
        Ed25519PrivateKey::generate_for_testing(),
        waypoint,
    );
    let safety_rules_manager = SafetyRulesManager::new_local(storage, false);
    lsr(safety_rules_manager.client(), signer, n);
}

fn on_disk(n: u64) {
    let signer = ValidatorSigner::from_int(0);
    let file_path = NamedTempFile::new().unwrap().into_temp_path().to_path_buf();
    let waypoint = test_utils::validator_signers_to_waypoint(&[&signer]);
    let storage = PersistentSafetyStorage::initialize(
        Storage::from(OnDiskStorage::new(file_path)),
        signer.author(),
        signer.private_key().clone(),
        Ed25519PrivateKey::generate_for_testing(),
        waypoint,
    );
    let safety_rules_manager = SafetyRulesManager::new_local(storage, false);
    lsr(safety_rules_manager.client(), signer, n);
}

fn serializer(n: u64) {
    let signer = ValidatorSigner::from_int(0);
    let file_path = NamedTempFile::new().unwrap().into_temp_path().to_path_buf();
    let waypoint = test_utils::validator_signers_to_waypoint(&[&signer]);
    let storage = PersistentSafetyStorage::initialize(
        Storage::from(OnDiskStorage::new(file_path)),
        signer.author(),
        signer.private_key().clone(),
        Ed25519PrivateKey::generate_for_testing(),
        waypoint,
    );
    let safety_rules_manager = SafetyRulesManager::new_serializer(storage, false);
    lsr(safety_rules_manager.client(), signer, n);
}

fn thread(n: u64) {
    let signer = ValidatorSigner::from_int(0);
    let file_path = NamedTempFile::new().unwrap().into_temp_path().to_path_buf();
    let waypoint = test_utils::validator_signers_to_waypoint(&[&signer]);
    let storage = PersistentSafetyStorage::initialize(
        Storage::from(OnDiskStorage::new(file_path)),
        signer.author(),
        signer.private_key().clone(),
        Ed25519PrivateKey::generate_for_testing(),
        waypoint,
    );
    let safety_rules_manager = SafetyRulesManager::new_thread(storage, false);
    lsr(safety_rules_manager.client(), signer, n);
}

fn vault(n: u64) {
    let signer = ValidatorSigner::from_int(0);
    let waypoint = test_utils::validator_signers_to_waypoint(&[&signer]);

    let mut storage =
        VaultStorage::new(VAULT_HOST.to_string(), VAULT_TOKEN.to_string(), None, None);
    storage.reset_and_clear().unwrap();

    let storage = PersistentSafetyStorage::initialize(
        Storage::from(storage),
        signer.author(),
        signer.private_key().clone(),
        Ed25519PrivateKey::generate_for_testing(),
        waypoint,
    );
    let safety_rules_manager = SafetyRulesManager::new_thread(storage, false);
    lsr(safety_rules_manager.client(), signer, n);
}

pub fn benchmark(c: &mut Criterion) {
    let count = 100;
    let duration_secs = 5;
    let samples = 10;

    let storage = VaultStorage::new(VAULT_HOST.to_string(), VAULT_TOKEN.to_string(), None, None);

    let enable_vault = if storage.available().is_err() {
        println!(
            "Vault ({}) is not availble, experiment will not be launched",
            VAULT_HOST
        );
        false
    } else {
        true
    };

    let mut group = c.benchmark_group("SafetyRules");
    group
        .measurement_time(std::time::Duration::from_secs(duration_secs))
        .sample_size(samples);
    group.bench_function("InMemory", |b| b.iter(|| in_memory(black_box(count))));
    group.bench_function("OnDisk", |b| b.iter(|| on_disk(black_box(count))));
    group.bench_function("Serializer", |b| b.iter(|| serializer(black_box(count))));
    group.bench_function("Thread", |b| b.iter(|| thread(black_box(count))));

    if enable_vault {
        group.bench_function("Vault", |b| b.iter(|| vault(black_box(count))));
    }
}

criterion_group!(benches, benchmark);
criterion_main!(benches);
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(feature="serde1")] use serde::{Serialize, Deserialize};
use rand_core::impls::{next_u64_via_u32, fill_bytes_via_next};
use rand_core::le::read_u32_into;
use rand_core::{SeedableRng, RngCore, Error};

/// A xoshiro128** random number generator.
///
/// The xoshiro128** algorithm is not suitable for cryptographic purposes, but
/// is very fast and has excellent statistical properties.
///
/// The algorithm used here is translated from [the `xoshiro128starstar.c`
/// reference source code](http://xoshiro.di.unimi.it/xoshiro128starstar.c) by
/// David Blackman and Sebastiano Vigna.
#[derive(Debug, Clone)]
#[cfg_attr(feature="serde1", derive(Serialize, Deserialize))]
pub struct Xoshiro128StarStar {
    s: [u32; 4],
}

impl Xoshiro128StarStar {
    /// Jump forward, equivalently to 2^64 calls to `next_u32()`.
    ///
    /// This can be used to generate 2^64 non-overlapping subsequences for
    /// parallel computations.
    ///
    /// ```
    /// use rand_xoshiro::rand_core::SeedableRng;
    /// use rand_xoshiro::Xoroshiro128StarStar;
    ///
    /// let rng1 = Xoroshiro128StarStar::seed_from_u64(0);
    /// let mut rng2 = rng1.clone();
    /// rng2.jump();
    /// let mut rng3 = rng2.clone();
    /// rng3.jump();
    /// ```
    pub fn jump(&mut self) {
        impl_jump!(u32, self, [0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b]);
    }

    /// Jump forward, equivalently to 2^96 calls to `next_u32()`.
    ///
    /// This can be used to generate 2^32 starting points, from each of which
    /// `jump()` will generate 2^32 non-overlapping subsequences for parallel
    /// distributed computations.
    pub fn long_jump(&mut self) {
        impl_jump!(u32, self, [0xb523952e, 0x0b6f099f, 0xccf5a0ef, 0x1c580662]);
    }
}

impl SeedableRng for Xoshiro128StarStar {
    type Seed = [u8; 16];

    /// Create a new `Xoshiro128StarStar`.  If `seed` is entirely 0, it will be
    /// mapped to a different seed.
    #[inline]
    fn from_seed(seed: [u8; 16]) -> Xoshiro128StarStar {
        deal_with_zero_seed!(seed, Self);
        let mut state = [0; 4];
        read_u32_into(&seed, &mut state);
        Xoshiro128StarStar { s: state }
    }

    /// Seed a `Xoshiro128StarStar` from a `u64` using `SplitMix64`.
    fn seed_from_u64(seed: u64) -> Xoshiro128StarStar {
        from_splitmix!(seed)
    }
}

impl RngCore for Xoshiro128StarStar {
    #[inline]
    fn next_u32(&mut self) -> u32 {
        let result_starstar = starstar_u64!(self.s[0]);
        impl_xoshiro_u32!(self);
        result_starstar
    }

    #[inline]
    fn next_u64(&mut self) -> u64 {
        next_u64_via_u32(self)
    }

    #[inline]
    fn fill_bytes(&mut self, dest: &mut [u8]) {
        fill_bytes_via_next(self, dest);
    }

    #[inline]
    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        self.fill_bytes(dest);
        Ok(())
    }
}

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

    #[test]
    fn reference() {
        let mut rng = Xoshiro128StarStar::from_seed(
            [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]);
        // These values were produced with the reference implementation:
        // http://xoshiro.di.unimi.it/xoshiro128starstar.c
        let expected = [
            5760, 40320, 70819200, 3297914139, 2480851620, 1792823698,
            4118739149, 1251203317, 1581886583, 1721184582,
        ];
        for &e in &expected {
            assert_eq!(rng.next_u32(), e);
        }
    }
}
<commit_msg>rand_xoshiro: Update xoshiro128** to version 1.1<commit_after>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(feature="serde1")] use serde::{Serialize, Deserialize};
use rand_core::impls::{next_u64_via_u32, fill_bytes_via_next};
use rand_core::le::read_u32_into;
use rand_core::{SeedableRng, RngCore, Error};

/// A xoshiro128** random number generator.
///
/// The xoshiro128** algorithm is not suitable for cryptographic purposes, but
/// is very fast and has excellent statistical properties.
///
/// The algorithm used here is translated from [the `xoshiro128starstar.c`
/// reference source code](http://xoshiro.di.unimi.it/xoshiro128starstar.c) by
/// David Blackman and Sebastiano Vigna.
#[derive(Debug, Clone)]
#[cfg_attr(feature="serde1", derive(Serialize, Deserialize))]
pub struct Xoshiro128StarStar {
    s: [u32; 4],
}

impl Xoshiro128StarStar {
    /// Jump forward, equivalently to 2^64 calls to `next_u32()`.
    ///
    /// This can be used to generate 2^64 non-overlapping subsequences for
    /// parallel computations.
    ///
    /// ```
    /// use rand_xoshiro::rand_core::SeedableRng;
    /// use rand_xoshiro::Xoroshiro128StarStar;
    ///
    /// let rng1 = Xoroshiro128StarStar::seed_from_u64(0);
    /// let mut rng2 = rng1.clone();
    /// rng2.jump();
    /// let mut rng3 = rng2.clone();
    /// rng3.jump();
    /// ```
    pub fn jump(&mut self) {
        impl_jump!(u32, self, [0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b]);
    }

    /// Jump forward, equivalently to 2^96 calls to `next_u32()`.
    ///
    /// This can be used to generate 2^32 starting points, from each of which
    /// `jump()` will generate 2^32 non-overlapping subsequences for parallel
    /// distributed computations.
    pub fn long_jump(&mut self) {
        impl_jump!(u32, self, [0xb523952e, 0x0b6f099f, 0xccf5a0ef, 0x1c580662]);
    }
}

impl SeedableRng for Xoshiro128StarStar {
    type Seed = [u8; 16];

    /// Create a new `Xoshiro128StarStar`.  If `seed` is entirely 0, it will be
    /// mapped to a different seed.
    #[inline]
    fn from_seed(seed: [u8; 16]) -> Xoshiro128StarStar {
        deal_with_zero_seed!(seed, Self);
        let mut state = [0; 4];
        read_u32_into(&seed, &mut state);
        Xoshiro128StarStar { s: state }
    }

    /// Seed a `Xoshiro128StarStar` from a `u64` using `SplitMix64`.
    fn seed_from_u64(seed: u64) -> Xoshiro128StarStar {
        from_splitmix!(seed)
    }
}

impl RngCore for Xoshiro128StarStar {
    #[inline]
    fn next_u32(&mut self) -> u32 {
        let result_starstar = starstar_u64!(self.s[1]);
        impl_xoshiro_u32!(self);
        result_starstar
    }

    #[inline]
    fn next_u64(&mut self) -> u64 {
        next_u64_via_u32(self)
    }

    #[inline]
    fn fill_bytes(&mut self, dest: &mut [u8]) {
        fill_bytes_via_next(self, dest);
    }

    #[inline]
    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        self.fill_bytes(dest);
        Ok(())
    }
}

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

    #[test]
    fn reference() {
        let mut rng = Xoshiro128StarStar::from_seed(
            [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]);
        // These values were produced with the reference implementation (v1.1):
        // http://xoshiro.di.unimi.it/xoshiro128starstar.c
        let expected = [
            11520, 0, 5927040, 70819200, 2031721883, 1637235492, 1287239034,
            3734860849, 3729100597, 4258142804,
        ];
        for &e in &expected {
            assert_eq!(rng.next_u32(), e);
        }
    }
}
<|endoftext|>


<commit_before>use moqt_gui::QWindow;
use moqt_core::BasicClass;
use cpp_utils::{CppBox, Ptr};

#[test]
fn create() {
    unsafe {
        let mut window = QWindow::new();
        let mut object: CppBox<BasicClass> = window.get_basic_class();
        assert_eq!(object.foo(), 42);
        let mut object_ptr: Ptr<BasicClass> = window.get_basic_class_ptr();
        assert_eq!(object_ptr.foo(), 43);
    }
}
<commit_msg>More QWindow tests<commit_after>use moqt_gui::{QWindow, get_window};
use moqt_core::BasicClass;
use cpp_utils::{CppBox, Ptr};

#[test]
fn test_qwindow() {
    unsafe {
        let mut window = QWindow::new();
        let mut object: CppBox<BasicClass> = window.get_basic_class();
        assert_eq!(object.foo(), 42);
        let mut object_ptr: Ptr<BasicClass> = window.get_basic_class_ptr();
        assert_eq!(object_ptr.foo(), 43);
    }
}

#[test]
fn test_get_window() {
    unsafe {
        let window: Ptr<QWindow> = get_window();
        assert!(window.is_null());
    }
}
<|endoftext|>


<commit_before>
use wtest_basic::*;

#[cfg( feature = "in_wtools" )]
use wtools::string as TheModule;
#[cfg( not( feature = "in_wtools" ) )]
use wstring_tools as TheModule;

// use TheModule::prelude::*;

//

fn _basic()
{
  let src = "abc";
  let iter = TheModule::string::split()
  .src( src )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "", "", "a", "", "b", "", "c", "", "", ] );
}

//

fn _split_with_option_preserving_empty()
{
  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( true )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( false )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  /* */

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( true )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "", "b", "", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( false )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );
}

//

fn _split_with_option_preserving_delimeters()
{
  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_delimeters( true )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_delimeters( false )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );
}

//

fn _split_with_option_stripping()
{
  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "", "b", "", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  /* */

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( "b" )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( "b" )
  .preserving_delimeters( false )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "c" ] );
}

//

fn _basic_split_with_vector()
{
  let src = "abc";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( vec![] )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "abc", ] );

  let src = "abc";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( vec![ "a", "b", "" ] )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "", "", "a", "", "b", "", "c", "", "", ] );

  let src = "abc";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( vec![ "b", "d" ] )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );
}

//

test_suite!
{
  basic,
  split_with_option_preserving_empty,
  split_with_option_preserving_delimeters,
  split_with_option_stripping,
  basic_split_with_vector,
}
<commit_msg>Write test routine `basic_form_and_methods`<commit_after>
use wtest_basic::*;

#[cfg( feature = "in_wtools" )]
use wtools::string as TheModule;
#[cfg( not( feature = "in_wtools" ) )]
use wstring_tools as TheModule;

// use TheModule::prelude::*;

//

fn _basic()
{
  let src = "abc";
  let iter = TheModule::string::split()
  .src( src )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "", "", "a", "", "b", "", "c", "", "", ] );
}

fn _basic_form_and_methods()
{
  let src = "abc";
  let opts = TheModule::string::split()
  .src( src )
  .form();
  let iter = opts.split();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "", "", "a", "", "b", "", "c", "", "", ] );

  let src = "abc";
  let opts = TheModule::string::split()
  .src( src )
  .form();
  let iter = opts.split_fast();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "", "", "a", "", "b", "", "c", "", "", ] );
}

//

fn _split_with_option_preserving_empty()
{
  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( true )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( false )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  /* */

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( true )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "", "b", "", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_empty( false )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );
}

//

fn _split_with_option_preserving_delimeters()
{
  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_delimeters( true )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .preserving_delimeters( false )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );
}

//

fn _split_with_option_stripping()
{
  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "", "b", "", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( " " )
  .stripping( false )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", " ", "b", " ", "c" ] );

  /* */

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( "b" )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );

  let src = "a b c";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( "b" )
  .preserving_delimeters( false )
  .stripping( true )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "c" ] );
}

//

fn _basic_split_with_vector()
{
  let src = "abc";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( vec![] )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "abc", ] );

  let src = "abc";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( vec![ "a", "b", "" ] )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "", "", "a", "", "b", "", "c", "", "", ] );

  let src = "abc";
  let iter = TheModule::string::split()
  .src( src )
  .delimeter( vec![ "b", "d" ] )
  .perform();
  assert_eq!( iter.map( | e | String::from( e ) ).collect::< Vec< _ > >(), vec![ "a", "b", "c" ] );
}

//

test_suite!
{
  basic,
  basic_form_and_methods,
  split_with_option_preserving_empty,
  split_with_option_preserving_delimeters,
  split_with_option_stripping,
  basic_split_with_vector,
}
<|endoftext|>


<commit_before>//! Implements the "trellis" convolutional error correcting code specified by P25.

use std;

use bits;

/// Half-rate convolutional ("trellis") code state machine.
pub type DibitFSM = TrellisFSM<DibitStates>;

/// 3/4-rate convolutional ("trellis") code state machine.
pub type TribitFSM = TrellisFSM<TribitStates>;

pub trait States {
    /// Symbol type to use for states and input.
    type Symbol;

    /// Number of rows/columns in the state machine.
    fn size() -> usize;

    /// Get the "constallation point" on the transition from the current state to the next
    /// state.
    fn pair_idx(cur: usize, next: usize) -> usize;

    /// Convert the given symbol to a state.
    fn state(input: Self::Symbol) -> usize;
    /// Convert the given state to a symbol.
    fn symbol(state: usize) -> Self::Symbol;

    /// Get the "flushing" symbol fed in at the end of a stream.
    fn finisher() -> Self::Symbol;

    /// Get the dibit pair on the transition from the current state to the next state.
    fn pair(state: usize, next: usize) -> (bits::Dibit, bits::Dibit) {
        const PAIRS: [(u8, u8); 16] = [
            (0b00, 0b10),
            (0b10, 0b10),
            (0b01, 0b11),
            (0b11, 0b11),
            (0b11, 0b10),
            (0b01, 0b10),
            (0b10, 0b11),
            (0b00, 0b11),
            (0b11, 0b01),
            (0b01, 0b01),
            (0b10, 0b00),
            (0b00, 0b00),
            (0b00, 0b01),
            (0b10, 0b01),
            (0b01, 0b00),
            (0b11, 0b00),
        ];

        let (hi, lo) = PAIRS[Self::pair_idx(state, next)];
        (bits::Dibit::new(hi), bits::Dibit::new(lo))
    }
}

/// Half-rate state machine (dibit input).
pub struct DibitStates;

impl States for DibitStates {
    type Symbol = bits::Dibit;

    fn size() -> usize { 4 }

    fn pair_idx(cur: usize, next: usize) -> usize {
        const STATES: [[usize; 4]; 4] = [
            [0, 15, 12, 3],
            [4, 11, 8, 7],
            [13, 2, 1, 14],
            [9, 6, 5, 10],
        ];

        STATES[cur][next]
    }

    fn state(input: bits::Dibit) -> usize { input.bits() as usize }
    fn finisher() -> Self::Symbol { bits::Dibit::new(0b00) }
    fn symbol(state: usize) -> Self::Symbol { bits::Dibit::new(state as u8) }
}

/// 3/4-rate state machine (tribit input).
pub struct TribitStates;

impl States for TribitStates {
    type Symbol = bits::Tribit;

    fn size() -> usize { 8 }

    fn pair_idx(cur: usize, next: usize) -> usize {
        const STATES: [[usize; 8]; 8] = [
            [0, 8, 4, 12, 2, 10, 6, 14],
            [4, 12, 2, 10, 6, 14, 0, 8],
            [1, 9, 5, 13, 3, 11, 7, 15],
            [5, 13, 3, 11, 7, 15, 1, 9],
            [3, 11, 7, 15, 1, 9, 5, 13],
            [7, 15, 1, 9, 5, 13, 3, 11],
            [2, 10, 6, 14, 0, 8, 4, 12],
            [6, 14, 0, 8, 4, 12, 2, 10],
        ];

        STATES[cur][next]
    }

    fn state(input: bits::Tribit) -> usize { input.bits() as usize }
    fn finisher() -> Self::Symbol { bits::Tribit::new(0b000) }
    fn symbol(state: usize) -> Self::Symbol { bits::Tribit::new(state as u8) }
}

/// Convolutional code finite state machine with the given transition table. Each fed-in
/// symbol is used as the next state.
pub struct TrellisFSM<S: States> {
    states: std::marker::PhantomData<S>,
    /// Current state.
    state: usize,
}

impl<S: States> TrellisFSM<S> {
    /// Construct a new `TrellisFSM` at the initial state.
    pub fn new() -> TrellisFSM<S> {
        TrellisFSM {
            states: std::marker::PhantomData,
            state: 0,
        }
    }

    /// Apply the given symbol to the state machine and return the dibit pair on the
    /// transition.
    pub fn feed(&mut self, input: S::Symbol) -> (bits::Dibit, bits::Dibit) {
        let next = S::state(input);
        let pair = S::pair(self.state, next);

        self.state = next;

        pair
    }

    /// Flush the state machine with the finishing symbol and return the final transition.
    pub fn finish(&mut self) -> (bits::Dibit, bits::Dibit) {
        self.feed(S::finisher())
    }
}

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

    #[test]
    fn test_dibit_code() {
        let mut fsm = DibitFSM::new();
        assert_eq!(fsm.feed(Dibit::new(0b00)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Dibit::new(0b00)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Dibit::new(0b01)), (Dibit::new(0b11), Dibit::new(0b00)));
        assert_eq!(fsm.feed(Dibit::new(0b01)), (Dibit::new(0b00), Dibit::new(0b00)));
        assert_eq!(fsm.feed(Dibit::new(0b10)), (Dibit::new(0b11), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Dibit::new(0b10)), (Dibit::new(0b10), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Dibit::new(0b11)), (Dibit::new(0b01), Dibit::new(0b00)));
        assert_eq!(fsm.feed(Dibit::new(0b11)), (Dibit::new(0b10), Dibit::new(0b00)));
    }

    #[test]
    fn test_tribit_code() {
        let mut fsm = TribitFSM::new();
        assert_eq!(fsm.feed(Tribit::new(0b000)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Tribit::new(0b000)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Tribit::new(0b001)), (Dibit::new(0b11), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Tribit::new(0b010)), (Dibit::new(0b01), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b100)), (Dibit::new(0b11), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b101)), (Dibit::new(0b01), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Tribit::new(0b110)), (Dibit::new(0b11), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b111)), (Dibit::new(0b00), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Tribit::new(0b000)), (Dibit::new(0b10), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b111)), (Dibit::new(0b01), Dibit::new(0b00)));
    }
}
<commit_msg>Fix alignment<commit_after>//! Implements the "trellis" convolutional error correcting code specified by P25.

use std;

use bits;

/// Half-rate convolutional ("trellis") code state machine.
pub type DibitFSM = TrellisFSM<DibitStates>;

/// 3/4-rate convolutional ("trellis") code state machine.
pub type TribitFSM = TrellisFSM<TribitStates>;

pub trait States {
    /// Symbol type to use for states and input.
    type Symbol;

    /// Number of rows/columns in the state machine.
    fn size() -> usize;

    /// Get the "constallation point" on the transition from the current state to the next
    /// state.
    fn pair_idx(cur: usize, next: usize) -> usize;

    /// Convert the given symbol to a state.
    fn state(input: Self::Symbol) -> usize;
    /// Convert the given state to a symbol.
    fn symbol(state: usize) -> Self::Symbol;

    /// Get the "flushing" symbol fed in at the end of a stream.
    fn finisher() -> Self::Symbol;

    /// Get the dibit pair on the transition from the current state to the next state.
    fn pair(state: usize, next: usize) -> (bits::Dibit, bits::Dibit) {
        const PAIRS: [(u8, u8); 16] = [
            (0b00, 0b10),
            (0b10, 0b10),
            (0b01, 0b11),
            (0b11, 0b11),
            (0b11, 0b10),
            (0b01, 0b10),
            (0b10, 0b11),
            (0b00, 0b11),
            (0b11, 0b01),
            (0b01, 0b01),
            (0b10, 0b00),
            (0b00, 0b00),
            (0b00, 0b01),
            (0b10, 0b01),
            (0b01, 0b00),
            (0b11, 0b00),
        ];

        let (hi, lo) = PAIRS[Self::pair_idx(state, next)];
        (bits::Dibit::new(hi), bits::Dibit::new(lo))
    }
}

/// Half-rate state machine (dibit input).
pub struct DibitStates;

impl States for DibitStates {
    type Symbol = bits::Dibit;

    fn size() -> usize { 4 }

    fn pair_idx(cur: usize, next: usize) -> usize {
        const STATES: [[usize; 4]; 4] = [
            [0, 15, 12, 3],
            [4, 11, 8, 7],
            [13, 2, 1, 14],
            [9, 6, 5, 10],
        ];

        STATES[cur][next]
    }

    fn state(input: bits::Dibit) -> usize { input.bits() as usize }
    fn finisher() -> Self::Symbol { bits::Dibit::new(0b00) }
    fn symbol(state: usize) -> Self::Symbol { bits::Dibit::new(state as u8) }
}

/// 3/4-rate state machine (tribit input).
pub struct TribitStates;

impl States for TribitStates {
    type Symbol = bits::Tribit;

    fn size() -> usize { 8 }

    fn pair_idx(cur: usize, next: usize) -> usize {
        const STATES: [[usize; 8]; 8] = [
            [0,  8, 4, 12, 2, 10, 6, 14],
            [4, 12, 2, 10, 6, 14, 0,  8],
            [1,  9, 5, 13, 3, 11, 7, 15],
            [5, 13, 3, 11, 7, 15, 1,  9],
            [3, 11, 7, 15, 1,  9, 5, 13],
            [7, 15, 1,  9, 5, 13, 3, 11],
            [2, 10, 6, 14, 0,  8, 4, 12],
            [6, 14, 0,  8, 4, 12, 2, 10],
        ];

        STATES[cur][next]
    }

    fn state(input: bits::Tribit) -> usize { input.bits() as usize }
    fn finisher() -> Self::Symbol { bits::Tribit::new(0b000) }
    fn symbol(state: usize) -> Self::Symbol { bits::Tribit::new(state as u8) }
}

/// Convolutional code finite state machine with the given transition table. Each fed-in
/// symbol is used as the next state.
pub struct TrellisFSM<S: States> {
    states: std::marker::PhantomData<S>,
    /// Current state.
    state: usize,
}

impl<S: States> TrellisFSM<S> {
    /// Construct a new `TrellisFSM` at the initial state.
    pub fn new() -> TrellisFSM<S> {
        TrellisFSM {
            states: std::marker::PhantomData,
            state: 0,
        }
    }

    /// Apply the given symbol to the state machine and return the dibit pair on the
    /// transition.
    pub fn feed(&mut self, input: S::Symbol) -> (bits::Dibit, bits::Dibit) {
        let next = S::state(input);
        let pair = S::pair(self.state, next);

        self.state = next;

        pair
    }

    /// Flush the state machine with the finishing symbol and return the final transition.
    pub fn finish(&mut self) -> (bits::Dibit, bits::Dibit) {
        self.feed(S::finisher())
    }
}

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

    #[test]
    fn test_dibit_code() {
        let mut fsm = DibitFSM::new();
        assert_eq!(fsm.feed(Dibit::new(0b00)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Dibit::new(0b00)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Dibit::new(0b01)), (Dibit::new(0b11), Dibit::new(0b00)));
        assert_eq!(fsm.feed(Dibit::new(0b01)), (Dibit::new(0b00), Dibit::new(0b00)));
        assert_eq!(fsm.feed(Dibit::new(0b10)), (Dibit::new(0b11), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Dibit::new(0b10)), (Dibit::new(0b10), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Dibit::new(0b11)), (Dibit::new(0b01), Dibit::new(0b00)));
        assert_eq!(fsm.feed(Dibit::new(0b11)), (Dibit::new(0b10), Dibit::new(0b00)));
    }

    #[test]
    fn test_tribit_code() {
        let mut fsm = TribitFSM::new();
        assert_eq!(fsm.feed(Tribit::new(0b000)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Tribit::new(0b000)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Tribit::new(0b001)), (Dibit::new(0b11), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Tribit::new(0b010)), (Dibit::new(0b01), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b100)), (Dibit::new(0b11), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b101)), (Dibit::new(0b01), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Tribit::new(0b110)), (Dibit::new(0b11), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b111)), (Dibit::new(0b00), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Tribit::new(0b000)), (Dibit::new(0b10), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b111)), (Dibit::new(0b01), Dibit::new(0b00)));
    }
}
<|endoftext|>


<commit_before>use clang::{Entity, EntityKind, EntityVisitResult, TemplateArgument, TranslationUnit};
use std::vec::Vec;
use std::string::String;
use std::option::Option;
use serde::ser::Serializer;
use rand::{self, Rng};

#[derive(Serialize, Debug, PartialEq, Clone)]
pub struct Model {
    pub interfaces: Vec<Interface>,
}

#[derive(Serialize, Debug, PartialEq, Clone)]
pub struct Interface {
    pub name: String,
    pub namespaces: Vec<String>,
    pub methods: Vec<Method>,
    pub template_parameters: Option<Vec<TemplateParameter>>,
}

#[derive(Serialize, Debug, PartialEq, Clone)]
pub struct Method {
    pub name: String,
    pub return_type: String,
    pub arguments: Vec<Argument>,
    pub template_arguments: Option<Vec<TemplateParameter>>,
}

#[derive(Serialize, Debug, PartialEq, Clone)]
pub struct Argument {
    #[serde(serialize_with="serialize_argument_name_with")]
    pub name: Option<String>,
    pub argument_type: String,
}

#[derive(Serialize, Debug, PartialEq, Clone)]
pub struct TemplateParameter {
    pub type_name: String,
}

impl Model {
    pub fn new(tu: &TranslationUnit) -> Model {
        let mut model = Model { interfaces: vec![] };
        {
            let visitor = |node: Entity, parent: Entity| build_model(&mut model, node, parent);
            tu.get_entity().visit_children(visitor);
        }
        model
    }
}

fn build_model(model: &mut Model, node: Entity, parent: Entity) -> EntityVisitResult {
    if !node.is_in_main_file() {
        return EntityVisitResult::Continue;
    }

    if !is_interface(node) {
        return EntityVisitResult::Recurse;
    }

    match node.get_kind() {
        EntityKind::StructDecl |
        EntityKind::ClassDecl |
        EntityKind::ClassTemplate => {
            model.interfaces.push(Interface {
                name: node.get_name().unwrap(),
                namespaces: parse_namespaces(parent),
                methods: parse_methods(node),
                template_parameters: parse_template_parameters(node),
            });
            EntityVisitResult::Continue
        }
        _ => EntityVisitResult::Recurse,
    }
}

fn parse_namespaces(node: Entity) -> Vec<String> {
    let mut pointer = node;
    let mut namespace_list = vec![];
    while pointer.get_kind() == EntityKind::Namespace {
        namespace_list.push(pointer.get_name().unwrap());
        match pointer.get_lexical_parent() {
            Some(n) => pointer = n,
            None => break,
        }
    }
    namespace_list.reverse();
    namespace_list
}

fn parse_methods(node: Entity) -> Vec<Method> {
    node.get_children()
        .into_iter()
        .filter(|method| {
            method.get_kind() != EntityKind::Destructor &&
            method.get_kind() != EntityKind::Constructor
        })
        .map(parse_method)
        .collect::<Vec<_>>()
}

fn parse_method(node: Entity) -> Method {
    Method {
        name: node.get_name().unwrap(),
        return_type: "void".to_string(),
        arguments: parse_arguments(node),
        template_arguments: parse_template_parameters(node),
    }
}

fn parse_arguments(node: Entity) -> Vec<Argument> {
    node.get_arguments().map_or(vec![],
                                |t| t.into_iter().map(parse_argument).collect::<Vec<_>>())
}

fn parse_argument(t: Entity) -> Argument {
    Argument {
        name: t.get_name(),
        argument_type: t.get_type().unwrap().get_display_name(),
    }
}

fn parse_template_parameters(t: Entity) -> Option<Vec<TemplateParameter>> {
    let params = t.get_children()
        .into_iter()
        .filter_map(|x: Entity| {
            match x.get_kind() {
                EntityKind::TemplateTypeParameter => {
                    Some(TemplateParameter { type_name: x.get_name().unwrap() })
                }
                _ => None,
            }
        })
        .collect::<Vec<_>>();
    if params.is_empty() {
        None
    } else {
        Some(params)
    }
}

fn is_interface(node: Entity) -> bool {
    let res = node.get_children()
        .into_iter()
        .all(|method| method.get_kind() != EntityKind::Method || method.is_virtual_method());
    res
}

fn serialize_argument_name_with<'a, S: Serializer>(name: &'a Option<String>,
                                                   serializer: &mut S)
                                                   -> Result<(), S::Error> {
    let s = match name {
        &Some(ref n) => n.clone(),
        &None => {
            rand::thread_rng()
                .gen_ascii_chars()
                .take(10)
                .collect::<String>().clone()
        },
    };
    serializer.serialize_str(s.to_lowercase().as_str())
}
<commit_msg>Remove unused use<commit_after>use clang::{Entity, EntityKind, EntityVisitResult, TranslationUnit};
use std::vec::Vec;
use std::string::String;
use std::option::Option;
use serde::ser::Serializer;
use rand::{self, Rng};

#[derive(Serialize, Debug, PartialEq, Clone)]
pub struct Model {
    pub interfaces: Vec<Interface>,
}

#[derive(Serialize, Debug, PartialEq, Clone)]
pub struct Interface {
    pub name: String,
    pub namespaces: Vec<String>,
    pub methods: Vec<Method>,
    pub template_parameters: Option<Vec<TemplateParameter>>,
}

#[derive(Serialize, Debug, PartialEq, Clone)]
pub struct Method {
    pub name: String,
    pub return_type: String,
    pub arguments: Vec<Argument>,
    pub template_arguments: Option<Vec<TemplateParameter>>,
}

#[derive(Serialize, Debug, PartialEq, Clone)]
pub struct Argument {
    #[serde(serialize_with="serialize_argument_name_with")]
    pub name: Option<String>,
    pub argument_type: String,
}

#[derive(Serialize, Debug, PartialEq, Clone)]
pub struct TemplateParameter {
    pub type_name: String,
}

impl Model {
    pub fn new(tu: &TranslationUnit) -> Model {
        let mut model = Model { interfaces: vec![] };
        {
            let visitor = |node: Entity, parent: Entity| build_model(&mut model, node, parent);
            tu.get_entity().visit_children(visitor);
        }
        model
    }
}

fn build_model(model: &mut Model, node: Entity, parent: Entity) -> EntityVisitResult {
    if !node.is_in_main_file() {
        return EntityVisitResult::Continue;
    }

    if !is_interface(node) {
        return EntityVisitResult::Recurse;
    }

    match node.get_kind() {
        EntityKind::StructDecl |
        EntityKind::ClassDecl |
        EntityKind::ClassTemplate => {
            model.interfaces.push(Interface {
                name: node.get_name().unwrap(),
                namespaces: parse_namespaces(parent),
                methods: parse_methods(node),
                template_parameters: parse_template_parameters(node),
            });
            EntityVisitResult::Continue
        }
        _ => EntityVisitResult::Recurse,
    }
}

fn parse_namespaces(node: Entity) -> Vec<String> {
    let mut pointer = node;
    let mut namespace_list = vec![];
    while pointer.get_kind() == EntityKind::Namespace {
        namespace_list.push(pointer.get_name().unwrap());
        match pointer.get_lexical_parent() {
            Some(n) => pointer = n,
            None => break,
        }
    }
    namespace_list.reverse();
    namespace_list
}

fn parse_methods(node: Entity) -> Vec<Method> {
    node.get_children()
        .into_iter()
        .filter(|method| {
            method.get_kind() != EntityKind::Destructor &&
            method.get_kind() != EntityKind::Constructor
        })
        .map(parse_method)
        .collect::<Vec<_>>()
}

fn parse_method(node: Entity) -> Method {
    Method {
        name: node.get_name().unwrap(),
        return_type: "void".to_string(),
        arguments: parse_arguments(node),
        template_arguments: parse_template_parameters(node),
    }
}

fn parse_arguments(node: Entity) -> Vec<Argument> {
    node.get_arguments().map_or(vec![],
                                |t| t.into_iter().map(parse_argument).collect::<Vec<_>>())
}

fn parse_argument(t: Entity) -> Argument {
    Argument {
        name: t.get_name(),
        argument_type: t.get_type().unwrap().get_display_name(),
    }
}

fn parse_template_parameters(t: Entity) -> Option<Vec<TemplateParameter>> {
    let params = t.get_children()
        .into_iter()
        .filter_map(|x: Entity| {
            match x.get_kind() {
                EntityKind::TemplateTypeParameter => {
                    Some(TemplateParameter { type_name: x.get_name().unwrap() })
                }
                _ => None,
            }
        })
        .collect::<Vec<_>>();
    if params.is_empty() {
        None
    } else {
        Some(params)
    }
}

fn is_interface(node: Entity) -> bool {
    let res = node.get_children()
        .into_iter()
        .all(|method| method.get_kind() != EntityKind::Method || method.is_virtual_method());
    res
}

fn serialize_argument_name_with<'a, S: Serializer>(name: &'a Option<String>,
                                                   serializer: &mut S)
                                                   -> Result<(), S::Error> {
    let s = match name {
        &Some(ref n) => n.clone(),
        &None => {
            rand::thread_rng()
                .gen_ascii_chars()
                .take(10)
                .collect::<String>().clone()
        },
    };
    serializer.serialize_str(s.to_lowercase().as_str())
}
<|endoftext|>


<commit_before>//! FIXME: write short doc here

use std::fmt;

use ra_parser::ParseError;

use crate::{validation::EscapeError, TextRange, TextUnit, TokenizeError};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SyntaxError {
    kind: SyntaxErrorKind,
    location: Location,
}

// FIXME: Location should be just `Location(TextRange)`
// TextUnit enum member just unnecessarily compicates things,
// we should'n treat it specially, it just as a `TextRange { start: x, end: x + 1 }`
// see `location_to_range()` in ra_ide/src/diagnostics
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum Location {
    Offset(TextUnit),
    Range(TextRange),
}

impl From<TextUnit> for Location {
    fn from(offset: TextUnit) -> Location {
        Location::Offset(offset)
    }
}

impl From<TextRange> for Location {
    fn from(range: TextRange) -> Location {
        Location::Range(range)
    }
}

impl fmt::Debug for Location {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Location::Offset(it) => fmt::Debug::fmt(it, f),
            Location::Range(it) => fmt::Debug::fmt(it, f),
        }
    }
}

impl SyntaxError {
    pub fn new<L: Into<Location>>(kind: SyntaxErrorKind, loc: L) -> SyntaxError {
        SyntaxError { kind, location: loc.into() }
    }

    pub fn kind(&self) -> SyntaxErrorKind {
        self.kind.clone()
    }

    pub fn location(&self) -> Location {
        self.location.clone()
    }

    pub fn offset(&self) -> TextUnit {
        match self.location {
            Location::Offset(offset) => offset,
            Location::Range(range) => range.start(),
        }
    }

    pub fn add_offset(mut self, plus_offset: TextUnit, minus_offset: TextUnit) -> SyntaxError {
        self.location = match self.location {
            Location::Range(range) => Location::Range(range + plus_offset - minus_offset),
            Location::Offset(offset) => Location::Offset(offset + plus_offset - minus_offset),
        };

        self
    }
}

impl fmt::Display for SyntaxError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.kind.fmt(f)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum SyntaxErrorKind {
    ParseError(ParseError),
    EscapeError(EscapeError),
    TokenizeError(TokenizeError),
    // FIXME: the obvious pattern of this enum dictates that the following enum variants
    // should be wrapped into something like `SemmanticError(SemmanticError)`
    // or `ValidateError(ValidateError)` or `SemmanticValidateError(...)`
    InvalidBlockAttr,
    InvalidMatchInnerAttr,
    InvalidTupleIndexFormat,
    VisibilityNotAllowed,
    InclusiveRangeMissingEnd,
}

impl fmt::Display for SyntaxErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::SyntaxErrorKind::*;
        match self {
            InvalidBlockAttr => {
                write!(f, "A block in this position cannot accept inner attributes")
            }
            InvalidMatchInnerAttr => {
                write!(f, "Inner attributes are only allowed directly after the opening brace of the match expression")
            }
            InvalidTupleIndexFormat => {
                write!(f, "Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix")
            }
            ParseError(msg) => write!(f, "{}", msg.0),
            EscapeError(err) => write!(f, "{}", err),
            TokenizeError(err) => write!(f, "{}", err),
            VisibilityNotAllowed => {
                write!(f, "unnecessary visibility qualifier")
            }
            InclusiveRangeMissingEnd => {
                write!(f, "An inclusive range must have an end expression")
            }
        }
    }
}

impl fmt::Display for TokenizeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let msg = match self {
            TokenizeError::EmptyInt => "Missing digits after integer base prefix",
            TokenizeError::EmptyExponent => "Missing digits after the exponent symbol",
            TokenizeError::UnterminatedBlockComment => {
                "Missing trailing `*/` symbols to terminate the block comment"
            }
            TokenizeError::UnterminatedChar => {
                "Missing trailing `'` symbol to terminate the character literal"
            }
            TokenizeError::UnterminatedByte => {
                "Missing trailing `'` symbol to terminate the byte literal"
            }
            TokenizeError::UnterminatedString => {
                "Missing trailing `\"` symbol to terminate the string literal"
            }
            TokenizeError::UnterminatedByteString => {
                "Missing trailing `\"` symbol to terminate the byte string literal"
            }
            TokenizeError::UnterminatedRawString => {
                "Missing trailing `\"` with `#` symbols to terminate the raw string literal"
            }
            TokenizeError::UnterminatedRawByteString => {
                "Missing trailing `\"` with `#` symbols to terminate the raw byte string literal"
            }
            TokenizeError::UnstartedRawString => {
                "Missing `\"` symbol after `#` symbols to begin the raw string literal"
            }
            TokenizeError::UnstartedRawByteString => {
                "Missing `\"` symbol after `#` symbols to begin the raw byte string literal"
            }
            TokenizeError::LifetimeStartsWithNumber => "Lifetime name cannot start with a number",
        };
        write!(f, "{}", msg)
    }
}

impl fmt::Display for EscapeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let msg = match self {
            EscapeError::ZeroChars => "Empty literal",
            EscapeError::MoreThanOneChar => "Literal should be one character long",
            EscapeError::LoneSlash => "Character must be escaped: '\\'",
            EscapeError::InvalidEscape => "Invalid escape sequence",
            EscapeError::BareCarriageReturn => "Character must be escaped: '\r'",
            EscapeError::EscapeOnlyChar => "Character must be escaped",
            EscapeError::TooShortHexEscape => "Escape sequence should have two digits",
            EscapeError::InvalidCharInHexEscape => "Escape sequence should be a hexadecimal number",
            EscapeError::OutOfRangeHexEscape => "Escape sequence should be ASCII",
            EscapeError::NoBraceInUnicodeEscape => "Invalid escape sequence",
            EscapeError::InvalidCharInUnicodeEscape => "Invalid escape sequence",
            EscapeError::EmptyUnicodeEscape => "Invalid escape sequence",
            EscapeError::UnclosedUnicodeEscape => "Missing '}'",
            EscapeError::LeadingUnderscoreUnicodeEscape => "Invalid escape sequence",
            EscapeError::OverlongUnicodeEscape => {
                "Unicode escape sequence should have at most 6 digits"
            }
            EscapeError::LoneSurrogateUnicodeEscape => {
                "Unicode escape code should not be a surrogate"
            }
            EscapeError::OutOfRangeUnicodeEscape => {
                "Unicode escape code should be at most 0x10FFFF"
            }
            EscapeError::UnicodeEscapeInByte => "Unicode escapes are not allowed in bytes",
            EscapeError::NonAsciiCharInByte => "Non ASCII characters are not allowed in bytes",
        };
        write!(f, "{}", msg)
    }
}

impl From<EscapeError> for SyntaxErrorKind {
    fn from(err: EscapeError) -> Self {
        SyntaxErrorKind::EscapeError(err)
    }
}
<commit_msg>ra_syntax: remove backticks from TokenizeError message since that is not Markdown ;(<commit_after>//! FIXME: write short doc here

use std::fmt;

use ra_parser::ParseError;

use crate::{validation::EscapeError, TextRange, TextUnit, TokenizeError};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SyntaxError {
    kind: SyntaxErrorKind,
    location: Location,
}

// FIXME: Location should be just `Location(TextRange)`
// TextUnit enum member just unnecessarily compicates things,
// we should'n treat it specially, it just as a `TextRange { start: x, end: x + 1 }`
// see `location_to_range()` in ra_ide/src/diagnostics
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum Location {
    Offset(TextUnit),
    Range(TextRange),
}

impl From<TextUnit> for Location {
    fn from(offset: TextUnit) -> Location {
        Location::Offset(offset)
    }
}

impl From<TextRange> for Location {
    fn from(range: TextRange) -> Location {
        Location::Range(range)
    }
}

impl fmt::Debug for Location {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Location::Offset(it) => fmt::Debug::fmt(it, f),
            Location::Range(it) => fmt::Debug::fmt(it, f),
        }
    }
}

impl SyntaxError {
    pub fn new<L: Into<Location>>(kind: SyntaxErrorKind, loc: L) -> SyntaxError {
        SyntaxError { kind, location: loc.into() }
    }

    pub fn kind(&self) -> SyntaxErrorKind {
        self.kind.clone()
    }

    pub fn location(&self) -> Location {
        self.location.clone()
    }

    pub fn offset(&self) -> TextUnit {
        match self.location {
            Location::Offset(offset) => offset,
            Location::Range(range) => range.start(),
        }
    }

    pub fn add_offset(mut self, plus_offset: TextUnit, minus_offset: TextUnit) -> SyntaxError {
        self.location = match self.location {
            Location::Range(range) => Location::Range(range + plus_offset - minus_offset),
            Location::Offset(offset) => Location::Offset(offset + plus_offset - minus_offset),
        };

        self
    }
}

impl fmt::Display for SyntaxError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.kind.fmt(f)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum SyntaxErrorKind {
    ParseError(ParseError),
    EscapeError(EscapeError),
    TokenizeError(TokenizeError),
    // FIXME: the obvious pattern of this enum dictates that the following enum variants
    // should be wrapped into something like `SemmanticError(SemmanticError)`
    // or `ValidateError(ValidateError)` or `SemmanticValidateError(...)`
    InvalidBlockAttr,
    InvalidMatchInnerAttr,
    InvalidTupleIndexFormat,
    VisibilityNotAllowed,
    InclusiveRangeMissingEnd,
}

impl fmt::Display for SyntaxErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::SyntaxErrorKind::*;
        match self {
            InvalidBlockAttr => {
                write!(f, "A block in this position cannot accept inner attributes")
            }
            InvalidMatchInnerAttr => {
                write!(f, "Inner attributes are only allowed directly after the opening brace of the match expression")
            }
            InvalidTupleIndexFormat => {
                write!(f, "Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix")
            }
            ParseError(msg) => write!(f, "{}", msg.0),
            EscapeError(err) => write!(f, "{}", err),
            TokenizeError(err) => write!(f, "{}", err),
            VisibilityNotAllowed => {
                write!(f, "unnecessary visibility qualifier")
            }
            InclusiveRangeMissingEnd => {
                write!(f, "An inclusive range must have an end expression")
            }
        }
    }
}

impl fmt::Display for TokenizeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let msg = match self {
            TokenizeError::EmptyInt => "Missing digits after integer base prefix",
            TokenizeError::EmptyExponent => "Missing digits after the exponent symbol",
            TokenizeError::UnterminatedBlockComment => {
                "Missing trailing */ symbols to terminate the block comment"
            }
            TokenizeError::UnterminatedChar => {
                "Missing trailing ' symbol to terminate the character literal"
            }
            TokenizeError::UnterminatedByte => {
                "Missing trailing ' symbol to terminate the byte literal"
            }
            TokenizeError::UnterminatedString => {
                "Missing trailing \" symbol to terminate the string literal"
            }
            TokenizeError::UnterminatedByteString => {
                "Missing trailing \" symbol to terminate the byte string literal"
            }
            TokenizeError::UnterminatedRawString => {
                "Missing trailing \" with # symbols to terminate the raw string literal"
            }
            TokenizeError::UnterminatedRawByteString => {
                "Missing trailing \" with # symbols to terminate the raw byte string literal"
            }
            TokenizeError::UnstartedRawString => {
                "Missing \" symbol after # symbols to begin the raw string literal"
            }
            TokenizeError::UnstartedRawByteString => {
                "Missing \" symbol after # symbols to begin the raw byte string literal"
            }
            TokenizeError::LifetimeStartsWithNumber => "Lifetime name cannot start with a number",
        };
        write!(f, "{}", msg)
    }
}

impl fmt::Display for EscapeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let msg = match self {
            EscapeError::ZeroChars => "Empty literal",
            EscapeError::MoreThanOneChar => "Literal should be one character long",
            EscapeError::LoneSlash => "Character must be escaped: '\\'",
            EscapeError::InvalidEscape => "Invalid escape sequence",
            EscapeError::BareCarriageReturn => "Character must be escaped: '\r'",
            EscapeError::EscapeOnlyChar => "Character must be escaped",
            EscapeError::TooShortHexEscape => "Escape sequence should have two digits",
            EscapeError::InvalidCharInHexEscape => "Escape sequence should be a hexadecimal number",
            EscapeError::OutOfRangeHexEscape => "Escape sequence should be ASCII",
            EscapeError::NoBraceInUnicodeEscape => "Invalid escape sequence",
            EscapeError::InvalidCharInUnicodeEscape => "Invalid escape sequence",
            EscapeError::EmptyUnicodeEscape => "Invalid escape sequence",
            EscapeError::UnclosedUnicodeEscape => "Missing '}'",
            EscapeError::LeadingUnderscoreUnicodeEscape => "Invalid escape sequence",
            EscapeError::OverlongUnicodeEscape => {
                "Unicode escape sequence should have at most 6 digits"
            }
            EscapeError::LoneSurrogateUnicodeEscape => {
                "Unicode escape code should not be a surrogate"
            }
            EscapeError::OutOfRangeUnicodeEscape => {
                "Unicode escape code should be at most 0x10FFFF"
            }
            EscapeError::UnicodeEscapeInByte => "Unicode escapes are not allowed in bytes",
            EscapeError::NonAsciiCharInByte => "Non ASCII characters are not allowed in bytes",
        };
        write!(f, "{}", msg)
    }
}

impl From<EscapeError> for SyntaxErrorKind {
    fn from(err: EscapeError) -> Self {
        SyntaxErrorKind::EscapeError(err)
    }
}
<|endoftext|>


<commit_before>#![feature(mpsc_select)]

extern crate crossbeam;

use std::sync::mpsc;

mod message;

const MESSAGES: usize = 5_000_000;
const THREADS: usize = 4;

pub fn shuffle<T>(v: &mut [T]) {
    use std::cell::Cell;
    use std::num::Wrapping;

    let len = v.len();
    if len <= 1 {
        return;
    }

    thread_local! {
        static RNG: Cell<Wrapping<u32>> = Cell::new(Wrapping(1));
    }

    RNG.with(|rng| {
        for i in 1..len {
            // This is the 32-bit variant of Xorshift.
            // https://en.wikipedia.org/wiki/Xorshift
            let mut x = rng.get();
            x ^= x << 13;
            x ^= x >> 17;
            x ^= x << 5;
            rng.set(x);

            let x = x.0;
            let n = i + 1;

            // This is a fast alternative to `let j = x % n`.
            // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
            let j = ((x as u64).wrapping_mul(n as u64) >> 32) as u32 as usize;

            v.swap(i, j);
        }
    });
}

fn seq_async() {
    let (tx, rx) = mpsc::channel();

    for i in 0..MESSAGES {
        tx.send(message::new(i)).unwrap();
    }

    for _ in 0..MESSAGES {
        rx.recv().unwrap();
    }
}

fn seq_sync(cap: usize) {
    let (tx, rx) = mpsc::sync_channel(cap);

    for i in 0..MESSAGES {
        tx.send(message::new(i)).unwrap();
    }

    for _ in 0..MESSAGES {
        rx.recv().unwrap();
    }
}

fn spsc_async() {
    let (tx, rx) = mpsc::channel();

    crossbeam::scope(|scope| {
        scope.spawn(move |_| {
            for i in 0..MESSAGES {
                tx.send(message::new(i)).unwrap();
            }
        });

        for _ in 0..MESSAGES {
            rx.recv().unwrap();
        }
    })
    .unwrap();
}

fn spsc_sync(cap: usize) {
    let (tx, rx) = mpsc::sync_channel(cap);

    crossbeam::scope(|scope| {
        scope.spawn(move |_| {
            for i in 0..MESSAGES {
                tx.send(message::new(i)).unwrap();
            }
        });

        for _ in 0..MESSAGES {
            rx.recv().unwrap();
        }
    })
    .unwrap();
}

fn mpsc_async() {
    let (tx, rx) = mpsc::channel();

    crossbeam::scope(|scope| {
        for _ in 0..THREADS {
            let tx = tx.clone();
            scope.spawn(move |_| {
                for i in 0..MESSAGES / THREADS {
                    tx.send(message::new(i)).unwrap();
                }
            });
        }

        for _ in 0..MESSAGES {
            rx.recv().unwrap();
        }
    })
    .unwrap();
}

fn mpsc_sync(cap: usize) {
    let (tx, rx) = mpsc::sync_channel(cap);

    crossbeam::scope(|scope| {
        for _ in 0..THREADS {
            let tx = tx.clone();
            scope.spawn(move |_| {
                for i in 0..MESSAGES / THREADS {
                    tx.send(message::new(i)).unwrap();
                }
            });
        }

        for _ in 0..MESSAGES {
            rx.recv().unwrap();
        }
    })
    .unwrap();
}

fn select_rx_async() {
    assert_eq!(THREADS, 4);
    let mut chans = (0..THREADS).map(|_| mpsc::channel()).collect::<Vec<_>>();

    crossbeam::scope(|scope| {
        for &(ref tx, _) in &chans {
            let tx = tx.clone();
            scope.spawn(move |_| {
                for i in 0..MESSAGES / THREADS {
                    tx.send(message::new(i)).unwrap();
                }
            });
        }

        for _ in 0..MESSAGES {
            shuffle(&mut chans);
            let rx0 = &chans[0].1;
            let rx1 = &chans[1].1;
            let rx2 = &chans[2].1;
            let rx3 = &chans[3].1;

            #[allow(deprecated)]
            {
                select! {
                    m = rx0.recv() => assert!(m.is_ok()),
                    m = rx1.recv() => assert!(m.is_ok()),
                    m = rx2.recv() => assert!(m.is_ok()),
                    m = rx3.recv() => assert!(m.is_ok())
                }
            }
        }
    })
    .unwrap();
}

fn select_rx_sync(cap: usize) {
    assert_eq!(THREADS, 4);
    let mut chans = (0..THREADS)
        .map(|_| mpsc::sync_channel(cap))
        .collect::<Vec<_>>();

    crossbeam::scope(|scope| {
        for &(ref tx, _) in &chans {
            let tx = tx.clone();
            scope.spawn(move |_| {
                for i in 0..MESSAGES / THREADS {
                    tx.send(message::new(i)).unwrap();
                }
            });
        }

        for _ in 0..MESSAGES {
            shuffle(&mut chans);
            let rx0 = &chans[0].1;
            let rx1 = &chans[1].1;
            let rx2 = &chans[2].1;
            let rx3 = &chans[3].1;

            #[allow(deprecated)]
            {
                select! {
                    m = rx0.recv() => assert!(m.is_ok()),
                    m = rx1.recv() => assert!(m.is_ok()),
                    m = rx2.recv() => assert!(m.is_ok()),
                    m = rx3.recv() => assert!(m.is_ok())
                }
            }
        }
    })
    .unwrap();
}

fn main() {
    macro_rules! run {
        ($name:expr, $f:expr) => {
            let now = ::std::time::Instant::now();
            $f;
            let elapsed = now.elapsed();
            println!(
                "{:25} {:15} {:7.3} sec",
                $name,
                "Rust mpsc",
                elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 / 1e9
            );
        };
    }

    run!("bounded0_mpsc", mpsc_sync(0));
    run!("bounded0_select_rx", select_rx_sync(0));
    run!("bounded0_spsc", spsc_sync(0));

    run!("bounded1_mpsc", mpsc_sync(1));
    run!("bounded1_select_rx", select_rx_sync(1));
    run!("bounded1_spsc", spsc_sync(1));

    run!("bounded_mpsc", mpsc_sync(MESSAGES));
    run!("bounded_select_rx", select_rx_sync(MESSAGES));
    run!("bounded_seq", seq_sync(MESSAGES));
    run!("bounded_spsc", spsc_sync(MESSAGES));

    run!("unbounded_mpsc", mpsc_async());
    run!("unbounded_select_rx", select_rx_async());
    run!("unbounded_seq", seq_async());
    run!("unbounded_spsc", spsc_async());
}
<commit_msg>Remove code using mpsc_select<commit_after>extern crate crossbeam;

use std::sync::mpsc;

mod message;

const MESSAGES: usize = 5_000_000;
const THREADS: usize = 4;

pub fn shuffle<T>(v: &mut [T]) {
    use std::cell::Cell;
    use std::num::Wrapping;

    let len = v.len();
    if len <= 1 {
        return;
    }

    thread_local! {
        static RNG: Cell<Wrapping<u32>> = Cell::new(Wrapping(1));
    }

    RNG.with(|rng| {
        for i in 1..len {
            // This is the 32-bit variant of Xorshift.
            // https://en.wikipedia.org/wiki/Xorshift
            let mut x = rng.get();
            x ^= x << 13;
            x ^= x >> 17;
            x ^= x << 5;
            rng.set(x);

            let x = x.0;
            let n = i + 1;

            // This is a fast alternative to `let j = x % n`.
            // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
            let j = ((x as u64).wrapping_mul(n as u64) >> 32) as u32 as usize;

            v.swap(i, j);
        }
    });
}

fn seq_async() {
    let (tx, rx) = mpsc::channel();

    for i in 0..MESSAGES {
        tx.send(message::new(i)).unwrap();
    }

    for _ in 0..MESSAGES {
        rx.recv().unwrap();
    }
}

fn seq_sync(cap: usize) {
    let (tx, rx) = mpsc::sync_channel(cap);

    for i in 0..MESSAGES {
        tx.send(message::new(i)).unwrap();
    }

    for _ in 0..MESSAGES {
        rx.recv().unwrap();
    }
}

fn spsc_async() {
    let (tx, rx) = mpsc::channel();

    crossbeam::scope(|scope| {
        scope.spawn(move |_| {
            for i in 0..MESSAGES {
                tx.send(message::new(i)).unwrap();
            }
        });

        for _ in 0..MESSAGES {
            rx.recv().unwrap();
        }
    })
    .unwrap();
}

fn spsc_sync(cap: usize) {
    let (tx, rx) = mpsc::sync_channel(cap);

    crossbeam::scope(|scope| {
        scope.spawn(move |_| {
            for i in 0..MESSAGES {
                tx.send(message::new(i)).unwrap();
            }
        });

        for _ in 0..MESSAGES {
            rx.recv().unwrap();
        }
    })
    .unwrap();
}

fn mpsc_async() {
    let (tx, rx) = mpsc::channel();

    crossbeam::scope(|scope| {
        for _ in 0..THREADS {
            let tx = tx.clone();
            scope.spawn(move |_| {
                for i in 0..MESSAGES / THREADS {
                    tx.send(message::new(i)).unwrap();
                }
            });
        }

        for _ in 0..MESSAGES {
            rx.recv().unwrap();
        }
    })
    .unwrap();
}

fn mpsc_sync(cap: usize) {
    let (tx, rx) = mpsc::sync_channel(cap);

    crossbeam::scope(|scope| {
        for _ in 0..THREADS {
            let tx = tx.clone();
            scope.spawn(move |_| {
                for i in 0..MESSAGES / THREADS {
                    tx.send(message::new(i)).unwrap();
                }
            });
        }

        for _ in 0..MESSAGES {
            rx.recv().unwrap();
        }
    })
    .unwrap();
}

fn main() {
    macro_rules! run {
        ($name:expr, $f:expr) => {
            let now = ::std::time::Instant::now();
            $f;
            let elapsed = now.elapsed();
            println!(
                "{:25} {:15} {:7.3} sec",
                $name,
                "Rust mpsc",
                elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 / 1e9
            );
        };
    }

    run!("bounded0_mpsc", mpsc_sync(0));
    run!("bounded0_spsc", spsc_sync(0));

    run!("bounded1_mpsc", mpsc_sync(1));
    run!("bounded1_spsc", spsc_sync(1));

    run!("bounded_mpsc", mpsc_sync(MESSAGES));
    run!("bounded_seq", seq_sync(MESSAGES));
    run!("bounded_spsc", spsc_sync(MESSAGES));

    run!("unbounded_mpsc", mpsc_async());
    run!("unbounded_seq", seq_async());
    run!("unbounded_spsc", spsc_async());
}
<|endoftext|>


<commit_before>#![crate_type = "rlib"]
#![feature(macro_rules,globs)]

#[macro_export]
macro_rules! monad(
    ($m:ident {
        let $p:pat <- $e:expr;
        $(let $p_rest:pat <- $e_rest:expr;)*
    } in $y:expr) => (
        $m::mbind($e,|$p| {
            monad!($m {
                $(let $p_rest <- $e_rest;)*
            } in $y)
        }));
    ($m:ident { } in $y:expr) => ($m::mpure($y));
)

pub struct OptionMonad;

impl OptionMonad {
    pub fn mpure<T>(value: T) -> Option<T> { Some(value) }
    pub fn mbind<T,U>(value: Option<T>, func: |T| -> Option<U>) -> Option<U> {
        match value {
            Some(v) => func(v),
            None => None
        }
    }
}

pub struct ResultMonad;

impl ResultMonad {
    pub fn mpure<T,E>(value: T) -> Result<T,E> { Ok(value) }
    pub fn mbind<T,U,E>(value: Result<T,E>, func: |T| -> Result<U,E>) -> Result<U,E> {
        match value {
            Ok(v) => func(v),
            Err(e) => Err(e)
        }
    }
}

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

    #[test]
    fn option() {
        let result = monad!(OptionMonad {
            let (a,x) <- Some((2i,6i));
            let (b,y) <- Some((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, Some((2+3,6*7)));
    }

    #[test]
    fn option_fail() {
        let result = monad!(OptionMonad {
            let (a,x) <- None::<(int,int)>;
            let (b,y) <- Some((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, None);
    }

    #[test]
    fn result() {
        let result: Result<(int,int),()> = monad!(ResultMonad {
            let (a,x) <- Ok((2i,6i));
            let (b,y) <- Ok((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, Ok((2+3,6*7)));
    }

    #[test]
    fn result_fail() {
        let result: Result<(int,int),()> = monad!(ResultMonad {
            let (a,x) <- Err::<(int,int),()>(());
            let (b,y) <- Ok((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, Err(()));
    }
}
<commit_msg>Add support for iterators<commit_after>#![crate_type = "rlib"]
#![feature(macro_rules,globs)]

#[macro_export]
macro_rules! monad(
    ($m:ident {
        let $p:pat <- $e:expr;
        $(let $p_rest:pat <- $e_rest:expr;)*
    } in $y:expr) => (
        $m::mbind($e,|$p| {
            monad!($m {
                $(let $p_rest <- $e_rest;)*
            } in $y)
        }));
    ($m:ident { } in $y:expr) => ($m::mpure($y));
)

pub struct OptionMonad;

impl OptionMonad {
    pub fn mpure<T>(value: T) -> Option<T> { Some(value) }
    pub fn mbind<T,U>(value: Option<T>, func: |T| -> Option<U>) -> Option<U> {
        match value {
            Some(v) => func(v),
            None => None
        }
    }
}

pub struct ResultMonad;

impl ResultMonad {
    pub fn mpure<T,E>(value: T) -> Result<T,E> { Ok(value) }
    pub fn mbind<T,U,E>(value: Result<T,E>, func: |T| -> Result<U,E>) -> Result<U,E> {
        match value {
            Ok(v) => func(v),
            Err(e) => Err(e)
        }
    }
}

pub struct IterMonad;

impl IterMonad {
    pub fn mpure<T>(value: T) -> std::option::Item<T> {
        Some(value).move_iter()
    }
    pub fn mbind<T,U,I:Iterator<T>,J:Iterator<U>>(value: I, func: |T| -> J)
                                                  -> std::vec::MoveItems<U> {
        value.flat_map(func).collect::<Vec<U>>().move_iter()
    }
}

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

    #[test]
    fn option() {
        let result = monad!(OptionMonad {
            let (a,x) <- Some((2i,6i));
            let (b,y) <- Some((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, Some((2+3,6*7)));
    }

    #[test]
    fn option_fail() {
        let result = monad!(OptionMonad {
            let (a,x) <- None::<(int,int)>;
            let (b,y) <- Some((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, None);
    }

    #[test]
    fn result() {
        let result: Result<(int,int),()> = monad!(ResultMonad {
            let (a,x) <- Ok((2i,6i));
            let (b,y) <- Ok((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, Ok((2+3,6*7)));
    }

    #[test]
    fn result_fail() {
        let result: Result<(int,int),()> = monad!(ResultMonad {
            let (a,x) <- Err::<(int,int),()>(());
            let (b,y) <- Ok((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, Err(()));
    }

    #[test]
    fn iter() {
        let mut result = monad!(IterMonad {
            let a <- vec![1u,2,3].move_iter();
            let b <- vec!["hello"].move_iter();
        } in (a,b));

        assert_eq!(result.collect::<Vec<(uint,&'static str)>>(),
                   vec![(1u,"hello"),(2,"hello"),(3,"hello")]);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate slog;

extern crate futures;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_uds;

extern crate rdmcommon;

use std::io;

use rdmcommon::ipc;
use rdmcommon::util;

use futures::{Future, Stream, Sink};
use slog::Logger;
use tokio_core::reactor::{Core, Handle};
use tokio_io::AsyncRead;
use tokio_uds::UnixStream;

pub struct RdmGreeter {
    log: Logger,
    core: Core,
    receiver: Box<Stream<Item = ipc::IpcMessage, Error = ipc::IpcError>>,
    sender: Box<Sink<SinkItem = ipc::IpcMessage, SinkError = ipc::IpcError>>,
}

#[derive(Debug)]
pub enum RdmGreeterError {
    Ipc(ipc::IpcError),
    Io(io::Error),
    FailedHandshake
}

impl From<io::Error> for RdmGreeterError {
    fn from(err: io::Error) -> RdmGreeterError {
        RdmGreeterError::Io(err)
    }
}

impl From<ipc::IpcError> for RdmGreeterError {
    fn from(err: ipc::IpcError) -> RdmGreeterError {
        RdmGreeterError::Ipc(err)
    }
}

impl RdmGreeter {
    pub fn new<L : Into<Option<Logger>>>(logger: L) -> Result<RdmGreeter, RdmGreeterError> {
        let log = logger.into().unwrap_or_else(util::plain_logger);
        let mut core = Core::new()?;
        let handle = core.handle();
        // TODO: move this into private fn
        debug!(log, "[RdmGreeter::new] Connecting server socket");
        let sock = UnixStream::connect("/home/florian/tmp/sock", &handle)?;
        let (tx, rx) = sock.framed(ipc::IpcMessageCodec).split();

        debug!(log, "[RdmGreeter::new] Sending ClientHello");
        let tx = core.run(tx.send(ipc::IpcMessage::ClientHello))?;

        debug!(log, "[RdmGreeter::new] Reading server response");
        let (resp, rx) = core.run(rx.take(1).into_future().map_err(|(err, _)| err))?;
        debug!(log, "[RdmGreeter::new] Got server response"; "response" => ?resp);

        match resp {
            Some(ipc::IpcMessage::ServerHello) => Ok(RdmGreeter {
                                                        core: core,
                                                        receiver: Box::new(rx),
                                                        sender: Box::new(tx),
                                                        log: log,
                                                  }),
            _ => Err(RdmGreeterError::FailedHandshake)
        }
    }
}

impl Drop for RdmGreeter {
    fn drop(&mut self) {
        debug!(self.log, "[RdmGreeter::drop] Dropping RdmGreeter..");
    }
}<commit_msg>[libgreeter] Remove unused import<commit_after>#[macro_use]
extern crate slog;

extern crate futures;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_uds;

extern crate rdmcommon;

use std::io;

use rdmcommon::ipc;
use rdmcommon::util;

use futures::{Future, Stream, Sink};
use slog::Logger;
use tokio_core::reactor::Core;
use tokio_io::AsyncRead;
use tokio_uds::UnixStream;

pub struct RdmGreeter {
    log: Logger,
    core: Core,
    receiver: Box<Stream<Item = ipc::IpcMessage, Error = ipc::IpcError>>,
    sender: Box<Sink<SinkItem = ipc::IpcMessage, SinkError = ipc::IpcError>>,
}

#[derive(Debug)]
pub enum RdmGreeterError {
    Ipc(ipc::IpcError),
    Io(io::Error),
    FailedHandshake
}

impl From<io::Error> for RdmGreeterError {
    fn from(err: io::Error) -> RdmGreeterError {
        RdmGreeterError::Io(err)
    }
}

impl From<ipc::IpcError> for RdmGreeterError {
    fn from(err: ipc::IpcError) -> RdmGreeterError {
        RdmGreeterError::Ipc(err)
    }
}

impl RdmGreeter {
    pub fn new<L : Into<Option<Logger>>>(logger: L) -> Result<RdmGreeter, RdmGreeterError> {
        let log = logger.into().unwrap_or_else(util::plain_logger);
        let mut core = Core::new()?;
        let handle = core.handle();
        // TODO: move this into private fn
        debug!(log, "[RdmGreeter::new] Connecting server socket");
        let sock = UnixStream::connect("/home/florian/tmp/sock", &handle)?;
        let (tx, rx) = sock.framed(ipc::IpcMessageCodec).split();

        debug!(log, "[RdmGreeter::new] Sending ClientHello");
        let tx = core.run(tx.send(ipc::IpcMessage::ClientHello))?;

        debug!(log, "[RdmGreeter::new] Reading server response");
        let (resp, rx) = core.run(rx.take(1).into_future().map_err(|(err, _)| err))?;
        debug!(log, "[RdmGreeter::new] Got server response"; "response" => ?resp);

        match resp {
            Some(ipc::IpcMessage::ServerHello) => Ok(RdmGreeter {
                                                        core: core,
                                                        receiver: Box::new(rx),
                                                        sender: Box::new(tx),
                                                        log: log,
                                                  }),
            _ => Err(RdmGreeterError::FailedHandshake)
        }
    }
}

impl Drop for RdmGreeter {
    fn drop(&mut self) {
        debug!(self.log, "[RdmGreeter::drop] Dropping RdmGreeter..");
    }
}<|endoftext|>