<commit_before>use num::bigint::{ToBigUint, RandBigInt, BigUint};
use num::{Zero, One};
use num::integer::Integer;
use rand::thread_rng;
use std::sync::{Arc, mpsc};
use std::thread;

/// Cryptographically useful extensions to the provided BigUint functionality.
pub trait BigUintCrypto {
    /// Find the next prime from the current BigUint
    fn next_prime(&self) -> BigUint;

    /// use the extended euclidean algorithm to solve for (g,x,y) given (a,b) such that
    /// g = gcd(a,b) = a*x + b*y.
    fn gcdext(&self, other: &BigUint) -> (BigUint, BigUint, BigUint);

    /// Is this number a prime number. Uses a probablistic function to determine primality.
    fn is_prime(n: &BigUint) -> bool;

    /// perform the function (base^exponent) % modulus using exponentiation by sqauring
    fn mod_exp(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint;
}

impl BigUintCrypto for BigUint {
    fn next_prime(&self) -> BigUint {
        let one: BigUint = One::one();
        let two = 2.to_biguint().unwrap();
        let mut next_prime = self.clone();
        if &next_prime % &two == Zero::zero() {
            next_prime = &next_prime + &one;
        } else {
            next_prime = &next_prime + &two;
        }
        while !BigUint::is_prime(&next_prime) {
            next_prime = &next_prime + &two;
        }
        next_prime
    }

    fn gcdext(&self, other: &BigUint) -> (BigUint, BigUint, BigUint) {

        (Zero::zero(), Zero::zero(), Zero::zero())
    }

    fn is_prime(n: &BigUint) -> bool {
        let two = 2.to_biguint().unwrap();
        let three = 3.to_biguint().unwrap();
        if *n == three || *n == two {
            return true;
        }
        if *n < two || n % two == Zero::zero() {
            return false;
        }
        miller_rabin(n, 100)
    }

    fn mod_exp(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint {
        let zero = Zero::zero();
        let one: BigUint = One::one();
        let two = &one + &one;
        let mut result: BigUint = One::one();
        let mut base_acc = base.clone();
        let mut exp_acc = exponent.clone();
        while exp_acc > zero {
            if (&exp_acc % &two) == one {
                result = (result * &base_acc) % modulus;
            }
            exp_acc = exp_acc >> 1;
            base_acc = (&base_acc * &base_acc) % modulus;
        }
        result
    }
}

/// n must be greater than 3 and k indicates the number of rounds
fn miller_rabin(n: &BigUint, k: usize) -> bool{
    let one: BigUint = One::one();
    let (tx, rx) = mpsc::channel();

    let mut d: BigUint = n - &One::one();
    let mut s: BigUint = Zero::zero();
    while d.is_even() {
        d = d >> 1;
        s = s + &one;
    }
    let shared_n = Arc::new(n.clone());
    let shared_d = Arc::new(d);
    let shared_s = Arc::new(s);

    // miller rabin lends itself to being concurrent since a is completely random
    // here we spawn multiple threads to help speed up the process
    for _ in 0..8 {
        let tx = tx.clone();
        //let thread_n = n.clone();
        let shared_d = shared_d.clone();
        let shared_s = shared_s.clone();
        let shared_n = shared_n.clone();
        thread::spawn(move || {
            let result = miller_rabin_thread(&shared_n, &shared_d, &shared_s, k/8);
            tx.send(result);
            });
    }

    for _ in 0..8 {
        if !rx.recv().ok().expect("A thread failed") {
            return false;
        }
    }
    true
}

fn miller_rabin_thread(n: &BigUint, d: &BigUint, s: &BigUint, k: usize) -> bool {
    let one: BigUint = One::one();
    let two: BigUint = &one + &one;

    for _ in 0..k {
        //println!("loop {} of {}", j, k);
        let a = thread_rng().gen_biguint_range(&two, &(n - &two));
        let mut x = mod_exp(&a, d, n);
        //let mut x = two.clone();
        if (x == one) || (x == (n - &one)) {
            continue;
        }

        // Use a while loop instead of for here because range does not accept BigUint
        let mut i: BigUint = Zero::zero();
        loop  {
            x = mod_exp(&x, &two, n);
            if x == one || i == (s - &one) {
                return false;
            }
            if x == (n - &one) {
                break;
            }
            i = i + &one;
        }
    }
    true
}

fn mod_exp(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint {
    let zero = Zero::zero();
    let one: BigUint = One::one();
    let two = &one + &one;
    let mut result: BigUint = One::one();
    let mut base_acc = base.clone();
    let mut exp_acc = exponent.clone();
    while exp_acc > zero {
        if (&exp_acc % &two) == one {
            result = (result * &base_acc) % modulus;
        }
        exp_acc = exp_acc >> 1;
        base_acc = (&base_acc * &base_acc) % modulus;
    }
    result
}

#[cfg(test)]
mod test_BigUint_crypto {
    use super::{BigUintCrypto, mod_exp};
    use num::bigint::{RandBigInt, BigUint};
    use std::num::FromPrimitive;
    use num::One;
    use rand::thread_rng;

    #[test]
    fn next_prime_test() {
        let test_num = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875258".as_bytes(), 10).unwrap();

        let expected_next = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();

        assert!(test_num.next_prime() == expected_next);
    }

    #[test]
    fn mod_exp_test() {
        let base = BigUint::from_isize(4).unwrap();
        let exponent = BigUint::from_isize(13).unwrap();
        let modulus = BigUint::from_isize(497).unwrap();
        let expected_result = BigUint::from_isize(445).unwrap();

        assert!(mod_exp(&base, &exponent, &modulus) == expected_result);
    }

    #[test]
    fn is_prime_test() {
        let known_prime = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();

        assert!(BigUint::is_prime(&known_prime));
    }

    #[test]
    #[should_fail]
    fn is_prime_test_failuire() {
        let not_prime = BigUint::
        parse_bytes("359709793871987301975987296195681798740165298740176567105918720469720137416098423"
        .as_bytes(), 10).unwrap();

        assert!(BigUint::is_prime(&not_prime));
    }

}
<commit_msg>Add non-threaded option.<commit_after>use num::bigint::{ToBigUint, RandBigInt, BigUint};
use num::{Zero, One};
use num::integer::Integer;
use rand::thread_rng;
use std::sync::{Arc, mpsc};
use std::thread;

/// Cryptographically useful extensions to the provided BigUint functionality.
pub trait BigUintCrypto {
    /// Find the next prime from the current BigUint
    fn next_prime(&self) -> BigUint;

    fn next_prime_threaded(&self) -> BigUint;
    /// use the extended euclidean algorithm to solve for (g,x,y) given (a,b) such that
    /// g = gcd(a,b) = a*x + b*y.
    fn gcdext(&self, other: &BigUint) -> (BigUint, BigUint, BigUint);

    /// Is this number a prime number. Uses a probablistic function to determine primality.
    fn is_prime(n: &BigUint) -> bool;

    /// perform the function (base^exponent) % modulus using exponentiation by sqauring
    fn mod_exp(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint;
}

impl BigUintCrypto for BigUint {
    fn next_prime(&self) -> BigUint {
        next_prime_helper(&self.clone(), false)
    }

    fn next_prime_threaded(&self) -> BigUint {
        next_prime_helper(&self.clone(), true)
    }

    fn gcdext(&self, other: &BigUint) -> (BigUint, BigUint, BigUint) {

        (Zero::zero(), Zero::zero(), Zero::zero())
    }

    fn is_prime(n: &BigUint) -> bool {
        is_prime_helper(n, false)
    }

    fn mod_exp(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint {
        let zero = Zero::zero();
        let one: BigUint = One::one();
        let two = &one + &one;
        let mut result: BigUint = One::one();
        let mut base_acc = base.clone();
        let mut exp_acc = exponent.clone();
        while exp_acc > zero {
            if (&exp_acc % &two) == one {
                result = (result * &base_acc) % modulus;
            }
            exp_acc = exp_acc >> 1;
            base_acc = (&base_acc * &base_acc) % modulus;
        }
        result
    }
}

fn next_prime_helper(n: &BigUint, thread: bool) -> BigUint {
    let one: BigUint = One::one();
    let two = 2.to_biguint().unwrap();
    let mut next_prime = n.clone();
    if &next_prime % &two == Zero::zero() {
        next_prime = &next_prime + &one;
    } else {
        next_prime = &next_prime + &two;
    }
    while !is_prime_helper(&next_prime, thread) {
        next_prime = &next_prime + &two;
    }
    next_prime
}

fn is_prime_helper(n: &BigUint, thread: bool) -> bool {
    let two = 2.to_biguint().unwrap();
    let three = 3.to_biguint().unwrap();
    if *n == three || *n == two {
        return true;
    }
    if *n < two || n % two == Zero::zero() {
        return false;
    }
    miller_rabin(n, 100, thread)
}
/// n must be greater than 3 and k indicates the number of rounds
fn miller_rabin(n: &BigUint, k: usize, thread: bool) -> bool{
    let one: BigUint = One::one();
    let (tx, rx) = mpsc::channel();

    let mut d: BigUint = n - &One::one();
    let mut s: BigUint = Zero::zero();
    while d.is_even() {
        d = d >> 1;
        s = s + &one;
    }
    if thread {
        let shared_n = Arc::new(n.clone());
        let shared_d = Arc::new(d);
        let shared_s = Arc::new(s);

        // miller rabin lends itself to being concurrent since a is completely random
        // here we spawn multiple threads to help speed up the process
        for _ in 0..8 {
            let tx = tx.clone();
            //let thread_n = n.clone();
            let shared_d = shared_d.clone();
            let shared_s = shared_s.clone();
            let shared_n = shared_n.clone();
            thread::spawn(move || {
                let result = miller_rabin_thread(&shared_n, &shared_d, &shared_s, k/8);
                tx.send(result);
                });
        }

        for _ in 0..8 {
            if !rx.recv().ok().expect("A thread failed") {
                return false;
            }
        }
    } else {
        return miller_rabin_thread(n, &d, &s, k);
    }
    true
}

fn miller_rabin_thread(n: &BigUint, d: &BigUint, s: &BigUint, k: usize) -> bool {
    let one: BigUint = One::one();
    let two: BigUint = &one + &one;

    for _ in 0..k {
        //println!("loop {} of {}", j, k);
        let a = thread_rng().gen_biguint_range(&two, &(n - &two));
        let mut x = mod_exp(&a, d, n);
        //let mut x = two.clone();
        if (x == one) || (x == (n - &one)) {
            continue;
        }

        // Use a while loop instead of for here because range does not accept BigUint
        let mut i: BigUint = Zero::zero();
        loop  {
            x = mod_exp(&x, &two, n);
            if x == one || i == (s - &one) {
                return false;
            }
            if x == (n - &one) {
                break;
            }
            i = i + &one;
        }
    }
    true
}

fn mod_exp(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint {
    let zero = Zero::zero();
    let one: BigUint = One::one();
    let two = &one + &one;
    let mut result: BigUint = One::one();
    let mut base_acc = base.clone();
    let mut exp_acc = exponent.clone();
    while exp_acc > zero {
        if (&exp_acc % &two) == one {
            result = (result * &base_acc) % modulus;
        }
        exp_acc = exp_acc >> 1;
        base_acc = (&base_acc * &base_acc) % modulus;
    }
    result
}

#[cfg(test)]
mod test_BigUint_crypto {
    use super::{BigUintCrypto, mod_exp};
    use num::bigint::{RandBigInt, BigUint};
    use std::num::FromPrimitive;
    use num::One;
    use rand::thread_rng;

    #[test]
    fn next_prime_test() {
        let test_num = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875258".as_bytes(), 10).unwrap();

        let expected_next = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();

        assert!(test_num.next_prime() == expected_next);
    }

    #[test]
    fn next_prime_threaded_test() {
        let test_num = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875258".as_bytes(), 10).unwrap();

        let expected_next = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();

        assert!(test_num.next_prime_threaded() == expected_next);
    }

    #[test]
    fn mod_exp_test() {
        let base = BigUint::from_isize(4).unwrap();
        let exponent = BigUint::from_isize(13).unwrap();
        let modulus = BigUint::from_isize(497).unwrap();
        let expected_result = BigUint::from_isize(445).unwrap();

        assert!(mod_exp(&base, &exponent, &modulus) == expected_result);
    }

    #[test]
    fn is_prime_test() {
        let known_prime = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();

        assert!(BigUint::is_prime(&known_prime));
    }

    #[test]
    #[should_fail]
    fn is_prime_test_failuire() {
        let not_prime = BigUint::
        parse_bytes("359709793871987301975987296195681798740165298740176567105918720469720137416098423"
        .as_bytes(), 10).unwrap();

        assert!(BigUint::is_prime(&not_prime));
    }

}
<|endoftext|>


<commit_before>//! The `TextCell` type for the details and lines views.

use std::ops::{Deref, DerefMut};

use ansi_term::{Style, ANSIString, ANSIStrings};
use unicode_width::UnicodeWidthStr;

/// An individual cell that holds text in a table, used in the details and
/// lines views to store ANSI-terminal-formatted data before it is printed.
///
/// A text cell is made up of zero or more strings coupled with the
/// pre-computed length of all the strings combined. When constructing details
/// or grid-details tables, the length will have to be queried multiple times,
/// so it makes sense to cache it.
///
/// (This used to be called `Cell`, but was renamed because there’s a Rust
/// type by that name too.)
#[derive(PartialEq, Debug, Clone, Default)]
pub struct TextCell {

    /// The contents of this cell, as a vector of ANSI-styled strings.
    pub contents: TextCellContents,

    /// The Unicode “display width” of this cell.
    pub width: DisplayWidth,
}

impl Deref for TextCell {
    type Target = TextCellContents;

    fn deref<'a>(&'a self) -> &'a Self::Target {
        &self.contents
    }
}

impl TextCell {

    /// Creates a new text cell that holds the given text in the given style,
    /// computing the Unicode width of the text.
    pub fn paint(style: Style, text: String) -> Self {
        let width = DisplayWidth::from(&*text);

        TextCell {
            contents: vec![ style.paint(text) ].into(),
            width:    width,
        }
    }

    /// Creates a new text cell that holds the given text in the given style,
    /// computing the Unicode width of the text. (This could be merged with
    /// `paint`, but.)
    pub fn paint_str(style: Style, text: &'static str) -> Self {
        let width = DisplayWidth::from(text);

        TextCell {
            contents: vec![ style.paint(text) ].into(),
            width:    width,
        }
    }

    /// Creates a new “blank” text cell that contains a single hyphen in the
    /// given style, which should be the “punctuation” style from a `Colours`
    /// value.
    ///
    /// This is used in place of empty table cells, as it is easier to read
    /// tabular data when there is *something* in each cell.
    pub fn blank(style: Style) -> Self {
        TextCell {
            contents: vec![ style.paint("-") ].into(),
            width:    DisplayWidth::from(1),
        }
    }

    /// Adds the given number of unstyled spaces after this cell.
    ///
    /// This method allocates a `String` to hold the spaces.
    pub fn add_spaces(&mut self, count: usize) {
        use std::iter::repeat;

        (*self.width) += count;

        let spaces: String = repeat(' ').take(count).collect();
        self.contents.0.push(Style::default().paint(spaces));
    }

    /// Adds the contents of another `ANSIString` to the end of this cell.
    pub fn push(&mut self, string: ANSIString<'static>, extra_width: usize) {
        self.contents.0.push(string);
        (*self.width) += extra_width;
    }

    /// Adds all the contents of another `TextCell` to the end of this cell.
    pub fn append(&mut self, other: TextCell) {
        (*self.width) += *other.width;
        self.contents.0.extend(other.contents.0);
    }
}

// I’d like to eventually abstract cells so that instead of *every* cell
// storing a vector, only variable-length cells would, and individual cells
// would just store an array of a fixed length (which would usually be just 1
// or 2), which wouldn’t require a heap allocation.
//
// For examples, look at the `render_*` methods in the `Table` object in the
// details view:
//
// - `render_blocks`, `inode`, and `links` will always return a
//   one-string-long TextCell;
// - `render_size` will return one or two strings in a TextCell, depending on
//   the size and whether one is present;
// - `render_permissions` will return ten or eleven strings;
// - `filename` and `symlink_filename` in the output module root return six or
//   five strings.
//
// In none of these cases are we dealing with a *truly variable* number of
// strings: it is only when the strings are concatenated together do we need a
// growable, heap-allocated buffer.
//
// So it would be nice to abstract the `TextCell` type so instead of a `Vec`,
// it can use anything of type `T: IntoIterator<Item=ANSIString<’static>>`.
// This would allow us to still hold all the data, but allocate less.
//
// But exa still has bugs and I need to fix those first :(

/// The contents of a text cell, as a vector of ANSI-styled strings.
///
/// It’s possible to use this type directly in the case where you want a
/// `TextCell` but aren’t concerned with tracking its width, because it occurs
/// in the final cell of a table or grid and there’s no point padding it. This
/// happens when dealing with file names.
#[derive(PartialEq, Debug, Clone, Default)]
pub struct TextCellContents(Vec<ANSIString<'static>>);

impl From<Vec<ANSIString<'static>>> for TextCellContents {
    fn from(strings: Vec<ANSIString<'static>>) -> TextCellContents {
        TextCellContents(strings)
    }
}

impl Deref for TextCellContents {
    type Target = [ANSIString<'static>];

    fn deref<'a>(&'a self) -> &'a Self::Target {
        &*self.0
    }
}

// No DerefMut implementation here -- it would be publicly accessible, and as
// the contents only get changed in this module, the mutators in the struct
// above can just access the value directly.

impl TextCellContents {

    /// Produces an `ANSIStrings` value that can be used to print the styled
    /// values of this cell as an ANSI-terminal-formatted string.
    pub fn strings(&self) -> ANSIStrings {
        ANSIStrings(&self.0)
    }
}

/// The Unicode “display width” of a string.
///
/// This is related to the number of *graphemes* of a string, rather than the
/// number of *characters*, or *bytes*: although most characters are one
/// column wide, a few can be two columns wide, and this is important to note
/// when calculating widths for displaying tables in a terminal.
///
/// This type is used to ensure that the width, rather than the length, is
/// used when constructing a `TextCell` -- it's too easy to write something
/// like `file_name.len()` and assume it will work!
///
/// It has `From` impls that convert an input string or fixed with to values
/// of this type, and will `Deref` to the contained `usize` value.
#[derive(PartialEq, Debug, Clone, Copy, Default)]
pub struct DisplayWidth(usize);

impl<'a> From<&'a str> for DisplayWidth {
    fn from(input: &'a str) -> DisplayWidth {
        DisplayWidth(UnicodeWidthStr::width(input))
    }
}

impl From<usize> for DisplayWidth {
    fn from(width: usize) -> DisplayWidth {
        DisplayWidth(width)
    }
}

impl Deref for DisplayWidth {
    type Target = usize;

    fn deref<'a>(&'a self) -> &'a Self::Target {
        &self.0
    }
}

impl DerefMut for DisplayWidth {
    fn deref_mut<'a>(&'a mut self) -> &'a mut Self::Target {
        &mut self.0
    }
}<commit_msg>Add Add impl and various tests for DisplayWidth<commit_after>//! The `TextCell` type for the details and lines views.

use std::ops::{Add, Deref, DerefMut};

use ansi_term::{Style, ANSIString, ANSIStrings};
use unicode_width::UnicodeWidthStr;

/// An individual cell that holds text in a table, used in the details and
/// lines views to store ANSI-terminal-formatted data before it is printed.
///
/// A text cell is made up of zero or more strings coupled with the
/// pre-computed length of all the strings combined. When constructing details
/// or grid-details tables, the length will have to be queried multiple times,
/// so it makes sense to cache it.
///
/// (This used to be called `Cell`, but was renamed because there’s a Rust
/// type by that name too.)
#[derive(PartialEq, Debug, Clone, Default)]
pub struct TextCell {

    /// The contents of this cell, as a vector of ANSI-styled strings.
    pub contents: TextCellContents,

    /// The Unicode “display width” of this cell.
    pub width: DisplayWidth,
}

impl Deref for TextCell {
    type Target = TextCellContents;

    fn deref<'a>(&'a self) -> &'a Self::Target {
        &self.contents
    }
}

impl TextCell {

    /// Creates a new text cell that holds the given text in the given style,
    /// computing the Unicode width of the text.
    pub fn paint(style: Style, text: String) -> Self {
        let width = DisplayWidth::from(&*text);

        TextCell {
            contents: vec![ style.paint(text) ].into(),
            width:    width,
        }
    }

    /// Creates a new text cell that holds the given text in the given style,
    /// computing the Unicode width of the text. (This could be merged with
    /// `paint`, but.)
    pub fn paint_str(style: Style, text: &'static str) -> Self {
        let width = DisplayWidth::from(text);

        TextCell {
            contents: vec![ style.paint(text) ].into(),
            width:    width,
        }
    }

    /// Creates a new “blank” text cell that contains a single hyphen in the
    /// given style, which should be the “punctuation” style from a `Colours`
    /// value.
    ///
    /// This is used in place of empty table cells, as it is easier to read
    /// tabular data when there is *something* in each cell.
    pub fn blank(style: Style) -> Self {
        TextCell {
            contents: vec![ style.paint("-") ].into(),
            width:    DisplayWidth::from(1),
        }
    }

    /// Adds the given number of unstyled spaces after this cell.
    ///
    /// This method allocates a `String` to hold the spaces.
    pub fn add_spaces(&mut self, count: usize) {
        use std::iter::repeat;

        (*self.width) += count;

        let spaces: String = repeat(' ').take(count).collect();
        self.contents.0.push(Style::default().paint(spaces));
    }

    /// Adds the contents of another `ANSIString` to the end of this cell.
    pub fn push(&mut self, string: ANSIString<'static>, extra_width: usize) {
        self.contents.0.push(string);
        (*self.width) += extra_width;
    }

    /// Adds all the contents of another `TextCell` to the end of this cell.
    pub fn append(&mut self, other: TextCell) {
        (*self.width) += *other.width;
        self.contents.0.extend(other.contents.0);
    }
}

// I’d like to eventually abstract cells so that instead of *every* cell
// storing a vector, only variable-length cells would, and individual cells
// would just store an array of a fixed length (which would usually be just 1
// or 2), which wouldn’t require a heap allocation.
//
// For examples, look at the `render_*` methods in the `Table` object in the
// details view:
//
// - `render_blocks`, `inode`, and `links` will always return a
//   one-string-long TextCell;
// - `render_size` will return one or two strings in a TextCell, depending on
//   the size and whether one is present;
// - `render_permissions` will return ten or eleven strings;
// - `filename` and `symlink_filename` in the output module root return six or
//   five strings.
//
// In none of these cases are we dealing with a *truly variable* number of
// strings: it is only when the strings are concatenated together do we need a
// growable, heap-allocated buffer.
//
// So it would be nice to abstract the `TextCell` type so instead of a `Vec`,
// it can use anything of type `T: IntoIterator<Item=ANSIString<’static>>`.
// This would allow us to still hold all the data, but allocate less.
//
// But exa still has bugs and I need to fix those first :(

/// The contents of a text cell, as a vector of ANSI-styled strings.
///
/// It’s possible to use this type directly in the case where you want a
/// `TextCell` but aren’t concerned with tracking its width, because it occurs
/// in the final cell of a table or grid and there’s no point padding it. This
/// happens when dealing with file names.
#[derive(PartialEq, Debug, Clone, Default)]
pub struct TextCellContents(Vec<ANSIString<'static>>);

impl From<Vec<ANSIString<'static>>> for TextCellContents {
    fn from(strings: Vec<ANSIString<'static>>) -> TextCellContents {
        TextCellContents(strings)
    }
}

impl Deref for TextCellContents {
    type Target = [ANSIString<'static>];

    fn deref<'a>(&'a self) -> &'a Self::Target {
        &*self.0
    }
}

// No DerefMut implementation here -- it would be publicly accessible, and as
// the contents only get changed in this module, the mutators in the struct
// above can just access the value directly.

impl TextCellContents {

    /// Produces an `ANSIStrings` value that can be used to print the styled
    /// values of this cell as an ANSI-terminal-formatted string.
    pub fn strings(&self) -> ANSIStrings {
        ANSIStrings(&self.0)
    }
}

/// The Unicode “display width” of a string.
///
/// This is related to the number of *graphemes* of a string, rather than the
/// number of *characters*, or *bytes*: although most characters are one
/// column wide, a few can be two columns wide, and this is important to note
/// when calculating widths for displaying tables in a terminal.
///
/// This type is used to ensure that the width, rather than the length, is
/// used when constructing a `TextCell` -- it's too easy to write something
/// like `file_name.len()` and assume it will work!
///
/// It has `From` impls that convert an input string or fixed with to values
/// of this type, and will `Deref` to the contained `usize` value.
#[derive(PartialEq, Debug, Clone, Copy, Default)]
pub struct DisplayWidth(usize);

impl<'a> From<&'a str> for DisplayWidth {
    fn from(input: &'a str) -> DisplayWidth {
        DisplayWidth(UnicodeWidthStr::width(input))
    }
}

impl From<usize> for DisplayWidth {
    fn from(width: usize) -> DisplayWidth {
        DisplayWidth(width)
    }
}

impl Deref for DisplayWidth {
    type Target = usize;

    fn deref<'a>(&'a self) -> &'a Self::Target {
        &self.0
    }
}

impl DerefMut for DisplayWidth {
    fn deref_mut<'a>(&'a mut self) -> &'a mut Self::Target {
        &mut self.0
    }
}

impl Add for DisplayWidth {
    type Output = DisplayWidth;

    fn add(self, rhs: DisplayWidth) -> Self::Output {
        DisplayWidth(self.0 + rhs.0)
    }
}

impl Add<usize> for DisplayWidth {
    type Output = DisplayWidth;

    fn add(self, rhs: usize) -> Self::Output {
        DisplayWidth(self.0 + rhs)
    }
}

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

    #[test]
    fn empty_string() {
        let cell = DisplayWidth::from("");
        assert_eq!(*cell, 0);
    }

    #[test]
    fn test_string() {
        let cell = DisplayWidth::from("Diss Playwidth");
        assert_eq!(*cell, 14);
    }

    #[test]
    fn addition() {
        let cell_one = DisplayWidth::from("/usr/bin/");
        let cell_two = DisplayWidth::from("drinking");
        assert_eq!(*(cell_one + cell_two), 17);
    }

    #[test]
    fn addition_usize() {
        let cell = DisplayWidth::from("/usr/bin/");
        assert_eq!(*(cell + 8), 17);
    }
}
<|endoftext|>


<commit_before>/// External linking is a complex implementation to be able to serve a clean and easy-to-use
/// interface.
///
/// Internally, there are no such things as "external links" (plural). Each Entry in the store can
/// only have _one_ external link.
///
/// This library does the following therefor: It allows you to have several external links with one
/// entry, which are internally one file in the store for each link, linked with "internal
/// linking".
///
/// This helps us greatly with deduplication of URLs.
///

use std::ops::DerefMut;
use std::collections::BTreeMap;

use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;
use libimagutil::debug_result::*;

use error::LinkError as LE;
use error::LinkErrorKind as LEK;
use error::MapErrInto;
use result::Result;
use internal::InternalLinker;
use module_path::ModuleEntryPath;

use toml::Value;
use url::Url;
use crypto::sha1::Sha1;
use crypto::digest::Digest;

/// "Link" Type, just an abstraction over `FileLockEntry` to have some convenience internally.
pub struct Link<'a> {
    link: FileLockEntry<'a>
}

impl<'a> Link<'a> {

    pub fn new(fle: FileLockEntry<'a>) -> Link<'a> {
        Link { link: fle }
    }

    /// Get a link Url object from a `FileLockEntry`, ignore errors.
    fn get_link_uri_from_filelockentry(file: &FileLockEntry<'a>) -> Option<Url> {
        file.get_header()
            .read("imag.content.url")
            .ok()
            .and_then(|opt| match opt {
                Some(Value::String(s)) => Url::parse(&s[..]).ok(),
                _ => None
            })
    }

    pub fn get_url(&self) -> Result<Option<Url>> {
        let opt = self.link
            .get_header()
            .read("imag.content.url");

        match opt {
            Ok(Some(Value::String(s))) => {
                Url::parse(&s[..])
                     .map(Some)
                     .map_err(|e| LE::new(LEK::EntryHeaderReadError, Some(Box::new(e))))
            },
            Ok(None) => Ok(None),
            _ => Err(LE::new(LEK::EntryHeaderReadError, None))
        }
    }

}

pub trait ExternalLinker : InternalLinker {

    /// Get the external links from the implementor object
    fn get_external_links(&self, store: &Store) -> Result<Vec<Url>>;

    /// Set the external links for the implementor object
    fn set_external_links(&mut self, store: &Store, links: Vec<Url>) -> Result<()>;

    /// Add an external link to the implementor object
    fn add_external_link(&mut self, store: &Store, link: Url) -> Result<()>;

    /// Remove an external link from the implementor object
    fn remove_external_link(&mut self, store: &Store, link: Url) -> Result<()>;

}

/// Check whether the StoreId starts with `/link/external/`
pub fn is_external_link_storeid(id: &StoreId) -> bool {
    debug!("Checking whether this is a link/external/*: '{:?}'", id);
    id.local().starts_with("link/external")
}

fn get_external_link_from_file(entry: &FileLockEntry) -> Result<Url> {
    Link::get_link_uri_from_filelockentry(entry) // TODO: Do not hide error by using this function
        .ok_or(LE::new(LEK::StoreReadError, None))
}

/// Implement `ExternalLinker` for `Entry`, hiding the fact that there is no such thing as an external
/// link in an entry, but internal links to other entries which serve as external links, as one
/// entry in the store can only have one external link.
impl ExternalLinker for Entry {

    /// Get the external links from the implementor object
    fn get_external_links(&self, store: &Store) -> Result<Vec<Url>> {
        // Iterate through all internal links and filter for FileLockEntries which live in
        // /link/external/<SHA> -> load these files and get the external link from their headers,
        // put them into the return vector.
        self.get_internal_links()
            .map(|vect| {
                debug!("Getting external links");
                vect.into_iter()
                    .filter(is_external_link_storeid)
                    .map(|id| {
                        debug!("Retrieving entry for id: '{:?}'", id);
                        match store.retrieve(id.clone()) {
                            Ok(f) => get_external_link_from_file(&f),
                            Err(e) => {
                                debug!("Retrieving entry for id: '{:?}' failed", id);
                                Err(LE::new(LEK::StoreReadError, Some(Box::new(e))))
                            }
                        }
                    })
                    .filter_map(|x| x.ok()) // TODO: Do not ignore error here
                    .collect()
            })
            .map_err(|e| LE::new(LEK::StoreReadError, Some(Box::new(e))))
    }

    /// Set the external links for the implementor object
    fn set_external_links(&mut self, store: &Store, links: Vec<Url>) -> Result<()> {
        // Take all the links, generate a SHA sum out of each one, filter out the already existing
        // store entries and store the other URIs in the header of one FileLockEntry each, in
        // the path /link/external/<SHA of the URL>

        debug!("Iterating {} links = {:?}", links.len(), links);
        for link in links { // for all links
            let hash = {
                let mut s = Sha1::new();
                s.input_str(&link.as_str()[..]);
                s.result_str()
            };
            let file_id = try!(
                ModuleEntryPath::new(format!("external/{}", hash)).into_storeid()
                    .map_err_into(LEK::StoreWriteError)
                    .map_dbg_err(|_| {
                        format!("Failed to build StoreId for this hash '{:?}'", hash)
                    })
                );

            debug!("Link    = '{:?}'", link);
            debug!("Hash    = '{:?}'", hash);
            debug!("StoreId = '{:?}'", file_id);

            // retrieve the file from the store, which implicitely creates the entry if it does not
            // exist
            let mut file = try!(store
                .retrieve(file_id.clone())
                .map_err_into(LEK::StoreWriteError)
                .map_dbg_err(|_| {
                    format!("Failed to create or retrieve an file for this link '{:?}'", link)
                }));

            debug!("Generating header content!");
            {
                let mut hdr = file.deref_mut().get_header_mut();

                let mut table = match hdr.read("imag.content") {
                    Ok(Some(Value::Table(table))) => table,
                    Ok(Some(_)) => {
                        warn!("There is a value at 'imag.content' which is not a table.");
                        warn!("Going to override this value");
                        BTreeMap::new()
                    },
                    Ok(None) => BTreeMap::new(),
                    Err(e)   => return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e)))),
                };

                let v = Value::String(link.into_string());

                debug!("setting URL = '{:?}", v);
                table.insert(String::from("url"), v);

                if let Err(e) = hdr.set("imag.content", Value::Table(table)) {
                    return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e))));
                } else {
                    debug!("Setting URL worked");
                }
            }

            // then add an internal link to the new file or return an error if this fails
            if let Err(e) = self.add_internal_link(file.deref_mut()) {
                debug!("Error adding internal link");
                return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e))));
            }
        }
        debug!("Ready iterating");
        Ok(())
    }

    /// Add an external link to the implementor object
    fn add_external_link(&mut self, store: &Store, link: Url) -> Result<()> {
        // get external links, add this one, save them
        debug!("Getting links");
        self.get_external_links(store)
            .and_then(|mut links| {
                debug!("Adding link = '{:?}' to links = {:?}", link, links);
                links.push(link);
                debug!("Setting {} links = {:?}", links.len(), links);
                self.set_external_links(store, links)
            })
    }

    /// Remove an external link from the implementor object
    fn remove_external_link(&mut self, store: &Store, link: Url) -> Result<()> {
        // get external links, remove this one, save them
        self.get_external_links(store)
            .and_then(|links| {
                debug!("Removing link = '{:?}' from links = {:?}", link, links);
                let links = links.into_iter()
                    .filter(|l| l.as_str() != link.as_str())
                    .collect();
                self.set_external_links(store, links)
            })
    }

}

<commit_msg>Add debug output<commit_after>/// External linking is a complex implementation to be able to serve a clean and easy-to-use
/// interface.
///
/// Internally, there are no such things as "external links" (plural). Each Entry in the store can
/// only have _one_ external link.
///
/// This library does the following therefor: It allows you to have several external links with one
/// entry, which are internally one file in the store for each link, linked with "internal
/// linking".
///
/// This helps us greatly with deduplication of URLs.
///

use std::ops::DerefMut;
use std::collections::BTreeMap;

use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;
use libimagutil::debug_result::*;

use error::LinkError as LE;
use error::LinkErrorKind as LEK;
use error::MapErrInto;
use result::Result;
use internal::InternalLinker;
use module_path::ModuleEntryPath;

use toml::Value;
use url::Url;
use crypto::sha1::Sha1;
use crypto::digest::Digest;

/// "Link" Type, just an abstraction over `FileLockEntry` to have some convenience internally.
pub struct Link<'a> {
    link: FileLockEntry<'a>
}

impl<'a> Link<'a> {

    pub fn new(fle: FileLockEntry<'a>) -> Link<'a> {
        Link { link: fle }
    }

    /// Get a link Url object from a `FileLockEntry`, ignore errors.
    fn get_link_uri_from_filelockentry(file: &FileLockEntry<'a>) -> Option<Url> {
        file.get_header()
            .read("imag.content.url")
            .ok()
            .and_then(|opt| match opt {
                Some(Value::String(s)) => {
                    debug!("Found url, parsing: {:?}", s);
                    Url::parse(&s[..]).ok()
                },
                _ => None
            })
    }

    pub fn get_url(&self) -> Result<Option<Url>> {
        let opt = self.link
            .get_header()
            .read("imag.content.url");

        match opt {
            Ok(Some(Value::String(s))) => {
                Url::parse(&s[..])
                     .map(Some)
                     .map_err(|e| LE::new(LEK::EntryHeaderReadError, Some(Box::new(e))))
            },
            Ok(None) => Ok(None),
            _ => Err(LE::new(LEK::EntryHeaderReadError, None))
        }
    }

}

pub trait ExternalLinker : InternalLinker {

    /// Get the external links from the implementor object
    fn get_external_links(&self, store: &Store) -> Result<Vec<Url>>;

    /// Set the external links for the implementor object
    fn set_external_links(&mut self, store: &Store, links: Vec<Url>) -> Result<()>;

    /// Add an external link to the implementor object
    fn add_external_link(&mut self, store: &Store, link: Url) -> Result<()>;

    /// Remove an external link from the implementor object
    fn remove_external_link(&mut self, store: &Store, link: Url) -> Result<()>;

}

/// Check whether the StoreId starts with `/link/external/`
pub fn is_external_link_storeid(id: &StoreId) -> bool {
    debug!("Checking whether this is a link/external/*: '{:?}'", id);
    id.local().starts_with("link/external")
}

fn get_external_link_from_file(entry: &FileLockEntry) -> Result<Url> {
    Link::get_link_uri_from_filelockentry(entry) // TODO: Do not hide error by using this function
        .ok_or(LE::new(LEK::StoreReadError, None))
}

/// Implement `ExternalLinker` for `Entry`, hiding the fact that there is no such thing as an external
/// link in an entry, but internal links to other entries which serve as external links, as one
/// entry in the store can only have one external link.
impl ExternalLinker for Entry {

    /// Get the external links from the implementor object
    fn get_external_links(&self, store: &Store) -> Result<Vec<Url>> {
        // Iterate through all internal links and filter for FileLockEntries which live in
        // /link/external/<SHA> -> load these files and get the external link from their headers,
        // put them into the return vector.
        self.get_internal_links()
            .map(|vect| {
                debug!("Getting external links");
                vect.into_iter()
                    .filter(is_external_link_storeid)
                    .map(|id| {
                        debug!("Retrieving entry for id: '{:?}'", id);
                        match store.retrieve(id.clone()) {
                            Ok(f) => {
                                debug!("Store::retrieve({:?}) succeeded", id);
                                debug!("getting external link from file now");
                                get_external_link_from_file(&f)
                                    .map_err(|e| { debug!("URL -> Err = {:?}", e); e })
                            },
                            Err(e) => {
                                debug!("Retrieving entry for id: '{:?}' failed", id);
                                Err(LE::new(LEK::StoreReadError, Some(Box::new(e))))
                            }
                        }
                    })
                    .filter_map(|x| x.ok()) // TODO: Do not ignore error here
                    .collect()
            })
            .map_err(|e| LE::new(LEK::StoreReadError, Some(Box::new(e))))
    }

    /// Set the external links for the implementor object
    fn set_external_links(&mut self, store: &Store, links: Vec<Url>) -> Result<()> {
        // Take all the links, generate a SHA sum out of each one, filter out the already existing
        // store entries and store the other URIs in the header of one FileLockEntry each, in
        // the path /link/external/<SHA of the URL>

        debug!("Iterating {} links = {:?}", links.len(), links);
        for link in links { // for all links
            let hash = {
                let mut s = Sha1::new();
                s.input_str(&link.as_str()[..]);
                s.result_str()
            };
            let file_id = try!(
                ModuleEntryPath::new(format!("external/{}", hash)).into_storeid()
                    .map_err_into(LEK::StoreWriteError)
                    .map_dbg_err(|_| {
                        format!("Failed to build StoreId for this hash '{:?}'", hash)
                    })
                );

            debug!("Link    = '{:?}'", link);
            debug!("Hash    = '{:?}'", hash);
            debug!("StoreId = '{:?}'", file_id);

            // retrieve the file from the store, which implicitely creates the entry if it does not
            // exist
            let mut file = try!(store
                .retrieve(file_id.clone())
                .map_err_into(LEK::StoreWriteError)
                .map_dbg_err(|_| {
                    format!("Failed to create or retrieve an file for this link '{:?}'", link)
                }));

            debug!("Generating header content!");
            {
                let mut hdr = file.deref_mut().get_header_mut();

                let mut table = match hdr.read("imag.content") {
                    Ok(Some(Value::Table(table))) => table,
                    Ok(Some(_)) => {
                        warn!("There is a value at 'imag.content' which is not a table.");
                        warn!("Going to override this value");
                        BTreeMap::new()
                    },
                    Ok(None) => BTreeMap::new(),
                    Err(e)   => return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e)))),
                };

                let v = Value::String(link.into_string());

                debug!("setting URL = '{:?}", v);
                table.insert(String::from("url"), v);

                if let Err(e) = hdr.set("imag.content", Value::Table(table)) {
                    return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e))));
                } else {
                    debug!("Setting URL worked");
                }
            }

            // then add an internal link to the new file or return an error if this fails
            if let Err(e) = self.add_internal_link(file.deref_mut()) {
                debug!("Error adding internal link");
                return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e))));
            }
        }
        debug!("Ready iterating");
        Ok(())
    }

    /// Add an external link to the implementor object
    fn add_external_link(&mut self, store: &Store, link: Url) -> Result<()> {
        // get external links, add this one, save them
        debug!("Getting links");
        self.get_external_links(store)
            .and_then(|mut links| {
                debug!("Adding link = '{:?}' to links = {:?}", link, links);
                links.push(link);
                debug!("Setting {} links = {:?}", links.len(), links);
                self.set_external_links(store, links)
            })
    }

    /// Remove an external link from the implementor object
    fn remove_external_link(&mut self, store: &Store, link: Url) -> Result<()> {
        // get external links, remove this one, save them
        self.get_external_links(store)
            .and_then(|links| {
                debug!("Removing link = '{:?}' from links = {:?}", link, links);
                let links = links.into_iter()
                    .filter(|l| l.as_str() != link.as_str())
                    .collect();
                self.set_external_links(store, links)
            })
    }

}

<|endoftext|>


<commit_before>#![feature(globs, phase)]

extern crate collections;
#[phase(plugin, link)] extern crate log;
extern crate graphics;
extern crate piston;

use graphics::*;
use piston::{Game, GameIteratorSettings, GameWindowSDL2, GameWindowSettings, KeyReleaseArgs, MouseMoveArgs, MouseReleaseArgs, RenderArgs};

pub static WINDOW_HEIGHT: uint = 480;
pub static WINDOW_WIDTH: uint = 640;

pub static BLOCK_SIZE: uint = 10;  // NOTE: WINDOW_HEIGHT and WINDOW_WIDTH should be divisible by this

pub enum Neighbor {
	Block(Block),
	Location(Location)
}

pub struct Grid {
	grid: Vec<Vec<Option<Block>>>,
	blocks: Vec<Block>
}

#[deriving(Clone, PartialEq)]
pub struct Block {
	pub loc: Location
}

#[deriving(Clone, PartialEq)]
pub struct Location {
	pub x: uint,
	pub y: uint
}

pub struct App {
	gl: Gl,
	grid: Grid,
	started: bool,
	count: uint,
	mouse_loc: (f64, f64)
}

impl Grid {
	pub fn new() -> Grid {
		let mut rows: Vec<Vec<Option<Block>>> = vec!();
		rows.reserve(WINDOW_HEIGHT / BLOCK_SIZE);
		for _ in range(0, WINDOW_HEIGHT / BLOCK_SIZE) {
			rows.push(Vec::from_elem(WINDOW_WIDTH / BLOCK_SIZE, None));
		}
		Grid {
			grid: rows,
			blocks: vec!()
		}
	}

	pub fn insert(&mut self, block: Block) {
		let (x, y) = (block.loc.x, block.loc.y);
		if !self.valid(x, y) {
			return;
		}
		let gr_loc = self.grid.get_mut(y).get_mut(x);
		if *gr_loc == None {
			*gr_loc = Some(block);
			self.blocks.push(gr_loc.unwrap());
		} else if gr_loc.unwrap() != block {
			let idx = {
				let old = gr_loc.get_ref();
				let mut i = 0;
				let len = self.blocks.len();
				while i < len {
					if old == self.blocks.get(i) {
						break;
					}
					i += 1;
				}
				i
			};
			*gr_loc = Some(block);
			*self.blocks.get_mut(idx) = gr_loc.unwrap();
		}
	}

	pub fn remove(&mut self, block: &Block) {
		if self.valid(block.loc.x, block.loc.y) {
			let mut i = 0;
			while i < self.blocks.len() {
				if self.blocks.get(i) == block {
					self.blocks.remove(i);
					break;
				}
				i += 1;
			}
			let gr_loc = self.grid.get_mut(block.loc.y).get_mut(block.loc.x);
			*gr_loc = None;
		}
	}

	pub fn neighbors(&self, block: &Block) -> Vec<Neighbor> {
		let mut vec = vec!();
		if self.valid(block.loc.x, block.loc.y) {
			for i in range(if block.loc.x > 0 { -1 } else { 0 }, if block.loc.x < self.grid.len() - 1 { 2 } else { 1 }) {
				if block.loc.y > 0 {
					let row = self.grid.get(block.loc.y - 1);
					let xpos = (i + block.loc.x as int) as uint;
					vec.push(match *row.get(xpos) {
						Some(blk) => Block(blk),
						None => Location(Location::new(xpos, block.loc.y - 1))
					});
				}
				if block.loc.y < self.grid.len() - 1 {
					let row = self.grid.get(block.loc.y + 1);
					let xpos = (i + block.loc.x as int) as uint;
					vec.push(match *row.get(xpos) {
						Some(blk) => Block(blk),
						None => Location(Location::new(xpos, block.loc.y + 1))
					});
				}
			}
			let row = self.grid.get(block.loc.y);
			if block.loc.x > 0 {
				vec.push(match *row.get(block.loc.x - 1) {
					Some(blk) => Block(blk),
					None => Location(Location::new(block.loc.x - 1, block.loc.y))
				});
			}
			if block.loc.x < self.grid.get(0).len() - 1 {
				vec.push(match *row.get(block.loc.x + 1) {
					Some(blk) => Block(blk),
					None => Location(Location::new(block.loc.x + 1, block.loc.y))
				});
			}
		}
		vec
	}

	#[inline]
	pub fn live_neighbors(&self, block: &Block) -> Vec<Block> {
		let mut live = vec!();
		for neighbor in self.neighbors(block).move_iter() {
			match neighbor {
				Block(blk) => live.push(blk),
				_ => {}
			}
		}
		live
	}

	#[inline]
	pub fn dead_neighbors(&self, block: &Block) -> Vec<Location> {
		let mut dead = vec!();
		for neighbor in self.neighbors(block).move_iter() {
			match neighbor {
				Location(loc) => dead.push(loc),
				_ => {}
			}
		}
		dead
	}

	pub fn contains(&self, block: &Block) -> bool {
		if self.valid(block.loc.x, block.loc.y) {
			self.grid.get(block.loc.y).get(block.loc.x).is_some()
		} else {
			false
		}
	}

	#[inline]
	fn valid(&self, x: uint, y: uint) -> bool {
		y < self.grid.len() && x < self.grid.get(0).len()
	}

	#[inline]
	pub fn render(&self, gl: &mut Gl, win_ctx: &Context) {
		for block in self.blocks.iter() {
			block.render(gl, win_ctx);
		}
	}
}

impl Block {
	#[inline]
	pub fn new(loc: Location) -> Block {
		Block {
			loc: loc
		}
	}

	#[inline]
	pub fn render(&self, gl: &mut Gl, win_ctx: &Context) {
		win_ctx
		       .rect((self.loc.x * BLOCK_SIZE) as f64, (self.loc.y * BLOCK_SIZE) as f64, BLOCK_SIZE as f64, BLOCK_SIZE as f64)
		       .rgb(0.0, 0.0, 0.0).fill(gl);
	}
}

impl Location {
	#[inline]
	pub fn new(x: uint, y: uint) -> Location {
		assert!(x <= WINDOW_WIDTH / BLOCK_SIZE);
		assert!(y <= WINDOW_HEIGHT / BLOCK_SIZE);
		Location {
			x: x,
			y: y
		}
	}
}

impl App {
	#[inline]
	pub fn new() -> App {
		App {
			gl: Gl::new(),
			grid: Grid::new(),
			started: false,
			count: 30,
			mouse_loc: (0.0, 0.0)
		}
	}

	#[cfg(random)]
	#[inline]
	fn render_logic(&mut self) {
		use std::rand::random;

		let mut x = (random::<f64>() * WINDOW_WIDTH as f64) as uint;
		x = (x - x % BLOCK_SIZE) / BLOCK_SIZE;
		let mut y = (random::<f64>() * WINDOW_HEIGHT as f64) as uint;
		y = (y - y % BLOCK_SIZE) / BLOCK_SIZE;
		self.grid.insert(Block::new(Location::new(x, y)));
	}

	#[cfg(not(random))]
	#[inline]
	fn render_logic(&mut self) {
		let mut remove = vec!();
		let mut add = vec!();
		for block in self.grid.blocks.iter() {
			let live = self.grid.live_neighbors(block);
			let livelen = live.len();
			if livelen != 2 && livelen != 3 {
				remove.push(block.clone());
			}
			for &loc in self.grid.dead_neighbors(block).iter() {
				let block = Block::new(loc);
				if self.grid.live_neighbors(&block).len() == 3 {
					add.push(block);
				}
			}
		}
		for block in remove.iter() {
			self.grid.remove(block);
		}
		for block in add.move_iter() {
			self.grid.insert(block);
		}
	}
}

impl Game for App {
	fn key_release(&mut self, args: &KeyReleaseArgs) {
		if !self.started && args.key == piston::keyboard::Return {
			self.started = true;
		} else {
			match args.key {
				piston::keyboard::R => {
					self.grid = Grid::new();
					self.started = false;
					self.count = 30;
					self.mouse_loc = (0.0, 0.0);
				}
				_ => {}
			}
		}
		debug!("released key: {}", args.key);
	}

	fn mouse_release(&mut self, args: &MouseReleaseArgs) {
		if !self.started {
			let (mut x, mut y) = self.mouse_loc;
			x = (x - (x as uint % BLOCK_SIZE) as f64) / BLOCK_SIZE as f64;
			y = (y - (y as uint % BLOCK_SIZE) as f64) / BLOCK_SIZE as f64;
			self.grid.insert(Block::new(Location::new(x as uint, y as uint)))
		}
		debug!("released mouse button: {}", args.button);
	}

	fn mouse_move(&mut self, args: &MouseMoveArgs) {
		self.mouse_loc = (args.x, args.y);
	}

	fn render(&mut self, args: &mut RenderArgs) {
		(&mut self.gl).viewport(0, 0, args.width as i32, args.height as i32);
		let ref c = Context::abs(args.width as f64, args.height as f64);
		c.rgb(1.0, 1.0, 1.0).clear(&mut self.gl);

		if self.started {
			if self.count > 0 {
				self.count -= 1;
			} else {
				self.count = 30;
				self.render_logic();
			}
		}

		self.grid.render(&mut self.gl, c);
	}
}

#[start]
fn start(argc: int, argv: **u8) -> int {
	native::start(argc, argv, main)
}

fn main() {
	assert!(WINDOW_WIDTH % BLOCK_SIZE == 0);
	assert!(WINDOW_HEIGHT % BLOCK_SIZE == 0);
	let mut window = GameWindowSDL2::new(
		GameWindowSettings {
			title: "Conway's Game of Life".to_string(),
			size: [WINDOW_WIDTH as u32, WINDOW_HEIGHT as u32],
			fullscreen: false,
			exit_on_esc: true
		}
	);
	let mut app = App::new();
	let game_iter_settings = GameIteratorSettings {
		updates_per_second: 120,
		max_frames_per_second: 60
	};
	app.run(&mut window, &game_iter_settings);
}
<commit_msg>Add capability to pause<commit_after>#![feature(globs, phase)]

extern crate collections;
#[phase(plugin, link)] extern crate log;
extern crate graphics;
extern crate piston;

use graphics::*;
use piston::{Game, GameIteratorSettings, GameWindowSDL2, GameWindowSettings, KeyReleaseArgs, MouseMoveArgs, MouseReleaseArgs, RenderArgs};

pub static WINDOW_HEIGHT: uint = 480;
pub static WINDOW_WIDTH: uint = 640;

pub static BLOCK_SIZE: uint = 10;  // NOTE: WINDOW_HEIGHT and WINDOW_WIDTH should be divisible by this

pub enum Neighbor {
	Block(Block),
	Location(Location)
}

pub struct Grid {
	grid: Vec<Vec<Option<Block>>>,
	blocks: Vec<Block>
}

#[deriving(Clone, PartialEq)]
pub struct Block {
	pub loc: Location
}

#[deriving(Clone, PartialEq)]
pub struct Location {
	pub x: uint,
	pub y: uint
}

pub struct App {
	gl: Gl,
	grid: Grid,
	started: bool,
	count: uint,
	mouse_loc: (f64, f64)
}

impl Grid {
	pub fn new() -> Grid {
		let mut rows: Vec<Vec<Option<Block>>> = vec!();
		rows.reserve(WINDOW_HEIGHT / BLOCK_SIZE);
		for _ in range(0, WINDOW_HEIGHT / BLOCK_SIZE) {
			rows.push(Vec::from_elem(WINDOW_WIDTH / BLOCK_SIZE, None));
		}
		Grid {
			grid: rows,
			blocks: vec!()
		}
	}

	pub fn insert(&mut self, block: Block) {
		let (x, y) = (block.loc.x, block.loc.y);
		if !self.valid(x, y) {
			return;
		}
		let gr_loc = self.grid.get_mut(y).get_mut(x);
		if *gr_loc == None {
			*gr_loc = Some(block);
			self.blocks.push(gr_loc.unwrap());
		} else if gr_loc.unwrap() != block {
			let idx = {
				let old = gr_loc.get_ref();
				let mut i = 0;
				let len = self.blocks.len();
				while i < len {
					if old == self.blocks.get(i) {
						break;
					}
					i += 1;
				}
				i
			};
			*gr_loc = Some(block);
			*self.blocks.get_mut(idx) = gr_loc.unwrap();
		}
	}

	pub fn remove(&mut self, block: &Block) {
		if self.valid(block.loc.x, block.loc.y) {
			let mut i = 0;
			while i < self.blocks.len() {
				if self.blocks.get(i) == block {
					self.blocks.remove(i);
					break;
				}
				i += 1;
			}
			let gr_loc = self.grid.get_mut(block.loc.y).get_mut(block.loc.x);
			*gr_loc = None;
		}
	}

	pub fn neighbors(&self, block: &Block) -> Vec<Neighbor> {
		let mut vec = vec!();
		if self.valid(block.loc.x, block.loc.y) {
			for i in range(if block.loc.x > 0 { -1 } else { 0 }, if block.loc.x < self.grid.len() - 1 { 2 } else { 1 }) {
				if block.loc.y > 0 {
					let row = self.grid.get(block.loc.y - 1);
					let xpos = (i + block.loc.x as int) as uint;
					vec.push(match *row.get(xpos) {
						Some(blk) => Block(blk),
						None => Location(Location::new(xpos, block.loc.y - 1))
					});
				}
				if block.loc.y < self.grid.len() - 1 {
					let row = self.grid.get(block.loc.y + 1);
					let xpos = (i + block.loc.x as int) as uint;
					vec.push(match *row.get(xpos) {
						Some(blk) => Block(blk),
						None => Location(Location::new(xpos, block.loc.y + 1))
					});
				}
			}
			let row = self.grid.get(block.loc.y);
			if block.loc.x > 0 {
				vec.push(match *row.get(block.loc.x - 1) {
					Some(blk) => Block(blk),
					None => Location(Location::new(block.loc.x - 1, block.loc.y))
				});
			}
			if block.loc.x < self.grid.get(0).len() - 1 {
				vec.push(match *row.get(block.loc.x + 1) {
					Some(blk) => Block(blk),
					None => Location(Location::new(block.loc.x + 1, block.loc.y))
				});
			}
		}
		vec
	}

	#[inline]
	pub fn live_neighbors(&self, block: &Block) -> Vec<Block> {
		let mut live = vec!();
		for neighbor in self.neighbors(block).move_iter() {
			match neighbor {
				Block(blk) => live.push(blk),
				_ => {}
			}
		}
		live
	}

	#[inline]
	pub fn dead_neighbors(&self, block: &Block) -> Vec<Location> {
		let mut dead = vec!();
		for neighbor in self.neighbors(block).move_iter() {
			match neighbor {
				Location(loc) => dead.push(loc),
				_ => {}
			}
		}
		dead
	}

	pub fn contains(&self, block: &Block) -> bool {
		if self.valid(block.loc.x, block.loc.y) {
			self.grid.get(block.loc.y).get(block.loc.x).is_some()
		} else {
			false
		}
	}

	#[inline]
	fn valid(&self, x: uint, y: uint) -> bool {
		y < self.grid.len() && x < self.grid.get(0).len()
	}

	#[inline]
	pub fn render(&self, gl: &mut Gl, win_ctx: &Context) {
		for block in self.blocks.iter() {
			block.render(gl, win_ctx);
		}
	}
}

impl Block {
	#[inline]
	pub fn new(loc: Location) -> Block {
		Block {
			loc: loc
		}
	}

	#[inline]
	pub fn render(&self, gl: &mut Gl, win_ctx: &Context) {
		win_ctx
		       .rect((self.loc.x * BLOCK_SIZE) as f64, (self.loc.y * BLOCK_SIZE) as f64, BLOCK_SIZE as f64, BLOCK_SIZE as f64)
		       .rgb(0.0, 0.0, 0.0).fill(gl);
	}
}

impl Location {
	#[inline]
	pub fn new(x: uint, y: uint) -> Location {
		assert!(x <= WINDOW_WIDTH / BLOCK_SIZE);
		assert!(y <= WINDOW_HEIGHT / BLOCK_SIZE);
		Location {
			x: x,
			y: y
		}
	}
}

impl App {
	#[inline]
	pub fn new() -> App {
		App {
			gl: Gl::new(),
			grid: Grid::new(),
			started: false,
			count: 30,
			mouse_loc: (0.0, 0.0)
		}
	}

	#[cfg(random)]
	#[inline]
	fn render_logic(&mut self) {
		use std::rand::random;

		let mut x = (random::<f64>() * WINDOW_WIDTH as f64) as uint;
		x = (x - x % BLOCK_SIZE) / BLOCK_SIZE;
		let mut y = (random::<f64>() * WINDOW_HEIGHT as f64) as uint;
		y = (y - y % BLOCK_SIZE) / BLOCK_SIZE;
		self.grid.insert(Block::new(Location::new(x, y)));
	}

	#[cfg(not(random))]
	#[inline]
	fn render_logic(&mut self) {
		let mut remove = vec!();
		let mut add = vec!();
		for block in self.grid.blocks.iter() {
			let live = self.grid.live_neighbors(block);
			let livelen = live.len();
			if livelen != 2 && livelen != 3 {
				remove.push(block.clone());
			}
			for &loc in self.grid.dead_neighbors(block).iter() {
				let block = Block::new(loc);
				if self.grid.live_neighbors(&block).len() == 3 {
					add.push(block);
				}
			}
		}
		for block in remove.iter() {
			self.grid.remove(block);
		}
		for block in add.move_iter() {
			self.grid.insert(block);
		}
	}
}

impl Game for App {
	fn key_release(&mut self, args: &KeyReleaseArgs) {
		match args.key {
			piston::keyboard::R => {
				self.grid = Grid::new();
				self.started = false;
				self.count = 30;
				self.mouse_loc = (0.0, 0.0);
			}
			piston::keyboard::P | piston::keyboard::Return => self.started = !self.started,
			_ => {}
		}
		debug!("released key: {}", args.key);
	}

	fn mouse_release(&mut self, args: &MouseReleaseArgs) {
		if !self.started {
			let (mut x, mut y) = self.mouse_loc;
			x = (x - (x as uint % BLOCK_SIZE) as f64) / BLOCK_SIZE as f64;
			y = (y - (y as uint % BLOCK_SIZE) as f64) / BLOCK_SIZE as f64;
			self.grid.insert(Block::new(Location::new(x as uint, y as uint)))
		}
		debug!("released mouse button: {}", args.button);
	}

	fn mouse_move(&mut self, args: &MouseMoveArgs) {
		self.mouse_loc = (args.x, args.y);
	}

	fn render(&mut self, args: &mut RenderArgs) {
		(&mut self.gl).viewport(0, 0, args.width as i32, args.height as i32);
		let ref c = Context::abs(args.width as f64, args.height as f64);
		c.rgb(1.0, 1.0, 1.0).clear(&mut self.gl);

		if self.started {
			if self.count > 0 {
				self.count -= 1;
			} else {
				self.count = 30;
				self.render_logic();
			}
		}

		self.grid.render(&mut self.gl, c);
	}
}

#[start]
fn start(argc: int, argv: **u8) -> int {
	native::start(argc, argv, main)
}

fn main() {
	assert!(WINDOW_WIDTH % BLOCK_SIZE == 0);
	assert!(WINDOW_HEIGHT % BLOCK_SIZE == 0);
	let mut window = GameWindowSDL2::new(
		GameWindowSettings {
			title: "Conway's Game of Life".to_string(),
			size: [WINDOW_WIDTH as u32, WINDOW_HEIGHT as u32],
			fullscreen: false,
			exit_on_esc: true
		}
	);
	let mut app = App::new();
	let game_iter_settings = GameIteratorSettings {
		updates_per_second: 120,
		max_frames_per_second: 60
	};
	app.run(&mut window, &game_iter_settings);
}
<|endoftext|>


<commit_before>use ecs::{ComponentManager, Entity};
use std::any::Any;
use std::cell::{Cell, RefCell};
use std::collections::{HashMap, HashSet};
use std::ops::{Deref, DerefMut};
use super::{EntityMap, EntitySet};

const MAX_CAPACITY: usize = 1_000;

/// A default manager for component types that can be represented as a single struct.
#[derive(Debug, Clone)]
pub struct StructComponentManager<T: Clone + Any> {
    components: Vec<RefCell<Option<T>>>,
    entities: Vec<RefCell<Option<Entity>>>,
    indices: RefCell<EntityMap<usize>>,

    /// Tracks the maximum "count" of the components.
    ///
    /// This replaces the `.count()` value that would normally be gotten from the `Vec`, however we
    /// can't actually change the number of elements in the `Vec` (it all has to be immutable
    /// borrows), so we track it manually. This allows us to determine where to insert new
    /// components and which elements we need to iterate over.
    filled_count: Cell<usize>,

    marked_for_destroy: RefCell<EntitySet>,
}

impl<T: Clone + Any> StructComponentManager<T> {
    pub fn new() -> StructComponentManager<T> {
        let mut manager = StructComponentManager::<T> {
            components: Vec::with_capacity(MAX_CAPACITY),
            entities: Vec::with_capacity(MAX_CAPACITY),
            indices: RefCell::new(HashMap::default()),

            filled_count: Cell::new(0),

            marked_for_destroy: RefCell::new(HashSet::default()),
        };

        manager.components.resize(MAX_CAPACITY, RefCell::new(None));
        manager.entities.resize(MAX_CAPACITY, RefCell::new(None));

        manager
    }

    pub fn assign(&self, entity: Entity, component: T) -> RefMut<T> {
        debug_assert!(!self.indices.borrow().contains_key(&entity));

        let index = self.filled_count.get();
        debug_assert!(index < MAX_CAPACITY);

        // Write the new component data into the open slot.
        let mut component_slot = self.components[index].borrow_mut();
        debug_assert!(component_slot.is_none());

        *component_slot = Some(component);

        // Write entity to entities list.
        let mut entity_slot = self.entities[index].borrow_mut();
        debug_assert!(entity_slot.is_none());

        *entity_slot = Some(entity);

        // Add entity index to index map.
        let mut indices = self.indices.borrow_mut();
        indices.insert(entity, index);

        // Update filled count.
        self.filled_count.set(index + 1);

        RefMut(component_slot)
    }

    pub fn get(&self, entity: Entity) -> Option<Ref<T>> {
        if let Some(index) = self.indices.borrow().get(&entity) {
            Some(Ref(self.components[*index].borrow()))
        } else {
            None
        }
    }

    pub fn get_mut(&self, entity: Entity) -> Option<RefMut<T>> {
        if let Some(index) = self.indices.borrow().get(&entity) {
            Some(RefMut(self.components[*index].borrow_mut()))
        } else {
            None
        }
    }

    pub fn iter(&self) -> Iter<T> {
        Iter {
            component_iter: self.components.iter(),
            entity_iter: self.entities.iter(),
        }
    }

    pub fn iter_mut(&self) -> IterMut<T> {
        IterMut {
            component_iter: self.components.iter(),
            entity_iter: self.entities.iter(),
        }
    }
}

impl<T: Clone + Any> ComponentManager for StructComponentManager<T> {
    fn destroy_all(&self, entity: Entity) {
        let maybe_index = self.indices.borrow_mut().remove(&entity);
        if let Some(index) = maybe_index {
            let mut component_slot = self.components[index].borrow_mut();
            let mut entity_slot = self.entities[index].borrow_mut();

            debug_assert!(component_slot.is_some());
            debug_assert!(entity_slot.is_some() && entity_slot.unwrap() == entity);

            *component_slot = None;
            *entity_slot = None;
        }
    }

    fn destroy_marked(&mut self) {
    }
}

pub struct Ref<'a, T: 'a>(::std::cell::Ref<'a, Option<T>>);

impl<'a, T: 'a> Deref for Ref<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        self.0.as_ref().unwrap()
    }
}

pub struct RefMut<'a, T: 'a>(::std::cell::RefMut<'a, Option<T>>);

impl<'a, T: 'a> Deref for RefMut<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        self.0.as_ref().unwrap()
    }
}

impl<'a, T: 'a> DerefMut for RefMut<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        self.0.as_mut().unwrap()
    }
}

pub struct Iter<'a, T: 'a> {
    component_iter: ::std::slice::Iter<'a, RefCell<Option<T>>>,
    entity_iter: ::std::slice::Iter<'a, RefCell<Option<Entity>>>,
}

impl<'a, T: 'a + Clone> Iterator for Iter<'a, T> {
    type Item = (Ref<'a, T>, Entity);

    fn next(&mut self) -> Option<(Ref<'a, T>, Entity)> {
        loop {
            let next_entity = self.entity_iter.next();
            match self.component_iter.next() {
                None => return None,
                Some(maybe_component) => {
                    if maybe_component.borrow().is_none() {
                        continue;
                    }

                    return Some((Ref(maybe_component.borrow()), next_entity.unwrap().borrow().unwrap()));
                },
            }
        }
    }
}

pub struct IterMut<'a, T: 'a + Clone> {
    component_iter: ::std::slice::Iter<'a, RefCell<Option<T>>>,
    entity_iter: ::std::slice::Iter<'a, RefCell<Option<Entity>>>,
}

impl<'a, T: 'a + Clone> Iterator for IterMut<'a, T> {
    type Item = (RefMut<'a, T>, Entity);

    fn next(&mut self) -> Option<(RefMut<'a, T>, Entity)> {
        loop {
            let next_entity = self.entity_iter.next();
            match self.component_iter.next() {
                None => return None,
                Some(maybe_component) => {
                    if maybe_component.borrow().is_none() {
                        continue;
                    }

                    return Some((RefMut(maybe_component.borrow_mut()), next_entity.unwrap().borrow().unwrap()));
                },
            }
        }
    }
}
<commit_msg>feature(struct_component_manager): add StructComponentManager::len()<commit_after>use ecs::{ComponentManager, Entity};
use std::any::Any;
use std::cell::{Cell, RefCell};
use std::collections::{HashMap, HashSet};
use std::ops::{Deref, DerefMut};
use super::{EntityMap, EntitySet};

const MAX_CAPACITY: usize = 1_000;

/// A default manager for component types that can be represented as a single struct.
#[derive(Debug, Clone)]
pub struct StructComponentManager<T: Clone + Any> {
    components: Vec<RefCell<Option<T>>>,
    entities: Vec<RefCell<Option<Entity>>>,
    indices: RefCell<EntityMap<usize>>,

    /// Tracks the maximum "count" of the components.
    ///
    /// This replaces the `.count()` value that would normally be gotten from the `Vec`, however we
    /// can't actually change the number of elements in the `Vec` (it all has to be immutable
    /// borrows), so we track it manually. This allows us to determine where to insert new
    /// components and which elements we need to iterate over.
    filled_count: Cell<usize>,
    entity_count: Cell<usize>,

    marked_for_destroy: RefCell<EntitySet>,
}

impl<T: Clone + Any> StructComponentManager<T> {
    pub fn new() -> StructComponentManager<T> {
        let mut manager = StructComponentManager::<T> {
            components: Vec::with_capacity(MAX_CAPACITY),
            entities: Vec::with_capacity(MAX_CAPACITY),
            indices: RefCell::new(HashMap::default()),

            filled_count: Cell::new(0),
            entity_count: Cell::new(0),

            marked_for_destroy: RefCell::new(HashSet::default()),
        };

        manager.components.resize(MAX_CAPACITY, RefCell::new(None));
        manager.entities.resize(MAX_CAPACITY, RefCell::new(None));

        manager
    }

    pub fn assign(&self, entity: Entity, component: T) -> RefMut<T> {
        debug_assert!(!self.indices.borrow().contains_key(&entity));

        let index = self.filled_count.get();
        debug_assert!(index < MAX_CAPACITY);

        // Write the new component data into the open slot.
        let mut component_slot = self.components[index].borrow_mut();
        debug_assert!(component_slot.is_none());

        *component_slot = Some(component);

        // Write entity to entities list.
        let mut entity_slot = self.entities[index].borrow_mut();
        debug_assert!(entity_slot.is_none());

        *entity_slot = Some(entity);

        // Add entity index to index map.
        let mut indices = self.indices.borrow_mut();
        indices.insert(entity, index);

        // Update filled count.
        self.filled_count.set(index + 1);
        self.entity_count.set(self.entity_count.get() + 1);

        RefMut(component_slot)
    }

    pub fn get(&self, entity: Entity) -> Option<Ref<T>> {
        if let Some(index) = self.indices.borrow().get(&entity) {
            Some(Ref(self.components[*index].borrow()))
        } else {
            None
        }
    }

    pub fn get_mut(&self, entity: Entity) -> Option<RefMut<T>> {
        if let Some(index) = self.indices.borrow().get(&entity) {
            Some(RefMut(self.components[*index].borrow_mut()))
        } else {
            None
        }
    }

    pub fn iter(&self) -> Iter<T> {
        Iter {
            component_iter: self.components.iter(),
            entity_iter: self.entities.iter(),
        }
    }

    pub fn iter_mut(&self) -> IterMut<T> {
        IterMut {
            component_iter: self.components.iter(),
            entity_iter: self.entities.iter(),
        }
    }

    /// Returns the number of entities with a component associated.
    pub fn len(&self) -> usize {
        self.entity_count.get()
    }
}

impl<T: Clone + Any> ComponentManager for StructComponentManager<T> {
    fn destroy_all(&self, entity: Entity) {
        let maybe_index = self.indices.borrow_mut().remove(&entity);
        if let Some(index) = maybe_index {
            let mut component_slot = self.components[index].borrow_mut();
            let mut entity_slot = self.entities[index].borrow_mut();

            debug_assert!(component_slot.is_some());
            debug_assert!(entity_slot.is_some() && entity_slot.unwrap() == entity);

            *component_slot = None;
            *entity_slot = None;

            self.entity_count.set(self.entity_count.get() - 1);
        }
    }

    fn destroy_marked(&mut self) {
    }
}

pub struct Ref<'a, T: 'a>(::std::cell::Ref<'a, Option<T>>);

impl<'a, T: 'a> Deref for Ref<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        self.0.as_ref().unwrap()
    }
}

pub struct RefMut<'a, T: 'a>(::std::cell::RefMut<'a, Option<T>>);

impl<'a, T: 'a> Deref for RefMut<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        self.0.as_ref().unwrap()
    }
}

impl<'a, T: 'a> DerefMut for RefMut<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        self.0.as_mut().unwrap()
    }
}

pub struct Iter<'a, T: 'a> {
    component_iter: ::std::slice::Iter<'a, RefCell<Option<T>>>,
    entity_iter: ::std::slice::Iter<'a, RefCell<Option<Entity>>>,
}

impl<'a, T: 'a + Clone> Iterator for Iter<'a, T> {
    type Item = (Ref<'a, T>, Entity);

    fn next(&mut self) -> Option<(Ref<'a, T>, Entity)> {
        loop {
            let next_entity = self.entity_iter.next();
            match self.component_iter.next() {
                None => return None,
                Some(maybe_component) => {
                    if maybe_component.borrow().is_none() {
                        continue;
                    }

                    return Some((Ref(maybe_component.borrow()), next_entity.unwrap().borrow().unwrap()));
                },
            }
        }
    }
}

pub struct IterMut<'a, T: 'a + Clone> {
    component_iter: ::std::slice::Iter<'a, RefCell<Option<T>>>,
    entity_iter: ::std::slice::Iter<'a, RefCell<Option<Entity>>>,
}

impl<'a, T: 'a + Clone> Iterator for IterMut<'a, T> {
    type Item = (RefMut<'a, T>, Entity);

    fn next(&mut self) -> Option<(RefMut<'a, T>, Entity)> {
        loop {
            let next_entity = self.entity_iter.next();
            match self.component_iter.next() {
                None => return None,
                Some(maybe_component) => {
                    if maybe_component.borrow().is_none() {
                        continue;
                    }

                    return Some((RefMut(maybe_component.borrow_mut()), next_entity.unwrap().borrow().unwrap()));
                },
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate cc;
extern crate metadeps;

use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::PathBuf;
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(e) => panic!("{} return the error {}", stringify!($e), e),
    })
}

fn main() {
    // Use the installed libcares if it is available.
    if metadeps::probe().is_ok() {
        return;
    }

    // Rerun if the c-ares source code has changed.
    println!("cargo:rerun-if-changed=c-ares");

    // MSVC builds are different.
    let target = env::var("TARGET").unwrap();
    if target.contains("msvc") {
        build_msvc(&target);
        return;
    }

    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dst.join("build");
    let _ = fs::create_dir(&build);

    // Prepare.
    let src = env::current_dir().unwrap();
    run(
        Command::new("sh")
            .current_dir(&src.join("c-ares"))
            .arg("buildconf"),
    );

    // Configure.
    let cfg = cc::Build::new();
    let compiler = cfg.get_compiler();
    let mut cflags = OsString::new();
    for arg in compiler.args() {
        cflags.push(arg);
        cflags.push(" ");
    }

    let mut cmd = Command::new("sh");
    cmd.env("CFLAGS", &cflags)
        .env("CC", compiler.path())
        .current_dir(&build)
        .arg(format!("{}", src.join("c-ares/configure").display()))
        .arg("--enable-static=yes")
        .arg("--enable-shared=no")
        .arg("--enable-optimize")
        .arg(format!("--prefix={}", dst.display()));

    // This code fragment copied from curl-rust... c-ares and curl come from
    // the same developer so are usually pretty similar, and this seems to
    // work.
    //
    // NOTE GNU terminology
    // BUILD = machine where we are (cross) compiling
    // HOST = machine where the compiled binary will be used
    // TARGET = only relevant when compiling compilers
    let host = env::var("HOST").unwrap();
    if target != host && (!target.contains("windows") || !host.contains("windows")) {
        if target.contains("windows") {
            cmd.arg(format!("--host={}", host));
            cmd.arg(format!("--target={}", target));
        } else {
            cmd.arg(format!("--build={}", host));
            cmd.arg(format!("--host={}", target));
        }
    }
    run(&mut cmd);

    // Compile.
    run(
        Command::new(make())
            .arg(format!("-j{}", env::var("NUM_JOBS").unwrap()))
            .current_dir(&build),
    );

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/.libs", build.display());
    println!("cargo:rustc-link-lib=static=cares");
}

fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    assert!(t!(cmd.status()).success());
}

fn make() -> &'static str {
    if cfg!(target_os = "freebsd") {
        "gmake"
    } else {
        "make"
    }
}

fn nmake(target: &str) -> Command {
    // cargo messes with the environment in a way that nmake does not like -
    // see https://github.com/rust-lang/cargo/issues/4156.  Explicitly remove
    // the unwanted variables.
    let mut cmd = cc::windows_registry::find(target, "nmake.exe").unwrap();
    cmd.env_remove("MAKEFLAGS").env_remove("MFLAGS");
    cmd
}

fn build_msvc(target: &str) {
    // Prepare.
    let src = env::current_dir().unwrap();
    let c_ares_dir = &src.join("c-ares");
    run(
        Command::new("cmd")
            .current_dir(c_ares_dir)
            .arg("/c")
            .arg("buildconf.bat"),
    );

    // Compile.
    let mut cmd = nmake(target);
    cmd.current_dir(c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "CFG=lib-release", "c-ares"]);
    run(&mut cmd);

    // Install library.
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dst.join("build");
    let mut cmd = nmake(target);
    cmd.current_dir(c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "/a", "CFG=lib-release", "install"]);
    cmd.env("INSTALL_DIR", format!("{}", build.display()));
    run(&mut cmd);

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/lib", build.display());
    println!("cargo:rustc-link-lib=static=libcares");
}
<commit_msg>rustfmt changes its mind again<commit_after>extern crate cc;
extern crate metadeps;

use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::PathBuf;
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(e) => panic!("{} return the error {}", stringify!($e), e),
    })
}

fn main() {
    // Use the installed libcares if it is available.
    if metadeps::probe().is_ok() {
        return;
    }

    // Rerun if the c-ares source code has changed.
    println!("cargo:rerun-if-changed=c-ares");

    // MSVC builds are different.
    let target = env::var("TARGET").unwrap();
    if target.contains("msvc") {
        build_msvc(&target);
        return;
    }

    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dst.join("build");
    let _ = fs::create_dir(&build);

    // Prepare.
    let src = env::current_dir().unwrap();
    run(Command::new("sh")
        .current_dir(&src.join("c-ares"))
        .arg("buildconf"));

    // Configure.
    let cfg = cc::Build::new();
    let compiler = cfg.get_compiler();
    let mut cflags = OsString::new();
    for arg in compiler.args() {
        cflags.push(arg);
        cflags.push(" ");
    }

    let mut cmd = Command::new("sh");
    cmd.env("CFLAGS", &cflags)
        .env("CC", compiler.path())
        .current_dir(&build)
        .arg(format!("{}", src.join("c-ares/configure").display()))
        .arg("--enable-static=yes")
        .arg("--enable-shared=no")
        .arg("--enable-optimize")
        .arg(format!("--prefix={}", dst.display()));

    // This code fragment copied from curl-rust... c-ares and curl come from
    // the same developer so are usually pretty similar, and this seems to
    // work.
    //
    // NOTE GNU terminology
    // BUILD = machine where we are (cross) compiling
    // HOST = machine where the compiled binary will be used
    // TARGET = only relevant when compiling compilers
    let host = env::var("HOST").unwrap();
    if target != host && (!target.contains("windows") || !host.contains("windows")) {
        if target.contains("windows") {
            cmd.arg(format!("--host={}", host));
            cmd.arg(format!("--target={}", target));
        } else {
            cmd.arg(format!("--build={}", host));
            cmd.arg(format!("--host={}", target));
        }
    }
    run(&mut cmd);

    // Compile.
    run(Command::new(make())
        .arg(format!("-j{}", env::var("NUM_JOBS").unwrap()))
        .current_dir(&build));

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/.libs", build.display());
    println!("cargo:rustc-link-lib=static=cares");
}

fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    assert!(t!(cmd.status()).success());
}

fn make() -> &'static str {
    if cfg!(target_os = "freebsd") {
        "gmake"
    } else {
        "make"
    }
}

fn nmake(target: &str) -> Command {
    // cargo messes with the environment in a way that nmake does not like -
    // see https://github.com/rust-lang/cargo/issues/4156.  Explicitly remove
    // the unwanted variables.
    let mut cmd = cc::windows_registry::find(target, "nmake.exe").unwrap();
    cmd.env_remove("MAKEFLAGS").env_remove("MFLAGS");
    cmd
}

fn build_msvc(target: &str) {
    // Prepare.
    let src = env::current_dir().unwrap();
    let c_ares_dir = &src.join("c-ares");
    run(Command::new("cmd")
        .current_dir(c_ares_dir)
        .arg("/c")
        .arg("buildconf.bat"));

    // Compile.
    let mut cmd = nmake(target);
    cmd.current_dir(c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "CFG=lib-release", "c-ares"]);
    run(&mut cmd);

    // Install library.
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dst.join("build");
    let mut cmd = nmake(target);
    cmd.current_dir(c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "/a", "CFG=lib-release", "install"]);
    cmd.env("INSTALL_DIR", format!("{}", build.display()));
    run(&mut cmd);

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/lib", build.display());
    println!("cargo:rustc-link-lib=static=libcares");
}
<|endoftext|>