<commit_before>// Copyright 2013-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.

//! Windows console handling

// FIXME (#13400): this is only a tiny fraction of the Windows console api

extern crate "kernel32-sys" as kernel32;
extern crate winapi;

use std::io::IoResult;

use Attr;
use color;
use {Terminal,UnwrappableTerminal};

/// A Terminal implementation which uses the Win32 Console API.
pub struct WinConsole<T> {
    buf: T,
    def_foreground: color::Color,
    def_background: color::Color,
    foreground: color::Color,
    background: color::Color,
}

fn color_to_bits(color: color::Color) -> u16 {
    // magic numbers from mingw-w64's wincon.h

    let bits = match color % 8 {
        color::BLACK   => 0,
        color::BLUE    => 0x1,
        color::GREEN   => 0x2,
        color::RED     => 0x4,
        color::YELLOW  => 0x2 | 0x4,
        color::MAGENTA => 0x1 | 0x4,
        color::CYAN    => 0x1 | 0x2,
        color::WHITE   => 0x1 | 0x2 | 0x4,
        _ => unreachable!()
    };

    if color >= 8 {
        bits | 0x8
    } else {
        bits
    }
}

fn bits_to_color(bits: u16) -> color::Color {
    let color = match bits & 0x7 {
        0 => color::BLACK,
        0x1 => color::BLUE,
        0x2 => color::GREEN,
        0x4 => color::RED,
        0x6 => color::YELLOW,
        0x5 => color::MAGENTA,
        0x3 => color::CYAN,
        0x7 => color::WHITE,
        _ => unreachable!()
    };

    color | (bits & 0x8) // copy the hi-intensity bit
}

impl<T: Writer+Send> WinConsole<T> {
    fn apply(&mut self) {
        let _unused = self.buf.flush();
        let mut accum: winapi::WORD = 0;
        accum |= color_to_bits(self.foreground);
        accum |= color_to_bits(self.background) << 4;

        unsafe {
            // Magic -11 means stdout, from
            // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx
            //
            // You may be wondering, "but what about stderr?", and the answer
            // to that is that setting terminal attributes on the stdout
            // handle also sets them for stderr, since they go to the same
            // terminal! Admittedly, this is fragile, since stderr could be
            // redirected to a different console. This is good enough for
            // rustc though. See #13400.
            let out = kernel32::GetStdHandle(-11);
            kernel32::SetConsoleTextAttribute(out, accum);
        }
    }

    /// Returns `None` whenever the terminal cannot be created for some
    /// reason.
    pub fn new(out: T) -> Option<WinConsole<T>> {
        let fg;
        let bg;
        unsafe {
            let mut buffer_info = ::std::mem::uninitialized();
            let out = kernel32::GetStdHandle(-11);
            if kernel32::GetConsoleScreenBufferInfo(out, &mut buffer_info) != 0 {
                fg = bits_to_color(buffer_info.wAttributes);
                bg = bits_to_color(buffer_info.wAttributes >> 4);
            } else {
                fg = color::WHITE;
                bg = color::BLACK;
            }
        }
        Some(WinConsole {
            buf: out,
            def_foreground: fg,
            def_background: bg,
            foreground: fg,
            background: bg,
        })
    }
}

impl<T: Writer> Writer for WinConsole<T> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.buf.write(buf)
    }

    fn flush(&mut self) -> IoResult<()> {
        self.buf.flush()
    }
}

impl<T: Writer+Send> Terminal<T> for WinConsole<T> {
    fn fg(&mut self, color: color::Color) -> IoResult<bool> {
        self.foreground = color;
        self.apply();

        Ok(true)
    }

    fn bg(&mut self, color: color::Color) -> IoResult<bool> {
        self.background = color;
        self.apply();

        Ok(true)
    }

    fn attr(&mut self, attr: Attr) -> IoResult<bool> {
        match attr {
            Attr::ForegroundColor(f) => {
                self.foreground = f;
                self.apply();
                Ok(true)
            },
            Attr::BackgroundColor(b) => {
                self.background = b;
                self.apply();
                Ok(true)
            },
            _ => Ok(false)
        }
    }

    fn supports_attr(&self, attr: Attr) -> bool {
        // it claims support for underscore and reverse video, but I can't get
        // it to do anything -cmr
        match attr {
            Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => true,
            _ => false
        }
    }

    fn reset(&mut self) -> IoResult<bool> {
        self.foreground = self.def_foreground;
        self.background = self.def_background;
        self.apply();

        Ok(true)
    }

    fn get_ref<'a>(&'a self) -> &'a T { &self.buf }

    fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf }
}

impl<T: Writer+Send> UnwrappableTerminal<T> for WinConsole<T> {
    fn unwrap(self) -> T { self.buf }
}
<commit_msg>Fix windows<commit_after>// Copyright 2013-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.

//! Windows console handling

// FIXME (#13400): this is only a tiny fraction of the Windows console api

extern crate "kernel32-sys" as kernel32;
extern crate winapi;

use std::old_io::IoResult;

use Attr;
use color;
use {Terminal,UnwrappableTerminal};

/// A Terminal implementation which uses the Win32 Console API.
pub struct WinConsole<T> {
    buf: T,
    def_foreground: color::Color,
    def_background: color::Color,
    foreground: color::Color,
    background: color::Color,
}

fn color_to_bits(color: color::Color) -> u16 {
    // magic numbers from mingw-w64's wincon.h

    let bits = match color % 8 {
        color::BLACK   => 0,
        color::BLUE    => 0x1,
        color::GREEN   => 0x2,
        color::RED     => 0x4,
        color::YELLOW  => 0x2 | 0x4,
        color::MAGENTA => 0x1 | 0x4,
        color::CYAN    => 0x1 | 0x2,
        color::WHITE   => 0x1 | 0x2 | 0x4,
        _ => unreachable!()
    };

    if color >= 8 {
        bits | 0x8
    } else {
        bits
    }
}

fn bits_to_color(bits: u16) -> color::Color {
    let color = match bits & 0x7 {
        0 => color::BLACK,
        0x1 => color::BLUE,
        0x2 => color::GREEN,
        0x4 => color::RED,
        0x6 => color::YELLOW,
        0x5 => color::MAGENTA,
        0x3 => color::CYAN,
        0x7 => color::WHITE,
        _ => unreachable!()
    };

    color | (bits & 0x8) // copy the hi-intensity bit
}

impl<T: Writer+Send> WinConsole<T> {
    fn apply(&mut self) {
        let _unused = self.buf.flush();
        let mut accum: winapi::WORD = 0;
        accum |= color_to_bits(self.foreground);
        accum |= color_to_bits(self.background) << 4;

        unsafe {
            // Magic -11 means stdout, from
            // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx
            //
            // You may be wondering, "but what about stderr?", and the answer
            // to that is that setting terminal attributes on the stdout
            // handle also sets them for stderr, since they go to the same
            // terminal! Admittedly, this is fragile, since stderr could be
            // redirected to a different console. This is good enough for
            // rustc though. See #13400.
            let out = kernel32::GetStdHandle(-11);
            kernel32::SetConsoleTextAttribute(out, accum);
        }
    }

    /// Returns `None` whenever the terminal cannot be created for some
    /// reason.
    pub fn new(out: T) -> Option<WinConsole<T>> {
        let fg;
        let bg;
        unsafe {
            let mut buffer_info = ::std::mem::uninitialized();
            let out = kernel32::GetStdHandle(-11);
            if kernel32::GetConsoleScreenBufferInfo(out, &mut buffer_info) != 0 {
                fg = bits_to_color(buffer_info.wAttributes);
                bg = bits_to_color(buffer_info.wAttributes >> 4);
            } else {
                fg = color::WHITE;
                bg = color::BLACK;
            }
        }
        Some(WinConsole {
            buf: out,
            def_foreground: fg,
            def_background: bg,
            foreground: fg,
            background: bg,
        })
    }
}

impl<T: Writer> Writer for WinConsole<T> {
    fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
        self.buf.write_all(buf)
    }

    fn flush(&mut self) -> IoResult<()> {
        self.buf.flush()
    }
}

impl<T: Writer+Send> Terminal<T> for WinConsole<T> {
    fn fg(&mut self, color: color::Color) -> IoResult<bool> {
        self.foreground = color;
        self.apply();

        Ok(true)
    }

    fn bg(&mut self, color: color::Color) -> IoResult<bool> {
        self.background = color;
        self.apply();

        Ok(true)
    }

    fn attr(&mut self, attr: Attr) -> IoResult<bool> {
        match attr {
            Attr::ForegroundColor(f) => {
                self.foreground = f;
                self.apply();
                Ok(true)
            },
            Attr::BackgroundColor(b) => {
                self.background = b;
                self.apply();
                Ok(true)
            },
            _ => Ok(false)
        }
    }

    fn supports_attr(&self, attr: Attr) -> bool {
        // it claims support for underscore and reverse video, but I can't get
        // it to do anything -cmr
        match attr {
            Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => true,
            _ => false
        }
    }

    fn reset(&mut self) -> IoResult<bool> {
        self.foreground = self.def_foreground;
        self.background = self.def_background;
        self.apply();

        Ok(true)
    }

    fn get_ref<'a>(&'a self) -> &'a T { &self.buf }

    fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf }
}

impl<T: Writer+Send> UnwrappableTerminal<T> for WinConsole<T> {
    fn unwrap(self) -> T { self.buf }
}
<|endoftext|>


<commit_before>//! Definition of the `JoinAll` combinator, waiting for all of a list of futures
//! to finish.

use alloc::boxed::Box;
use alloc::vec::Vec;
use core::fmt;
use core::future::Future;
use core::iter::FromIterator;
use core::mem;
use core::pin::Pin;
use core::task::{Context, Poll};

use super::{assert_future, MaybeDone};

fn iter_pin_mut<T>(slice: Pin<&mut [T]>) -> impl Iterator<Item = Pin<&mut T>> {
    // Safety: `std` _could_ make this unsound if it were to decide Pin's
    // invariants aren't required to transmit through slices. Otherwise this has
    // the same safety as a normal field pin projection.
    unsafe { slice.get_unchecked_mut() }.iter_mut().map(|t| unsafe { Pin::new_unchecked(t) })
}

/// Future for the [`join_all`] function.
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct JoinAll<F>
where
    F: Future,
{
    elems: Pin<Box<[MaybeDone<F>]>>,
}

impl<F> fmt::Debug for JoinAll<F>
where
    F: Future + fmt::Debug,
    F::Output: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("JoinAll").field("elems", &self.elems).finish()
    }
}

/// Creates a future which represents a collection of the outputs of the futures
/// given.
///
/// The returned future will drive execution for all of its underlying futures,
/// collecting the results into a destination `Vec<T>` in the same order as they
/// were provided.
///
/// This function is only available when the `std` or `alloc` feature of this
/// library is activated, and it is activated by default.
///
/// # See Also
///
/// This is purposefully a very simple API for basic use-cases. In a lot of
/// cases you will want to use the more powerful
/// [`FuturesOrdered`][crate::stream::FuturesOrdered] APIs, or, if order does
/// not matter, [`FuturesUnordered`][crate::stream::FuturesUnordered].
///
/// Some examples for additional functionality provided by these are:
///
///  * Adding new futures to the set even after it has been started.
///
///  * Only polling the specific futures that have been woken. In cases where
///    you have a lot of futures this will result in much more efficient polling.
///
/// # Examples
///
/// ```
/// # futures::executor::block_on(async {
/// use futures::future::join_all;
///
/// async fn foo(i: u32) -> u32 { i }
///
/// let futures = vec![foo(1), foo(2), foo(3)];
///
/// assert_eq!(join_all(futures).await, [1, 2, 3]);
/// # });
/// ```
pub fn join_all<I>(i: I) -> JoinAll<I::Item>
where
    I: IntoIterator,
    I::Item: Future,
{
    let elems: Box<[_]> = i.into_iter().map(MaybeDone::Future).collect();
    assert_future::<Vec<<I::Item as Future>::Output>, _>(JoinAll { elems: elems.into() })
}

impl<F> Future for JoinAll<F>
where
    F: Future,
{
    type Output = Vec<F::Output>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let mut all_done = true;

        for elem in iter_pin_mut(self.elems.as_mut()) {
            if elem.poll(cx).is_pending() {
                all_done = false;
            }
        }

        if all_done {
            let mut elems = mem::replace(&mut self.elems, Box::pin([]));
            let result = iter_pin_mut(elems.as_mut()).map(|e| e.take_output().unwrap()).collect();
            Poll::Ready(result)
        } else {
            Poll::Pending
        }
    }
}

impl<F: Future> FromIterator<F> for JoinAll<F> {
    fn from_iter<T: IntoIterator<Item = F>>(iter: T) -> Self {
        join_all(iter)
    }
}
<commit_msg>Use FuturesOrdered in join_all (#2412)<commit_after>//! Definition of the `JoinAll` combinator, waiting for all of a list of futures
//! to finish.

use alloc::boxed::Box;
use alloc::vec::Vec;
use core::fmt;
use core::future::Future;
use core::iter::FromIterator;
use core::mem;
use core::pin::Pin;
use core::task::{Context, Poll};

use super::{assert_future, MaybeDone};

#[cfg(not(futures_no_atomic_cas))]
use crate::stream::{Collect, FuturesOrdered, StreamExt};

fn iter_pin_mut<T>(slice: Pin<&mut [T]>) -> impl Iterator<Item = Pin<&mut T>> {
    // Safety: `std` _could_ make this unsound if it were to decide Pin's
    // invariants aren't required to transmit through slices. Otherwise this has
    // the same safety as a normal field pin projection.
    unsafe { slice.get_unchecked_mut() }.iter_mut().map(|t| unsafe { Pin::new_unchecked(t) })
}

#[must_use = "futures do nothing unless you `.await` or poll them"]
/// Future for the [`join_all`] function.
pub struct JoinAll<F>
where
    F: Future,
{
    kind: JoinAllKind<F>,
}

#[cfg(not(futures_no_atomic_cas))]
const SMALL: usize = 30;

pub(crate) enum JoinAllKind<F>
where
    F: Future,
{
    Small {
        elems: Pin<Box<[MaybeDone<F>]>>,
    },
    #[cfg(not(futures_no_atomic_cas))]
    Big {
        fut: Collect<FuturesOrdered<F>, Vec<F::Output>>,
    },
}

impl<F> fmt::Debug for JoinAll<F>
where
    F: Future + fmt::Debug,
    F::Output: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.kind {
            JoinAllKind::Small { ref elems } => {
                f.debug_struct("JoinAll").field("elems", elems).finish()
            }
            #[cfg(not(futures_no_atomic_cas))]
            JoinAllKind::Big { ref fut, .. } => fmt::Debug::fmt(fut, f),
        }
    }
}

/// Creates a future which represents a collection of the outputs of the futures
/// given.
///
/// The returned future will drive execution for all of its underlying futures,
/// collecting the results into a destination `Vec<T>` in the same order as they
/// were provided.
///
/// This function is only available when the `std` or `alloc` feature of this
/// library is activated, and it is activated by default.
///
/// # See Also
///
/// `join_all` will switch to the more powerful [`FuturesOrdered`] for performance
/// reasons if the number of futures is large. You may want to look into using it or
/// it's counterpart [`FuturesUnordered`][crate::stream::FuturesUnordered] directly.
///
/// Some examples for additional functionality provided by these are:
///
///  * Adding new futures to the set even after it has been started.
///
///  * Only polling the specific futures that have been woken. In cases where
///    you have a lot of futures this will result in much more efficient polling.
///
/// # Examples
///
/// ```
/// # futures::executor::block_on(async {
/// use futures::future::join_all;
///
/// async fn foo(i: u32) -> u32 { i }
///
/// let futures = vec![foo(1), foo(2), foo(3)];
///
/// assert_eq!(join_all(futures).await, [1, 2, 3]);
/// # });
/// ```
pub fn join_all<I>(iter: I) -> JoinAll<I::Item>
where
    I: IntoIterator,
    I::Item: Future,
{
    #[cfg(futures_no_atomic_cas)]
    {
        let elems = iter.into_iter().map(MaybeDone::Future).collect::<Box<[_]>>().into();
        let kind = JoinAllKind::Small { elems };
        assert_future::<Vec<<I::Item as Future>::Output>, _>(JoinAll { kind })
    }
    #[cfg(not(futures_no_atomic_cas))]
    {
        let iter = iter.into_iter();
        let kind = match iter.size_hint().1 {
            None => JoinAllKind::Big { fut: iter.collect::<FuturesOrdered<_>>().collect() },
            Some(max) => {
                if max <= SMALL {
                    let elems = iter.map(MaybeDone::Future).collect::<Box<[_]>>().into();
                    JoinAllKind::Small { elems }
                } else {
                    JoinAllKind::Big { fut: iter.collect::<FuturesOrdered<_>>().collect() }
                }
            }
        };
        assert_future::<Vec<<I::Item as Future>::Output>, _>(JoinAll { kind })
    }
}

impl<F> Future for JoinAll<F>
where
    F: Future,
{
    type Output = Vec<F::Output>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        match &mut self.kind {
            JoinAllKind::Small { elems } => {
                let mut all_done = true;

                for elem in iter_pin_mut(elems.as_mut()) {
                    if elem.poll(cx).is_pending() {
                        all_done = false;
                    }
                }

                if all_done {
                    let mut elems = mem::replace(elems, Box::pin([]));
                    let result =
                        iter_pin_mut(elems.as_mut()).map(|e| e.take_output().unwrap()).collect();
                    Poll::Ready(result)
                } else {
                    Poll::Pending
                }
            }
            #[cfg(not(futures_no_atomic_cas))]
            JoinAllKind::Big { fut } => Pin::new(fut).poll(cx),
        }
    }
}

impl<F: Future> FromIterator<F> for JoinAll<F> {
    fn from_iter<T: IntoIterator<Item = F>>(iter: T) -> Self {
        join_all(iter)
    }
}
<|endoftext|>


<commit_before>use address::{LENGTH, Address, Addressable};
use num::bigint::{BigUint, ToBigUint};
use std::collections::HashMap;
use num;

struct NodeBucket<A: Addressable> {
    k: usize,
    min: BigUint,
    max: BigUint,
    addresses: Vec<Address>,
    nodes: HashMap<Address, A>
}

impl<A: Addressable> NodeBucket<A> {
    pub fn new(k: usize) -> NodeBucket<A> {
        let min = 0.to_biguint().unwrap();
        let max = num::pow(2.to_biguint().unwrap(), LENGTH);
        NodeBucket {
            k: k,
            min: min,
            max: max,
            addresses: Vec::with_capacity(k),
            nodes: HashMap::with_capacity(k)
        }
    }

    pub fn contains(&self, address: &Address) -> bool {
        self.addresses.contains(address)
    }

    pub fn covers(&self, address: &Address) -> bool {
        let numeric = address.as_numeric();
        self.min <= numeric && numeric < self.max
    }

    pub fn insert(&mut self, node: A) {
        let address = node.address();
        if let Some(pos) = self.addresses.iter().position(|&a| a == address) {
            self.addresses.remove(pos);
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        } else if !self.is_full() {
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        }
    }

    pub fn is_full(&self) -> bool {
        self.addresses.len() >= self.k
    }

    pub fn split(&mut self) -> (Self, Self) {
        let partition = self.max.clone() / 2.to_biguint().unwrap();
        let addresses = self.addresses.clone();
        let (a_addresses, b_addresses): (Vec<Address>, Vec<Address>) = addresses
            .into_iter()
            .partition(|&a| a.as_numeric() < partition);
        let mut a_nodes = HashMap::new();
        let mut b_nodes = HashMap::new();
        for (address, node) in self.nodes.drain() {
            if address.as_numeric() < partition {
                a_nodes.insert(address, node);
            } else {
                b_nodes.insert(address, node);
            }
        }

        let a = NodeBucket {
            k: self.k,
            min: self.min.clone(),
            max: partition.clone(),
            addresses: a_addresses,
            nodes: a_nodes
        };
        let b = NodeBucket {
            k: self.k,
            min: partition.clone(),
            max: self.max.clone(),
            addresses: b_addresses,
            nodes: b_nodes
        };
        (a, b)
    }
}

#[cfg(test)]
mod tests {
    use address::{Address, Addressable};
    use super::NodeBucket;

    #[derive(Clone,Copy,Debug,PartialEq,Eq)]
    struct Node {
        pub address: Address
    }

    impl Node {
        fn new(address: Address) -> Node {
            Node { address: address }
        }
    }

    impl Addressable for Node {
        fn address(&self) -> Address {
            self.address
        }
    }

    #[test]
    fn test_insert() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        let node = Node::new(Address::for_content("some string"));
        bucket.insert(node);
        assert_eq!(bucket.addresses.len(), 1);
    }

    #[test]
    fn test_insert_duplicate() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        let a = Node::new(Address::for_content("node 1"));
        let b = Node::new(Address::for_content("node 2"));
        let c = Node::new(Address::for_content("node 1"));

        bucket.insert(a.clone());
        bucket.insert(b);
        bucket.insert(c);

        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes[&Address::for_content("node 1")], a);
    }

    #[test]
    fn test_insert_full() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(2);
        bucket.insert(Node::new(Address::for_content("node 1")));
        bucket.insert(Node::new(Address::for_content("node 2")));
        bucket.insert(Node::new(Address::for_content("node 3")));
        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes.get(&Address::for_content("node 3")), None);
    }

    #[test]
    fn test_is_full() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(2);
        assert!(!bucket.is_full());

        bucket.insert(Node::new(Address::for_content("node 1")));
        bucket.insert(Node::new(Address::for_content("node 2")));
        assert!(bucket.is_full());
    }

    #[test]
    fn test_contains() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        bucket.insert(Node::new(Address::for_content("node 1")));
        assert!(bucket.contains(&Address::for_content("node 1")));
    }

    #[test]
    fn test_covers() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        let address_1 = Address::from_str("0000000000000000000000000000000000000000");
        let address_2 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        assert!(bucket.covers(&address_1));
        assert!(bucket.covers(&address_2));
    }

    #[test]
    fn test_split() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(4);
        let node_1 = Node::new(Address::from_str("0000000000000000000000000000000000000000"));
        let node_2 = Node::new(Address::from_str("7fffffffffffffffffffffffffffffffffffffff"));
        let node_3 = Node::new(Address::from_str("8000000000000000000000000000000000000000"));
        let node_4 = Node::new(Address::from_str("ffffffffffffffffffffffffffffffffffffffff"));

        bucket.insert(node_1);
        bucket.insert(node_2);
        bucket.insert(node_3);
        bucket.insert(node_4);

        let (a, b) = bucket.split();

        // Splits up known address
        assert_eq!(a.addresses.len(), 2);
        assert_eq!(b.addresses.len(), 2);

        // Splits up known nodes
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")], node_1);
        assert_eq!(a.nodes[&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")], node_2);
        assert_eq!(b.nodes[&Address::from_str("8000000000000000000000000000000000000000")], node_3);
        assert_eq!(b.nodes[&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")], node_4);

        // Equitably covers address space
        assert!(a.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(!b.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(a.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!b.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!a.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(b.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(!a.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
        assert!(b.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
    }
}
<commit_msg>Unmut a variable<commit_after>use address::{LENGTH, Address, Addressable};
use num::bigint::{BigUint, ToBigUint};
use std::collections::HashMap;
use num;

struct NodeBucket<A: Addressable> {
    k: usize,
    min: BigUint,
    max: BigUint,
    addresses: Vec<Address>,
    nodes: HashMap<Address, A>
}

impl<A: Addressable> NodeBucket<A> {
    pub fn new(k: usize) -> NodeBucket<A> {
        let min = 0.to_biguint().unwrap();
        let max = num::pow(2.to_biguint().unwrap(), LENGTH);
        NodeBucket {
            k: k,
            min: min,
            max: max,
            addresses: Vec::with_capacity(k),
            nodes: HashMap::with_capacity(k)
        }
    }

    pub fn contains(&self, address: &Address) -> bool {
        self.addresses.contains(address)
    }

    pub fn covers(&self, address: &Address) -> bool {
        let numeric = address.as_numeric();
        self.min <= numeric && numeric < self.max
    }

    pub fn insert(&mut self, node: A) {
        let address = node.address();
        if let Some(pos) = self.addresses.iter().position(|&a| a == address) {
            self.addresses.remove(pos);
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        } else if !self.is_full() {
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        }
    }

    pub fn is_full(&self) -> bool {
        self.addresses.len() >= self.k
    }

    pub fn split(&mut self) -> (Self, Self) {
        let partition = self.max.clone() / 2.to_biguint().unwrap();
        let addresses = self.addresses.clone();
        let (a_addresses, b_addresses): (Vec<Address>, Vec<Address>) = addresses
            .into_iter()
            .partition(|&a| a.as_numeric() < partition);
        let mut a_nodes = HashMap::new();
        let mut b_nodes = HashMap::new();
        for (address, node) in self.nodes.drain() {
            if address.as_numeric() < partition {
                a_nodes.insert(address, node);
            } else {
                b_nodes.insert(address, node);
            }
        }

        let a = NodeBucket {
            k: self.k,
            min: self.min.clone(),
            max: partition.clone(),
            addresses: a_addresses,
            nodes: a_nodes
        };
        let b = NodeBucket {
            k: self.k,
            min: partition.clone(),
            max: self.max.clone(),
            addresses: b_addresses,
            nodes: b_nodes
        };
        (a, b)
    }
}

#[cfg(test)]
mod tests {
    use address::{Address, Addressable};
    use super::NodeBucket;

    #[derive(Clone,Copy,Debug,PartialEq,Eq)]
    struct Node {
        pub address: Address
    }

    impl Node {
        fn new(address: Address) -> Node {
            Node { address: address }
        }
    }

    impl Addressable for Node {
        fn address(&self) -> Address {
            self.address
        }
    }

    #[test]
    fn test_insert() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        let node = Node::new(Address::for_content("some string"));
        bucket.insert(node);
        assert_eq!(bucket.addresses.len(), 1);
    }

    #[test]
    fn test_insert_duplicate() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        let a = Node::new(Address::for_content("node 1"));
        let b = Node::new(Address::for_content("node 2"));
        let c = Node::new(Address::for_content("node 1"));

        bucket.insert(a.clone());
        bucket.insert(b);
        bucket.insert(c);

        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes[&Address::for_content("node 1")], a);
    }

    #[test]
    fn test_insert_full() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(2);
        bucket.insert(Node::new(Address::for_content("node 1")));
        bucket.insert(Node::new(Address::for_content("node 2")));
        bucket.insert(Node::new(Address::for_content("node 3")));
        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes.get(&Address::for_content("node 3")), None);
    }

    #[test]
    fn test_is_full() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(2);
        assert!(!bucket.is_full());

        bucket.insert(Node::new(Address::for_content("node 1")));
        bucket.insert(Node::new(Address::for_content("node 2")));
        assert!(bucket.is_full());
    }

    #[test]
    fn test_contains() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        bucket.insert(Node::new(Address::for_content("node 1")));
        assert!(bucket.contains(&Address::for_content("node 1")));
    }

    #[test]
    fn test_covers() {
        let bucket: NodeBucket<Node> = NodeBucket::new(8);
        let address_1 = Address::from_str("0000000000000000000000000000000000000000");
        let address_2 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        assert!(bucket.covers(&address_1));
        assert!(bucket.covers(&address_2));
    }

    #[test]
    fn test_split() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(4);
        let node_1 = Node::new(Address::from_str("0000000000000000000000000000000000000000"));
        let node_2 = Node::new(Address::from_str("7fffffffffffffffffffffffffffffffffffffff"));
        let node_3 = Node::new(Address::from_str("8000000000000000000000000000000000000000"));
        let node_4 = Node::new(Address::from_str("ffffffffffffffffffffffffffffffffffffffff"));

        bucket.insert(node_1);
        bucket.insert(node_2);
        bucket.insert(node_3);
        bucket.insert(node_4);

        let (a, b) = bucket.split();

        // Splits up known address
        assert_eq!(a.addresses.len(), 2);
        assert_eq!(b.addresses.len(), 2);

        // Splits up known nodes
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")], node_1);
        assert_eq!(a.nodes[&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")], node_2);
        assert_eq!(b.nodes[&Address::from_str("8000000000000000000000000000000000000000")], node_3);
        assert_eq!(b.nodes[&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")], node_4);

        // Equitably covers address space
        assert!(a.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(!b.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(a.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!b.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!a.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(b.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(!a.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
        assert!(b.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
    }
}
<|endoftext|>


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

use ffi;
use gstr;
use types::gchar;

use std::mem;
use std::str;
use std::sync::atomic;

#[deriving(Copy, Eq, PartialEq)]
pub struct Quark(ffi::GQuark);

pub struct StaticQuark(pub &'static [u8], pub atomic::AtomicUint);

impl Quark {

    #[inline]
    pub unsafe fn new(raw: ffi::GQuark) -> Quark {
        Quark(raw)
    }

    #[inline]
    pub fn from_static_str(s: &'static str) -> Quark {
        Quark::from_static_bytes(s.as_bytes())
    }

    pub fn from_static_bytes(s: &'static [u8]) -> Quark {
        assert!(s[s.len() - 1] == 0);
        unsafe {
            let p = s.as_ptr() as *const gchar;
            let q = ffi::g_quark_from_static_string(p);
            Quark::new(q)
        }
    }

    #[inline]
    pub fn to_uint(&self) -> uint {
        let Quark(raw) = *self;
        raw as uint
    }

    pub fn to_bytes(&self) -> &'static [u8] {
        let Quark(raw) = *self;
        unsafe {
            let s = ffi::g_quark_to_string(raw);
            let r = mem::copy_lifetime("", &s);
            gstr::parse_as_bytes(r)
        }
    }

    #[inline]
    pub fn to_str(&self) -> Result<&'static str, str::Utf8Error> {
        str::from_utf8(self.to_bytes())
    }
}

impl StaticQuark {

    pub fn get(&self) -> Quark {
        let StaticQuark(s, ref cached) = *self;
        let mut q = cached.load(atomic::Ordering::Relaxed);
        if q == 0 {
            unsafe {
                let p = s.as_ptr() as *const gchar;
                q = ffi::g_quark_from_static_string(p) as uint;
            }
            cached.store(q, atomic::Ordering::Relaxed);
        }
        unsafe { Quark::new(q as ffi::GQuark) }
    }
}
<commit_msg>quark: improve panics in Quark::from_static_*<commit_after>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use ffi;
use gstr;
use types::gchar;

use std::mem;
use std::str;
use std::sync::atomic;

#[deriving(Copy, Eq, PartialEq)]
pub struct Quark(ffi::GQuark);

pub struct StaticQuark(pub &'static [u8], pub atomic::AtomicUint);

impl Quark {

    #[inline]
    pub unsafe fn new(raw: ffi::GQuark) -> Quark {
        Quark(raw)
    }

    pub fn from_static_str(s: &'static str) -> Quark {
        if !s.ends_with("\0") {
            panic!("static string is not null-terminated: \"{}\"", s);
        }
        unsafe { Quark::from_static_internal(s.as_bytes()) }
    }

    pub fn from_static_bytes(bytes: &'static [u8]) -> Quark {
        assert!(!bytes.is_empty());
        if bytes[bytes.len() - 1] != 0 {
            panic!("static byte string is not null-terminated: \"{}\"", bytes);
        }
        unsafe { Quark::from_static_internal(bytes) }
    }

    unsafe fn from_static_internal(s: &'static [u8]) -> Quark {
        let p = s.as_ptr() as *const gchar;
        let q = ffi::g_quark_from_static_string(p);
        Quark::new(q)
    }

    #[inline]
    pub fn to_uint(&self) -> uint {
        let Quark(raw) = *self;
        raw as uint
    }

    pub fn to_bytes(&self) -> &'static [u8] {
        let Quark(raw) = *self;
        unsafe {
            let s = ffi::g_quark_to_string(raw);
            let r = mem::copy_lifetime("", &s);
            gstr::parse_as_bytes(r)
        }
    }

    #[inline]
    pub fn to_str(&self) -> Result<&'static str, str::Utf8Error> {
        str::from_utf8(self.to_bytes())
    }
}

impl StaticQuark {

    pub fn get(&self) -> Quark {
        let StaticQuark(s, ref cached) = *self;
        let mut q = cached.load(atomic::Ordering::Relaxed);
        if q == 0 {
            unsafe {
                let p = s.as_ptr() as *const gchar;
                q = ffi::g_quark_from_static_string(p) as uint;
            }
            cached.store(q, atomic::Ordering::Relaxed);
        }
        unsafe { Quark::new(q as ffi::GQuark) }
    }
}
<|endoftext|>


<commit_before>/// Circular bounded queue.
pub struct Queue<T> {
  pub contents: Vec<T>,
  /// index in `contents` the queue starts at
  pub head: uint,
  /// index in `contents` to place the next element at
  pub tail: uint,
  /// number of elements used
  pub length: uint,
}

impl<T: Clone> Queue<T> {
  pub fn new(capacity: uint) -> Queue<T> {
    Queue {
      contents: Vec::with_capacity(capacity),
      head: 0,
      tail: 0,
      length: 0,
    }
  }

  fn wrap(&self, i: uint) -> uint {
    let r =
      if i >= self.contents.capacity() {
        i - self.contents.capacity()
      } else {
        i
      };
    assert!(r < self.contents.capacity());
    r
  }

  pub fn push(&mut self, t: T) {
    assert!(
      self.length < self.contents.capacity(),
      "Bounded queue (capacity {}) exceeded",
      self.contents.len()
    );

    if self.contents.len() < self.contents.capacity() {
      self.contents.push(t);
    } else {
      *self.contents.get_mut(self.tail) = t;
    }

    self.tail = self.wrap(self.tail + 1);
    self.length += 1;
  }

  pub fn push_all(&mut self, ts: &[T]) {
    for t in ts.iter() {
      self.push(t.clone());
    }
  }

  pub fn pop(&mut self, count: uint) {
    assert!(count <= self.length);
    self.head = self.wrap(self.head + count);
    self.length -= count;
  }

  pub fn is_empty(&self) -> bool {
    self.length == 0
  }

  pub fn swap_remove(&mut self, idx: uint, count: uint) {
    assert!(count <= self.length);
    // TODO: do this in bigger chunks
    for i in range(0, count) {
      if self.tail > 0 {
        self.tail -= 1;
      } else {
        self.tail = self.contents.len() - 1;
      };

      let swapped = self.contents[self.tail].clone();
      let idx = self.wrap(self.head + idx + i);
      *self.contents.get_mut(idx) = swapped;
    }

    self.length -= count;
  }

  pub fn len(&self) -> uint {
    self.length
  }

  #[allow(dead_code)]
  pub fn clear(&mut self) {
    self.contents.clear();
    self.head = 0;
    self.tail = 0;
    self.length = 0;
  }

  pub fn slices<'a>(&'a self, low: uint, high: uint) -> (&'a [T], &'a [T]) {
    assert!(low <= self.length);
    assert!(high <= self.length);
    let low = self.wrap(self.head + low);
    let high = self.wrap(self.head + high);
    if low < high {
      (self.contents.slice(low, high), self.contents.slice(high, high))
    } else {
      (self.contents.slice(low, self.contents.len()), self.contents.slice(0, high))
    }
  }
}
<commit_msg>tests for queue<commit_after>// for testing
#[allow(unused_imports)]
use std::iter::range_inclusive;

/// Circular bounded queue.
pub struct Queue<T> {
  pub contents: Vec<T>,
  /// index in `contents` the queue starts at
  pub head: uint,
  /// index in `contents` to place the next element at
  pub tail: uint,
  /// number of elements used
  pub length: uint,
}

impl<T: Clone> Queue<T> {
  pub fn new(capacity: uint) -> Queue<T> {
    Queue {
      contents: Vec::with_capacity(capacity),
      head: 0,
      tail: 0,
      length: 0,
    }
  }

  fn wrap(&self, i: uint) -> uint {
    let r =
      if i >= self.contents.capacity() {
        i - self.contents.capacity()
      } else {
        i
      };
    assert!(r < self.contents.capacity());
    r
  }

  pub fn push(&mut self, t: T) {
    assert!(
      self.length < self.contents.capacity(),
      "Bounded queue (capacity {}) exceeded",
      self.contents.len()
    );

    if self.contents.len() < self.contents.capacity() {
      self.contents.push(t);
    } else {
      *self.contents.get_mut(self.tail) = t;
    }

    self.tail = self.wrap(self.tail + 1);
    self.length += 1;
  }

  pub fn push_all(&mut self, ts: &[T]) {
    for t in ts.iter() {
      self.push(t.clone());
    }
  }

  pub fn pop(&mut self, count: uint) {
    assert!(count <= self.length);
    self.head = self.wrap(self.head + count);
    self.length -= count;
  }

  pub fn is_empty(&self) -> bool {
    self.length == 0
  }

  pub fn swap_remove(&mut self, idx: uint, count: uint) {
    assert!(count <= self.length);
    // TODO: do this in bigger chunks
    for i in range(0, count) {
      if self.tail > 0 {
        self.tail -= 1;
      } else {
        self.tail = self.contents.len() - 1;
      };

      let swapped = self.contents[self.tail].clone();
      let idx = self.wrap(self.head + idx + i);
      *self.contents.get_mut(idx) = swapped;
    }

    self.length -= count;
  }

  pub fn len(&self) -> uint {
    self.length
  }

  #[allow(dead_code)]
  pub fn clear(&mut self) {
    self.contents.clear();
    self.head = 0;
    self.tail = 0;
    self.length = 0;
  }

  pub fn slices<'a>(&'a self, low: uint, high: uint) -> (&'a [T], &'a [T]) {
    assert!(low <= self.length);
    assert!(high <= self.length);
    let low = self.wrap(self.head + low);
    let high = self.wrap(self.head + high);
    if low < high {
      (self.contents.slice(low, high), self.contents.slice(high, high))
    } else {
      (self.contents.slice(low, self.contents.len()), self.contents.slice(0, high))
    }
  }
}

#[test]
fn push_then_slice() {
  let elems: Vec<int> = Vec::from_slice([1, 2, 3]);
  let mut q = Queue::new(32);
  q.push_all(elems.as_slice());
  assert!(q.len() == elems.len());
  let (l, h) = q.slices(0, q.len() - 1);
  assert!(l.len() + h.len() == elems.len() - 1);
  for (i, elem) in l.iter().enumerate() {
    assert!(*elem == elems[i]);
  }
  for (i, elem) in h.iter().enumerate() {
    assert!(*elem == elems[i + l.len()]);
  }
}

#[test]
fn push_then_pop() {
  let popped_pushes: Vec<int> = Vec::from_slice([1, 2, 3]);
  let more_pushes: Vec<int> = Vec::from_slice([4, 5]);
  let mut q = Queue::new(32);
  q.push_all(popped_pushes.as_slice());
  q.push_all(more_pushes.as_slice());
  assert!(q.len() == popped_pushes.len() + more_pushes.len());
  q.pop(popped_pushes.len());
  assert!(q.len() == more_pushes.len());
  let (l, h) = q.slices(0, q.len());
  assert!(l.len() + h.len() == more_pushes.len());
  for (i, elem) in l.iter().enumerate() {
    assert!(*elem == more_pushes[i]);
  }
  for (i, elem) in h.iter().enumerate() {
    assert!(*elem == more_pushes[i + l.len()]);
  }
}

#[test]
fn wrapped_pushes() {
  static capacity: uint = 32;
  let popped_pushes = Vec::from_elem(capacity / 2, 0);
  let more_pushes: Vec<int> = range_inclusive(1, capacity as int).collect();
  let mut q: Queue<int> = Queue::new(capacity);
  q.push_all(popped_pushes.as_slice());
  q.pop(popped_pushes.len());
  q.push_all(more_pushes.as_slice());
  assert!(q.len() == more_pushes.len());
  let (l, h) = q.slices(0, q.len());
  assert!(l.len() + h.len() == more_pushes.len());
  assert!(h.len() > 0);
  for (i, elem) in l.iter().enumerate() {
    assert!(*elem == more_pushes[i]);
  }
  for (i, elem) in h.iter().enumerate() {
    assert!(*elem == more_pushes[i + l.len()]);
  }
}
<|endoftext|>


<commit_before>use std::sync::atomic::Ordering::{Acquire, Release, Relaxed};
use std::cell::RefCell;

use mem::epoch::{self, AtomicPtr, Owned};

pub struct Queue<T> {
    head: AtomicPtr<Node<T>>,
    tail: AtomicPtr<Node<T>>,
}

struct Node<T> {
    data: RefCell<Option<T>>,
    next: AtomicPtr<Node<T>>,
}

impl<T> Queue<T> {
    pub fn new() -> Queue<T> {
        let q = Queue { head: AtomicPtr::new(), tail: AtomicPtr::new() };
        let sentinel = Owned::new(Node {
            data: RefCell::new(None),
            next: AtomicPtr::new()
        });
        let guard = epoch::pin();
        let sentinel = q.head.store_and_ref(sentinel, Relaxed, &guard);
        unsafe { q.tail.store_shared(Some(sentinel), Relaxed); }
        q
    }

    pub fn push(&self, t: T) {
        let mut n = Owned::new(Node {
            data: RefCell::new(Some(t)),
            next: AtomicPtr::new()
        });
        let guard = epoch::pin();
        loop {
            let tail = self.tail.load(Acquire, &guard).unwrap();
            if let Some(next) = tail.next.load(Relaxed, &guard) {
                unsafe { self.tail.cas_shared(Some(tail), Some(next), Relaxed); }
                continue;
            }

            match tail.next.cas_and_ref(None, n, Release, &guard) {
                Ok(shared) => {
                    unsafe { self.tail.cas_shared(Some(tail), Some(shared), Relaxed); }
                    break;
                }
                Err(owned) => {
                    n = owned;
                }
            }
        }
    }

    pub fn pop(&self) -> Option<T> {
        let guard = epoch::pin();
        loop {
            let head = self.head.load(Acquire, &guard).unwrap();

            if let Some(next) = head.next.load(Relaxed, &guard) {
                if unsafe { self.head.cas_shared(Some(head), Some(next), Relaxed) } {
                    unsafe { guard.unlinked(head); }
                    // FIXME: rustc bug that (*next) is required
                    return (*next).data.borrow_mut().take()
                }
            } else {
                return None
            }
        }
    }
}

/*
impl<T: Debug> Queue<T> {
    pub fn debug(&self) {
        writeln!(stderr(), "Debugging queue:");

        let guard = epoch::pin();
        let mut node = self.head.load(Acquire, &guard);
        while let Some(n) = node {
            writeln!(stderr(), "{:?}", (*n).data.borrow());
            node = n.next.load(Relaxed, &guard);
        }

        writeln!(stderr(), "");
    }
}
*/

#[cfg(test)]
mod test {
    use std::thread;

    use super::*;

    #[test]
    fn smoke_queue() {
        let q: Queue<i32> = Queue::new();
    }

    #[test]
    fn push_pop_1() {
        let q: Queue<i32> = Queue::new();
        q.push(37);
        assert_eq!(q.pop(), Some(37));
    }

    #[test]
    fn push_pop_2() {
        let q: Queue<i32> = Queue::new();
        q.push(37);
        q.push(48);
        assert_eq!(q.pop(), Some(37));
        assert_eq!(q.pop(), Some(48));
    }

    #[test]
    fn push_pop_many_seq() {
        let q: Queue<i32> = Queue::new();
        for i in 0..200 {
            q.push(i)
        }
        for i in 0..200 {
            assert_eq!(q.pop(), Some(i));
        }
    }

    #[test]
    fn push_pop_many_spsc() {
        let q: Queue<i32> = Queue::new();
        for i in 0..200 {
            q.push(i)
        }
        for i in 0..200 {
            assert_eq!(q.pop(), Some(i));
        }
    }
}
<commit_msg>Tighten up tests<commit_after>use std::sync::atomic::Ordering::{Acquire, Release, Relaxed};
use std::cell::RefCell;

use mem::epoch::{self, AtomicPtr, Owned};

pub struct Queue<T> {
    head: AtomicPtr<Node<T>>,
    tail: AtomicPtr<Node<T>>,
}

struct Node<T> {
    data: RefCell<Option<T>>,
    next: AtomicPtr<Node<T>>,
}

impl<T> Queue<T> {
    pub fn new() -> Queue<T> {
        let q = Queue { head: AtomicPtr::new(), tail: AtomicPtr::new() };
        let sentinel = Owned::new(Node {
            data: RefCell::new(None),
            next: AtomicPtr::new()
        });
        let guard = epoch::pin();
        let sentinel = q.head.store_and_ref(sentinel, Relaxed, &guard);
        unsafe { q.tail.store_shared(Some(sentinel), Relaxed); }
        q
    }

    pub fn push(&self, t: T) {
        let mut n = Owned::new(Node {
            data: RefCell::new(Some(t)),
            next: AtomicPtr::new()
        });
        let guard = epoch::pin();
        loop {
            let tail = self.tail.load(Acquire, &guard).unwrap();
            if let Some(next) = tail.next.load(Relaxed, &guard) {
                unsafe { self.tail.cas_shared(Some(tail), Some(next), Relaxed); }
                continue;
            }

            match tail.next.cas_and_ref(None, n, Release, &guard) {
                Ok(shared) => {
                    unsafe { self.tail.cas_shared(Some(tail), Some(shared), Relaxed); }
                    break;
                }
                Err(owned) => {
                    n = owned;
                }
            }
        }
    }

    pub fn pop(&self) -> Option<T> {
        let guard = epoch::pin();
        loop {
            let head = self.head.load(Acquire, &guard).unwrap();

            if let Some(next) = head.next.load(Relaxed, &guard) {
                if unsafe { self.head.cas_shared(Some(head), Some(next), Relaxed) } {
                    unsafe { guard.unlinked(head); }
                    // FIXME: rustc bug that (*next) is required
                    return (*next).data.borrow_mut().take()
                }
            } else {
                return None
            }
        }
    }
}

/*
impl<T: Debug> Queue<T> {
    pub fn debug(&self) {
        writeln!(stderr(), "Debugging queue:");

        let guard = epoch::pin();
        let mut node = self.head.load(Acquire, &guard);
        while let Some(n) = node {
            writeln!(stderr(), "{:?}", (*n).data.borrow());
            node = n.next.load(Relaxed, &guard);
        }

        writeln!(stderr(), "");
    }
}
*/

#[cfg(test)]
mod test {
    const CONC_COUNT: i64 = 10000000;

    use std::io::stderr;
    use std::io::prelude::*;

    use mem::epoch;
    use thread;
    use super::*;

    #[test]
    fn smoke_queue() {
        let q: Queue<i64> = Queue::new();
    }

    #[test]
    fn push_pop_1() {
        let q: Queue<i64> = Queue::new();
        q.push(37);
        assert_eq!(q.pop(), Some(37));
    }

    #[test]
    fn push_pop_2() {
        let q: Queue<i64> = Queue::new();
        q.push(37);
        q.push(48);
        assert_eq!(q.pop(), Some(37));
        assert_eq!(q.pop(), Some(48));
    }

    #[test]
    fn push_pop_many_seq() {
        let q: Queue<i64> = Queue::new();
        for i in 0..200 {
            q.push(i)
        }
        for i in 0..200 {
            assert_eq!(q.pop(), Some(i));
        }
    }

    #[test]
    fn push_pop_many_spsc() {
        let q: Queue<i64> = Queue::new();

        thread::scope(|scope| {
            scope.spawn(|| {
                let mut next = 0;

                while next < CONC_COUNT {
                    if let Some(elem) = q.pop() {
                        assert_eq!(elem, next);
                        next += 1;
                    }
                }
            });

            for i in 0..CONC_COUNT {
                q.push(i)
            }
        });
    }

    #[test]
    fn push_pop_many_spmc() {
        fn recv(t: i32, q: &Queue<i64>) {
            let mut cur = -1;
            for i in 0..CONC_COUNT {
                if let Some(elem) = q.pop() {
                    if elem <= cur {
                        writeln!(stderr(), "{}: {} <= {}", t, elem, cur);
                    }
                    assert!(elem > cur);
                    cur = elem;

                    if cur == CONC_COUNT - 1 { break }
                }

                if i % 10000 == 0 {
                    writeln!(stderr(), "{}: {} @ {}", t, i, cur);
                }
            }
        }

        let q: Queue<i64> = Queue::new();
        let qr = &q;

        thread::scope(|scope| {
            for i in 0..2 {
                scope.spawn(move || recv(i, qr));
            }

            for i in 0..CONC_COUNT {
                q.push(i);

                if i % 10000 == 0 {
                    writeln!(stderr(), "Push: {}", i);
                }
            }
        })
    }

    #[test]
    fn push_pop_many_mpmc() {
        enum LR { Left(i64), Right(i64) }

        let q: Queue<LR> = Queue::new();

        thread::scope(|scope| {
            for _t in 0..2 {
                scope.spawn(|| {
                    for i in CONC_COUNT-1..CONC_COUNT {
                        q.push(LR::Left(i))
                    }
                });
                scope.spawn(|| {
                    for i in CONC_COUNT-1..CONC_COUNT {
                        q.push(LR::Right(i))
                    }
                });
                scope.spawn(|| {
                    let mut vl = vec![];
                    let mut vr = vec![];
                    for _i in 0..CONC_COUNT {
                        match q.pop() {
                            Some(LR::Left(x)) => vl.push(x),
                            Some(LR::Right(x)) => vr.push(x),
                            _ => {}
                        }
                    }

                    let mut vl2 = vl.clone();
                    let mut vr2 = vr.clone();
                    vl2.sort();
                    vr2.sort();

                    assert_eq!(vl, vl2);
                    assert_eq!(vr, vr2);
                });
            }
        });
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Jason White
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Provides the ability to retry an operation until it succeeds.
//!
//! # Examples
//!
//! ```
//! use std::time::Duration;
//! use std::io;
//! use std::io::Write;
//! use std::error::Error;
//!
//! fn find_answer(answer: &str) -> io::Result<()> {
//!     print!("Please enter the correct answer: ");
//!     io::stdout().flush()?;
//!
//!     let mut buf = String::new();
//!     io::stdin().read_line(&mut buf)?;
//!
//!     return if buf.trim() == answer {
//!         Ok(())
//!     } else {
//!         Err(io::Error::new(io::ErrorKind::Other, "Sorry, that is not the answer."))
//!     }
//! }
//!
//! fn retry_progress(retry: &retry::Retry,
//!                   err: &io::Error,
//!                   remaining: u32,
//!                   delay: Duration) -> bool {
//!     println!("Error: {} ({} attempt(s) remaining. Retrying in ~{} seconds...)",
//!         err.description(),
//!         remaining,
//!         delay.as_secs()
//!     );
//!     true
//! }
//!
//! let result = retry::Retry::new()
//!     .with_retries(4)
//!     .with_delay(Duration::from_secs(1))
//!     .with_max_delay(Duration::from_secs(4))
//!     .call(|| find_answer("42"), retry_progress);
//!
//! match result {
//!     Ok(()) => println!("Correct!"),
//!     Err(err) => println!("{}", err),
//! };
//! ```

// TODO: Allow specifying a non-integer exponential backoff factor.
// TODO: Allow jittering to further help avoid the "thundering herd" problem by
// keeping retries from stacking up. Jittering is just adjusting the delay by a
// random offset within an interval. If the interval length is 0, there is
// effectively no jittering.

use std::thread::sleep;
use std::time::Duration;
use std::cmp::min;

#[derive(Serialize, Deserialize, Ord, PartialOrd, Eq, PartialEq, Hash, Copy, Clone)]
pub struct Retry {
    /// The number of times to *retry* a function. Note that the function is
    /// always called at least once.
    pub retries: u32,

    /// The initial duration to wait. For each retry, this is multiplied by the
    /// exponential backoff factor. Set to a duration of 0 for no delay.
    pub delay: Duration,

    /// The backoff factor. A value of 1 means linear backoff. A value of 2
    /// means exponential backoff. A value of 0 means no delay at all.
    pub backoff: u32,

    /// The maximum possible delay. If `None`, there is no maximum delay.
    pub max_delay: Option<Duration>,
}

impl Default for Retry {
    fn default() -> Retry {
        Retry {
            retries: 0,
            delay: Duration::from_secs(1),
            backoff: 2,
            max_delay: None,
        }
    }
}

impl Retry {
    /// Initializes a default `Retry`.
    #[allow(dead_code)]
    pub fn new() -> Retry {
        Retry::default()
    }

    /// Sets the number of retries.
    #[allow(dead_code)]
    pub fn with_retries(mut self, retries: u32) -> Retry {
        self.retries = retries;
        self
    }

    /// Sets the initial delay.
    #[allow(dead_code)]
    pub fn with_delay(mut self, delay: Duration) -> Retry {
        self.delay = delay;
        self
    }

    /// Sets the backoff.
    #[allow(dead_code)]
    pub fn with_backoff(mut self, backoff: u32) -> Retry {
        self.backoff = backoff;
        self
    }

    /// Sets the maximum possible delay.
    #[allow(dead_code)]
    pub fn with_max_delay(mut self, max_delay: Duration) -> Retry {
        self.max_delay = Some(max_delay);
        self
    }

    /// Calls the function until it returns a `Ok` result. If an `Ok` result is
    /// never produced, returns the `Result` from the last call to the function
    /// that failed.
    pub fn call<F, T, E, P>(&self, mut f: F, mut progress: P) -> Result<T, E>
        where F: FnMut() -> Result<T, E>,
              P: FnMut(&Retry, &E, u32, Duration) -> bool
    {
        let mut attempt = self.retries + 1;
        let mut delay = self.delay;

        loop {
            match f() {
                Ok(value) => return Ok(value),
                Err(err) => {
                    attempt -= 1;

                    if attempt > 0 {
                        if !progress(&self, &err, attempt, delay) {
                            return Err(err);
                        }

                        sleep(delay);

                        // Increase the delay.
                        delay = match self.max_delay {
                            Some(max_delay) => min(delay * self.backoff, max_delay),
                            None => delay * self.backoff,
                        };
                    } else {
                        // No more remaining attempts.
                        return Err(err);
                    }
                },
            }
        }
    }
}

/// Dummy progress callback function. If you don't want to report progress on
/// for each retry, use this function.
#[allow(unused_variables)]
pub fn progress_dummy<E>(retry: &Retry,
                         err: &E,
                         remaining: u32,
                         delay: Duration) -> bool
{
    // Keep going.
    true
}
<commit_msg>Clean up retry code<commit_after>// Copyright (c) 2017 Jason White
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Provides the ability to retry an operation until it succeeds.
//!
//! # Examples
//!
//! ```
//! use std::time::Duration;
//! use std::io;
//! use std::io::Write;
//! use std::error::Error;
//!
//! fn find_answer(answer: &str) -> io::Result<()> {
//!     print!("Please enter the correct answer: ");
//!     io::stdout().flush()?;
//!
//!     let mut buf = String::new();
//!     io::stdin().read_line(&mut buf)?;
//!
//!     return if buf.trim() == answer {
//!         Ok(())
//!     } else {
//!         Err(io::Error::new(io::ErrorKind::Other, "Sorry, that is not the answer."))
//!     }
//! }
//!
//! fn retry_progress(retry: &retry::Retry,
//!                   err: &io::Error,
//!                   remaining: u32,
//!                   delay: Duration) -> bool {
//!     println!("Error: {} ({} attempt(s) remaining. Retrying in ~{} seconds...)",
//!         err.description(),
//!         remaining,
//!         delay.as_secs()
//!     );
//!     true
//! }
//!
//! let result = retry::Retry::new()
//!     .with_retries(4)
//!     .with_delay(Duration::from_secs(1))
//!     .with_max_delay(Duration::from_secs(4))
//!     .call(|| find_answer("42"), retry_progress);
//!
//! match result {
//!     Ok(()) => println!("Correct!"),
//!     Err(err) => println!("{}", err),
//! };
//! ```

// TODO: Allow specifying a non-integer exponential backoff factor.
// TODO: Allow jittering to further help avoid the "thundering herd" problem by
// keeping retries from stacking up. Jittering is just adjusting the delay by a
// random offset within an interval. If the interval length is 0, there is
// effectively no jittering.

use std::thread::sleep;
use std::time::Duration;
use std::cmp::min;
use std::error::Error;

#[derive(Serialize, Deserialize, Ord, PartialOrd, Eq, PartialEq, Hash, Copy, Clone)]
pub struct Retry {
    /// The number of times to *retry* a function. Note that the function is
    /// always called at least once.
    pub retries: u32,

    /// The initial duration to wait. For each retry, this is multiplied by the
    /// exponential backoff factor. Set to a duration of 0 for no delay.
    pub delay: Duration,

    /// The backoff factor. A value of 1 means linear backoff. A value of 2
    /// means exponential backoff. A value of 0 means no delay at all.
    pub backoff: u32,

    /// The maximum possible delay. If `None`, there is no maximum delay.
    pub max_delay: Option<Duration>,
}

impl Default for Retry {
    fn default() -> Retry {
        Retry {
            retries: 0,
            delay: Duration::from_secs(1),
            backoff: 2,
            max_delay: None,
        }
    }
}

impl Retry {
    /// Initializes a default `Retry`.
    #[allow(unused)]
    pub fn new() -> Retry {
        Retry::default()
    }

    /// Sets the number of retries.
    #[allow(unused)]
    pub fn with_retries(mut self, retries: u32) -> Retry {
        self.retries = retries;
        self
    }

    /// Sets the initial delay.
    #[allow(unused)]
    pub fn with_delay(mut self, delay: Duration) -> Retry {
        self.delay = delay;
        self
    }

    /// Sets the backoff.
    #[allow(unused)]
    pub fn with_backoff(mut self, backoff: u32) -> Retry {
        self.backoff = backoff;
        self
    }

    /// Sets the maximum possible delay.
    #[allow(unused)]
    pub fn with_max_delay(mut self, max_delay: Duration) -> Retry {
        self.max_delay = Some(max_delay);
        self
    }

    /// Calls the function until it returns a `Ok` result. If an `Ok` result is
    /// never produced, returns the `Result` from the last call to the function
    /// that failed.
    pub fn call<F, T, E, P>(&self, mut f: F, mut progress: P) -> Result<T, E>
        where F: FnMut() -> Result<T, E>,
              P: FnMut(&Retry, &E, u32, Duration) -> bool
    {
        let mut attempt = self.retries + 1;
        let mut delay = self.delay;

        loop {
            match f() {
                Ok(value) => return Ok(value),
                Err(err) => {
                    attempt -= 1;

                    if attempt > 0 {
                        if !progress(&self, &err, attempt, delay) {
                            return Err(err);
                        }

                        sleep(delay);

                        // Increase the delay.
                        delay = match self.max_delay {
                            Some(max_delay) => min(delay * self.backoff, max_delay),
                            None => delay * self.backoff,
                        };
                    } else {
                        // No more remaining attempts.
                        return Err(err);
                    }
                },
            }
        }
    }
}

/// Dummy progress callback function. If you don't want to report progress on
/// for each retry, use this function.
#[allow(unused_variables)]
pub fn progress_dummy<E>(retry: &Retry,
                         err: &E,
                         remaining: u32,
                         delay: Duration) -> bool
{
    // Keep going.
    true
}

/// Progress callback function for simply printing the progress of each retry.
#[allow(unused)]
pub fn progress_print<E>(retry: &Retry,
                         err: &E,
                         remaining: u32,
                         delay: Duration) -> bool
    where E: Error
{
    println!("Error: {} ({}/{} attempt(s) remaining. Retrying in ~{} seconds...)",
        err.description(),
        remaining,
        retry.retries,
        delay.as_secs()
    );
    true
}
<|endoftext|>


<commit_before>use cgmath::{Vector2, vec2, dot};
use calx_color::{color, Rgba};
use calx_layout::Rect;
use calx_layout::Anchor::*;
use wall::{Wall, Vertex};

/// Helper methods for render context that do not depend on the underlying
/// implementation details.
pub trait DrawUtil {
    /// Draw a thick solid line on the canvas.
    fn draw_line<C, V>(&mut self, width: f32, p1: V, p2: V, layer: f32, color: C)
        where C: Into<Rgba>+Copy,
              V: Into<[f32; 2]>;

    /// Get the size of an atlas image.
    fn image_dim(&self, img: usize) -> [u32; 2];

    /// Draw a stored image on the canvas.
    fn draw_image<C, D, V>(&mut self, img: usize, offset: V, z: f32, color: C, back_color: D)
        where C: Into<Rgba>+Copy,
              D: Into<Rgba>+Copy,
              V: Into<[f32; 2]>;

    /// Draw a filled rectangle.
    fn fill_rect<C: Into<Rgba>+Copy>(&mut self, rect: &Rect<f32>, z: f32, color: C);

    /// Draw a wireframe rectangle.
    fn draw_rect<C: Into<Rgba>+Copy>(&mut self, rect: &Rect<f32>, z: f32, color: C);
/*
    fn draw_char<C, D, V>(&mut self, c: char, offset: V, z: f32, color: C, border: Option<D>)
        where C: Into<Rgba>+Copy,
              D: Into<Rgba>+Copy,
              V: Into<[f32; 2]>;

    fn char_width(&self, c: char) -> f32;
    */

    /*
    /// Write a timestamped screenshot PNG to disk.
    fn save_screenshot(&mut self, basename: &str);
    */
}

impl DrawUtil for Wall {
    fn draw_line<C, V>(&mut self, width: f32, p1: V, p2: V, layer: f32, color: C)
        where C: Into<Rgba>+Copy,
              V: Into<[f32; 2]>
    {
        let p1: Vector2<f32> = Vector2::from(p1.into());
        let p2: Vector2<f32> = Vector2::from(p2.into());

        if p1 == p2 { return; }

        let tex = self.tiles[0].tex.top;

        // The front vector. Extend by width.
        let v1 = p2 - p1;
        let scalar = dot(v1, v1);
        let scalar = (scalar + width * width) / scalar;
        let v1 = v1 * scalar;

        // The sideways vector, turn into unit vector, then multiply by half the width.
        let v2 = vec2(-v1[1], v1[0]);
        let scalar = width / 2.0 * 1.0 / dot(v2, v2).sqrt();
        let v2 = v2 * scalar;

        let color: Rgba = color.into();
        self.add_mesh(
            vec![
            Vertex::new(p1 + v2, layer, tex, color, color::BLACK),
            Vertex::new(p1 - v2, layer, tex, color, color::BLACK),
            Vertex::new(p1 - v2 + v1, layer, tex, color, color::BLACK),
            Vertex::new(p1 + v2 + v1, layer, tex, color, color::BLACK),
            ],
            vec![[0, 1, 2], [0, 2, 3]]);
    }

    fn image_dim(&self, img: usize) -> [u32; 2] {
        let size = self.tiles[img].pos.size;
        [size[0] as u32, size[1] as u32]
    }

    fn draw_image<C, D, V>(&mut self, img: usize, offset: V, z: f32, color: C, back_color: D)
        where C: Into<Rgba>+Copy,
              D: Into<Rgba>+Copy,
              V: Into<[f32; 2]> {
        // Use round numbers, fractions seem to cause artifacts to pixels.
        let mut offset = offset.into();
        offset[0] = offset[0].floor();
        offset[1] = offset[1].floor();

        let mut pos;
        let tex;
        {
            let data = self.tiles[img];
            pos = data.pos;
            pos.top[0] += offset[0];
            pos.top[1] += offset[1];
            tex = data.tex;
        }

        let color: Rgba = color.into();
        let back_color: Rgba = back_color.into();
        self.add_mesh(
            vec![
            Vertex::new(pos.point(TopLeft), z, tex.point(TopLeft), color, back_color),
            Vertex::new(pos.point(TopRight), z, tex.point(TopRight), color, back_color),
            Vertex::new(pos.point(BottomRight), z, tex.point(BottomRight), color, back_color),
            Vertex::new(pos.point(BottomLeft), z, tex.point(BottomLeft), color, back_color),
            ],
            vec![[0, 1, 2], [0, 2, 3]]);
    }

    fn fill_rect<C: Into<Rgba>+Copy>(&mut self, rect: &Rect<f32>, z: f32, color: C) {
        let tex = self.tiles[0].tex.top;

        let color: Rgba = color.into();
        self.add_mesh(
            vec![
            Vertex::new(rect.point(TopLeft), z, tex, color, color::BLACK),
            Vertex::new(rect.point(TopRight), z, tex, color, color::BLACK),
            Vertex::new(rect.point(BottomRight), z, tex, color, color::BLACK),
            Vertex::new(rect.point(BottomLeft), z, tex, color, color::BLACK),
            ],
            vec![[0, 1, 2], [0, 2, 3]]);
    }

    fn draw_rect<C: Into<Rgba>+Copy>(&mut self, rect: &Rect<f32>, z: f32, color: C) {
        self.draw_line(1.0, Vector2::from(rect.point(TopLeft)), Vector2::from(rect.point(TopRight)) - vec2(1.0, 0.0), z, color);
        self.draw_line(1.0, Vector2::from(rect.point(TopRight)) - vec2(1.0, 0.0), Vector2::from(rect.point(BottomRight)) - vec2(1.0, 0.0), z, color);
        self.draw_line(1.0, Vector2::from(rect.point(BottomLeft)) - vec2(0.0, 1.0), Vector2::from(rect.point(BottomRight)) - vec2(1.0, 1.0), z, color);
        self.draw_line(1.0, rect.point(TopLeft), rect.point(BottomLeft), z, color);
    }

    /*
    fn draw_char<C: Into<Rgba>+Copy, D: Into<Rgba>+Copy>(&mut self, c: char, offset: V2<f32>, z: f32, color: C, border: Option<D>) {
        static BORDER: [V2<f32>; 8] =
            [V2(-1.0, -1.0), V2( 0.0, -1.0), V2( 1.0, -1.0),
             V2(-1.0,  0.0),                 V2( 1.0,  0.0),
             V2(-1.0,  1.0), V2( 0.0,  1.0), V2( 1.0,  1.0)];
        if let Some(img) = self.font_image(c) {
            if let Some(b) = border {
                // Put the border a tiny bit further in the z-buffer so it
                // won't clobber the text on the same layer.
                let border_z = z + 0.00001;
                for &d in BORDER.iter() {
                    self.draw_image(img, offset + d, border_z, b, color::BLACK);
                }
            }
            self.draw_image(img, offset, z, color, color::BLACK);
        }
    }

    fn char_width(&self, c: char) -> f32 {
        // Infer letter width from the cropped atlas image. (Use mx instead of
        // dim on the pos rectangle so that the left-side space will be
        // preserved and the letters are kept slightly apart.)
        if let Some(img) = self.font_image(c) {
            let width = self.tiles[img].pos.mx().0;
            return width;
        }

        // Not a valid letter.
        (FONT_W / 2) as f32
    }
    */

    /*
    fn save_screenshot(&mut self, basename: &str) {
        use time;
        use std::path::{Path};
        use std::fs::{self, File};
        use image;

        let shot = self.screenshot();

        let timestamp = time::precise_time_s() as u64;
        // Create screenshot filenames by concatenating the current timestamp in
        // seconds with a running number from 00 to 99. 100 shots per second
        // should be good enough.

        // Default if we fail to generate any of the 100 candidates for this
        // second, just overwrite with the "xx" prefix then.
        let mut filename = format!("{}-{}{}.png", basename, timestamp, "xx");

        // Run through candidates for this second.
        for i in 0..100 {
            let test_filename = format!("{}-{}{:02}.png", basename, timestamp, i);
            // If file does not exist.
            if fs::metadata(&test_filename).is_err() {
                // Thread-safe claiming: create_dir will fail if the dir
                // already exists (it'll exist if another thread is gunning
                // for the same filename and managed to get past us here).
                // At least assuming that create_dir is atomic...
                let squat_dir = format!(".tmp-{}{:02}", timestamp, i);
                if fs::create_dir(&squat_dir).is_ok() {
                    File::create(&test_filename).unwrap();
                    filename = test_filename;
                    fs::remove_dir(&squat_dir).unwrap();
                    break;
                } else {
                    continue;
                }
            }
        }

        let _ = image::save_buffer(&Path::new(&filename), &shot, shot.width(), shot.height(), image::ColorType::RGB(8));
    }
    */
}
<commit_msg>This stuff won't be here in the future either, delete<commit_after>use cgmath::{Vector2, vec2, dot};
use calx_color::{color, Rgba};
use calx_layout::Rect;
use calx_layout::Anchor::*;
use wall::{Wall, Vertex};

/// Helper methods for render context that do not depend on the underlying
/// implementation details.
pub trait DrawUtil {
    /// Draw a thick solid line on the canvas.
    fn draw_line<C, V>(&mut self, width: f32, p1: V, p2: V, layer: f32, color: C)
        where C: Into<Rgba>+Copy,
              V: Into<[f32; 2]>;

    /// Get the size of an atlas image.
    fn image_dim(&self, img: usize) -> [u32; 2];

    /// Draw a stored image on the canvas.
    fn draw_image<C, D, V>(&mut self, img: usize, offset: V, z: f32, color: C, back_color: D)
        where C: Into<Rgba>+Copy,
              D: Into<Rgba>+Copy,
              V: Into<[f32; 2]>;

    /// Draw a filled rectangle.
    fn fill_rect<C: Into<Rgba>+Copy>(&mut self, rect: &Rect<f32>, z: f32, color: C);

    /// Draw a wireframe rectangle.
    fn draw_rect<C: Into<Rgba>+Copy>(&mut self, rect: &Rect<f32>, z: f32, color: C);
}

impl DrawUtil for Wall {
    fn draw_line<C, V>(&mut self, width: f32, p1: V, p2: V, layer: f32, color: C)
        where C: Into<Rgba>+Copy,
              V: Into<[f32; 2]>
    {
        let p1: Vector2<f32> = Vector2::from(p1.into());
        let p2: Vector2<f32> = Vector2::from(p2.into());

        if p1 == p2 { return; }

        let tex = self.tiles[0].tex.top;

        // The front vector. Extend by width.
        let v1 = p2 - p1;
        let scalar = dot(v1, v1);
        let scalar = (scalar + width * width) / scalar;
        let v1 = v1 * scalar;

        // The sideways vector, turn into unit vector, then multiply by half the width.
        let v2 = vec2(-v1[1], v1[0]);
        let scalar = width / 2.0 * 1.0 / dot(v2, v2).sqrt();
        let v2 = v2 * scalar;

        let color: Rgba = color.into();
        self.add_mesh(
            vec![
            Vertex::new(p1 + v2, layer, tex, color, color::BLACK),
            Vertex::new(p1 - v2, layer, tex, color, color::BLACK),
            Vertex::new(p1 - v2 + v1, layer, tex, color, color::BLACK),
            Vertex::new(p1 + v2 + v1, layer, tex, color, color::BLACK),
            ],
            vec![[0, 1, 2], [0, 2, 3]]);
    }

    fn image_dim(&self, img: usize) -> [u32; 2] {
        let size = self.tiles[img].pos.size;
        [size[0] as u32, size[1] as u32]
    }

    fn draw_image<C, D, V>(&mut self, img: usize, offset: V, z: f32, color: C, back_color: D)
        where C: Into<Rgba>+Copy,
              D: Into<Rgba>+Copy,
              V: Into<[f32; 2]> {
        // Use round numbers, fractions seem to cause artifacts to pixels.
        let mut offset = offset.into();
        offset[0] = offset[0].floor();
        offset[1] = offset[1].floor();

        let mut pos;
        let tex;
        {
            let data = self.tiles[img];
            pos = data.pos;
            pos.top[0] += offset[0];
            pos.top[1] += offset[1];
            tex = data.tex;
        }

        let color: Rgba = color.into();
        let back_color: Rgba = back_color.into();
        self.add_mesh(
            vec![
            Vertex::new(pos.point(TopLeft), z, tex.point(TopLeft), color, back_color),
            Vertex::new(pos.point(TopRight), z, tex.point(TopRight), color, back_color),
            Vertex::new(pos.point(BottomRight), z, tex.point(BottomRight), color, back_color),
            Vertex::new(pos.point(BottomLeft), z, tex.point(BottomLeft), color, back_color),
            ],
            vec![[0, 1, 2], [0, 2, 3]]);
    }

    fn fill_rect<C: Into<Rgba>+Copy>(&mut self, rect: &Rect<f32>, z: f32, color: C) {
        let tex = self.tiles[0].tex.top;

        let color: Rgba = color.into();
        self.add_mesh(
            vec![
            Vertex::new(rect.point(TopLeft), z, tex, color, color::BLACK),
            Vertex::new(rect.point(TopRight), z, tex, color, color::BLACK),
            Vertex::new(rect.point(BottomRight), z, tex, color, color::BLACK),
            Vertex::new(rect.point(BottomLeft), z, tex, color, color::BLACK),
            ],
            vec![[0, 1, 2], [0, 2, 3]]);
    }

    fn draw_rect<C: Into<Rgba>+Copy>(&mut self, rect: &Rect<f32>, z: f32, color: C) {
        self.draw_line(1.0, Vector2::from(rect.point(TopLeft)), Vector2::from(rect.point(TopRight)) - vec2(1.0, 0.0), z, color);
        self.draw_line(1.0, Vector2::from(rect.point(TopRight)) - vec2(1.0, 0.0), Vector2::from(rect.point(BottomRight)) - vec2(1.0, 0.0), z, color);
        self.draw_line(1.0, Vector2::from(rect.point(BottomLeft)) - vec2(0.0, 1.0), Vector2::from(rect.point(BottomRight)) - vec2(1.0, 1.0), z, color);
        self.draw_line(1.0, rect.point(TopLeft), rect.point(BottomLeft), z, color);
    }

    /*
    fn draw_char<C: Into<Rgba>+Copy, D: Into<Rgba>+Copy>(&mut self, c: char, offset: V2<f32>, z: f32, color: C, border: Option<D>) {
        static BORDER: [V2<f32>; 8] =
            [V2(-1.0, -1.0), V2( 0.0, -1.0), V2( 1.0, -1.0),
             V2(-1.0,  0.0),                 V2( 1.0,  0.0),
             V2(-1.0,  1.0), V2( 0.0,  1.0), V2( 1.0,  1.0)];
        if let Some(img) = self.font_image(c) {
            if let Some(b) = border {
                // Put the border a tiny bit further in the z-buffer so it
                // won't clobber the text on the same layer.
                let border_z = z + 0.00001;
                for &d in BORDER.iter() {
                    self.draw_image(img, offset + d, border_z, b, color::BLACK);
                }
            }
            self.draw_image(img, offset, z, color, color::BLACK);
        }
    }

    fn char_width(&self, c: char) -> f32 {
        // Infer letter width from the cropped atlas image. (Use mx instead of
        // dim on the pos rectangle so that the left-side space will be
        // preserved and the letters are kept slightly apart.)
        if let Some(img) = self.font_image(c) {
            let width = self.tiles[img].pos.mx().0;
            return width;
        }

        // Not a valid letter.
        (FONT_W / 2) as f32
    }
    */

    /*
    fn save_screenshot(&mut self, basename: &str) {
        use time;
        use std::path::{Path};
        use std::fs::{self, File};
        use image;

        let shot = self.screenshot();

        let timestamp = time::precise_time_s() as u64;
        // Create screenshot filenames by concatenating the current timestamp in
        // seconds with a running number from 00 to 99. 100 shots per second
        // should be good enough.

        // Default if we fail to generate any of the 100 candidates for this
        // second, just overwrite with the "xx" prefix then.
        let mut filename = format!("{}-{}{}.png", basename, timestamp, "xx");

        // Run through candidates for this second.
        for i in 0..100 {
            let test_filename = format!("{}-{}{:02}.png", basename, timestamp, i);
            // If file does not exist.
            if fs::metadata(&test_filename).is_err() {
                // Thread-safe claiming: create_dir will fail if the dir
                // already exists (it'll exist if another thread is gunning
                // for the same filename and managed to get past us here).
                // At least assuming that create_dir is atomic...
                let squat_dir = format!(".tmp-{}{:02}", timestamp, i);
                if fs::create_dir(&squat_dir).is_ok() {
                    File::create(&test_filename).unwrap();
                    filename = test_filename;
                    fs::remove_dir(&squat_dir).unwrap();
                    break;
                } else {
                    continue;
                }
            }
        }

        let _ = image::save_buffer(&Path::new(&filename), &shot, shot.width(), shot.height(), image::ColorType::RGB(8));
    }
    */
}
<|endoftext|>