<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A priority queue implemented with a binary heap

#[allow(missing_doc)];

use core::prelude::*;

use core::unstable::intrinsics::{move_val_init, init};
use core::util::{replace, swap};
use core::vec;

/// A priority queue implemented with a binary heap
pub struct PriorityQueue<T> {
    priv data: ~[T],
}

impl<T:Ord> Container for PriorityQueue<T> {
    /// Returns the length of the queue
    fn len(&self) -> uint { self.data.len() }

    /// Returns true if a queue contains no elements
    fn is_empty(&self) -> bool { self.len() == 0 }
}

impl<T:Ord> Mutable for PriorityQueue<T> {
    /// Drop all items from the queue
    fn clear(&mut self) { self.data.truncate(0) }
}

impl<T:Ord> PriorityQueue<T> {
    /// Visit all values in the underlying vector.
    ///
    /// The values are **not** visited in order.
    pub fn each(&self, f: &fn(&T) -> bool) -> bool { self.data.iter().advance(f) }

    /// Returns the greatest item in the queue - fails if empty
    pub fn top<'a>(&'a self) -> &'a T { &self.data[0] }

    /// Returns the greatest item in the queue - None if empty
    pub fn maybe_top<'a>(&'a self) -> Option<&'a T> {
        if self.is_empty() { None } else { Some(self.top()) }
    }

    /// Returns the number of elements the queue can hold without reallocating
    pub fn capacity(&self) -> uint { vec::capacity(&self.data) }

    pub fn reserve(&mut self, n: uint) { vec::reserve(&mut self.data, n) }

    pub fn reserve_at_least(&mut self, n: uint) {
        vec::reserve_at_least(&mut self.data, n)
    }

    /// Pop the greatest item from the queue - fails if empty
    pub fn pop(&mut self) -> T {
        let mut item = self.data.pop();
        if !self.is_empty() {
            swap(&mut item, &mut self.data[0]);
            self.siftdown(0);
        }
        item
    }

    /// Pop the greatest item from the queue - None if empty
    pub fn maybe_pop(&mut self) -> Option<T> {
        if self.is_empty() { None } else { Some(self.pop()) }
    }

    /// Push an item onto the queue
    pub fn push(&mut self, item: T) {
        self.data.push(item);
        let new_len = self.len() - 1;
        self.siftup(0, new_len);
    }

    /// Optimized version of a push followed by a pop
    pub fn push_pop(&mut self, mut item: T) -> T {
        if !self.is_empty() && self.data[0] > item {
            swap(&mut item, &mut self.data[0]);
            self.siftdown(0);
        }
        item
    }

    /// Optimized version of a pop followed by a push - fails if empty
    pub fn replace(&mut self, mut item: T) -> T {
        swap(&mut item, &mut self.data[0]);
        self.siftdown(0);
        item
    }

    /// Consume the PriorityQueue and return the underlying vector
    pub fn to_vec(self) -> ~[T] { let PriorityQueue{data: v} = self; v }

    /// Consume the PriorityQueue and return a vector in sorted
    /// (ascending) order
    pub fn to_sorted_vec(self) -> ~[T] {
        let mut q = self;
        let mut end = q.len();
        while end > 1 {
            end -= 1;
            vec::swap(q.data, 0, end);
            q.siftdown_range(0, end)
        }
        q.to_vec()
    }

    /// Create an empty PriorityQueue
    pub fn new() -> PriorityQueue<T> { PriorityQueue{data: ~[],} }

    /// Create a PriorityQueue from a vector (heapify)
    pub fn from_vec(xs: ~[T]) -> PriorityQueue<T> {
        let mut q = PriorityQueue{data: xs,};
        let mut n = q.len() / 2;
        while n > 0 {
            n -= 1;
            q.siftdown(n)
        }
        q
    }

    // The implementations of siftup and siftdown use unsafe blocks in
    // order to move an element out of the vector (leaving behind a
    // zeroed element), shift along the others and move it back into the
    // vector over the junk element.  This reduces the constant factor
    // compared to using swaps, which involves twice as many moves.
    fn siftup(&mut self, start: uint, mut pos: uint) {
        unsafe {
            let new = replace(&mut self.data[pos], init());

            while pos > start {
                let parent = (pos - 1) >> 1;
                if new > self.data[parent] {
                    let x = replace(&mut self.data[parent], init());
                    move_val_init(&mut self.data[pos], x);
                    pos = parent;
                    loop
                }
                break
            }
            move_val_init(&mut self.data[pos], new);
        }
    }

    fn siftdown_range(&mut self, mut pos: uint, end: uint) {
        unsafe {
            let start = pos;
            let new = replace(&mut self.data[pos], init());

            let mut child = 2 * pos + 1;
            while child < end {
                let right = child + 1;
                if right < end && !(self.data[child] > self.data[right]) {
                    child = right;
                }
                let x = replace(&mut self.data[child], init());
                move_val_init(&mut self.data[pos], x);
                pos = child;
                child = 2 * pos + 1;
            }

            move_val_init(&mut self.data[pos], new);
            self.siftup(start, pos);
        }
    }

    fn siftdown(&mut self, pos: uint) {
        let len = self.len();
        self.siftdown_range(pos, len);
    }
}

#[cfg(test)]
mod tests {
    use sort::merge_sort;
    use priority_queue::PriorityQueue;

    #[test]
    fn test_top_and_pop() {
        let data = ~[2u, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
        let mut sorted = merge_sort(data, |x, y| x.le(y));
        let mut heap = PriorityQueue::from_vec(data);
        while !heap.is_empty() {
            assert_eq!(heap.top(), sorted.last());
            assert_eq!(heap.pop(), sorted.pop());
        }
    }

    #[test]
    fn test_push() {
        let mut heap = PriorityQueue::from_vec(~[2, 4, 9]);
        assert_eq!(heap.len(), 3);
        assert!(*heap.top() == 9);
        heap.push(11);
        assert_eq!(heap.len(), 4);
        assert!(*heap.top() == 11);
        heap.push(5);
        assert_eq!(heap.len(), 5);
        assert!(*heap.top() == 11);
        heap.push(27);
        assert_eq!(heap.len(), 6);
        assert!(*heap.top() == 27);
        heap.push(3);
        assert_eq!(heap.len(), 7);
        assert!(*heap.top() == 27);
        heap.push(103);
        assert_eq!(heap.len(), 8);
        assert!(*heap.top() == 103);
    }

    #[test]
    fn test_push_unique() {
        let mut heap = PriorityQueue::from_vec(~[~2, ~4, ~9]);
        assert_eq!(heap.len(), 3);
        assert!(*heap.top() == ~9);
        heap.push(~11);
        assert_eq!(heap.len(), 4);
        assert!(*heap.top() == ~11);
        heap.push(~5);
        assert_eq!(heap.len(), 5);
        assert!(*heap.top() == ~11);
        heap.push(~27);
        assert_eq!(heap.len(), 6);
        assert!(*heap.top() == ~27);
        heap.push(~3);
        assert_eq!(heap.len(), 7);
        assert!(*heap.top() == ~27);
        heap.push(~103);
        assert_eq!(heap.len(), 8);
        assert!(*heap.top() == ~103);
    }

    #[test]
    fn test_push_pop() {
        let mut heap = PriorityQueue::from_vec(~[5, 5, 2, 1, 3]);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(6), 6);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(0), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(4), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(1), 4);
        assert_eq!(heap.len(), 5);
    }

    #[test]
    fn test_replace() {
        let mut heap = PriorityQueue::from_vec(~[5, 5, 2, 1, 3]);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(6), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(0), 6);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(4), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(1), 4);
        assert_eq!(heap.len(), 5);
    }

    fn check_to_vec(data: ~[int]) {
        let heap = PriorityQueue::from_vec(copy data);
        assert_eq!(merge_sort((copy heap).to_vec(), |x, y| x.le(y)),
                   merge_sort(data, |x, y| x.le(y)));
        assert_eq!(heap.to_sorted_vec(), merge_sort(data, |x, y| x.le(y)));
    }

    #[test]
    fn test_to_vec() {
        check_to_vec(~[]);
        check_to_vec(~[5]);
        check_to_vec(~[3, 2]);
        check_to_vec(~[2, 3]);
        check_to_vec(~[5, 1, 2]);
        check_to_vec(~[1, 100, 2, 3]);
        check_to_vec(~[1, 3, 5, 7, 9, 2, 4, 6, 8, 0]);
        check_to_vec(~[2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]);
        check_to_vec(~[9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]);
        check_to_vec(~[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        check_to_vec(~[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]);
        check_to_vec(~[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]);
        check_to_vec(~[5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]);
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn test_empty_pop() { let mut heap = PriorityQueue::new::<int>(); heap.pop(); }

    #[test]
    fn test_empty_maybe_pop() {
        let mut heap = PriorityQueue::new::<int>();
        assert!(heap.maybe_pop().is_none());
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn test_empty_top() { let empty = PriorityQueue::new::<int>(); empty.top(); }

    #[test]
    fn test_empty_maybe_top() {
        let empty = PriorityQueue::new::<int>();
        assert!(empty.maybe_top().is_none());
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn test_empty_replace() { let mut heap = PriorityQueue::new(); heap.replace(5); }
}
<commit_msg>priority_queue: implement simple iterator<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A priority queue implemented with a binary heap

#[allow(missing_doc)];

use core::prelude::*;

use core::unstable::intrinsics::{move_val_init, init};
use core::util::{replace, swap};
use core::vec;

/// A priority queue implemented with a binary heap
pub struct PriorityQueue<T> {
    priv data: ~[T],
}

impl<T:Ord> Container for PriorityQueue<T> {
    /// Returns the length of the queue
    fn len(&self) -> uint { self.data.len() }

    /// Returns true if a queue contains no elements
    fn is_empty(&self) -> bool { self.len() == 0 }
}

impl<T:Ord> Mutable for PriorityQueue<T> {
    /// Drop all items from the queue
    fn clear(&mut self) { self.data.truncate(0) }
}

impl<T:Ord> PriorityQueue<T> {
    /// An iterator visiting all values in underlying vector, in
    /// arbitrary order.
    pub fn iter<'a>(&'a self) -> PriorityQueueIterator<'a, T> {
        PriorityQueueIterator { iter: self.data.iter() }
    }

    /// Returns the greatest item in the queue - fails if empty
    pub fn top<'a>(&'a self) -> &'a T { &self.data[0] }

    /// Returns the greatest item in the queue - None if empty
    pub fn maybe_top<'a>(&'a self) -> Option<&'a T> {
        if self.is_empty() { None } else { Some(self.top()) }
    }

    /// Returns the number of elements the queue can hold without reallocating
    pub fn capacity(&self) -> uint { vec::capacity(&self.data) }

    pub fn reserve(&mut self, n: uint) { vec::reserve(&mut self.data, n) }

    pub fn reserve_at_least(&mut self, n: uint) {
        vec::reserve_at_least(&mut self.data, n)
    }

    /// Pop the greatest item from the queue - fails if empty
    pub fn pop(&mut self) -> T {
        let mut item = self.data.pop();
        if !self.is_empty() {
            swap(&mut item, &mut self.data[0]);
            self.siftdown(0);
        }
        item
    }

    /// Pop the greatest item from the queue - None if empty
    pub fn maybe_pop(&mut self) -> Option<T> {
        if self.is_empty() { None } else { Some(self.pop()) }
    }

    /// Push an item onto the queue
    pub fn push(&mut self, item: T) {
        self.data.push(item);
        let new_len = self.len() - 1;
        self.siftup(0, new_len);
    }

    /// Optimized version of a push followed by a pop
    pub fn push_pop(&mut self, mut item: T) -> T {
        if !self.is_empty() && self.data[0] > item {
            swap(&mut item, &mut self.data[0]);
            self.siftdown(0);
        }
        item
    }

    /// Optimized version of a pop followed by a push - fails if empty
    pub fn replace(&mut self, mut item: T) -> T {
        swap(&mut item, &mut self.data[0]);
        self.siftdown(0);
        item
    }

    /// Consume the PriorityQueue and return the underlying vector
    pub fn to_vec(self) -> ~[T] { let PriorityQueue{data: v} = self; v }

    /// Consume the PriorityQueue and return a vector in sorted
    /// (ascending) order
    pub fn to_sorted_vec(self) -> ~[T] {
        let mut q = self;
        let mut end = q.len();
        while end > 1 {
            end -= 1;
            vec::swap(q.data, 0, end);
            q.siftdown_range(0, end)
        }
        q.to_vec()
    }

    /// Create an empty PriorityQueue
    pub fn new() -> PriorityQueue<T> { PriorityQueue{data: ~[],} }

    /// Create a PriorityQueue from a vector (heapify)
    pub fn from_vec(xs: ~[T]) -> PriorityQueue<T> {
        let mut q = PriorityQueue{data: xs,};
        let mut n = q.len() / 2;
        while n > 0 {
            n -= 1;
            q.siftdown(n)
        }
        q
    }

    // The implementations of siftup and siftdown use unsafe blocks in
    // order to move an element out of the vector (leaving behind a
    // zeroed element), shift along the others and move it back into the
    // vector over the junk element.  This reduces the constant factor
    // compared to using swaps, which involves twice as many moves.
    fn siftup(&mut self, start: uint, mut pos: uint) {
        unsafe {
            let new = replace(&mut self.data[pos], init());

            while pos > start {
                let parent = (pos - 1) >> 1;
                if new > self.data[parent] {
                    let x = replace(&mut self.data[parent], init());
                    move_val_init(&mut self.data[pos], x);
                    pos = parent;
                    loop
                }
                break
            }
            move_val_init(&mut self.data[pos], new);
        }
    }

    fn siftdown_range(&mut self, mut pos: uint, end: uint) {
        unsafe {
            let start = pos;
            let new = replace(&mut self.data[pos], init());

            let mut child = 2 * pos + 1;
            while child < end {
                let right = child + 1;
                if right < end && !(self.data[child] > self.data[right]) {
                    child = right;
                }
                let x = replace(&mut self.data[child], init());
                move_val_init(&mut self.data[pos], x);
                pos = child;
                child = 2 * pos + 1;
            }

            move_val_init(&mut self.data[pos], new);
            self.siftup(start, pos);
        }
    }

    fn siftdown(&mut self, pos: uint) {
        let len = self.len();
        self.siftdown_range(pos, len);
    }
}

/// PriorityQueue iterator
pub struct PriorityQueueIterator <'self, T> {
    priv iter: vec::VecIterator<'self, T>,
}

impl<'self, T> Iterator<&'self T> for PriorityQueueIterator<'self, T> {
    #[inline]
    fn next(&mut self) -> Option<(&'self T)> { self.iter.next() }
}

#[cfg(test)]
mod tests {
    use sort::merge_sort;
    use priority_queue::PriorityQueue;

    #[test]
    fn test_iterator() {
        let data = ~[5, 9, 3];
        let iterout = ~[9, 5, 3];
        let pq = PriorityQueue::from_vec(data);
        let mut i = 0;
        for pq.iter().advance |el| {
            assert_eq!(*el, iterout[i]);
            i += 1;
        }
    }

    #[test]
    fn test_top_and_pop() {
        let data = ~[2u, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
        let mut sorted = merge_sort(data, |x, y| x.le(y));
        let mut heap = PriorityQueue::from_vec(data);
        while !heap.is_empty() {
            assert_eq!(heap.top(), sorted.last());
            assert_eq!(heap.pop(), sorted.pop());
        }
    }

    #[test]
    fn test_push() {
        let mut heap = PriorityQueue::from_vec(~[2, 4, 9]);
        assert_eq!(heap.len(), 3);
        assert!(*heap.top() == 9);
        heap.push(11);
        assert_eq!(heap.len(), 4);
        assert!(*heap.top() == 11);
        heap.push(5);
        assert_eq!(heap.len(), 5);
        assert!(*heap.top() == 11);
        heap.push(27);
        assert_eq!(heap.len(), 6);
        assert!(*heap.top() == 27);
        heap.push(3);
        assert_eq!(heap.len(), 7);
        assert!(*heap.top() == 27);
        heap.push(103);
        assert_eq!(heap.len(), 8);
        assert!(*heap.top() == 103);
    }

    #[test]
    fn test_push_unique() {
        let mut heap = PriorityQueue::from_vec(~[~2, ~4, ~9]);
        assert_eq!(heap.len(), 3);
        assert!(*heap.top() == ~9);
        heap.push(~11);
        assert_eq!(heap.len(), 4);
        assert!(*heap.top() == ~11);
        heap.push(~5);
        assert_eq!(heap.len(), 5);
        assert!(*heap.top() == ~11);
        heap.push(~27);
        assert_eq!(heap.len(), 6);
        assert!(*heap.top() == ~27);
        heap.push(~3);
        assert_eq!(heap.len(), 7);
        assert!(*heap.top() == ~27);
        heap.push(~103);
        assert_eq!(heap.len(), 8);
        assert!(*heap.top() == ~103);
    }

    #[test]
    fn test_push_pop() {
        let mut heap = PriorityQueue::from_vec(~[5, 5, 2, 1, 3]);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(6), 6);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(0), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(4), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(1), 4);
        assert_eq!(heap.len(), 5);
    }

    #[test]
    fn test_replace() {
        let mut heap = PriorityQueue::from_vec(~[5, 5, 2, 1, 3]);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(6), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(0), 6);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(4), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(1), 4);
        assert_eq!(heap.len(), 5);
    }

    fn check_to_vec(data: ~[int]) {
        let heap = PriorityQueue::from_vec(copy data);
        assert_eq!(merge_sort((copy heap).to_vec(), |x, y| x.le(y)),
                   merge_sort(data, |x, y| x.le(y)));
        assert_eq!(heap.to_sorted_vec(), merge_sort(data, |x, y| x.le(y)));
    }

    #[test]
    fn test_to_vec() {
        check_to_vec(~[]);
        check_to_vec(~[5]);
        check_to_vec(~[3, 2]);
        check_to_vec(~[2, 3]);
        check_to_vec(~[5, 1, 2]);
        check_to_vec(~[1, 100, 2, 3]);
        check_to_vec(~[1, 3, 5, 7, 9, 2, 4, 6, 8, 0]);
        check_to_vec(~[2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]);
        check_to_vec(~[9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]);
        check_to_vec(~[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        check_to_vec(~[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]);
        check_to_vec(~[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]);
        check_to_vec(~[5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]);
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn test_empty_pop() { let mut heap = PriorityQueue::new::<int>(); heap.pop(); }

    #[test]
    fn test_empty_maybe_pop() {
        let mut heap = PriorityQueue::new::<int>();
        assert!(heap.maybe_pop().is_none());
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn test_empty_top() { let empty = PriorityQueue::new::<int>(); empty.top(); }

    #[test]
    fn test_empty_maybe_top() {
        let empty = PriorityQueue::new::<int>();
        assert!(empty.maybe_top().is_none());
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn test_empty_replace() { let mut heap = PriorityQueue::new(); heap.replace(5); }
}
<|endoftext|>


<commit_before>extern crate libradium;

use std::sync::mpsc;
use std::io::prelude::*;
use std::io;
use std::sync::mpsc::{Sender, Receiver};

use libradium::entry::{Entry, Timestamp};
use libradium::worker::Listener;
use libradium::frontend::Frontend;

struct Data {
    age: u16
}

impl Data {
    pub fn new(age: u16) -> Self {
        Data { age }
    }

    pub fn age(&self) -> u16 {
        self.age
    }
}

struct TestListener {
    tx: Sender<Output>,
}

enum Output {
    Expired(Entry<Data>),
    Tick,
}

impl Listener<Data> for TestListener {
    fn on_expired(&self, entry: Entry<Data>) {
        self.tx.send(Output::Expired(entry)).unwrap();
    }

    fn on_tick(&self) {
        self.tx.send(Output::Tick).unwrap();
    }
}

fn main() {
    let (tx_listener, rx_listener): (Sender<Output>, Receiver<Output>) = mpsc::channel();
    let listener = Box::new(TestListener { tx: tx_listener });
    let (frontend, _) = Frontend::build(listener);

    let now = Timestamp::now();

    frontend.add_entry(Entry::gen(now, Data::new(10))).unwrap();
    frontend.add_entry(Entry::gen(now + 2, Data::new(20))).unwrap();
    frontend.add_entry(Entry::gen(now + 4, Data::new(30))).unwrap();
    frontend.add_entry(Entry::gen(now + 6, Data::new(40))).unwrap();
    frontend.add_entry(Entry::gen(now + 6, Data::new(50))).unwrap();
    frontend.add_entry(Entry::gen(now + 6, Data::new(60))).unwrap();
    frontend.add_entry(Entry::gen(now + 6, Data::new(70))).unwrap();
    frontend.add_entry(Entry::gen(now + 10, Data::new(80))).unwrap();

    loop {
        match rx_listener.recv().unwrap() {
            Output::Expired(entry) => {
                print!("({:?}, {})", entry.id().timestamp().sec, entry.data().age());
                io::stdout().flush().unwrap();
            }
            Output::Tick => {
                print!(".");
            }
        };
    }
}
<commit_msg>Rename Data -> User in example<commit_after>extern crate libradium;

use std::sync::mpsc;
use std::io::prelude::*;
use std::io;
use std::sync::mpsc::{Sender, Receiver};

use libradium::entry::{Entry, Timestamp};
use libradium::worker::Listener;
use libradium::frontend::Frontend;

struct User {
    age: u16
}

impl User {
    pub fn new(age: u16) -> Self {
        User { age }
    }

    pub fn age(&self) -> u16 {
        self.age
    }
}

struct TestListener {
    tx: Sender<Output>,
}

enum Output {
    Expired(Entry<User>),
    Tick,
}

impl Listener<User> for TestListener {
    fn on_expired(&self, entry: Entry<User>) {
        self.tx.send(Output::Expired(entry)).unwrap();
    }

    fn on_tick(&self) {
        self.tx.send(Output::Tick).unwrap();
    }
}

fn main() {
    let (tx_listener, rx_listener): (Sender<Output>, Receiver<Output>) = mpsc::channel();
    let listener = Box::new(TestListener { tx: tx_listener });
    let (frontend, _) = Frontend::build(listener);

    let now = Timestamp::now();

    frontend.add_entry(Entry::gen(now, User::new(10))).unwrap();
    frontend.add_entry(Entry::gen(now + 2, User::new(20))).unwrap();
    frontend.add_entry(Entry::gen(now + 4, User::new(30))).unwrap();
    frontend.add_entry(Entry::gen(now + 6, User::new(40))).unwrap();
    frontend.add_entry(Entry::gen(now + 6, User::new(50))).unwrap();
    frontend.add_entry(Entry::gen(now + 6, User::new(60))).unwrap();
    frontend.add_entry(Entry::gen(now + 6, User::new(70))).unwrap();
    frontend.add_entry(Entry::gen(now + 10, User::new(80))).unwrap();

    loop {
        match rx_listener.recv().unwrap() {
            Output::Expired(entry) => {
                print!("({:?}, {})", entry.id().timestamp().sec, entry.data().age());
                io::stdout().flush().unwrap();
            }
            Output::Tick => {
                print!(".");
            }
        };
    }
}
<|endoftext|>


<commit_before>use serde_json::builder::ObjectBuilder;
use serde_json::Value;
use super::connection_info::ConnectionInfo;
use ::constants::VoiceOpCode;

#[cfg(feature="cache")]
use ::client::CACHE;

#[inline]
pub fn build_identify(info: &ConnectionInfo) -> Value {
    ObjectBuilder::new()
        .insert("op", VoiceOpCode::Identify.num())
        .insert_object("d", |o| o
            .insert("server_id", info.target_id)
            .insert("session_id", &info.session_id)
            .insert("token", &info.token)
            .insert("user_id", info.user_id.0))
        .build()
}

#[inline]
pub fn build_keepalive() -> Value {
    ObjectBuilder::new()
        .insert("op", VoiceOpCode::KeepAlive.num())
        .insert("d", Value::Null)
        .build()
}

#[inline]
pub fn build_select_protocol(address: ::std::borrow::Cow<str>, port: u16) -> Value {
    ObjectBuilder::new()
        .insert("op", VoiceOpCode::SelectProtocol.num())
        .insert_object("d", |o| o
            .insert("protocol", "udp")
            .insert_object("data", |o| o
                .insert("address", address)
                .insert("mode", super::CRYPTO_MODE)
                .insert("port", port)))
        .build()
}

#[inline]
pub fn build_speaking(speaking: bool) -> Value {
    ObjectBuilder::new()
        .insert("op", VoiceOpCode::Speaking.num())
        .insert_object("d", |o| o
            .insert("delay", 0)
            .insert("speaking", speaking))
        .build()
}
<commit_msg>Remove useless cache use<commit_after>use serde_json::builder::ObjectBuilder;
use serde_json::Value;
use super::connection_info::ConnectionInfo;
use ::constants::VoiceOpCode;

#[inline]
pub fn build_identify(info: &ConnectionInfo) -> Value {
    ObjectBuilder::new()
        .insert("op", VoiceOpCode::Identify.num())
        .insert_object("d", |o| o
            .insert("server_id", info.target_id)
            .insert("session_id", &info.session_id)
            .insert("token", &info.token)
            .insert("user_id", info.user_id.0))
        .build()
}

#[inline]
pub fn build_keepalive() -> Value {
    ObjectBuilder::new()
        .insert("op", VoiceOpCode::KeepAlive.num())
        .insert("d", Value::Null)
        .build()
}

#[inline]
pub fn build_select_protocol(address: ::std::borrow::Cow<str>, port: u16) -> Value {
    ObjectBuilder::new()
        .insert("op", VoiceOpCode::SelectProtocol.num())
        .insert_object("d", |o| o
            .insert("protocol", "udp")
            .insert_object("data", |o| o
                .insert("address", address)
                .insert("mode", super::CRYPTO_MODE)
                .insert("port", port)))
        .build()
}

#[inline]
pub fn build_speaking(speaking: bool) -> Value {
    ObjectBuilder::new()
        .insert("op", VoiceOpCode::Speaking.num())
        .insert_object("d", |o| o
            .insert("delay", 0)
            .insert("speaking", speaking))
        .build()
}
<|endoftext|>


<commit_before>// A port of the simplistic benchmark from
//
//    http://github.com/PaulKeeble/ScalaVErlangAgents
//
// I *think* it's the same, more or less.

#![crate_name = "msgsend"]

extern crate time;
extern crate zmq;

use std::os;
use std::thread::Thread;
use std::sync::mpsc::{channel, Sender, Receiver};

fn server(mut pull_socket: zmq::Socket, mut push_socket: zmq::Socket, mut workers: uint) {
    let mut count = 0u;
    let mut msg = zmq::Message::new().unwrap();

    while workers != 0 {
        match pull_socket.recv(&mut msg, 0) {
            Err(e) => panic!(e.to_string()),
            Ok(()) => {
                let s = msg.as_str().ok().unwrap();
                if s.is_empty() {
                    workers -= 1;
                } else {
                    count += s.parse().unwrap();
                }
            }
        }
    }

    match push_socket.send_str(count.to_string().as_slice(), 0) {
        Ok(()) => { }
        Err(e) => panic!(e.to_string()),
    }
}

fn spawn_server(ctx: &mut zmq::Context, workers: uint) -> Sender<()> {
    let mut pull_socket = ctx.socket(zmq::PULL).unwrap();
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();

    pull_socket.bind("inproc://server-pull").unwrap();
    push_socket.bind("inproc://server-push").unwrap();

    // Spawn the server.
    let (ready_tx, ready_rx) = channel();
    let (start_tx, start_rx) = channel();

    Thread::spawn(move|| {
        // Let the main thread know we're ready.
        ready_tx.send(());

        // Wait until we need to start.
        start_rx.recv();

        server(pull_socket, push_socket, workers);
    });

    // Wait for the server to start.
    ready_rx.recv();

    start_tx
}

fn worker(mut push_socket: zmq::Socket, count: uint) {
    for _ in range(0, count) {
        push_socket.send_str(100u.to_string().as_slice(), 0).unwrap();
    }

    // Let the server know we're done.
    push_socket.send_str("", 0).unwrap();
}

fn spawn_worker(ctx: &mut zmq::Context, count: uint) -> Receiver<()> {
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();

    push_socket.connect("inproc://server-pull").unwrap();
    //push_socket.connect("tcp://127.0.0.1:3456").unwrap();

    // Spawn the worker.
    let (tx, rx) = channel();
    Thread::spawn(move|| {
        // Let the main thread we're ready.
        tx.send(());

        worker(push_socket, count);

        tx.send(());
    });

    // Wait for the worker to start.
    rx.recv();

    rx
}

fn run(ctx: &mut zmq::Context, size: uint, workers: uint) {
    let start_ch = spawn_server(ctx, workers);

    // Create some command/control sockets.
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();
    let mut pull_socket = ctx.socket(zmq::PULL).unwrap();

    push_socket.connect("inproc://server-pull").unwrap();
    pull_socket.connect("inproc://server-push").unwrap();
    //push_socket.connect("tcp://127.0.0.1:3456").unwrap();
    //pull_socket.connect("tcp://127.0.0.1:3457").unwrap();

    // Spawn all the workers.
    let mut worker_results = Vec::new();
    for _ in range(0, workers) {
        worker_results.push(spawn_worker(ctx, size / workers));
    }

    let start = time::precise_time_s();

    start_ch.send(());

    // Block until all the workers finish.
    for po in worker_results.iter() {
        po.recv();
    }

    // Receive the final count.
    let result: i32 = match pull_socket.recv_msg(0) {
        Ok(msg) => {
            let msg_str: &str = msg.as_str().ok().unwrap();
            msg_str.parse().unwrap()
        },
        Err(e) => panic!(e.to_string()),
    };

    let end = time::precise_time_s();
    let elapsed = end - start;

    println!("Count is {}", result);
    println!("Test took {} seconds", elapsed);
    let thruput = ((size / workers * workers) as f64) / elapsed;
    println!("Throughput={} per sec", thruput);
}

fn main() {
    let args = os::args();

    let args = if os::getenv("RUST_BENCH").is_some() {
        vec!("".to_string(), "1000000".to_string(), "10000".to_string())
    } else if args.len() <= 1u {
        vec!("".to_string(), "10000".to_string(), "4".to_string())
    } else {
        args
    };

    let size: uint = args[1].as_slice().parse().unwrap();
    let workers: uint = args[2].as_slice().parse().unwrap();

    let mut ctx = zmq::Context::new();

    run(&mut ctx, size, workers);
}
<commit_msg>Remove invalid uses of `to_string()`<commit_after>// A port of the simplistic benchmark from
//
//    http://github.com/PaulKeeble/ScalaVErlangAgents
//
// I *think* it's the same, more or less.

#![crate_name = "msgsend"]

extern crate time;
extern crate zmq;

use std::os;
use std::thread::Thread;
use std::sync::mpsc::{channel, Sender, Receiver};

fn server(mut pull_socket: zmq::Socket, mut push_socket: zmq::Socket, mut workers: uint) {
    let mut count = 0u;
    let mut msg = zmq::Message::new().unwrap();

    while workers != 0 {
        match pull_socket.recv(&mut msg, 0) {
            Err(e) => panic!(e),
            Ok(()) => {
                let s = msg.as_str().unwrap();
                if s.is_empty() {
                    workers -= 1;
                } else {
                    count += s.parse().unwrap();
                }
            }
        }
    }

    match push_socket.send_str(count.to_string().as_slice(), 0) {
        Ok(()) => { }
        Err(e) => panic!(e),
    }
}

fn spawn_server(ctx: &mut zmq::Context, workers: uint) -> Sender<()> {
    let mut pull_socket = ctx.socket(zmq::PULL).unwrap();
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();

    pull_socket.bind("inproc://server-pull").unwrap();
    push_socket.bind("inproc://server-push").unwrap();

    // Spawn the server.
    let (ready_tx, ready_rx) = channel();
    let (start_tx, start_rx) = channel();

    Thread::spawn(move|| {
        // Let the main thread know we're ready.
        ready_tx.send(());

        // Wait until we need to start.
        start_rx.recv();

        server(pull_socket, push_socket, workers);
    });

    // Wait for the server to start.
    ready_rx.recv();

    start_tx
}

fn worker(mut push_socket: zmq::Socket, count: uint) {
    for _ in range(0, count) {
        push_socket.send_str(100u.to_string().as_slice(), 0).unwrap();
    }

    // Let the server know we're done.
    push_socket.send_str("", 0).unwrap();
}

fn spawn_worker(ctx: &mut zmq::Context, count: uint) -> Receiver<()> {
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();

    push_socket.connect("inproc://server-pull").unwrap();
    //push_socket.connect("tcp://127.0.0.1:3456").unwrap();

    // Spawn the worker.
    let (tx, rx) = channel();
    Thread::spawn(move|| {
        // Let the main thread we're ready.
        tx.send(());

        worker(push_socket, count);

        tx.send(());
    });

    // Wait for the worker to start.
    rx.recv();

    rx
}

fn run(ctx: &mut zmq::Context, size: uint, workers: uint) {
    let start_ch = spawn_server(ctx, workers);

    // Create some command/control sockets.
    let mut push_socket = ctx.socket(zmq::PUSH).unwrap();
    let mut pull_socket = ctx.socket(zmq::PULL).unwrap();

    push_socket.connect("inproc://server-pull").unwrap();
    pull_socket.connect("inproc://server-push").unwrap();
    //push_socket.connect("tcp://127.0.0.1:3456").unwrap();
    //pull_socket.connect("tcp://127.0.0.1:3457").unwrap();

    // Spawn all the workers.
    let mut worker_results = Vec::new();
    for _ in range(0, workers) {
        worker_results.push(spawn_worker(ctx, size / workers));
    }

    let start = time::precise_time_s();

    start_ch.send(());

    // Block until all the workers finish.
    for po in worker_results.iter() {
        po.recv();
    }

    // Receive the final count.
    let result: i32 = match pull_socket.recv_msg(0) {
        Ok(msg) => {
            let msg_str: &str = msg.as_str().unwrap();
            msg_str.parse().unwrap()
        },
        Err(e) => panic!(e),
    };

    let end = time::precise_time_s();
    let elapsed = end - start;

    println!("Count is {}", result);
    println!("Test took {} seconds", elapsed);
    let thruput = ((size / workers * workers) as f64) / elapsed;
    println!("Throughput={} per sec", thruput);
}

fn main() {
    let args = os::args();

    let args = if os::getenv("RUST_BENCH").is_some() {
        vec!("".to_string(), "1000000".to_string(), "10000".to_string())
    } else if args.len() <= 1u {
        vec!("".to_string(), "10000".to_string(), "4".to_string())
    } else {
        args
    };

    let size: uint = args[1].as_slice().parse().unwrap();
    let workers: uint = args[2].as_slice().parse().unwrap();

    let mut ctx = zmq::Context::new();

    run(&mut ctx, size, workers);
}
<|endoftext|>


<commit_before>use glium::{Frame, VertexBuffer, Blend, Surface};
use glium::Display;
use glium::index::{IndexBuffer, PrimitiveType};
use glium::draw_parameters::DrawParameters;
use glium::draw_parameters::LinearBlendingFactor::*;
use glium::draw_parameters::BlendingFunction::*;
use glium::uniforms::{Uniforms, UniformsStorage, AsUniformValue, MagnifySamplerFilter, MinifySamplerFilter};

use nalgebra::Norm;

use {GameContext, Node, Vect};
use super::{RenderContext, Vertex, vert};
use math::*;
use quantum_circuit_wars::circuit::{GameView, Game, Port};

fn input_pos(gen: &Game<Node>, input: Port<u32>, _size: f32) -> Vect {
    let node = gen.get(input.node).unwrap();
    let pos = node.1.pos;
    let percent = (input.port + 1) as f32 / (node.0.max_in() + 1) as f32;
    Vect::new(pos[0] - 0.5 + percent, -(pos[1] - 0.5))
}

fn output_pos(gen: &Game<Node>, output: Port<u32>, size: f32) -> Vect {
    let node = gen.get(output.node).unwrap();
    let pos = node.1.pos;
    let percent = (output.port + 1) as f32 / (node.0.max_out() + 1) as f32;
    Vect::new(pos[0] - 0.5 + percent, -(pos[1] + 0.5 + size))
}

pub fn render(display: &Display, rctx: &mut RenderContext, world: GameView<Node>, ctx: &GameContext) {
    let mut target = display.draw();
    target.clear_color(0.0157, 0.0173, 0.0204, 1.);
    let draw_params = DrawParameters {
        blend: Blend {
            color: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            alpha: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            constant_value: (0f32, 0f32, 0f32, 1f32),
        },
        smooth: None,
        ..Default::default()
    };
    let dims = display.get_framebuffer_dimensions();
    for (_, data) in world.iter() {
        let pos = flip_y(data.pos);
        let corner_pos = pos - Vect::new(ctx.node_width, ctx.node_width) * 0.5;
        let matrix = rctx.cam * translation(corner_pos.x, corner_pos.y);
        let uniforms = uniform! {
            matrix: *matrix.as_ref(),
        };
        draw(&mut target, &rctx, "back", "plain", &uniforms, &draw_params);
        let matrix = rctx.cam * translation(corner_pos.x + 0.05, corner_pos.y + 0.05) * scale(0.9, 0.9);
        let program = rctx.programs.get("plain");
        let program = program.as_ref().expect("Node didn't have shader.");
        let uniforms = uniform! {
            matrix: *matrix.as_ref(),
        };
        let model = rctx.models.get("node").unwrap();
        target.draw(&model.vertices, &model.indices, &program, &uniforms, &draw_params).expect("Drawing node failed.");

        let mut draw = |things: &[_]| {
            for p in things {
                let p = pos + flip_y(*p) - Vect::new(ctx.port_size, ctx.port_size) * 0.5;
                let matrix = rctx.cam * translation(p.x, p.y) * scale(ctx.port_size, ctx.port_size);
                let uniforms = uniform! {
                    matrix: *matrix.as_ref(),
                };
                draw(&mut target, &rctx, "node", "plain", &uniforms, &draw_params);
            }
        };
        draw(&data.outputs.borrow());
        draw(&data.inputs.borrow());
    }
    let mut lines = Vec::with_capacity(world.connections());
    for (src, trg) in world.iter_connections() {
        let src = output_pos(&world, src, ctx.port_size);
        let trg = input_pos(&world, trg, ctx.port_size);
        let trg = Vect::new(trg[0], trg[1] + ctx.port_size);
        add_arrow(&mut lines, src, trg, 0.1, 0.1 * TAU);
    }
    let vertices = VertexBuffer::new(display, &lines).unwrap();
    let indices = (0..lines.len() as u32).collect::<Vec<_>>();
    let indices = IndexBuffer::new(display, PrimitiveType::LinesList, &indices).unwrap();
    let matrix = rctx.cam * translation(0., 0.);
    let uniforms = uniform! {
        matrix: *matrix.as_ref(),
    };
    let program = rctx.programs.get("plain").unwrap();
    target.draw(&vertices, &indices, program, &uniforms, &draw_params).unwrap();
    target.finish().unwrap();
}

pub fn render_splashscreen(render_context: &mut RenderContext) {
    let mut target = display.draw();
    let draw_params = DrawParameters {
        blend: Blend {
            color: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            alpha: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            constant_value: (0f32, 0f32, 0f32, 1f32),
        },
        smooth: None,
        ..Default::default()
    };
    let texture = render_context.textures.get("splash");
    let model = render_context.models.get("node").unwrap();
    let program = render_context.programs.get("plain");
    let splash_matrix = render_context.cam * math::translation(0., 0.) * scale(ctx.port_size, crtx.port_size);
    let uniforms = uniform! {
        matrix: *matrix.as_ref(),
        tex: texture.sampled()
            .magnify_filter(MagnifySamplerFilter::Nearest)
            .minify_filter(MinifySamplerFilter::Nearest),

    };
    target.draw(&model.vertices, &model.indices, program, uniforms, draw_params);
}

fn draw<A, B>(target: &mut Frame, rctx: &RenderContext, model: &str, program: &str, uniforms: &UniformsStorage<A, B>, draw_params: &DrawParameters)
    where A: AsUniformValue,
          B: Uniforms,
{
    let model = rctx.models.get(model).unwrap();
    let program = rctx.programs.get(program).unwrap();
    target.draw(&model.vertices, &model.indices, program, uniforms, draw_params).unwrap();
}

fn add_arrow(lines: &mut Vec<Vertex>, src: Vect, trg: Vect, len: f32, theta: f32) {
    lines.push(vert(src.x, src.y));
    lines.push(vert(trg.x, trg.y));
    let vec = (src - trg).normalize();
    let mut add_part = |theta: f32| {
        let (sin, cos) = theta.sin_cos();
        let arrow = Vect::new(
            vec.x * cos - vec.y * sin,
            vec.x * sin + vec.y * cos);
        lines.push(vert(trg.x, trg.y));
        let v = trg + (arrow * len);
        lines.push(vert(v.x, v.y));
    };
    add_part(theta);
    add_part(-theta);
}
<commit_msg>commit<commit_after>use glium::{Frame, VertexBuffer, Blend, Surface};
use glium::Display;
use glium::index::{IndexBuffer, PrimitiveType};
use glium::draw_parameters::DrawParameters;
use glium::draw_parameters::LinearBlendingFactor::*;
use glium::draw_parameters::BlendingFunction::*;
use glium::uniforms::{Uniforms, UniformsStorage, AsUniformValue, MagnifySamplerFilter, MinifySamplerFilter};

use nalgebra::Norm;
use std::convert::AsRef;

use {GameContext, Node, Vect};
use super::{RenderContext, Vertex, vert};
use math::*;
use quantum_circuit_wars::circuit::{GameView, Game, Port};

fn input_pos(gen: &Game<Node>, input: Port<u32>, _size: f32) -> Vect {
    let node = gen.get(input.node).unwrap();
    let pos = node.1.pos;
    let percent = (input.port + 1) as f32 / (node.0.max_in() + 1) as f32;
    Vect::new(pos[0] - 0.5 + percent, -(pos[1] - 0.5))
}

fn output_pos(gen: &Game<Node>, output: Port<u32>, size: f32) -> Vect {
    let node = gen.get(output.node).unwrap();
    let pos = node.1.pos;
    let percent = (output.port + 1) as f32 / (node.0.max_out() + 1) as f32;
    Vect::new(pos[0] - 0.5 + percent, -(pos[1] + 0.5 + size))
}

pub fn render(display: &Display, rctx: &mut RenderContext, world: GameView<Node>, ctx: &GameContext) {
    let mut target = display.draw();
    target.clear_color(0.0157, 0.0173, 0.0204, 1.);
    let draw_params = DrawParameters {
        blend: Blend {
            color: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            alpha: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            constant_value: (0f32, 0f32, 0f32, 1f32),
        },
        smooth: None,
        ..Default::default()
    };
    let dims = display.get_framebuffer_dimensions();
    for (_, data) in world.iter() {
        let pos = flip_y(data.pos);
        let corner_pos = pos - Vect::new(ctx.node_width, ctx.node_width) * 0.5;
        let matrix = rctx.cam * translation(corner_pos.x, corner_pos.y);
        let uniforms = uniform! {
            matrix: *matrix.as_ref(),
        };
        draw(&mut target, &rctx, "back", "plain", &uniforms, &draw_params);
        let matrix = rctx.cam * translation(corner_pos.x + 0.05, corner_pos.y + 0.05) * scale(0.9, 0.9);
        let program = rctx.programs.get("plain");
        let program = program.as_ref().expect("Node didn't have shader.");
        let uniforms = uniform! {
            matrix: *matrix.as_ref(),
        };
        let model = rctx.models.get("node").unwrap();
        target.draw(&model.vertices, &model.indices, &program, &uniforms, &draw_params).expect("Drawing node failed.");

        let mut draw = |things: &[_]| {
            for p in things {
                let p = pos + flip_y(*p) - Vect::new(ctx.port_size, ctx.port_size) * 0.5;
                let matrix = rctx.cam * translation(p.x, p.y) * scale(ctx.port_size, ctx.port_size);
                let uniforms = uniform! {
                    matrix: *matrix.as_ref(),
                };
                draw(&mut target, &rctx, "node", "plain", &uniforms, &draw_params);
            }
        };
        draw(&data.outputs.borrow());
        draw(&data.inputs.borrow());
    }
    let mut lines = Vec::with_capacity(world.connections());
    for (src, trg) in world.iter_connections() {
        let src = output_pos(&world, src, ctx.port_size);
        let trg = input_pos(&world, trg, ctx.port_size);
        let trg = Vect::new(trg[0], trg[1] + ctx.port_size);
        add_arrow(&mut lines, src, trg, 0.1, 0.1 * TAU);
    }
    let vertices = VertexBuffer::new(display, &lines).unwrap();
    let indices = (0..lines.len() as u32).collect::<Vec<_>>();
    let indices = IndexBuffer::new(display, PrimitiveType::LinesList, &indices).unwrap();
    let matrix = rctx.cam * translation(0., 0.);
    let uniforms = uniform! {
        matrix: *matrix.as_ref(),
    };
    let program = rctx.programs.get("plain").unwrap();
    target.draw(&vertices, &indices, program, &uniforms, &draw_params).unwrap();
    target.finish().unwrap();
}

pub fn render_splashscreen(render_context: &mut RenderContext) {
    use
    let mut target = display.draw();
    let draw_params = DrawParameters {
        blend: Blend {
            color: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            alpha: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            constant_value: (0f32, 0f32, 0f32, 1f32),
        },
        smooth: None,
        ..Default::default()
    };
    let texture = render_context.textures.get("splash").unwrap();
    let model = render_context.models.get("node").unwrap();
    let program = render_context.programs.get("plain");
    let splash_matrix = render_context.cam * math::translation(0., 0.) * scale(ctx.port_size, crtx.port_size);
    let uniforms = uniform! {
        matrix: *matrix.as_ref(),
        tex: texture.sampled()
            .magnify_filter(MagnifySamplerFilter::Nearest)
            .minify_filter(MinifySamplerFilter::Nearest),

    };
    target.draw(&model.vertices, &model.indices, program, uniforms, draw_params);
}

fn draw<A, B>(target: &mut Frame, rctx: &RenderContext, model: &str, program: &str, uniforms: &UniformsStorage<A, B>, draw_params: &DrawParameters)
    where A: AsUniformValue,
          B: Uniforms,
{
    let model = rctx.models.get(model).unwrap();
    let program = rctx.programs.get(program).unwrap();
    target.draw(&model.vertices, &model.indices, program, uniforms, draw_params).unwrap();
}

fn add_arrow(lines: &mut Vec<Vertex>, src: Vect, trg: Vect, len: f32, theta: f32) {
    lines.push(vert(src.x, src.y));
    lines.push(vert(trg.x, trg.y));
    let vec = (src - trg).normalize();
    let mut add_part = |theta: f32| {
        let (sin, cos) = theta.sin_cos();
        let arrow = Vect::new(
            vec.x * cos - vec.y * sin,
            vec.x * sin + vec.y * cos);
        lines.push(vert(trg.x, trg.y));
        let v = trg + (arrow * len);
        lines.push(vert(v.x, v.y));
    };
    add_part(theta);
    add_part(-theta);
}
<|endoftext|>


<commit_before>use rand_distr::weighted_alias::WeightedAliasIndex;
use rand_distr::Distribution;
use std::collections::HashMap;
use std::fmt;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MarkovChainError {
    NoNgrams,
    ZeroEntropy,
    ZeroStartOfWordEntropy,
}

impl std::error::Error for MarkovChainError {}

impl fmt::Display for MarkovChainError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Self::NoNgrams => write!(f, "No ngrams found in cleaned input."),
            Self::ZeroEntropy => write!(f, "Cleaned input has no entropy."),
            Self::ZeroStartOfWordEntropy => {
                write!(f, "Cleaned input has not start of word entropy.")
            }
        }
    }
}

struct MarkovChainIterator<'chain> {
    markov_chain: &'chain PassphraseMarkovChain<'chain>,
    current: &'chain str,
}

impl<'chain> Iterator for MarkovChainIterator<'chain> {
    type Item = &'chain str;

    fn next(&mut self) -> Option<Self::Item> {
        let last = self.current;
        self.current = self.markov_chain.get_next_ngram(self.current);

        Some(last)
    }
}

#[derive(Debug)]
struct MarkovNode<T> {
    pub value: T,
    transitions: Vec<T>,
    dist: WeightedAliasIndex<f64>,
    entropy: f64,
}

impl<T> MarkovNode<T> {
    pub fn new(value: T, values: Vec<T>, weights: Vec<f64>) -> Self {
        let entropy = weight_entropy(&weights);
        Self {
            value,
            transitions: values,
            dist: WeightedAliasIndex::new(weights).unwrap(),
            entropy,
        }
    }

    pub fn next(&self) -> &T {
        &self.transitions[self.dist.sample(&mut rand::rngs::OsRng)]
    }

    pub const fn entropy(&self) -> f64 {
        self.entropy
    }
}

#[derive(Debug)]
pub struct PassphraseMarkovChain<'ngrams> {
    nodes: HashMap<&'ngrams str, MarkovNode<&'ngrams str>>,
    starting_ngrams: Vec<&'ngrams str>,
    starting_dist: WeightedAliasIndex<f64>,
    starting_entropy: f64,
}

impl<'ngrams> PassphraseMarkovChain<'ngrams> {
    pub fn new(
        ngrams: impl Iterator<Item = &'ngrams str>,
    ) -> Result<PassphraseMarkovChain<'ngrams>, MarkovChainError> {
        // Count transitions and viable starting ngrams.
        // To get natural sounding words, starting ngrams should be at word start.
        let mut transition_counters: HashMap<&str, HashMap<&str, usize>> = HashMap::new();
        let mut starting_ngram_counts: HashMap<&str, usize> = HashMap::new();
        let mut ngrams = ngrams.peekable();
        let first_ngram = <&str>::clone(ngrams.peek().ok_or(MarkovChainError::NoNgrams)?);
        while let Some(current_ngram) = ngrams.next() {
            if current_ngram.starts_with(' ') {
                *starting_ngram_counts.entry(current_ngram).or_insert(0) += 1;
            }
            // To guarantee every ngram has at least one valid transition, let the last ngram
            // transition to the first.
            let next_ngram = ngrams.peek().unwrap_or(&first_ngram);
            *transition_counters
                .entry(current_ngram)
                .or_insert_with(HashMap::new)
                .entry(next_ngram)
                .or_insert(0) += 1;
        }

        // Generate the starting ngram probability distribution.
        let mut starting_ngrams = Vec::with_capacity(starting_ngram_counts.len());
        let mut starting_ngram_weights = Vec::with_capacity(starting_ngram_counts.len());
        for (value, weight) in starting_ngram_counts {
            starting_ngrams.push(value);
            starting_ngram_weights.push(weight as f64);
        }
        let starting_entropy = weight_entropy(&starting_ngram_weights);
        let starting_dist = WeightedAliasIndex::new(starting_ngram_weights).unwrap();

        // Build all the MarkovNodes from the transition counts.
        let mut nodes: HashMap<&str, MarkovNode<&str>> = HashMap::new();
        let mut total_entropy: f64 = 0.0;
        for (ngram, transition_counts) in transition_counters {
            let mut values = Vec::with_capacity(transition_counts.len());
            let mut weights = Vec::with_capacity(transition_counts.len());
            for (value, weight) in transition_counts {
                values.push(value);
                weights.push(weight as f64);
            }

            let node = MarkovNode::new(ngram, values, weights);
            total_entropy += node.entropy();
            nodes.insert(ngram, node);
        }

        if total_entropy == 0.0 {
            return Err(MarkovChainError::ZeroEntropy);
        }
        if starting_entropy == 0.0 {
            return Err(MarkovChainError::ZeroStartOfWordEntropy);
        }

        Ok(PassphraseMarkovChain {
            nodes,
            starting_ngrams,
            starting_dist,
            starting_entropy,
        })
    }

    pub fn passphrase(&self, min_entropy: f64) -> (String, f64) {
        let mut selected_ngrams = Vec::new();
        let mut entropy = self.starting_entropy;

        for ngram in self.iter() {
            selected_ngrams.push(ngram);
            entropy += self.ngram_entropy(ngram);
            if entropy >= min_entropy && ngram.ends_with(' ') {
                break;
            }
        }

        // Include the first character from each ngram, and the whole final ngram.
        let tail = selected_ngrams.last().unwrap().chars().skip(1);
        let chars = selected_ngrams
            .iter()
            .map(|n| n.chars().next().unwrap())
            .chain(tail);
        let passphrase = chars.collect::<String>().trim().to_string();

        (passphrase, entropy)
    }

    fn iter(&self) -> MarkovChainIterator {
        MarkovChainIterator {
            markov_chain: self,
            current: self.get_starting_ngram(),
        }
    }

    fn get_starting_ngram(&self) -> &str {
        self.nodes
            .get(&self.starting_ngrams[self.starting_dist.sample(&mut rand::rngs::OsRng)])
            .unwrap()
            .value
    }

    fn get_next_ngram(&self, ngram: &str) -> &str {
        self.nodes.get(ngram).unwrap().next()
    }

    fn ngram_entropy(&self, ngram: &str) -> f64 {
        self.nodes.get(ngram).unwrap().entropy()
    }
}

fn weight_entropy(weights: &[f64]) -> f64 {
    let total: f64 = weights.iter().sum();
    weights.iter().fold(0.0, |acc, weight| {
        let prob = weight / total;
        acc - prob * prob.log2()
    })
}

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

    #[test]
    fn test_passphrasemarkovchain_new() {
        let ngrams = vec![" ti", "tic", "ic ", "c t", " to", "toc", "oc ", "c t"];
        let result = PassphraseMarkovChain::new(ngrams.iter().cloned());
        assert!(result.is_ok());
        let chain = result.unwrap();
        assert_eq!(chain.starting_ngrams.len(), 2);
        assert!(chain.starting_ngrams.contains(&" ti"));
        assert!(chain.starting_ngrams.contains(&" to"));
        assert_eq!(chain.starting_entropy, 1.0);
        assert!(ngrams.contains(&chain.get_starting_ngram()));
        let (p, e) = chain.passphrase(60.0);
        assert_eq!(e, 60.0);
        assert_eq!(p.len(), 239);
    }

    #[test]
    fn test_passphrase_no_ngrams() {
        let result = PassphraseMarkovChain::new(std::iter::empty());
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), MarkovChainError::NoNgrams);
    }

    #[test]
    fn test_passphrase_no_entropy() {
        let ngrams = vec![" ab", "abc", "bcd", "cd ", "d a"];
        let result = PassphraseMarkovChain::new(ngrams.into_iter());
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), MarkovChainError::ZeroEntropy);
    }

    #[test]
    fn test_passphrases_no_starting_entropy() {
        let ngrams = vec![
            " ab", "abc", "bc ", "c a", " ab", "abc", "cbd", "bd ", "d a",
        ];
        let result = PassphraseMarkovChain::new(ngrams.into_iter());
        assert!(result.is_err());
        assert_eq!(
            result.unwrap_err(),
            MarkovChainError::ZeroStartOfWordEntropy
        );
    }
}
<commit_msg>Fix typo in error message<commit_after>use rand_distr::weighted_alias::WeightedAliasIndex;
use rand_distr::Distribution;
use std::collections::HashMap;
use std::fmt;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MarkovChainError {
    NoNgrams,
    ZeroEntropy,
    ZeroStartOfWordEntropy,
}

impl std::error::Error for MarkovChainError {}

impl fmt::Display for MarkovChainError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Self::NoNgrams => write!(f, "No ngrams found in cleaned input."),
            Self::ZeroEntropy => write!(f, "Cleaned input has no entropy."),
            Self::ZeroStartOfWordEntropy => {
                write!(f, "Cleaned input has no start of word entropy.")
            }
        }
    }
}

struct MarkovChainIterator<'chain> {
    markov_chain: &'chain PassphraseMarkovChain<'chain>,
    current: &'chain str,
}

impl<'chain> Iterator for MarkovChainIterator<'chain> {
    type Item = &'chain str;

    fn next(&mut self) -> Option<Self::Item> {
        let last = self.current;
        self.current = self.markov_chain.get_next_ngram(self.current);

        Some(last)
    }
}

#[derive(Debug)]
struct MarkovNode<T> {
    pub value: T,
    transitions: Vec<T>,
    dist: WeightedAliasIndex<f64>,
    entropy: f64,
}

impl<T> MarkovNode<T> {
    pub fn new(value: T, values: Vec<T>, weights: Vec<f64>) -> Self {
        let entropy = weight_entropy(&weights);
        Self {
            value,
            transitions: values,
            dist: WeightedAliasIndex::new(weights).unwrap(),
            entropy,
        }
    }

    pub fn next(&self) -> &T {
        &self.transitions[self.dist.sample(&mut rand::rngs::OsRng)]
    }

    pub const fn entropy(&self) -> f64 {
        self.entropy
    }
}

#[derive(Debug)]
pub struct PassphraseMarkovChain<'ngrams> {
    nodes: HashMap<&'ngrams str, MarkovNode<&'ngrams str>>,
    starting_ngrams: Vec<&'ngrams str>,
    starting_dist: WeightedAliasIndex<f64>,
    starting_entropy: f64,
}

impl<'ngrams> PassphraseMarkovChain<'ngrams> {
    pub fn new(
        ngrams: impl Iterator<Item = &'ngrams str>,
    ) -> Result<PassphraseMarkovChain<'ngrams>, MarkovChainError> {
        // Count transitions and viable starting ngrams.
        // To get natural sounding words, starting ngrams should be at word start.
        let mut transition_counters: HashMap<&str, HashMap<&str, usize>> = HashMap::new();
        let mut starting_ngram_counts: HashMap<&str, usize> = HashMap::new();
        let mut ngrams = ngrams.peekable();
        let first_ngram = <&str>::clone(ngrams.peek().ok_or(MarkovChainError::NoNgrams)?);
        while let Some(current_ngram) = ngrams.next() {
            if current_ngram.starts_with(' ') {
                *starting_ngram_counts.entry(current_ngram).or_insert(0) += 1;
            }
            // To guarantee every ngram has at least one valid transition, let the last ngram
            // transition to the first.
            let next_ngram = ngrams.peek().unwrap_or(&first_ngram);
            *transition_counters
                .entry(current_ngram)
                .or_insert_with(HashMap::new)
                .entry(next_ngram)
                .or_insert(0) += 1;
        }

        // Generate the starting ngram probability distribution.
        let mut starting_ngrams = Vec::with_capacity(starting_ngram_counts.len());
        let mut starting_ngram_weights = Vec::with_capacity(starting_ngram_counts.len());
        for (value, weight) in starting_ngram_counts {
            starting_ngrams.push(value);
            starting_ngram_weights.push(weight as f64);
        }
        let starting_entropy = weight_entropy(&starting_ngram_weights);
        let starting_dist = WeightedAliasIndex::new(starting_ngram_weights).unwrap();

        // Build all the MarkovNodes from the transition counts.
        let mut nodes: HashMap<&str, MarkovNode<&str>> = HashMap::new();
        let mut total_entropy: f64 = 0.0;
        for (ngram, transition_counts) in transition_counters {
            let mut values = Vec::with_capacity(transition_counts.len());
            let mut weights = Vec::with_capacity(transition_counts.len());
            for (value, weight) in transition_counts {
                values.push(value);
                weights.push(weight as f64);
            }

            let node = MarkovNode::new(ngram, values, weights);
            total_entropy += node.entropy();
            nodes.insert(ngram, node);
        }

        if total_entropy == 0.0 {
            return Err(MarkovChainError::ZeroEntropy);
        }
        if starting_entropy == 0.0 {
            return Err(MarkovChainError::ZeroStartOfWordEntropy);
        }

        Ok(PassphraseMarkovChain {
            nodes,
            starting_ngrams,
            starting_dist,
            starting_entropy,
        })
    }

    pub fn passphrase(&self, min_entropy: f64) -> (String, f64) {
        let mut selected_ngrams = Vec::new();
        let mut entropy = self.starting_entropy;

        for ngram in self.iter() {
            selected_ngrams.push(ngram);
            entropy += self.ngram_entropy(ngram);
            if entropy >= min_entropy && ngram.ends_with(' ') {
                break;
            }
        }

        // Include the first character from each ngram, and the whole final ngram.
        let tail = selected_ngrams.last().unwrap().chars().skip(1);
        let chars = selected_ngrams
            .iter()
            .map(|n| n.chars().next().unwrap())
            .chain(tail);
        let passphrase = chars.collect::<String>().trim().to_string();

        (passphrase, entropy)
    }

    fn iter(&self) -> MarkovChainIterator {
        MarkovChainIterator {
            markov_chain: self,
            current: self.get_starting_ngram(),
        }
    }

    fn get_starting_ngram(&self) -> &str {
        self.nodes
            .get(&self.starting_ngrams[self.starting_dist.sample(&mut rand::rngs::OsRng)])
            .unwrap()
            .value
    }

    fn get_next_ngram(&self, ngram: &str) -> &str {
        self.nodes.get(ngram).unwrap().next()
    }

    fn ngram_entropy(&self, ngram: &str) -> f64 {
        self.nodes.get(ngram).unwrap().entropy()
    }
}

fn weight_entropy(weights: &[f64]) -> f64 {
    let total: f64 = weights.iter().sum();
    weights.iter().fold(0.0, |acc, weight| {
        let prob = weight / total;
        acc - prob * prob.log2()
    })
}

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

    #[test]
    fn test_passphrasemarkovchain_new() {
        let ngrams = vec![" ti", "tic", "ic ", "c t", " to", "toc", "oc ", "c t"];
        let result = PassphraseMarkovChain::new(ngrams.iter().cloned());
        assert!(result.is_ok());
        let chain = result.unwrap();
        assert_eq!(chain.starting_ngrams.len(), 2);
        assert!(chain.starting_ngrams.contains(&" ti"));
        assert!(chain.starting_ngrams.contains(&" to"));
        assert_eq!(chain.starting_entropy, 1.0);
        assert!(ngrams.contains(&chain.get_starting_ngram()));
        let (p, e) = chain.passphrase(60.0);
        assert_eq!(e, 60.0);
        assert_eq!(p.len(), 239);
    }

    #[test]
    fn test_passphrase_no_ngrams() {
        let result = PassphraseMarkovChain::new(std::iter::empty());
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), MarkovChainError::NoNgrams);
    }

    #[test]
    fn test_passphrase_no_entropy() {
        let ngrams = vec![" ab", "abc", "bcd", "cd ", "d a"];
        let result = PassphraseMarkovChain::new(ngrams.into_iter());
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), MarkovChainError::ZeroEntropy);
    }

    #[test]
    fn test_passphrases_no_starting_entropy() {
        let ngrams = vec![
            " ab", "abc", "bc ", "c a", " ab", "abc", "cbd", "bd ", "d a",
        ];
        let result = PassphraseMarkovChain::new(ngrams.into_iter());
        assert!(result.is_err());
        assert_eq!(
            result.unwrap_err(),
            MarkovChainError::ZeroStartOfWordEntropy
        );
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The `bitflags!` macro generates a `struct` that holds a set of C-style
//! bitmask flags. It is useful for creating typesafe wrappers for C APIs.
//!
//! The flags should only be defined for integer types, otherwise unexpected
//! type errors may occur at compile time.
//!
//! # Example
//!
//! ~~~rust
//! bitflags!(
//!     flags Flags: u32 {
//!         static FlagA       = 0x00000001,
//!         static FlagB       = 0x00000010,
//!         static FlagC       = 0x00000100,
//!         static FlagABC     = FlagA.bits
//!                            | FlagB.bits
//!                            | FlagC.bits
//!     }
//! )
//!
//! fn main() {
//!     let e1 = FlagA | FlagC;
//!     let e2 = FlagB | FlagC;
//!     assert!((e1 | e2) == FlagABC);   // union
//!     assert!((e1 & e2) == FlagC);     // intersection
//!     assert!((e1 - e2) == FlagA);     // set difference
//! }
//! ~~~
//!
//! The generated `struct`s can also be extended with type and trait implementations:
//!
//! ~~~rust
//! use std::fmt;
//!
//! bitflags!(
//!     flags Flags: u32 {
//!         static FlagA   = 0x00000001,
//!         static FlagB   = 0x00000010
//!     }
//! )
//!
//! impl Flags {
//!     pub fn clear(&mut self) {
//!         self.bits = 0;  // The `bits` field can be accessed from within the
//!                         // same module where the `bitflags!` macro was invoked.
//!     }
//! }
//!
//! impl fmt::Show for Flags {
//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//!         write!(f.buf, "hi!")
//!     }
//! }
//!
//! fn main() {
//!     let mut flags = FlagA | FlagB;
//!     flags.clear();
//!     assert!(flags.is_empty());
//!     assert_eq!(format!("{}", flags).as_slice(), "hi!");
//! }
//! ~~~
//!
//! # Attributes
//!
//! Attributes can be attached to the generated `struct` by placing them
//! before the `flags` keyword.
//!
//! # Derived traits
//!
//! The `Eq` and `Clone` traits are automatically derived for the `struct` using
//! the `deriving` attribute. Additional traits can be derived by providing an
//! explicit `deriving` attribute on `flags`.
//!
//! # Operators
//!
//! The following operator traits are implemented for the generated `struct`:
//!
//! - `BitOr`: union
//! - `BitAnd`: intersection
//! - `Sub`: set difference
//!
//! # Methods
//!
//! The following methods are defined for the generated `struct`:
//!
//! - `empty`: an empty set of flags
//! - `bits`: the raw value of the flags currently stored
//! - `is_empty`: `true` if no flags are currently stored
//! - `intersects`: `true` if there are flags common to both `self` and `other`
//! - `contains`: `true` all of the flags in `other` are contained within `self`
//! - `insert`: inserts the specified flags in-place
//! - `remove`: removes the specified flags in-place

#![macro_escape]

#[macro_export]
macro_rules! bitflags(
    ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
        $($(#[$Flag_attr:meta])* static $Flag:ident = $value:expr),+
    }) => (
        #[deriving(Eq, TotalEq, Clone)]
        $(#[$attr])*
        pub struct $BitFlags {
            bits: $T,
        }

        $($(#[$Flag_attr])* pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+

        impl $BitFlags {
            /// Returns an empty set of flags.
            pub fn empty() -> $BitFlags {
                $BitFlags { bits: 0 }
            }

            /// Returns the raw value of the flags currently stored.
            pub fn bits(&self) -> $T {
                self.bits
            }

            /// Returns `true` if no flags are currently stored.
            pub fn is_empty(&self) -> bool {
                *self == $BitFlags::empty()
            }

            /// Returns `true` if there are flags common to both `self` and `other`.
            pub fn intersects(&self, other: $BitFlags) -> bool {
                !(self & other).is_empty()
            }

            /// Returns `true` all of the flags in `other` are contained within `self`.
            pub fn contains(&self, other: $BitFlags) -> bool {
                (self & other) == other
            }

            /// Inserts the specified flags in-place.
            pub fn insert(&mut self, other: $BitFlags) {
                self.bits |= other.bits;
            }

            /// Removes the specified flags in-place.
            pub fn remove(&mut self, other: $BitFlags) {
                self.bits &= !other.bits;
            }
        }

        impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the union of the two sets of flags.
            #[inline]
            fn bitor(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits | other.bits }
            }
        }

        impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the intersection between the two sets of flags.
            #[inline]
            fn bitand(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & other.bits }
            }
        }

        impl Sub<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the set difference of the two sets of flags.
            #[inline]
            fn sub(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & !other.bits }
            }
        }
    )
)

#[cfg(test)]
mod tests {
    use ops::{BitOr, BitAnd, Sub};

    bitflags!(
        flags Flags: u32 {
            static FlagA       = 0x00000001,
            static FlagB       = 0x00000010,
            static FlagC       = 0x00000100,
            static FlagABC     = FlagA.bits
                               | FlagB.bits
                               | FlagC.bits
        }
    )

    #[test]
    fn test_bits(){
        assert_eq!(Flags::empty().bits(), 0x00000000);
        assert_eq!(FlagA.bits(), 0x00000001);
        assert_eq!(FlagABC.bits(), 0x00000111);
    }

    #[test]
    fn test_is_empty(){
        assert!(Flags::empty().is_empty());
        assert!(!FlagA.is_empty());
        assert!(!FlagABC.is_empty());
    }

    #[test]
    fn test_two_empties_do_not_intersect() {
        let e1 = Flags::empty();
        let e2 = Flags::empty();
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_empty_does_not_intersect_with_full() {
        let e1 = Flags::empty();
        let e2 = FlagABC;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_disjoint_intersects() {
        let e1 = FlagA;
        let e2 = FlagB;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_overlapping_intersects() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(e1.intersects(e2));
    }

    #[test]
    fn test_contains() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(!e1.contains(e2));
        assert!(e2.contains(e1));
        assert!(FlagABC.contains(e2));
    }

    #[test]
    fn test_insert(){
        let mut e1 = FlagA;
        let e2 = FlagA | FlagB;
        e1.insert(e2);
        assert!(e1 == e2);
    }

    #[test]
    fn test_remove(){
        let mut e1 = FlagA | FlagB;
        let e2 = FlagA | FlagC;
        e1.remove(e2);
        assert!(e1 == FlagB);
    }

    #[test]
    fn test_operators() {
        let e1 = FlagA | FlagC;
        let e2 = FlagB | FlagC;
        assert!((e1 | e2) == FlagABC);   // union
        assert!((e1 & e2) == FlagC);     // intersection
        assert!((e1 - e2) == FlagA);     // set difference
    }
}
<commit_msg>Add (unsafe) coercion from bits to std::bitflags<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The `bitflags!` macro generates a `struct` that holds a set of C-style
//! bitmask flags. It is useful for creating typesafe wrappers for C APIs.
//!
//! The flags should only be defined for integer types, otherwise unexpected
//! type errors may occur at compile time.
//!
//! # Example
//!
//! ~~~rust
//! bitflags!(
//!     flags Flags: u32 {
//!         static FlagA       = 0x00000001,
//!         static FlagB       = 0x00000010,
//!         static FlagC       = 0x00000100,
//!         static FlagABC     = FlagA.bits
//!                            | FlagB.bits
//!                            | FlagC.bits
//!     }
//! )
//!
//! fn main() {
//!     let e1 = FlagA | FlagC;
//!     let e2 = FlagB | FlagC;
//!     assert!((e1 | e2) == FlagABC);   // union
//!     assert!((e1 & e2) == FlagC);     // intersection
//!     assert!((e1 - e2) == FlagA);     // set difference
//! }
//! ~~~
//!
//! The generated `struct`s can also be extended with type and trait implementations:
//!
//! ~~~rust
//! use std::fmt;
//!
//! bitflags!(
//!     flags Flags: u32 {
//!         static FlagA   = 0x00000001,
//!         static FlagB   = 0x00000010
//!     }
//! )
//!
//! impl Flags {
//!     pub fn clear(&mut self) {
//!         self.bits = 0;  // The `bits` field can be accessed from within the
//!                         // same module where the `bitflags!` macro was invoked.
//!     }
//! }
//!
//! impl fmt::Show for Flags {
//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//!         write!(f.buf, "hi!")
//!     }
//! }
//!
//! fn main() {
//!     let mut flags = FlagA | FlagB;
//!     flags.clear();
//!     assert!(flags.is_empty());
//!     assert_eq!(format!("{}", flags).as_slice(), "hi!");
//! }
//! ~~~
//!
//! # Attributes
//!
//! Attributes can be attached to the generated `struct` by placing them
//! before the `flags` keyword.
//!
//! # Derived traits
//!
//! The `Eq` and `Clone` traits are automatically derived for the `struct` using
//! the `deriving` attribute. Additional traits can be derived by providing an
//! explicit `deriving` attribute on `flags`.
//!
//! # Operators
//!
//! The following operator traits are implemented for the generated `struct`:
//!
//! - `BitOr`: union
//! - `BitAnd`: intersection
//! - `Sub`: set difference
//!
//! # Methods
//!
//! The following methods are defined for the generated `struct`:
//!
//! - `empty`: an empty set of flags
//! - `bits`: the raw value of the flags currently stored
//! - `is_empty`: `true` if no flags are currently stored
//! - `intersects`: `true` if there are flags common to both `self` and `other`
//! - `contains`: `true` all of the flags in `other` are contained within `self`
//! - `insert`: inserts the specified flags in-place
//! - `remove`: removes the specified flags in-place

#![macro_escape]

#[macro_export]
macro_rules! bitflags(
    ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
        $($(#[$Flag_attr:meta])* static $Flag:ident = $value:expr),+
    }) => (
        #[deriving(Eq, TotalEq, Clone)]
        $(#[$attr])*
        pub struct $BitFlags {
            bits: $T,
        }

        $($(#[$Flag_attr])* pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+

        impl $BitFlags {
            /// Returns an empty set of flags.
            pub fn empty() -> $BitFlags {
                $BitFlags { bits: 0 }
            }

            /// Returns the raw value of the flags currently stored.
            pub fn bits(&self) -> $T {
                self.bits
            }

            /// Convert from underlying bit representation. Unsafe because the
            /// bits are not guaranteed to represent valid flags.
            pub unsafe fn from_bits(bits: $T) -> $BitFlags {
                $BitFlags { bits: bits }
            }

            /// Returns `true` if no flags are currently stored.
            pub fn is_empty(&self) -> bool {
                *self == $BitFlags::empty()
            }

            /// Returns `true` if there are flags common to both `self` and `other`.
            pub fn intersects(&self, other: $BitFlags) -> bool {
                !(self & other).is_empty()
            }

            /// Returns `true` all of the flags in `other` are contained within `self`.
            pub fn contains(&self, other: $BitFlags) -> bool {
                (self & other) == other
            }

            /// Inserts the specified flags in-place.
            pub fn insert(&mut self, other: $BitFlags) {
                self.bits |= other.bits;
            }

            /// Removes the specified flags in-place.
            pub fn remove(&mut self, other: $BitFlags) {
                self.bits &= !other.bits;
            }
        }

        impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the union of the two sets of flags.
            #[inline]
            fn bitor(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits | other.bits }
            }
        }

        impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the intersection between the two sets of flags.
            #[inline]
            fn bitand(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & other.bits }
            }
        }

        impl Sub<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the set difference of the two sets of flags.
            #[inline]
            fn sub(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & !other.bits }
            }
        }
    )
)

#[cfg(test)]
mod tests {
    use ops::{BitOr, BitAnd, Sub};

    bitflags!(
        flags Flags: u32 {
            static FlagA       = 0x00000001,
            static FlagB       = 0x00000010,
            static FlagC       = 0x00000100,
            static FlagABC     = FlagA.bits
                               | FlagB.bits
                               | FlagC.bits
        }
    )

    #[test]
    fn test_bits(){
        assert_eq!(Flags::empty().bits(), 0x00000000);
        assert_eq!(FlagA.bits(), 0x00000001);
        assert_eq!(FlagABC.bits(), 0x00000111);
    }

    #[test]
    fn test_is_empty(){
        assert!(Flags::empty().is_empty());
        assert!(!FlagA.is_empty());
        assert!(!FlagABC.is_empty());
    }

    #[test]
    fn test_two_empties_do_not_intersect() {
        let e1 = Flags::empty();
        let e2 = Flags::empty();
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_empty_does_not_intersect_with_full() {
        let e1 = Flags::empty();
        let e2 = FlagABC;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_disjoint_intersects() {
        let e1 = FlagA;
        let e2 = FlagB;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_overlapping_intersects() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(e1.intersects(e2));
    }

    #[test]
    fn test_contains() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(!e1.contains(e2));
        assert!(e2.contains(e1));
        assert!(FlagABC.contains(e2));
    }

    #[test]
    fn test_insert(){
        let mut e1 = FlagA;
        let e2 = FlagA | FlagB;
        e1.insert(e2);
        assert!(e1 == e2);
    }

    #[test]
    fn test_remove(){
        let mut e1 = FlagA | FlagB;
        let e2 = FlagA | FlagC;
        e1.remove(e2);
        assert!(e1 == FlagB);
    }

    #[test]
    fn test_operators() {
        let e1 = FlagA | FlagC;
        let e2 = FlagB | FlagC;
        assert!((e1 | e2) == FlagABC);   // union
        assert!((e1 & e2) == FlagC);     // intersection
        assert!((e1 - e2) == FlagA);     // set difference
    }
}
<|endoftext|>