<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A work queue for scheduling units of work across threads in a fork-join fashion.
//!
//! Data associated with queues is simply a pair of unsigned integers. It is expected that a
//! higher-level API on top of this could allow safe fork-join parallelism.

use native;
use rand;
use rand::{Rng, XorShiftRng};
use std::cast;
use std::comm;
use std::mem;
use std::sync::atomics::{AtomicUint, SeqCst};
use std::sync::deque::{Abort, BufferPool, Data, Empty, Stealer, Worker};
use std::task::TaskOpts;

/// A unit of work.
///
/// The type parameter `QUD` stands for "queue user data" and represents global custom data for the
/// entire work queue, and the type parameter `WUD` stands for "work user data" and represents
/// custom data specific to each unit of work.
pub struct WorkUnit<QUD,WUD> {
    /// The function to execute.
    pub fun: extern "Rust" fn(WUD, &mut WorkerProxy<QUD,WUD>),
    /// Arbitrary data.
    pub data: WUD,
}

/// Messages from the supervisor to the worker.
enum WorkerMsg<QUD,WUD> {
    /// Tells the worker to start work.
    StartMsg(Worker<WorkUnit<QUD,WUD>>, *mut AtomicUint, *QUD),

    /// Tells the worker to stop. It can be restarted again with a `StartMsg`.
    StopMsg,

    /// Tells the worker thread to terminate.
    ExitMsg,
}

/// Messages to the supervisor.
enum SupervisorMsg<QUD,WUD> {
    FinishedMsg,
    ReturnDequeMsg(uint, Worker<WorkUnit<QUD,WUD>>),
}

/// Information that the supervisor thread keeps about the worker threads.
struct WorkerInfo<QUD,WUD> {
    /// The communication channel to the workers.
    chan: Sender<WorkerMsg<QUD,WUD>>,
    /// The buffer pool for this deque.
    pool: BufferPool<WorkUnit<QUD,WUD>>,
    /// The worker end of the deque, if we have it.
    deque: Option<Worker<WorkUnit<QUD,WUD>>>,
    /// The thief end of the work-stealing deque.
    thief: Stealer<WorkUnit<QUD,WUD>>,
}

/// Information specific to each worker thread that the thread keeps.
struct WorkerThread<QUD,WUD> {
    /// The index of this worker.
    index: uint,
    /// The communication port from the supervisor.
    port: Receiver<WorkerMsg<QUD,WUD>>,
    /// The communication channel on which messages are sent to the supervisor.
    chan: Sender<SupervisorMsg<QUD,WUD>>,
    /// The thief end of the work-stealing deque for all other workers.
    other_deques: ~[Stealer<WorkUnit<QUD,WUD>>],
    /// The random number generator for this worker.
    rng: XorShiftRng,
}

static SPIN_COUNT: uint = 1000;

impl<QUD:Send,WUD:Send> WorkerThread<QUD,WUD> {
    /// The main logic. This function starts up the worker and listens for
    /// messages.
    pub fn start(&mut self) {
        loop {
            // Wait for a start message.
            let (mut deque, ref_count, queue_data) = match self.port.recv() {
                StartMsg(deque, ref_count, queue_data) => (deque, ref_count, queue_data),
                StopMsg => fail!("unexpected stop message"),
                ExitMsg => return,
            };

            // We're off!
            //
            // FIXME(pcwalton): Can't use labeled break or continue cross-crate due to a Rust bug.
            loop {
                // FIXME(pcwalton): Nasty workaround for the lack of labeled break/continue
                // cross-crate.
                let mut work_unit = unsafe {
                    mem::uninit()
                };
                match deque.pop() {
                    Some(work) => work_unit = work,
                    None => {
                        // Become a thief.
                        let mut i = 0;
                        let mut should_continue = true;
                        loop {
                            let victim = (self.rng.next_u32() as uint) % self.other_deques.len();
                            match self.other_deques[victim].steal() {
                                Empty | Abort => {
                                    // Continue.
                                }
                                Data(work) => {
                                    work_unit = work;
                                    break
                                }
                            }

                            if i == SPIN_COUNT {
                                match self.port.try_recv() {
                                    comm::Data(StopMsg) => {
                                        should_continue = false;
                                        break
                                    }
                                    comm::Data(ExitMsg) => return,
                                    comm::Data(_) => fail!("unexpected message"),
                                    _ => {}
                                }

                                i = 0
                            } else {
                                i += 1
                            }
                        }

                        if !should_continue {
                            break
                        }
                    }
                }

                // At this point, we have some work. Perform it.
                let mut proxy = WorkerProxy {
                    worker: &mut deque,
                    ref_count: ref_count,
                    queue_data: queue_data,
                };
                (work_unit.fun)(work_unit.data, &mut proxy);

                // The work is done. Now decrement the count of outstanding work items. If this was
                // the last work unit in the queue, then send a message on the channel.
                unsafe {
                    if (*ref_count).fetch_sub(1, SeqCst) == 1 {
                        self.chan.send(FinishedMsg)
                    }
                }
            }

            // Give the deque back to the supervisor.
            self.chan.send(ReturnDequeMsg(self.index, deque))
        }
    }
}

/// A handle to the work queue that individual work units have.
pub struct WorkerProxy<'a,QUD,WUD> {
    pub worker: &'a mut Worker<WorkUnit<QUD,WUD>>,
    pub ref_count: *mut AtomicUint,
    pub queue_data: *QUD,
}

impl<'a,QUD,WUD:Send> WorkerProxy<'a,QUD,WUD> {
    /// Enqueues a block into the work queue.
    #[inline]
    pub fn push(&mut self, work_unit: WorkUnit<QUD,WUD>) {
        unsafe {
            drop((*self.ref_count).fetch_add(1, SeqCst));
        }
        self.worker.push(work_unit);
    }

    /// Retrieves the queue user data.
    #[inline]
    pub fn user_data<'a>(&'a self) -> &'a QUD {
        unsafe {
            cast::transmute(self.queue_data)
        }
    }
}

/// A work queue on which units of work can be submitted.
pub struct WorkQueue<QUD,WUD> {
    /// Information about each of the workers.
    workers: ~[WorkerInfo<QUD,WUD>],
    /// A port on which deques can be received from the workers.
    port: Receiver<SupervisorMsg<QUD,WUD>>,
    /// The amount of work that has been enqueued.
    pub work_count: uint,
    /// Arbitrary user data.
    pub data: QUD,
}

impl<QUD:Send,WUD:Send> WorkQueue<QUD,WUD> {
    /// Creates a new work queue and spawns all the threads associated with
    /// it.
    pub fn new(task_name: &'static str, thread_count: uint, user_data: QUD) -> WorkQueue<QUD,WUD> {
        // Set up data structures.
        let (supervisor_chan, supervisor_port) = channel();
        let (mut infos, mut threads) = (~[], ~[]);
        for i in range(0, thread_count) {
            let (worker_chan, worker_port) = channel();
            let mut pool = BufferPool::new();
            let (worker, thief) = pool.deque();
            infos.push(WorkerInfo {
                chan: worker_chan,
                pool: pool,
                deque: Some(worker),
                thief: thief,
            });
            threads.push(WorkerThread {
                index: i,
                port: worker_port,
                chan: supervisor_chan.clone(),
                other_deques: ~[],
                rng: rand::weak_rng(),
            });
        }

        // Connect workers to one another.
        for i in range(0, thread_count) {
            for j in range(0, thread_count) {
                if i != j {
                    threads[i].other_deques.push(infos[j].thief.clone())
                }
            }
            assert!(threads[i].other_deques.len() == thread_count - 1)
        }

        // Spawn threads.
        for thread in threads.move_iter() {
            let mut opts = TaskOpts::new();
            opts.name = Some(task_name.into_maybe_owned());
            native::task::spawn_opts(opts, proc() {
                let mut thread = thread;
                thread.start()
            })
        }

        WorkQueue {
            workers: infos,
            port: supervisor_port,
            work_count: 0,
            data: user_data,
        }
    }

    /// Enqueues a block into the work queue.
    #[inline]
    pub fn push(&mut self, work_unit: WorkUnit<QUD,WUD>) {
        match self.workers[0].deque {
            None => {
                fail!("tried to push a block but we don't have the deque?!")
            }
            Some(ref mut deque) => deque.push(work_unit),
        }
        self.work_count += 1
    }

    /// Synchronously runs all the enqueued tasks and waits for them to complete.
    pub fn run(&mut self) {
        // Tell the workers to start.
        let mut work_count = AtomicUint::new(self.work_count);
        for worker in self.workers.mut_iter() {
            worker.chan.send(StartMsg(worker.deque.take_unwrap(), &mut work_count, &self.data))
        }

        // Wait for the work to finish.
        drop(self.port.recv());
        self.work_count = 0;

        // Tell everyone to stop.
        for worker in self.workers.iter() {
            worker.chan.send(StopMsg)
        }

        // Get our deques back.
        for _ in range(0, self.workers.len()) {
            match self.port.recv() {
                ReturnDequeMsg(index, deque) => self.workers[index].deque = Some(deque),
                FinishedMsg => fail!("unexpected finished message!"),
            }
        }
    }

    pub fn shutdown(&mut self) {
        for worker in self.workers.iter() {
            worker.chan.send(ExitMsg)
        }
    }
}

<commit_msg>Use Vec in workqueue.rs.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A work queue for scheduling units of work across threads in a fork-join fashion.
//!
//! Data associated with queues is simply a pair of unsigned integers. It is expected that a
//! higher-level API on top of this could allow safe fork-join parallelism.

use native;
use rand;
use rand::{Rng, XorShiftRng};
use std::cast;
use std::comm;
use std::mem;
use std::sync::atomics::{AtomicUint, SeqCst};
use std::sync::deque::{Abort, BufferPool, Data, Empty, Stealer, Worker};
use std::task::TaskOpts;

/// A unit of work.
///
/// The type parameter `QUD` stands for "queue user data" and represents global custom data for the
/// entire work queue, and the type parameter `WUD` stands for "work user data" and represents
/// custom data specific to each unit of work.
pub struct WorkUnit<QUD,WUD> {
    /// The function to execute.
    pub fun: extern "Rust" fn(WUD, &mut WorkerProxy<QUD,WUD>),
    /// Arbitrary data.
    pub data: WUD,
}

/// Messages from the supervisor to the worker.
enum WorkerMsg<QUD,WUD> {
    /// Tells the worker to start work.
    StartMsg(Worker<WorkUnit<QUD,WUD>>, *mut AtomicUint, *QUD),

    /// Tells the worker to stop. It can be restarted again with a `StartMsg`.
    StopMsg,

    /// Tells the worker thread to terminate.
    ExitMsg,
}

/// Messages to the supervisor.
enum SupervisorMsg<QUD,WUD> {
    FinishedMsg,
    ReturnDequeMsg(uint, Worker<WorkUnit<QUD,WUD>>),
}

/// Information that the supervisor thread keeps about the worker threads.
struct WorkerInfo<QUD,WUD> {
    /// The communication channel to the workers.
    chan: Sender<WorkerMsg<QUD,WUD>>,
    /// The buffer pool for this deque.
    pool: BufferPool<WorkUnit<QUD,WUD>>,
    /// The worker end of the deque, if we have it.
    deque: Option<Worker<WorkUnit<QUD,WUD>>>,
    /// The thief end of the work-stealing deque.
    thief: Stealer<WorkUnit<QUD,WUD>>,
}

/// Information specific to each worker thread that the thread keeps.
struct WorkerThread<QUD,WUD> {
    /// The index of this worker.
    index: uint,
    /// The communication port from the supervisor.
    port: Receiver<WorkerMsg<QUD,WUD>>,
    /// The communication channel on which messages are sent to the supervisor.
    chan: Sender<SupervisorMsg<QUD,WUD>>,
    /// The thief end of the work-stealing deque for all other workers.
    other_deques: Vec<Stealer<WorkUnit<QUD,WUD>>>,
    /// The random number generator for this worker.
    rng: XorShiftRng,
}

static SPIN_COUNT: uint = 1000;

impl<QUD:Send,WUD:Send> WorkerThread<QUD,WUD> {
    /// The main logic. This function starts up the worker and listens for
    /// messages.
    pub fn start(&mut self) {
        loop {
            // Wait for a start message.
            let (mut deque, ref_count, queue_data) = match self.port.recv() {
                StartMsg(deque, ref_count, queue_data) => (deque, ref_count, queue_data),
                StopMsg => fail!("unexpected stop message"),
                ExitMsg => return,
            };

            // We're off!
            //
            // FIXME(pcwalton): Can't use labeled break or continue cross-crate due to a Rust bug.
            loop {
                // FIXME(pcwalton): Nasty workaround for the lack of labeled break/continue
                // cross-crate.
                let mut work_unit = unsafe {
                    mem::uninit()
                };
                match deque.pop() {
                    Some(work) => work_unit = work,
                    None => {
                        // Become a thief.
                        let mut i = 0;
                        let mut should_continue = true;
                        loop {
                            let victim = (self.rng.next_u32() as uint) % self.other_deques.len();
                            match self.other_deques.get_mut(victim).steal() {
                                Empty | Abort => {
                                    // Continue.
                                }
                                Data(work) => {
                                    work_unit = work;
                                    break
                                }
                            }

                            if i == SPIN_COUNT {
                                match self.port.try_recv() {
                                    comm::Data(StopMsg) => {
                                        should_continue = false;
                                        break
                                    }
                                    comm::Data(ExitMsg) => return,
                                    comm::Data(_) => fail!("unexpected message"),
                                    _ => {}
                                }

                                i = 0
                            } else {
                                i += 1
                            }
                        }

                        if !should_continue {
                            break
                        }
                    }
                }

                // At this point, we have some work. Perform it.
                let mut proxy = WorkerProxy {
                    worker: &mut deque,
                    ref_count: ref_count,
                    queue_data: queue_data,
                };
                (work_unit.fun)(work_unit.data, &mut proxy);

                // The work is done. Now decrement the count of outstanding work items. If this was
                // the last work unit in the queue, then send a message on the channel.
                unsafe {
                    if (*ref_count).fetch_sub(1, SeqCst) == 1 {
                        self.chan.send(FinishedMsg)
                    }
                }
            }

            // Give the deque back to the supervisor.
            self.chan.send(ReturnDequeMsg(self.index, deque))
        }
    }
}

/// A handle to the work queue that individual work units have.
pub struct WorkerProxy<'a,QUD,WUD> {
    pub worker: &'a mut Worker<WorkUnit<QUD,WUD>>,
    pub ref_count: *mut AtomicUint,
    pub queue_data: *QUD,
}

impl<'a,QUD,WUD:Send> WorkerProxy<'a,QUD,WUD> {
    /// Enqueues a block into the work queue.
    #[inline]
    pub fn push(&mut self, work_unit: WorkUnit<QUD,WUD>) {
        unsafe {
            drop((*self.ref_count).fetch_add(1, SeqCst));
        }
        self.worker.push(work_unit);
    }

    /// Retrieves the queue user data.
    #[inline]
    pub fn user_data<'a>(&'a self) -> &'a QUD {
        unsafe {
            cast::transmute(self.queue_data)
        }
    }
}

/// A work queue on which units of work can be submitted.
pub struct WorkQueue<QUD,WUD> {
    /// Information about each of the workers.
    workers: Vec<WorkerInfo<QUD,WUD>>,
    /// A port on which deques can be received from the workers.
    port: Receiver<SupervisorMsg<QUD,WUD>>,
    /// The amount of work that has been enqueued.
    pub work_count: uint,
    /// Arbitrary user data.
    pub data: QUD,
}

impl<QUD:Send,WUD:Send> WorkQueue<QUD,WUD> {
    /// Creates a new work queue and spawns all the threads associated with
    /// it.
    pub fn new(task_name: &'static str, thread_count: uint, user_data: QUD) -> WorkQueue<QUD,WUD> {
        // Set up data structures.
        let (supervisor_chan, supervisor_port) = channel();
        let (mut infos, mut threads) = (vec!(), vec!());
        for i in range(0, thread_count) {
            let (worker_chan, worker_port) = channel();
            let mut pool = BufferPool::new();
            let (worker, thief) = pool.deque();
            infos.push(WorkerInfo {
                chan: worker_chan,
                pool: pool,
                deque: Some(worker),
                thief: thief,
            });
            threads.push(WorkerThread {
                index: i,
                port: worker_port,
                chan: supervisor_chan.clone(),
                other_deques: vec!(),
                rng: rand::weak_rng(),
            });
        }

        // Connect workers to one another.
        for i in range(0, thread_count) {
            for j in range(0, thread_count) {
                if i != j {
                    threads.get_mut(i).other_deques.push(infos.get(j).thief.clone())
                }
            }
            assert!(threads.get(i).other_deques.len() == thread_count - 1)
        }

        // Spawn threads.
        for thread in threads.move_iter() {
            let mut opts = TaskOpts::new();
            opts.name = Some(task_name.into_maybe_owned());
            native::task::spawn_opts(opts, proc() {
                let mut thread = thread;
                thread.start()
            })
        }

        WorkQueue {
            workers: infos,
            port: supervisor_port,
            work_count: 0,
            data: user_data,
        }
    }

    /// Enqueues a block into the work queue.
    #[inline]
    pub fn push(&mut self, work_unit: WorkUnit<QUD,WUD>) {
        match self.workers.get_mut(0).deque {
            None => {
                fail!("tried to push a block but we don't have the deque?!")
            }
            Some(ref mut deque) => deque.push(work_unit),
        }
        self.work_count += 1
    }

    /// Synchronously runs all the enqueued tasks and waits for them to complete.
    pub fn run(&mut self) {
        // Tell the workers to start.
        let mut work_count = AtomicUint::new(self.work_count);
        for worker in self.workers.mut_iter() {
            worker.chan.send(StartMsg(worker.deque.take_unwrap(), &mut work_count, &self.data))
        }

        // Wait for the work to finish.
        drop(self.port.recv());
        self.work_count = 0;

        // Tell everyone to stop.
        for worker in self.workers.iter() {
            worker.chan.send(StopMsg)
        }

        // Get our deques back.
        for _ in range(0, self.workers.len()) {
            match self.port.recv() {
                ReturnDequeMsg(index, deque) => self.workers.get_mut(index).deque = Some(deque),
                FinishedMsg => fail!("unexpected finished message!"),
            }
        }
    }

    pub fn shutdown(&mut self) {
        for worker in self.workers.iter() {
            worker.chan.send(ExitMsg)
        }
    }
}

<|endoftext|>


<commit_before>extern crate sovrin;

#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;

#[macro_use]
#[path = "utils/mod.rs"]
mod utils;

#[cfg(feature = "local_nodes_pool")]
use sovrin::api::ErrorCode;

use utils::pool::PoolUtils;
use utils::test::TestUtils;

mod high_cases {
    use super::*;

    mod create {
        use super::*;

        #[test]
        fn create_pool_ledger_config_works() {
            TestUtils::cleanup_storage();

            PoolUtils::create_pool_ledger_config("pool_create", None).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod open {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works() {
            TestUtils::cleanup_storage();
            let name = "pool_open";

            PoolUtils::create_pool_ledger_config(name, None).unwrap();

            PoolUtils::open_pool_ledger(name).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_twice() {
            TestUtils::cleanup_storage();
            let pool_name = "pool_open_twice";

            PoolUtils::create_pool_ledger_config(pool_name, None).unwrap();

            PoolUtils::open_pool_ledger(pool_name).unwrap();
            let res = PoolUtils::open_pool_ledger(pool_name);
            assert_match!(Err(ErrorCode::PoolLedgerInvalidPoolHandle), res);

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_two_nodes() {
            TestUtils::cleanup_storage();
            let pool_name = "open_pool_ledger_works_for_two_nodes";

            let nodes = format!("{}\n{}\n",
                                "{\"data\":{\"alias\":\"Node1\",\"client_ip\":\"10.0.0.2\",\"client_port\":9702,\"node_ip\":\"10.0.0.2\",\"node_port\":9701,\"services\":[\"VALIDATOR\"]},\"dest\":\"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv\",\"identifier\":\"FYmoFw55GeQH7SRFa37dkx1d2dZ3zUF8ckg7wmL7ofN4\",\"txnId\":\"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62\",\"type\":\"0\"}",
                                "{\"data\":{\"alias\":\"Node2\",\"client_ip\":\"10.0.0.2\",\"client_port\":9704,\"node_ip\":\"10.0.0.2\",\"node_port\":9703,\"services\":[\"VALIDATOR\"]},\"dest\":\"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb\",\"identifier\":\"8QhFxKxyaFsJy4CyxeYX34dFH8oWqyBv1P4HLQCsoeLy\",\"txnId\":\"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc\",\"type\":\"0\"}");

            PoolUtils::create_pool_ledger_config(pool_name, Some(nodes)).unwrap();

            PoolUtils::open_pool_ledger(pool_name).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_three_nodes() {
            TestUtils::cleanup_storage();
            let pool_name = "open_pool_ledger_works_for_three_nodes";

            let nodes = format!("{}\n{}\n{}\n",
                                "{\"data\":{\"alias\":\"Node1\",\"client_ip\":\"10.0.0.2\",\"client_port\":9702,\"node_ip\":\"10.0.0.2\",\"node_port\":9701,\"services\":[\"VALIDATOR\"]},\"dest\":\"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv\",\"identifier\":\"FYmoFw55GeQH7SRFa37dkx1d2dZ3zUF8ckg7wmL7ofN4\",\"txnId\":\"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62\",\"type\":\"0\"}",
                                "{\"data\":{\"alias\":\"Node2\",\"client_ip\":\"10.0.0.2\",\"client_port\":9704,\"node_ip\":\"10.0.0.2\",\"node_port\":9703,\"services\":[\"VALIDATOR\"]},\"dest\":\"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb\",\"identifier\":\"8QhFxKxyaFsJy4CyxeYX34dFH8oWqyBv1P4HLQCsoeLy\",\"txnId\":\"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc\",\"type\":\"0\"}",
                                "{\"data\":{\"alias\":\"Node3\",\"client_ip\":\"10.0.0.2\",\"client_port\":9706,\"node_ip\":\"10.0.0.2\",\"node_port\":9705,\"services\":[\"VALIDATOR\"]},\"dest\":\"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya\",\"identifier\":\"2yAeV5ftuasWNgQwVYzeHeTuM7LwwNtPR3Zg9N4JiDgF\",\"txnId\":\"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4\",\"type\":\"0\"}");

            PoolUtils::create_pool_ledger_config(pool_name, Some(nodes)).unwrap();

            PoolUtils::open_pool_ledger(pool_name).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod close {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn sovrin_close_pool_ledger_works() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_close_pool_ledger_works";
            let pool_handle = PoolUtils::create_and_open_pool_ledger_config(pool_name).unwrap();

            PoolUtils::close(pool_handle).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn sovrin_close_pool_ledger_works_for_reopen_after_close() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_close_pool_ledger_works";
            let pool_handle = PoolUtils::create_and_open_pool_ledger_config(pool_name).unwrap();

            PoolUtils::close(pool_handle).unwrap();
            PoolUtils::open_pool_ledger(pool_name).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_delete_pool_ledger_config_works() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_remove_pool_ledger_config_works";
            PoolUtils::create_pool_ledger_config(pool_name, None).unwrap();

            PoolUtils::delete(pool_name).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn sovrin_delete_pool_ledger_config_works_for_opened() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_remove_pool_ledger_config_works";
            PoolUtils::create_and_open_pool_ledger_config(pool_name).unwrap();

            assert_eq!(PoolUtils::delete(pool_name).unwrap_err(), ErrorCode::CommonInvalidState);

            TestUtils::cleanup_storage();
        }
    }
}

mod medium_cases {
    use super::*;

    mod open {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_invalid_nodes_file() {
            TestUtils::cleanup_storage();
            let pool_name = "open_pool_ledger_works_for_invalid_nodes_file";

            let nodes = format!("{}\n{}\n{}\n{}\n",
                                "{\"data\":{\"client_port\":9702,\"client_ip\":\"10.0.0.2\",\"node_ip\":\"10.0.0.2\",\"node_port\":9701,\"services\":[\"VALIDATOR\"]},\"dest\":\"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv\",\"identifier\":\"FYmoFw55GeQH7SRFa37dkx1d2dZ3zUF8ckg7wmL7ofN4\",\"txnId\":\"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62\",\"type\":\"0\"}",
                                "{\"data\":{\"client_port\":9704,\"client_ip\":\"10.0.0.2\",\"node_ip\":\"10.0.0.2\",\"node_port\":9703,\"services\":[\"VALIDATOR\"]},\"dest\":\"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb\",\"identifier\":\"8QhFxKxyaFsJy4CyxeYX34dFH8oWqyBv1P4HLQCsoeLy\",\"txnId\":\"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc\",\"type\":\"0\"}",
                                "{\"data\":{\"client_port\":9706,\"client_ip\":\"10.0.0.2\",\"node_ip\":\"10.0.0.2\",\"node_port\":9705,\"services\":[\"VALIDATOR\"]},\"dest\":\"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya\",\"identifier\":\"2yAeV5ftuasWNgQwVYzeHeTuM7LwwNtPR3Zg9N4JiDgF\",\"txnId\":\"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4\",\"type\":\"0\"}",
                                "{\"data\":{\"client_port\":9708,\"client_ip\":\"10.0.0.2\",\"node_ip\":\"10.0.0.2\",\"node_port\":9707,\"services\":[\"VALIDATOR\"]},\"dest\":\"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA\",\"identifier\":\"FTE95CVthRtrBnK2PYCBbC9LghTcGwi9Zfi1Gz2dnyNx\",\"txnId\":\"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008\",\"type\":\"0\"}");

            PoolUtils::create_pool_ledger_config(pool_name, Some(nodes)).unwrap();

            let res = PoolUtils::open_pool_ledger(pool_name);
            assert_eq!(res.unwrap_err(), ErrorCode::PoolLedgerTerminated);//TODO Replace on InvalidState Error

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_wrong_alias() {
            TestUtils::cleanup_storage();
            let pool_name = "open_pool_ledger_works_for_wrong_alias";

            let nodes = format!("{}\n{}\n{}\n{}\n",
                                "{\"data\":{\"alias\":\"Node1\",\"client_ip\":\"10.0.0.2\",\"client_port\":9702,\"node_ip\":\"10.0.0.2\",\"node_port\":9701,\"services\":[\"VALIDATOR\"]},\"dest\":\"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv\",\"identifier\":\"FYmoFw55GeQH7SRFa37dkx1d2dZ3zUF8ckg7wmL7ofN4\",\"txnId\":\"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62\",\"type\":\"0\"}",
                                "{\"data\":{\"alias\":\"Node2\",\"client_ip\":\"10.0.0.2\",\"client_port\":9704,\"node_ip\":\"10.0.0.2\",\"node_port\":9703,\"services\":[\"VALIDATOR\"]},\"dest\":\"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb\",\"identifier\":\"8QhFxKxyaFsJy4CyxeYX34dFH8oWqyBv1P4HLQCsoeLy\",\"txnId\":\"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc\",\"type\":\"0\"}",
                                "{\"data\":{\"alias\":\"Node3\",\"client_ip\":\"10.0.0.2\",\"client_port\":9706,\"node_ip\":\"10.0.0.2\",\"node_port\":9705,\"services\":[\"VALIDATOR\"]},\"dest\":\"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya\",\"identifier\":\"2yAeV5ftuasWNgQwVYzeHeTuM7LwwNtPR3Zg9N4JiDgF\",\"txnId\":\"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4\",\"type\":\"0\"}",
                                "{\"data\":{\"alias\":\"ALIAS_NODE\",\"client_ip\":\"10.0.0.2\",\"client_port\":9708,\"node_ip\":\"10.0.0.2\",\"node_port\":9707,\"services\":[\"VALIDATOR\"]},\"dest\":\"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA\",\"identifier\":\"FTE95CVthRtrBnK2PYCBbC9LghTcGwi9Zfi1Gz2dnyNx\",\"txnId\":\"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008\",\"type\":\"0\"}");

            PoolUtils::create_pool_ledger_config(pool_name, Some(nodes)).unwrap();

            let res = PoolUtils::open_pool_ledger(pool_name);
            assert_eq!(res.unwrap_err(), ErrorCode::PoolLedgerTerminated);//TODO Replace on InvalidState Error

            TestUtils::cleanup_storage();
        }
    }
}<commit_msg>Move sovrin_delete_pool_ledger_config_* tests into appropriate submodule.<commit_after>extern crate sovrin;

#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;

#[macro_use]
#[path = "utils/mod.rs"]
mod utils;

#[cfg(feature = "local_nodes_pool")]
use sovrin::api::ErrorCode;

use utils::pool::PoolUtils;
use utils::test::TestUtils;

mod high_cases {
    use super::*;

    mod create {
        use super::*;

        #[test]
        fn create_pool_ledger_config_works() {
            TestUtils::cleanup_storage();

            PoolUtils::create_pool_ledger_config("pool_create", None).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod open {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works() {
            TestUtils::cleanup_storage();
            let name = "pool_open";

            PoolUtils::create_pool_ledger_config(name, None).unwrap();

            PoolUtils::open_pool_ledger(name).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_twice() {
            TestUtils::cleanup_storage();
            let pool_name = "pool_open_twice";

            PoolUtils::create_pool_ledger_config(pool_name, None).unwrap();

            PoolUtils::open_pool_ledger(pool_name).unwrap();
            let res = PoolUtils::open_pool_ledger(pool_name);
            assert_match!(Err(ErrorCode::PoolLedgerInvalidPoolHandle), res);

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_two_nodes() {
            TestUtils::cleanup_storage();
            let pool_name = "open_pool_ledger_works_for_two_nodes";

            let nodes = format!("{}\n{}\n",
                                "{\"data\":{\"alias\":\"Node1\",\"client_ip\":\"10.0.0.2\",\"client_port\":9702,\"node_ip\":\"10.0.0.2\",\"node_port\":9701,\"services\":[\"VALIDATOR\"]},\"dest\":\"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv\",\"identifier\":\"FYmoFw55GeQH7SRFa37dkx1d2dZ3zUF8ckg7wmL7ofN4\",\"txnId\":\"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62\",\"type\":\"0\"}",
                                "{\"data\":{\"alias\":\"Node2\",\"client_ip\":\"10.0.0.2\",\"client_port\":9704,\"node_ip\":\"10.0.0.2\",\"node_port\":9703,\"services\":[\"VALIDATOR\"]},\"dest\":\"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb\",\"identifier\":\"8QhFxKxyaFsJy4CyxeYX34dFH8oWqyBv1P4HLQCsoeLy\",\"txnId\":\"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc\",\"type\":\"0\"}");

            PoolUtils::create_pool_ledger_config(pool_name, Some(nodes)).unwrap();

            PoolUtils::open_pool_ledger(pool_name).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_three_nodes() {
            TestUtils::cleanup_storage();
            let pool_name = "open_pool_ledger_works_for_three_nodes";

            let nodes = format!("{}\n{}\n{}\n",
                                "{\"data\":{\"alias\":\"Node1\",\"client_ip\":\"10.0.0.2\",\"client_port\":9702,\"node_ip\":\"10.0.0.2\",\"node_port\":9701,\"services\":[\"VALIDATOR\"]},\"dest\":\"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv\",\"identifier\":\"FYmoFw55GeQH7SRFa37dkx1d2dZ3zUF8ckg7wmL7ofN4\",\"txnId\":\"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62\",\"type\":\"0\"}",
                                "{\"data\":{\"alias\":\"Node2\",\"client_ip\":\"10.0.0.2\",\"client_port\":9704,\"node_ip\":\"10.0.0.2\",\"node_port\":9703,\"services\":[\"VALIDATOR\"]},\"dest\":\"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb\",\"identifier\":\"8QhFxKxyaFsJy4CyxeYX34dFH8oWqyBv1P4HLQCsoeLy\",\"txnId\":\"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc\",\"type\":\"0\"}",
                                "{\"data\":{\"alias\":\"Node3\",\"client_ip\":\"10.0.0.2\",\"client_port\":9706,\"node_ip\":\"10.0.0.2\",\"node_port\":9705,\"services\":[\"VALIDATOR\"]},\"dest\":\"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya\",\"identifier\":\"2yAeV5ftuasWNgQwVYzeHeTuM7LwwNtPR3Zg9N4JiDgF\",\"txnId\":\"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4\",\"type\":\"0\"}");

            PoolUtils::create_pool_ledger_config(pool_name, Some(nodes)).unwrap();

            PoolUtils::open_pool_ledger(pool_name).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod close {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn sovrin_close_pool_ledger_works() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_close_pool_ledger_works";
            let pool_handle = PoolUtils::create_and_open_pool_ledger_config(pool_name).unwrap();

            PoolUtils::close(pool_handle).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn sovrin_close_pool_ledger_works_for_reopen_after_close() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_close_pool_ledger_works";
            let pool_handle = PoolUtils::create_and_open_pool_ledger_config(pool_name).unwrap();

            PoolUtils::close(pool_handle).unwrap();
            PoolUtils::open_pool_ledger(pool_name).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod delete {
        use super::*;

        #[test]
        fn sovrin_delete_pool_ledger_config_works() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_remove_pool_ledger_config_works";
            PoolUtils::create_pool_ledger_config(pool_name, None).unwrap();

            PoolUtils::delete(pool_name).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn sovrin_delete_pool_ledger_config_works_for_opened() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_remove_pool_ledger_config_works";
            PoolUtils::create_and_open_pool_ledger_config(pool_name).unwrap();

            assert_eq!(PoolUtils::delete(pool_name).unwrap_err(), ErrorCode::CommonInvalidState);

            TestUtils::cleanup_storage();
        }
    }
}

mod medium_cases {
    use super::*;

    mod open {
        use super::*;

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_invalid_nodes_file() {
            TestUtils::cleanup_storage();
            let pool_name = "open_pool_ledger_works_for_invalid_nodes_file";

            let nodes = format!("{}\n{}\n{}\n{}\n",
                                "{\"data\":{\"client_port\":9702,\"client_ip\":\"10.0.0.2\",\"node_ip\":\"10.0.0.2\",\"node_port\":9701,\"services\":[\"VALIDATOR\"]},\"dest\":\"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv\",\"identifier\":\"FYmoFw55GeQH7SRFa37dkx1d2dZ3zUF8ckg7wmL7ofN4\",\"txnId\":\"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62\",\"type\":\"0\"}",
                                "{\"data\":{\"client_port\":9704,\"client_ip\":\"10.0.0.2\",\"node_ip\":\"10.0.0.2\",\"node_port\":9703,\"services\":[\"VALIDATOR\"]},\"dest\":\"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb\",\"identifier\":\"8QhFxKxyaFsJy4CyxeYX34dFH8oWqyBv1P4HLQCsoeLy\",\"txnId\":\"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc\",\"type\":\"0\"}",
                                "{\"data\":{\"client_port\":9706,\"client_ip\":\"10.0.0.2\",\"node_ip\":\"10.0.0.2\",\"node_port\":9705,\"services\":[\"VALIDATOR\"]},\"dest\":\"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya\",\"identifier\":\"2yAeV5ftuasWNgQwVYzeHeTuM7LwwNtPR3Zg9N4JiDgF\",\"txnId\":\"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4\",\"type\":\"0\"}",
                                "{\"data\":{\"client_port\":9708,\"client_ip\":\"10.0.0.2\",\"node_ip\":\"10.0.0.2\",\"node_port\":9707,\"services\":[\"VALIDATOR\"]},\"dest\":\"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA\",\"identifier\":\"FTE95CVthRtrBnK2PYCBbC9LghTcGwi9Zfi1Gz2dnyNx\",\"txnId\":\"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008\",\"type\":\"0\"}");

            PoolUtils::create_pool_ledger_config(pool_name, Some(nodes)).unwrap();

            let res = PoolUtils::open_pool_ledger(pool_name);
            assert_eq!(res.unwrap_err(), ErrorCode::PoolLedgerTerminated);//TODO Replace on InvalidState Error

            TestUtils::cleanup_storage();
        }

        #[test]
        #[cfg(feature = "local_nodes_pool")]
        fn open_pool_ledger_works_for_wrong_alias() {
            TestUtils::cleanup_storage();
            let pool_name = "open_pool_ledger_works_for_wrong_alias";

            let nodes = format!("{}\n{}\n{}\n{}\n",
                                "{\"data\":{\"alias\":\"Node1\",\"client_ip\":\"10.0.0.2\",\"client_port\":9702,\"node_ip\":\"10.0.0.2\",\"node_port\":9701,\"services\":[\"VALIDATOR\"]},\"dest\":\"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv\",\"identifier\":\"FYmoFw55GeQH7SRFa37dkx1d2dZ3zUF8ckg7wmL7ofN4\",\"txnId\":\"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62\",\"type\":\"0\"}",
                                "{\"data\":{\"alias\":\"Node2\",\"client_ip\":\"10.0.0.2\",\"client_port\":9704,\"node_ip\":\"10.0.0.2\",\"node_port\":9703,\"services\":[\"VALIDATOR\"]},\"dest\":\"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb\",\"identifier\":\"8QhFxKxyaFsJy4CyxeYX34dFH8oWqyBv1P4HLQCsoeLy\",\"txnId\":\"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc\",\"type\":\"0\"}",
                                "{\"data\":{\"alias\":\"Node3\",\"client_ip\":\"10.0.0.2\",\"client_port\":9706,\"node_ip\":\"10.0.0.2\",\"node_port\":9705,\"services\":[\"VALIDATOR\"]},\"dest\":\"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya\",\"identifier\":\"2yAeV5ftuasWNgQwVYzeHeTuM7LwwNtPR3Zg9N4JiDgF\",\"txnId\":\"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4\",\"type\":\"0\"}",
                                "{\"data\":{\"alias\":\"ALIAS_NODE\",\"client_ip\":\"10.0.0.2\",\"client_port\":9708,\"node_ip\":\"10.0.0.2\",\"node_port\":9707,\"services\":[\"VALIDATOR\"]},\"dest\":\"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA\",\"identifier\":\"FTE95CVthRtrBnK2PYCBbC9LghTcGwi9Zfi1Gz2dnyNx\",\"txnId\":\"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008\",\"type\":\"0\"}");

            PoolUtils::create_pool_ledger_config(pool_name, Some(nodes)).unwrap();

            let res = PoolUtils::open_pool_ledger(pool_name);
            assert_eq!(res.unwrap_err(), ErrorCode::PoolLedgerTerminated);//TODO Replace on InvalidState Error

            TestUtils::cleanup_storage();
        }
    }
}<|endoftext|>


<commit_before>// edition:2018
// check-pass
#![allow(unused)]
#![deny(rust_2021_prelude_collisions)]

struct S;

impl S {
    fn try_into(self) -> S {
        S
    }
}

// See https://github.com/rust-lang/rust/issues/86633
fn main() {
    let s = S;
    let s2 = s.try_into();
}
<commit_msg>Add test for trait check in prelude collision lint.<commit_after>// edition:2018
// check-pass
#![allow(unused)]
#![deny(rust_2021_prelude_collisions)]

struct S;

impl S {
    fn try_into(self) -> S {
        S
    }
}

struct X;

trait Hey {
    fn from_iter(_: i32) -> Self;
}

impl Hey for X {
    fn from_iter(_: i32) -> Self {
        X
    }
}

fn main() {
    // See https://github.com/rust-lang/rust/issues/86633
    let s = S;
    let s2 = s.try_into();

    // See https://github.com/rust-lang/rust/issues/86902
    X::from_iter(1);
}
<|endoftext|>


<commit_before>use block_benching_builder::BlockBenchingBuilder;
use criterion::Criterion;
use criterion::{criterion_group, criterion_main};
use env_logger::{Builder, Env};
use log::info;
use types::*;

mod bench_block_processing;
mod bench_epoch_processing;
mod block_benching_builder;

pub const VALIDATOR_COUNT: usize = 16_384;

// `LOG_LEVEL == "debug"` gives logs, but they're very noisy and slow down benching.
pub const LOG_LEVEL: &str = "info";

/// Build a worst-case block and benchmark processing it.
pub fn block_processing_worst_case(c: &mut Criterion) {
    if LOG_LEVEL != "" {
        Builder::from_env(Env::default().default_filter_or(LOG_LEVEL)).init();
    }
    info!(
        "Building worst case block bench with {} validators",
        VALIDATOR_COUNT
    );

    // Use the specifications from the Eth2.0 spec.
    let spec = ChainSpec::foundation();

    // Create a builder for configuring the block and state for benching.
    let mut bench_builder = BlockBenchingBuilder::new(VALIDATOR_COUNT, &spec);

    // Set the number of included operations to be maximum (e.g., `MAX_ATTESTATIONS`, etc.)
    bench_builder.maximize_block_operations(&spec);

    // Set the state and block to be in the last slot of the 4th epoch.
    let last_slot_of_epoch = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch);
    bench_builder.set_slot(last_slot_of_epoch, &spec);

    // Build all the state caches so the build times aren't included in the benches.
    bench_builder.build_caches(&spec);

    // Generate the block and state.
    let (block, state) = bench_builder.build(&spec);

    // Run the benches.
    bench_block_processing::bench_block_processing(
        c,
        &block,
        &state,
        &spec,
        &format!("{}_validators/worst_case", VALIDATOR_COUNT),
    );
}

/// Build a reasonable-case block and benchmark processing it.
pub fn block_processing_reasonable_case(c: &mut Criterion) {
    info!(
        "Building reasonable case block bench with {} validators",
        VALIDATOR_COUNT
    );

    // Use the specifications from the Eth2.0 spec.
    let spec = ChainSpec::foundation();

    // Create a builder for configuring the block and state for benching.
    let mut bench_builder = BlockBenchingBuilder::new(VALIDATOR_COUNT, &spec);

    // Set the number of included operations to what we might expect normally.
    bench_builder.num_proposer_slashings = 0;
    bench_builder.num_attester_slashings = 0;
    bench_builder.num_attestations = (spec.shard_count / spec.slots_per_epoch) as usize;
    bench_builder.num_deposits = 2;
    bench_builder.num_exits = 2;
    bench_builder.num_transfers = 2;

    // Set the state and block to be in the last slot of the 4th epoch.
    let last_slot_of_epoch = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch);
    bench_builder.set_slot(last_slot_of_epoch, &spec);

    // Build all the state caches so the build times aren't included in the benches.
    bench_builder.build_caches(&spec);

    // Generate the block and state.
    let (block, state) = bench_builder.build(&spec);

    // Run the benches.
    bench_block_processing::bench_block_processing(
        c,
        &block,
        &state,
        &spec,
        &format!("{}_validators/reasonable_case", VALIDATOR_COUNT),
    );
}

pub fn state_processing(c: &mut Criterion) {
    bench_epoch_processing::bench_epoch_processing_n_validators(c, VALIDATOR_COUNT);
}

criterion_group!(
    benches,
    block_processing_reasonable_case,
    block_processing_worst_case,
    state_processing
);
criterion_main!(benches);
<commit_msg>Update loglevel, comments in benches<commit_after>use block_benching_builder::BlockBenchingBuilder;
use criterion::Criterion;
use criterion::{criterion_group, criterion_main};
use env_logger::{Builder, Env};
use log::info;
use types::*;

mod bench_block_processing;
mod bench_epoch_processing;
mod block_benching_builder;

pub const VALIDATOR_COUNT: usize = 16_384;

// `LOG_LEVEL == "info"` gives handy messages.
pub const LOG_LEVEL: &str = "info";

/// Build a worst-case block and benchmark processing it.
pub fn block_processing_worst_case(c: &mut Criterion) {
    if LOG_LEVEL != "" {
        Builder::from_env(Env::default().default_filter_or(LOG_LEVEL)).init();
    }
    info!(
        "Building worst case block bench with {} validators",
        VALIDATOR_COUNT
    );

    // Use the specifications from the Eth2.0 spec.
    let spec = ChainSpec::foundation();

    // Create a builder for configuring the block and state for benching.
    let mut bench_builder = BlockBenchingBuilder::new(VALIDATOR_COUNT, &spec);

    // Set the number of included operations to be maximum (e.g., `MAX_ATTESTATIONS`, etc.)
    bench_builder.maximize_block_operations(&spec);

    // Set the state and block to be in the last slot of the 4th epoch.
    let last_slot_of_epoch = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch);
    bench_builder.set_slot(last_slot_of_epoch, &spec);

    // Build all the state caches so the build times aren't included in the benches.
    bench_builder.build_caches(&spec);

    // Generate the block and state then run benches.
    let (block, state) = bench_builder.build(&spec);
    bench_block_processing::bench_block_processing(
        c,
        &block,
        &state,
        &spec,
        &format!("{}_validators/worst_case", VALIDATOR_COUNT),
    );
}

/// Build a reasonable-case block and benchmark processing it.
pub fn block_processing_reasonable_case(c: &mut Criterion) {
    info!(
        "Building reasonable case block bench with {} validators",
        VALIDATOR_COUNT
    );

    // Use the specifications from the Eth2.0 spec.
    let spec = ChainSpec::foundation();

    // Create a builder for configuring the block and state for benching.
    let mut bench_builder = BlockBenchingBuilder::new(VALIDATOR_COUNT, &spec);

    // Set the number of included operations to what we might expect normally.
    bench_builder.num_proposer_slashings = 0;
    bench_builder.num_attester_slashings = 0;
    bench_builder.num_attestations = (spec.shard_count / spec.slots_per_epoch) as usize;
    bench_builder.num_deposits = 2;
    bench_builder.num_exits = 2;
    bench_builder.num_transfers = 2;

    // Set the state and block to be in the last slot of the 4th epoch.
    let last_slot_of_epoch = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch);
    bench_builder.set_slot(last_slot_of_epoch, &spec);

    // Build all the state caches so the build times aren't included in the benches.
    bench_builder.build_caches(&spec);

    // Generate the block and state then run benches.
    let (block, state) = bench_builder.build(&spec);
    bench_block_processing::bench_block_processing(
        c,
        &block,
        &state,
        &spec,
        &format!("{}_validators/reasonable_case", VALIDATOR_COUNT),
    );
}

pub fn state_processing(c: &mut Criterion) {
    bench_epoch_processing::bench_epoch_processing_n_validators(c, VALIDATOR_COUNT);
}

criterion_group!(
    benches,
    block_processing_reasonable_case,
    block_processing_worst_case,
    state_processing
);
criterion_main!(benches);
<|endoftext|>


<commit_before>

#![feature(test)]
extern crate test;

fn main() {
    println!("{:?}", an_seq(10000, vec![]));
    // println!("{:?}", an_over_average(5));
    // println!("{:?}", pn(1));
    // println!("{:?}", max_pn(1));
//     println!("{:?}", gn(10, vec![]));
//     println!("{:?}", count_ones(10));
}

// println!("max_pn(n) : {}", n);

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

    // #[test]
    // fn returns_expected() {
    //     assert_eq!(count_ones(1), 1);
    //     assert_eq!(count_ones(10), 8);
    //     assert_eq!(count_ones(100), 90);

    //     assert_eq!(max_pn(1), 5);
    //     assert_eq!(max_pn(5), 47);
    //     assert_eq!(max_pn(7), 101);

    //     assert_eq!(an_over_average(5), 3);
    // }

    #[bench]
    fn bench_count_ones(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(count_ones(100), 90);
        });
    }

    #[bench]
    fn bench_max_pn(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(max_pn(7), 101);
        });
    }

    #[bench]
    fn bench_an_over_average(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(an_over_average(5), 3);
        });
    }
}

fn count_ones(n: i64) -> i64 {
    if n == 0 { return 0 }
    gn(n, vec![]).iter().filter(|&n| *n == 1).count() as i64
}

fn pn(n: i64) -> Vec<i64> {

    let mut count: i64 = n;
    let mut gn_vec: Vec<i64> = vec![];
    loop {
        gn_vec = gn(count, gn_vec);
        gn_vec.sort();
        gn_vec.dedup();
        gn_vec.remove(0);
        if gn_vec.len() == n as usize { return gn_vec }
        count += 1;
    }
}

fn max_pn(n: i64) -> i64 {
    *pn(n).last().unwrap()
}

fn an_over_average(n: i64) -> i64 {
    let mut avg: i64 = 0;
    let ao_s = an_over(n);
    let denom = ao_s.len() as i64;
    for elem in ao_s {
        avg += elem;
    }

    avg / (denom + 1)
}

fn an_over(n: i64) -> Vec<i64> {
    let pn_vec = pn(n);
    let mut ret: Vec<i64> = vec![];

    for (i, elem) in pn_vec.iter().enumerate() {
        if *elem != 1 {
            ret.push(elem/(i as i64 + 1));
        }
    }

    ret
}

fn an(n: i64) -> i64 {
    match n {
        0 => return 0,
        1 => return 7,
        _ => {
            let an_val = an(n-1); return an_val + gcd(n, an_val)
        }
    }
}

fn an_seq(n: i64, mut state: Vec<i64>) -> Vec<i64> {
    match n {
        0 => { return state }
        _ => for i in (state.len() + 1)..(n as usize + 1) { state.push(an(i as i64)); }
    }

    state
}

fn gn(n: i64, state: Vec<i64>) -> Vec<i64> {
    let mut last;
    let len = state.len();

    if  len > 0 {
        last = *state.last().unwrap() - 1; // starting from a previous state
    } else {
        last = 6; // starting from beginning, 7-6 == 1 at head of list...
    }

    let ret_vec = an_seq(n, state);
    let mut gn_vec: Vec<i64> = vec![];

    for elem in ret_vec[len..(n as usize)].iter() {
        let val = (elem - last).abs();
        gn_vec.push(val);
        last = *elem
    }

    gn_vec
}

fn gcd(v1: i64, v2: i64) -> i64 {
    let mut x = v1;
    let mut y = v2;
    while y != 0 {
        let t = y;
        y = x % y;
        x = t;
    }
    x
}
<commit_msg>passing example<commit_after>

#![feature(test)]
extern crate test;

fn main() {
    println!("an_over_average(9) -- {:?}", an_over_average(9));
    println!("max_pn {:?}", max_pn(2));
    println!("count_ones {:?}", count_ones(2));
}

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

    #[test]
    fn count_ones_returns_expected() {
        assert_eq!(count_ones(1), 1);
        assert_eq!(count_ones(10), 8);
        assert_eq!(count_ones(100), 90);
    }

    #[test]
    fn max_pn_returns_expected() {
        assert_eq!(max_pn(1), 5);
        assert_eq!(max_pn(5), 47);
        assert_eq!(max_pn(7), 101);
    }

    #[test]
    fn an_over_average_returns_expected() {
        assert_eq!(an_over_average(1), 3);
        assert_eq!(an_over_average(5), 3);
        assert_eq!(an_over_average(9), 3);
    }

    #[bench]
    fn bench_count_ones(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(count_ones(100), 90);
        });
    }

    #[bench]
    fn bench_max_pn(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(max_pn(7), 101);
        });
    }

    #[bench]
    fn bench_an_over_average(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(an_over_average(5), 3);
        });
    }
}

fn count_ones(n: i64) -> i64 {
    if n == 0 { return 0 }
    gn(n).iter().filter(|&n| *n == 1).count() as i64
}

fn pn(n: i64) -> Vec<i64> {
    let mut count: i64 = 2;
    let mut primes: Vec<i64> = vec![];
    let mut n_minus_1: i64 = 7;

    loop {
        let curr: i64 = n_minus_1 + gcd(count as i64, n_minus_1);
        let val = (curr - n_minus_1).abs();

        if (val != 1) && (primes.iter().find(|&&x| x == val) == None) {
            primes.push(val);
        }

        if primes.len() == n as usize {
            primes.sort();
            return primes
        }

        n_minus_1 = curr;
        count = count + 1;
    }
}

fn max_pn(n: i64) -> i64 {
    if n == 0 { return 0 }
    *pn(n).last().unwrap()
}

fn an_over_average(n: i64) -> i64 {
    if n == 0 { return 0 }
    let mut avg: i64 = 0;
    let an_over_vec = an_over(n);
    println!("an_over_vec {:?}", an_over_vec);
    let denom = an_over_vec.len() as i64;
    for elem in an_over_vec {
        avg += elem;
    }

    avg / denom
}

fn an_over(n: i64) -> Vec<i64> {
    let mut count: i64 = 2;
    let mut n_minus_1: i64 = 7;
    let mut ret: Vec<i64> = vec![];
    loop {
        let curr: i64 = n_minus_1 + gcd(count as i64, n_minus_1);
        let val = (curr - n_minus_1).abs();

        if val != 1 {
            ret.push(curr/count);
        }

        if ret.len() == n as usize {
            return ret
        }

        n_minus_1 = curr;
        count = count + 1;
    }
}

fn an(n: i64) -> Vec<i64> {
    let mut ret_vec: Vec<i64> = vec![7];
    let mut n_minus_1: i64 = 7;
    for i in 2..(n as usize) + 1 {
        let curr: i64 = n_minus_1 + gcd(i as i64, n_minus_1);
        ret_vec.push(curr);
        n_minus_1 = curr;
    }

    ret_vec
}

fn gn(n: i64) -> Vec<i64> {
    let ret_vec = an(n);
    let mut last = 6; // hack to get 1. abb(7-6)
    let mut gn_vec: Vec<i64> = vec![];

    for elem in ret_vec {
        let val = (elem - last).abs();
        gn_vec.push(val);
        last = elem
    }

    gn_vec
}

fn gcd(v1: i64, v2: i64) -> i64 {
    let mut x = v1;
    let mut y = v2;
    while y != 0 {
        let t = y;
        y = x % y;
        x = t;
    }
    x
}
<|endoftext|>


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

use serde::{Deserialize, Serialize};
use std::{net::SocketAddr, path::PathBuf};

const DEFAULT_JSON_RPC_ADDR: &str = "127.0.0.1";
const DEFAULT_JSON_RPC_PORT: u16 = 8080;

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct SecureConfig {
    pub key_manager: KeyManagerConfig,
}

impl Default for SecureConfig {
    fn default() -> Self {
        Self {
            key_manager: KeyManagerConfig::default(),
        }
    }
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct KeyManagerConfig {
    pub json_rpc_address: SocketAddr,
    pub secure_backend: SecureBackend,
}

impl Default for KeyManagerConfig {
    fn default() -> KeyManagerConfig {
        KeyManagerConfig {
            json_rpc_address: format!("{}:{}", DEFAULT_JSON_RPC_ADDR, DEFAULT_JSON_RPC_PORT)
                .parse()
                .unwrap(),
            secure_backend: SecureBackend::InMemoryStorage,
        }
    }
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(tag = "type")]
#[serde(rename_all = "snake_case")]
pub enum SecureBackend {
    InMemoryStorage,
    Vault(VaultConfig),
    OnDiskStorage(OnDiskStorageConfig),
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct VaultConfig {
    /// In testing scenarios this will install baseline data if it is not specified. Note: this can
    /// only be used if the token provided has root or sudo access.
    pub default: bool,
    /// A namespace is an optional portion of the path to a key stored within Vault. For example,
    /// a secret, S, without a namespace would be available in secret/data/S, with a namespace, N, it
    /// would be in secret/data/N/S.
    pub namespace: Option<String>,
    /// Vault's URL, note: only HTTP is currently supported.
    pub server: String,
    /// The authorization token for access secrets
    pub token: String,
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct OnDiskStorageConfig {
    // In testing scenarios this implies that the default state is okay if
    // a state is not specified.
    pub default: bool,
    // Required path for on disk storage
    pub path: PathBuf,
    #[serde(skip)]
    data_dir: PathBuf,
}

impl Default for OnDiskStorageConfig {
    fn default() -> Self {
        Self {
            default: false,
            path: PathBuf::from("safety_rules.toml"),
            data_dir: PathBuf::from("/opt/libra/data/common"),
        }
    }
}

impl OnDiskStorageConfig {
    pub fn path(&self) -> PathBuf {
        if self.path.is_relative() {
            self.data_dir.join(&self.path)
        } else {
            self.path.clone()
        }
    }

    pub fn set_data_dir(&mut self, data_dir: PathBuf) {
        self.data_dir = data_dir;
    }
}
<commit_msg>[config] use derived default when possible<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use serde::{Deserialize, Serialize};
use std::{net::SocketAddr, path::PathBuf};

const DEFAULT_JSON_RPC_ADDR: &str = "127.0.0.1";
const DEFAULT_JSON_RPC_PORT: u16 = 8080;

#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct SecureConfig {
    pub key_manager: KeyManagerConfig,
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct KeyManagerConfig {
    pub json_rpc_address: SocketAddr,
    pub secure_backend: SecureBackend,
}

impl Default for KeyManagerConfig {
    fn default() -> KeyManagerConfig {
        KeyManagerConfig {
            json_rpc_address: format!("{}:{}", DEFAULT_JSON_RPC_ADDR, DEFAULT_JSON_RPC_PORT)
                .parse()
                .unwrap(),
            secure_backend: SecureBackend::InMemoryStorage,
        }
    }
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(tag = "type")]
#[serde(rename_all = "snake_case")]
pub enum SecureBackend {
    InMemoryStorage,
    Vault(VaultConfig),
    OnDiskStorage(OnDiskStorageConfig),
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct VaultConfig {
    /// In testing scenarios this will install baseline data if it is not specified. Note: this can
    /// only be used if the token provided has root or sudo access.
    pub default: bool,
    /// A namespace is an optional portion of the path to a key stored within Vault. For example,
    /// a secret, S, without a namespace would be available in secret/data/S, with a namespace, N, it
    /// would be in secret/data/N/S.
    pub namespace: Option<String>,
    /// Vault's URL, note: only HTTP is currently supported.
    pub server: String,
    /// The authorization token for access secrets
    pub token: String,
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct OnDiskStorageConfig {
    // In testing scenarios this implies that the default state is okay if
    // a state is not specified.
    pub default: bool,
    // Required path for on disk storage
    pub path: PathBuf,
    #[serde(skip)]
    data_dir: PathBuf,
}

impl Default for OnDiskStorageConfig {
    fn default() -> Self {
        Self {
            default: false,
            path: PathBuf::from("safety_rules.toml"),
            data_dir: PathBuf::from("/opt/libra/data/common"),
        }
    }
}

impl OnDiskStorageConfig {
    pub fn path(&self) -> PathBuf {
        if self.path.is_relative() {
            self.data_dir.join(&self.path)
        } else {
            self.path.clone()
        }
    }

    pub fn set_data_dir(&mut self, data_dir: PathBuf) {
        self.data_dir = data_dir;
    }
}
<|endoftext|>


<commit_before>mod abbreviation;
mod bold;
mod citation;
mod code;
mod image;
mod italic;
mod link;
mod strikethrough;
mod subscript;
mod superscript;
mod underlined;

use parser::inline::abbreviation::parse_abbreviation;
use parser::inline::bold::parse_bold_text;
use parser::inline::italic::parse_italic_text;
use parser::inline::strikethrough::parse_strikethrough_text;
use parser::inline::underlined::parse_underlined_text;
use parser::inline::subscript::parse_subscript_text;
use parser::inline::superscript::parse_superscript_text;
use parser::inline::code::parse_code;
use parser::inline::citation::parse_citation;
use parser::inline::image::parse_image;
use parser::inline::link::parse_link;
use parser::Inline;

use regex::Regex;

pub fn parse_inline_elements(text: &str) -> Vec<Inline> {
    let text = match Regex::new("(?:\r|\n)$").unwrap().find(text) {
        Some((start, _)) => &text[0..start],
        None => text
    };

    let line_pattern = Regex::new("\r|\n|\r\n").unwrap();
    let lines = line_pattern.split(&text).collect::<Vec<&str>>();
    let mut tokens = Vec::new();

    for (idx, line) in lines.iter().enumerate() {
        let mut tmp = String::new();
        let mut i = 0;

        while i < line.len() {
            match parse_inline_element(&line[i..line.len()]) {
                Some((span, consumed_chars)) => {
                    if !tmp.is_empty() {
                        tokens.push(Inline::Text(tmp));
                    }
                    tokens.push(span);
                    tmp = String::new();
                    i += consumed_chars;
                }
                None => {
                    tmp.push_str(&line[i..i + 1]);
                    i += 1;
                }
            }
        }
        if !tmp.is_empty() {
            tokens.push(Inline::Text(tmp));
        }
        if idx > 0 && idx < lines.len() - 1 {
            tokens.push(Inline::Break);
        }
    }

    tokens
}

fn parse_inline_element(text: &str) -> Option<(Inline, usize)> {
    pipe_opt!(
        text
        => parse_bold_text
        => parse_italic_text
        => parse_strikethrough_text
        => parse_underlined_text
        => parse_subscript_text
        => parse_superscript_text
        => parse_abbreviation
        => parse_code
        => parse_citation
        => parse_image
        => parse_link
    )
}
<commit_msg>Simplify splitting text into lines in inline elements parser<commit_after>mod abbreviation;
mod bold;
mod citation;
mod code;
mod image;
mod italic;
mod link;
mod strikethrough;
mod subscript;
mod superscript;
mod underlined;

use parser::inline::abbreviation::parse_abbreviation;
use parser::inline::bold::parse_bold_text;
use parser::inline::italic::parse_italic_text;
use parser::inline::strikethrough::parse_strikethrough_text;
use parser::inline::underlined::parse_underlined_text;
use parser::inline::subscript::parse_subscript_text;
use parser::inline::superscript::parse_superscript_text;
use parser::inline::code::parse_code;
use parser::inline::citation::parse_citation;
use parser::inline::image::parse_image;
use parser::inline::link::parse_link;
use parser::Inline;

pub fn parse_inline_elements(text: &str) -> Vec<Inline> {
    let lines = text.trim().lines().collect::<Vec<&str>>();
    let mut tokens = Vec::new();

    for (idx, line) in lines.iter().enumerate() {
        let mut tmp = String::new();
        let mut i = 0;

        while i < line.len() {
            match parse_inline_element(&line[i..line.len()]) {
                Some((span, consumed_chars)) => {
                    if !tmp.is_empty() {
                        tokens.push(Inline::Text(tmp));
                    }
                    tokens.push(span);
                    tmp = String::new();
                    i += consumed_chars;
                }
                None => {
                    tmp.push_str(&line[i..i + 1]);
                    i += 1;
                }
            }
        }
        if !tmp.is_empty() {
            tokens.push(Inline::Text(tmp));
        }
        if idx > 0 && idx < lines.len() - 1 {
            tokens.push(Inline::Break);
        }
    }

    tokens
}

fn parse_inline_element(text: &str) -> Option<(Inline, usize)> {
    pipe_opt!(
        text
        => parse_bold_text
        => parse_italic_text
        => parse_strikethrough_text
        => parse_underlined_text
        => parse_subscript_text
        => parse_superscript_text
        => parse_abbreviation
        => parse_code
        => parse_citation
        => parse_image
        => parse_link
    )
}
<|endoftext|>


<commit_before>mod abbreviation;
mod bold;
mod citation;
mod code;
mod image;
mod italic;
mod link;
mod strikethrough;
mod subscript;
mod superscript;
mod underlined;

use parser::inline::abbreviation::parse_abbreviation;
use parser::inline::bold::parse_bold_text;
use parser::inline::italic::parse_italic_text;
use parser::inline::strikethrough::parse_strikethrough_text;
use parser::inline::underlined::parse_underlined_text;
use parser::inline::subscript::parse_subscript_text;
use parser::inline::superscript::parse_superscript_text;
use parser::inline::code::parse_code;
use parser::inline::citation::parse_citation;
use parser::inline::image::parse_image;
use parser::inline::link::parse_link;
use parser::Inline;

pub fn parse_inline_elements(text: &str) -> Vec<Inline> {
    let lines = text.lines().collect::<Vec<&str>>();
    let mut tokens = Vec::new();

    for (idx, line) in lines.iter().enumerate() {
        let mut tmp = String::new();
        let mut i = 0;

        while i < line.len() {
            match parse_inline_element(&line[i..line.len()]) {
                Some((span, consumed_chars)) => {
                    if !tmp.is_empty() {
                        tokens.push(Inline::Text(tmp));
                    }
                    tokens.push(span);
                    tmp = String::new();
                    i += consumed_chars;
                }
                None => {
                    tmp.push_str(&line[i..i + 1]);
                    i += 1;
                }
            }
        }
        if !tmp.is_empty() {
            tokens.push(Inline::Text(tmp));
        }
        if idx < lines.len() - 1 {
            tokens.push(Inline::Break);
        }
    }

    tokens
}

fn parse_inline_element(text: &str) -> Option<(Inline, usize)> {
    pipe_opt!(
        text
        => parse_bold_text
        => parse_italic_text
        => parse_strikethrough_text
        => parse_underlined_text
        => parse_subscript_text
        => parse_superscript_text
        => parse_abbreviation
        => parse_code
        => parse_citation
        => parse_image
        => parse_link
    )
}
<commit_msg>Rename variable in parse_inline_elements function<commit_after>mod abbreviation;
mod bold;
mod citation;
mod code;
mod image;
mod italic;
mod link;
mod strikethrough;
mod subscript;
mod superscript;
mod underlined;

use parser::inline::abbreviation::parse_abbreviation;
use parser::inline::bold::parse_bold_text;
use parser::inline::italic::parse_italic_text;
use parser::inline::strikethrough::parse_strikethrough_text;
use parser::inline::underlined::parse_underlined_text;
use parser::inline::subscript::parse_subscript_text;
use parser::inline::superscript::parse_superscript_text;
use parser::inline::code::parse_code;
use parser::inline::citation::parse_citation;
use parser::inline::image::parse_image;
use parser::inline::link::parse_link;
use parser::Inline;

pub fn parse_inline_elements(text: &str) -> Vec<Inline> {
    let lines = text.lines().collect::<Vec<&str>>();
    let mut tokens = Vec::new();

    for (idx, line) in lines.iter().enumerate() {
        let mut tmp = String::new();
        let mut pos = 0;

        while pos < line.len() {
            match parse_inline_element(&line[pos..line.len()]) {
                Some((span, consumed_chars)) => {
                    if !tmp.is_empty() {
                        tokens.push(Inline::Text(tmp));
                    }
                    tokens.push(span);
                    tmp = String::new();
                    pos += consumed_chars;
                }
                None => {
                    tmp.push_str(&line[pos..pos + 1]);
                    pos += 1;
                }
            }
        }
        if !tmp.is_empty() {
            tokens.push(Inline::Text(tmp));
        }
        if idx < lines.len() - 1 {
            tokens.push(Inline::Break);
        }
    }
    tokens
}

fn parse_inline_element(text: &str) -> Option<(Inline, usize)> {
    pipe_opt!(
        text
        => parse_bold_text
        => parse_italic_text
        => parse_strikethrough_text
        => parse_underlined_text
        => parse_subscript_text
        => parse_superscript_text
        => parse_abbreviation
        => parse_code
        => parse_citation
        => parse_image
        => parse_link
    )
}
<|endoftext|>


<commit_before>//#[cfg(test)] use racer::testutils::{rejustify, slice};

pub fn rejustify(src: &str) -> String {
    let s = &src[1..]; // remove the newline
    let mut sb = String::new();
    for l in s.lines() {
        let tabless = &l[4..];
        sb.push_str(tabless);
        if tabless.len() != 0 {
            sb.push_str("\n");
        }
    }
    let newlen = sb.len()-1; // remove the trailing newline
    sb.truncate(newlen);
    sb
}

pub fn slice(src: &str, (begin, end): (usize, usize)) -> &str{
    &src[begin..end]
}

enum State {
    StateCode,
    StateComment,
    StateCommentBlock,
    StateString,
    StateChar,
    StateFinished
}

pub struct CodeIndicesIter<'a> {
    src: &'a str,
    pos: usize,
    state: State
}

impl<'a> Iterator for CodeIndicesIter<'a> {
    type Item = (usize, usize);

    #[inline]
    fn next(&mut self) -> Option<(usize, usize)> {
        let res = match self.state {
            State::StateCode => Some(code(self)),
            State::StateComment => Some(comment(self)),
            State::StateCommentBlock  => Some(comment_block(self)),
            State::StateString => Some(string(self)),
            State::StateChar => Some(char(self)),
            State::StateFinished => None
        };
        res
    }
}

fn code(self_: &mut CodeIndicesIter) -> (usize,usize) {

    let start = match self_.state {
        State::StateString | State::StateChar => { self_.pos-1 }, // include quote
        _ => { self_.pos }
    };
    let src_bytes = self_.src.as_bytes();
    for &b in src_bytes[self_.pos..].iter(){
        self_.pos += 1;
        match b {
            b'/' => match src_bytes[self_.pos] {
                b'/' => {
                    self_.state = State::StateComment;
                    self_.pos +=1;
                    return (start, self_.pos-2);
                },
                b'*' => {
                    self_.state = State::StateCommentBlock;
                    self_.pos +=1;
                    return (start, self_.pos-2);
                },
                _ => {}
            },
            b'"' => {    // "
                self_.state = State::StateString;
                return (start, self_.pos); // include dblquotes
            },
            b'\'' => {
                self_.state = State::StateChar;
                return (start, self_.pos); // include single quote
            },
            _ => {}
        }
    }

    self_.state = State::StateFinished;
    (start, self_.src.len())
}

fn comment(self_: &mut CodeIndicesIter) -> (usize,usize) {
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        if b == b'\n' { break; }
    }
    code(self_)
}

fn comment_block(self_: &mut CodeIndicesIter) -> (usize,usize) {

    let mut nesting_level = 0u16; // should be enough
    let mut prev = b' ';
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'/' if prev == b'*' => {
                if nesting_level == 0 {
                    break;
                } else {
                    nesting_level -= 1;
                }
            },
            b'*' if prev == b'/' => {
                nesting_level += 1;
            },
            _ => { prev = b; }
        }
    }
    code(self_)
}

fn string(self_: &mut CodeIndicesIter) -> (usize,usize) {
    let mut is_not_escaped = true;
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'"' if is_not_escaped  => { break; }, // "
            b'\\' => { is_not_escaped = !is_not_escaped; },
            _ => { is_not_escaped = true; }
        }
    }
    code(self_)
}

fn char(self_: &mut CodeIndicesIter) -> (usize,usize) {
    let mut is_not_escaped = true;
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'\'' if is_not_escaped  => { break; },
            b'\\' => { is_not_escaped = !is_not_escaped; },
            _ => { is_not_escaped = true; }
        }
    }
    code(self_)
}

/// Returns indices of chunks of code (minus comments and string contents)
pub fn code_chunks<'a>(src: &'a str) -> CodeIndicesIter<'a> {
    CodeIndicesIter { src: src, state: State::StateCode, pos: 0 }
}

#[test]
fn removes_a_comment() {
    let src = &rejustify("
    this is some code // this is a comment
    some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_contents() {
    let src = &rejustify("
    this is some code \"this is a string\" more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_char_contents() {
    let src = &rejustify("
    this is some code \'\"\' more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \'", slice(src, it.next().unwrap()));
    assert_eq!("\' more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_contents_with_a_comment_in_it() {
    let src = &rejustify("
    this is some code \"string with a // fake comment \" more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_a_comment_with_a_dbl_quote_in_it() {
    let src = &rejustify("
    this is some code // comment with \" double quote
    some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_multiline_comment() {
    let src = &rejustify("
    this is some code /* this is a
    \"multiline\" comment */some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn handles_nesting_of_block_comments() {
    let src = &rejustify("
    this is some code /* nested /* block */ comment */ some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!(" some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_with_escaped_dblquote_in_it() {
    let src = &rejustify("
    this is some code \"string with a \\\" escaped dblquote fake comment \" more code
    ")[];

    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_with_escaped_slash_before_dblquote_in_it() {
    let src = &rejustify("
    this is some code \"string with an escaped slash, so dbl quote does end the string after all \\\\\" more code
    ")[];

    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn handles_tricky_bit_from_str_rs() {
    let src = &rejustify("
        before(\"\\\\\'\\\\\\\"\\\\\\\\\");
        more_code(\" skip me \")
    ")[];

    for (start,end) in code_chunks(src) {
        println!("BLOB |{}|",&src[start..end]);
        if (&src[start..end]).contains("skip me") {
            panic!("{}", &src[start..end]);
        }
    }
}

// fn main() {
//     use std::old_io::BufferedReader;
//     use std::old_io::File;
//     use std::str;

//     let filetxt = BufferedReader::new(File::open(&Path::new("/tmp/testcode.rs"))).read_to_end().unwrap();
//     let src = str::from_utf8(filetxt.as_slice()).unwrap();

//     for (start,end) in code_chunks(src) {
//         println!("BLOB |{}|",src.slice(start,end));
//     }

// }
<commit_msg>bugfix: codecleaner could mistake lifetime for single quote string<commit_after>//#[cfg(test)] use racer::testutils::{rejustify, slice};

pub fn rejustify(src: &str) -> String {
    let s = &src[1..]; // remove the newline
    let mut sb = String::new();
    for l in s.lines() {
        let tabless = &l[4..];
        sb.push_str(tabless);
        if tabless.len() != 0 {
            sb.push_str("\n");
        }
    }
    let newlen = sb.len()-1; // remove the trailing newline
    sb.truncate(newlen);
    sb
}

pub fn slice(src: &str, (begin, end): (usize, usize)) -> &str{
    &src[begin..end]
}

enum State {
    StateCode,
    StateComment,
    StateCommentBlock,
    StateString,
    StateChar,
    StateFinished
}

pub struct CodeIndicesIter<'a> {
    src: &'a str,
    pos: usize,
    state: State
}

impl<'a> Iterator for CodeIndicesIter<'a> {
    type Item = (usize, usize);

    #[inline]
    fn next(&mut self) -> Option<(usize, usize)> {
        let res = match self.state {
            State::StateCode => Some(code(self)),
            State::StateComment => Some(comment(self)),
            State::StateCommentBlock  => Some(comment_block(self)),
            State::StateString => Some(string(self)),
            State::StateChar => Some(char(self)),
            State::StateFinished => None
        };
        res
    }
}

fn code(self_: &mut CodeIndicesIter) -> (usize,usize) {
    let start = match self_.state {
        State::StateString | State::StateChar => { self_.pos-1 }, // include quote
        _ => { self_.pos }
    };
    let src_bytes = self_.src.as_bytes();
    for &b in src_bytes[self_.pos..].iter(){
        self_.pos += 1;
        match b {
            b'/' => match src_bytes[self_.pos] {
                b'/' => {
                    self_.state = State::StateComment;
                    self_.pos +=1;
                    return (start, self_.pos-2);
                },
                b'*' => {
                    self_.state = State::StateCommentBlock;
                    self_.pos +=1;
                    return (start, self_.pos-2);
                },
                _ => {}
            },
            b'"' => {    // "
                self_.state = State::StateString;
                return (start, self_.pos); // include dblquotes
            },
            b'\'' => {
                // single quotes are also used for lifetimes, so we need to
                // be confident that this is not a lifetime.
                // Look for closing quote:
                if src_bytes.len() > self_.pos + 2 &&
                    (src_bytes[self_.pos+1] == b'\'' ||
                     src_bytes[self_.pos+2] == b'\'') {
                    self_.state = State::StateChar;
                    return (start, self_.pos); // include single quote
                }
            },
            _ => {}
        }
    }

    self_.state = State::StateFinished;
    (start, self_.src.len())
}

fn comment(self_: &mut CodeIndicesIter) -> (usize,usize) {
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        if b == b'\n' { break; }
    }
    code(self_)
}

fn comment_block(self_: &mut CodeIndicesIter) -> (usize,usize) {

    let mut nesting_level = 0u16; // should be enough
    let mut prev = b' ';
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'/' if prev == b'*' => {
                if nesting_level == 0 {
                    break;
                } else {
                    nesting_level -= 1;
                }
            },
            b'*' if prev == b'/' => {
                nesting_level += 1;
            },
            _ => { prev = b; }
        }
    }
    code(self_)
}

fn string(self_: &mut CodeIndicesIter) -> (usize,usize) {
    let mut is_not_escaped = true;
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'"' if is_not_escaped  => { break; }, // "
            b'\\' => { is_not_escaped = !is_not_escaped; },
            _ => { is_not_escaped = true; }
        }
    }
    code(self_)
}

fn char(self_: &mut CodeIndicesIter) -> (usize,usize) {
    let mut is_not_escaped = true;
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'\'' if is_not_escaped  => { break; },
            b'\\' => { is_not_escaped = !is_not_escaped; },
            _ => { is_not_escaped = true; }
        }
    }
    code(self_)
}

/// Returns indices of chunks of code (minus comments and string contents)
pub fn code_chunks<'a>(src: &'a str) -> CodeIndicesIter<'a> {
    CodeIndicesIter { src: src, state: State::StateCode, pos: 0 }
}

#[test]
fn removes_a_comment() {
    let src = &rejustify("
    this is some code // this is a comment
    some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_contents() {
    let src = &rejustify("
    this is some code \"this is a string\" more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_char_contents() {
    let src = &rejustify("
    this is some code \'\"\' more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \'", slice(src, it.next().unwrap()));
    assert_eq!("\' more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_contents_with_a_comment_in_it() {
    let src = &rejustify("
    this is some code \"string with a // fake comment \" more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_a_comment_with_a_dbl_quote_in_it() {
    let src = &rejustify("
    this is some code // comment with \" double quote
    some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_multiline_comment() {
    let src = &rejustify("
    this is some code /* this is a
    \"multiline\" comment */some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn handles_nesting_of_block_comments() {
    let src = &rejustify("
    this is some code /* nested /* block */ comment */ some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!(" some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_with_escaped_dblquote_in_it() {
    let src = &rejustify("
    this is some code \"string with a \\\" escaped dblquote fake comment \" more code
    ")[];

    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_with_escaped_slash_before_dblquote_in_it() {
    let src = &rejustify("
    this is some code \"string with an escaped slash, so dbl quote does end the string after all \\\\\" more code
    ")[];

    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn handles_tricky_bit_from_str_rs() {
    let src = &rejustify("
        before(\"\\\\\'\\\\\\\"\\\\\\\\\");
        more_code(\" skip me \")
    ")[];

    for (start,end) in code_chunks(src) {
        println!("BLOB |{}|",&src[start..end]);
        if (&src[start..end]).contains("skip me") {
            panic!("{}", &src[start..end]);
        }
    }
}

// fn main() {
//     use std::old_io::BufferedReader;
//     use std::old_io::File;
//     use std::str;

//     let filetxt = BufferedReader::new(File::open(&Path::new("/tmp/testcode.rs"))).read_to_end().unwrap();
//     let src = str::from_utf8(filetxt.as_slice()).unwrap();

//     for (start,end) in code_chunks(src) {
//         println!("BLOB |{}|",src.slice(start,end));
//     }

// }
<|endoftext|>


<commit_before>use drivers::io::{Port, UnsafePort};
use spin::Mutex;

static PICS: Mutex<CascadedPics> = Mutex::new(unsafe { CascadedPics::new(0x20, 0x28) });

struct Pic {
    offset: u8,
    command: UnsafePort<u8>,
    data: UnsafePort<u8>
}

impl Pic {
	unsafe fn new(offset: u8, command_port: u8, data_port: u8) -> Pic {
        Pic {
            offset: offset,
            command: UnsafePort::new(command_port),
            data: UnsafePort::new(data_port)
        }
    }
}

struct CascadedPics {
    pics: [Pic; 2]
}

impl CascadedPics {
    unsafe fn new(offset_master: u8, offset_slave: u8) -> CascadedPics {
        CascadedPics {
            pics: [
                Pic::new(offset_master, 0x20, 0x21),
                Pic::new(offset_slave, 0xA0, 0xA1)
            ]
        }
    }

    unsafe fn initialize(&mut self) {

        // Writing to these ports create a small delay.
        // We need todo like these because we don't have access to any timer.
        let mut wait_port: Port<u8> = Port::new(0x80);
        let mut wait = || { wait_port.write(0) };

        // Save our original interrupt masks, because I'm too lazy to
        // figure out reasonable values.  We'll restore these when we're
        // done.
        let saved_mask1 = self.pics[0].data.read();
        let saved_mask2 = self.pics[1].data.read();

        // Initialization of ICW1
        // |0|0|0|1|c|0|b|a|
        // With ICW4 a = 1  otherwise a = 0
        // Only one controler b = 1, if cascading b = 0
        // Triggered by edge c = 0, otherwise triggered by level c = 1
        let  icw1 = 0b0001_0001;
        self.pics[0].command.write(icw1);
        wait();
        self.pics[1].command.write(icw1);
        wait();

        // Initialization of ICW2
        // Define the offsets of the interrupt vector
        self.pics[0].data.write(self.pics[0].offset);
        wait();
        self.pics[1].data.write(self.pics[1].offset);
        wait();

        // Initialization of ICW3
        // Discribe how the two pics are connected
        // master: |x|x|x|x|x|x|x|x|  1 on the bit where the connection is.
        // slave: |0|0|0|0|0|x|x|x| the number of the connection.
        self.pics[0].data.write(0x04);
        wait();
        self.pics[1].data.write(0x02);
        wait();

        // Initialization of ICW4
        // |0|0|0|d|c|b|a|1| Define how the controler work
        // Automatic EOI, a = 1
        // TODO: Define others modes
        let icw4 = 0b0000_0001;
        self.pics[0].data.write(icw4);
        wait();
        self.pics[1].data.write(icw4);
        wait();

        // Restore our saved masks.
        self.pics[0].data.write(saved_mask1);
        self.pics[1].data.write(saved_mask2);
    }
}

pub unsafe fn initialize() {
    PICS.lock().initialize();
}
<commit_msg>Minor type fix<commit_after>use drivers::io::{Port, UnsafePort};
use spin::Mutex;

static PICS: Mutex<CascadedPics> = Mutex::new(unsafe { CascadedPics::new(0x20, 0x28) });

struct Pic {
    offset: u8,
    command: UnsafePort<u8>,
    data: UnsafePort<u8>
}

impl Pic {
	unsafe fn new(offset: u8, command_port: u16, data_port: u16) -> Pic {
        Pic {
            offset: offset,
            command: UnsafePort::new(command_port),
            data: UnsafePort::new(data_port)
        }
    }
}

struct CascadedPics {
    pics: [Pic; 2]
}

impl CascadedPics {
    unsafe fn new(offset_master: u8, offset_slave: u8) -> CascadedPics {
        CascadedPics {
            pics: [
                Pic::new(offset_master, 0x20, 0x21),
                Pic::new(offset_slave, 0xA0, 0xA1)
            ]
        }
    }

    unsafe fn initialize(&mut self) {

        // Writing to these ports create a small delay.
        // We need todo like these because we don't have access to any timer.
        let mut wait_port: Port<u8> = Port::new(0x80);
        let mut wait = || { wait_port.write(0) };

        // Save our original interrupt masks, because I'm too lazy to
        // figure out reasonable values.  We'll restore these when we're
        // done.
        let saved_mask1 = self.pics[0].data.read();
        let saved_mask2 = self.pics[1].data.read();

        // Initialization of ICW1
        // |0|0|0|1|c|0|b|a|
        // With ICW4 a = 1  otherwise a = 0
        // Only one controler b = 1, if cascading b = 0
        // Triggered by edge c = 0, otherwise triggered by level c = 1
        let  icw1 = 0b0001_0001;
        self.pics[0].command.write(icw1);
        wait();
        self.pics[1].command.write(icw1);
        wait();

        // Initialization of ICW2
        // Define the offsets of the interrupt vector
        self.pics[0].data.write(self.pics[0].offset);
        wait();
        self.pics[1].data.write(self.pics[1].offset);
        wait();

        // Initialization of ICW3
        // Discribe how the two pics are connected
        // master: |x|x|x|x|x|x|x|x|  1 on the bit where the connection is.
        // slave: |0|0|0|0|0|x|x|x| the number of the connection.
        self.pics[0].data.write(0x04);
        wait();
        self.pics[1].data.write(0x02);
        wait();

        // Initialization of ICW4
        // |0|0|0|d|c|b|a|1| Define how the controler work
        // Automatic EOI, a = 1
        // TODO: Define others modes
        let icw4 = 0b0000_0001;
        self.pics[0].data.write(icw4);
        wait();
        self.pics[1].data.write(icw4);
        wait();

        // Restore our saved masks.
        self.pics[0].data.write(saved_mask1);
        self.pics[1].data.write(saved_mask2);
    }
}

pub unsafe fn initialize() {
    PICS.lock().initialize();
}
<|endoftext|>


<commit_before>use std::vec;

use la::matrix::*;

use super::super::opt::graddescent;

struct LinearRegression {
  theta : ~Matrix<f64>
}

pub fn train(x : &Matrix<f64>, y : &Matrix<f64>, alpha : f64, num_iter : int) -> LinearRegression {
  let extx = one_vector(x.rows()).cr(x);
  let mut theta = ~matrix(extx.cols(), 1, vec::from_elem(extx.cols(), 0.0f64));
  graddescent::gradient_descent(&extx, y, theta, alpha, num_iter);
  LinearRegression {
    theta : theta
  }
}

impl LinearRegression {
  pub fn predict(&self, x : &Matrix<f64>) -> f64 {
    assert!(x.noCols == 1);
    assert!((x.noRows + 1) == self.theta.data.len());

    let mut sum = self.theta.data[0];
    for i in range(1, self.theta.data.len()) {
      sum += self.theta.data[i] * x.data[i - 1];
    }

    sum
  }

  #[inline]
  pub fn hypothesis(&self, x : &Matrix<f64>) -> f64 {
    self.predict(x)
  }
}

<commit_msg>Add normal equations for linear regression.<commit_after>use std::vec;

use la::matrix::*;

use super::super::opt::graddescent;

struct LinearRegression {
  theta : ~Matrix<f64>
}

pub fn train(x : &Matrix<f64>, y : &Matrix<f64>, alpha : f64, num_iter : int) -> LinearRegression {
  let extx = one_vector(x.rows()).cr(x);
  let mut theta = ~matrix(extx.cols(), 1, vec::from_elem(extx.cols(), 0.0f64));
  graddescent::gradient_descent(&extx, y, theta, alpha, num_iter);
  LinearRegression {
    theta : theta
  }
}

pub fn normal_eq(x : &Matrix<f64>, y : &Matrix<f64>) -> LinearRegression {
  let extx = one_vector(x.rows()).cr(x);
  LinearRegression {
    theta : ~((extx.t() * extx).inverse().unwrap() * extx.t() * *y)
  }
}

impl LinearRegression {
  pub fn predict(&self, x : &Matrix<f64>) -> f64 {
    assert!(x.noCols == 1);
    assert!((x.noRows + 1) == self.theta.data.len());

    let mut sum = self.theta.data[0];
    for i in range(1, self.theta.data.len()) {
      sum += self.theta.data[i] * x.data[i - 1];
    }

    sum
  }

  #[inline]
  pub fn hypothesis(&self, x : &Matrix<f64>) -> f64 {
    self.predict(x)
  }
}

<|endoftext|>