<commit_before>use super::utils::*;
use super::surname;
use super::namecase;
use std::borrow::Cow;
use std::ascii::AsciiExt;
use phf;
use unicode_segmentation::UnicodeSegmentation;

// If Start and End overlap, use End
#[derive(Eq,PartialEq,Debug)]
pub enum Location {
    Start,
    Middle,
    End,
}

pub struct NameParts<'a> {
    text: &'a str,
    trust_capitalization: bool,
    location: Location,
}

impl <'a>NameParts<'a> {
    fn next_location(&mut self) -> Location {
        if self.location == Location::Middle {
            // If the whole section is in the middle, so are all parts
            Location::Middle
        } else if self.location == Location::Start {
            self.location = Location::Middle;
            Location::Start
        } else if self.text.chars().find(|c| c.is_alphabetic()).is_none() {
            Location::End
        } else {
            Location::Middle
        }
    }
}

impl <'a>Iterator for NameParts<'a> {
    type Item = NamePart<'a>;

    fn next(&mut self) -> Option<NamePart<'a>> {
        // Skip any leading whitespace
        self.text = self.text.trim_left();

        if self.text.is_empty() {
            return None;
        }

        // Now look for the next whitespace that remains
        let next_whitespace = self.text.find(char::is_whitespace).unwrap_or(self.text.len());
        let next_inner_period = self.text[0..next_whitespace].find('.');
        let next_boundary = match next_inner_period {
            Some(i) => i + 1,
            None => next_whitespace,
        };

        let word = &self.text[0..next_boundary];

        if word == "&" {
            // Special case: only allowed word without alphabetical characters
            self.text = &self.text[next_boundary..];
            Some(NamePart {
                word: word,
                chars: 1,
                category: Category::Other,
                namecased: Cow::Borrowed(word),
            })
        } else if !word.chars().any(char::is_alphabetic) {
            // Not a word, skip it by recursing
            self.text = &self.text[next_boundary..];
            self.next()
        } else if !word.chars().any(|c| c.is_ascii()) {
            // For non-ASCII, we defer to the unicode_segmentation library
            let (next_word_boundary, subword) = word.split_word_bound_indices()
                                                    .find(|&(_, subword)| {
                                                        subword.chars().any(char::is_alphabetic)
                                                    })
                                                    .unwrap();
            self.text = &self.text[next_word_boundary + subword.len()..];
            Some(NamePart::from_word(subword, self.trust_capitalization, self.next_location()))
        } else {
            // For ASCII, we split on whitespace and periods only
            self.text = &self.text[next_boundary..];
            Some(NamePart::from_word(word, self.trust_capitalization, self.next_location()))
        }
    }
}

#[derive(Eq,PartialEq,Debug)]
pub enum Category {
    Name,
    Initials,
    Abbreviation,
    Other,
}

#[derive(Debug)]
pub struct NamePart<'a> {
    pub word: &'a str,
    pub chars: usize,
    pub category: Category,
    pub namecased: Cow<'a, str>,
}

impl <'a>NamePart<'a> {

    pub fn all_from_text(text: &str, trust_capitalization: bool, location: Location) -> NameParts {
        NameParts {
            text: text,
            trust_capitalization: trust_capitalization,
            location: location,
        }
    }

    pub fn from_word(word: &str, trust_capitalization: bool, location: Location) -> NamePart {
        let chars = word.chars().count();
        let ascii = word.chars().all(|c| c.is_ascii());

        let category = if chars == 1 && ascii {
            Category::Initials
        } else if chars == 1 {
            Category::Name
        } else if word.ends_with('.') {
            if chars > 2 && has_sequential_alphas(word) {
                Category::Abbreviation
            } else {
                Category::Initials
            }
        } else if word.chars()
                              .filter(|c| !c.is_alphabetic() && !is_combining(*c))
                              .count() > 2 {
            Category::Other
        } else if is_missing_vowels(word) {
            if trust_capitalization &&
               word.chars().all(|c| !c.is_alphabetic() || c.is_uppercase()) {
                Category::Initials
            } else if location == Location::End &&
               surname::is_vowelless_surname(word, trust_capitalization) {
                Category::Name
            } else if chars <= 5 {
                Category::Initials
            } else {
                Category::Other
            }
        } else {
            if chars <= 5 && trust_capitalization &&
               word.chars().all(|c| !c.is_alphabetic() || c.is_uppercase()) {
                Category::Initials
            } else if chars == 2 && !trust_capitalization && !TWO_LETTER_GIVEN_NAMES.contains(word) {
                Category::Initials
            } else {
                Category::Name
            }
        };

        let namecased = if trust_capitalization && ascii && is_capitalized(word) {
            Cow::Borrowed(word)
        } else {
            let might_be_particle = location == Location::Middle;
            Cow::Owned(namecase::namecase(word, might_be_particle))
        };

        NamePart {
            word: word,
            chars: chars,
            category: category,
            namecased: namecased,
        }
    }

    #[inline]
    pub fn is_initials(&self) -> bool {
        self.category == Category::Initials
    }

    #[inline]
    pub fn is_namelike(&self) -> bool {
        self.category == Category::Name
    }

    #[inline]
    pub fn is_abbreviation(&self) -> bool {
        self.category == Category::Abbreviation
    }
}

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

    #[test]
    fn one_word() {
        assert_eq!(1,
                   NamePart::all_from_text("John", true, Location::Start).count());
    }

    #[test]
    fn two_words() {
        assert_eq!(2,
                   NamePart::all_from_text("&* John Doe! ☃", true, Location::Start).count());
    }

    #[test]
    fn only_junk() {
        assert_eq!(0,
                   NamePart::all_from_text(" ... 23 ", true, Location::Start).count());
    }

    #[test]
    fn single_ascii() {
        assert_eq!(Category::Initials,
                   NamePart::from_word("I", true, Location::Start).category);
    }

    #[test]
    fn single_han() {
        assert_eq!(Category::Name,
                   NamePart::from_word("鄭", true, Location::Start).category);
    }

    #[test]
    fn abbreviated_ascii() {
        assert_eq!(Category::Initials,
                   NamePart::from_word("I.", true, Location::Start).category);
    }

    #[test]
    fn abbreviated_double_ascii() {
        assert_eq!(Category::Abbreviation,
                   NamePart::from_word("MI.", true, Location::Start).category);
    }

    #[test]
    fn double_abbreviated_double_ascii() {
        assert_eq!(Category::Initials,
                   NamePart::from_word("M.I.", true, Location::Start).category);
    }

    #[test]
    fn junk() {
        assert_eq!(Category::Other,
                   NamePart::from_word("503(a)", true, Location::Start).category);
    }

    #[test]
    fn no_vowels() {
        assert_eq!(Category::Initials,
                   NamePart::from_word("JM", true, Location::Start).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("jm", true, Location::Start).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("JM", false, Location::Start).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("JMMMMM", true, Location::Start).category);
        assert_eq!(Category::Other,
                   NamePart::from_word("jmmmmm", true, Location::Start).category);
        assert_eq!(Category::Other,
                   NamePart::from_word("JMMMMM", false, Location::Start).category);
    }

    #[test]
    fn vowelless_surname() {
        assert_eq!(Category::Initials,
                   NamePart::from_word("NG", true, Location::Start).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("Ng", true, Location::Start).category);
        assert_eq!(Category::Name,
                   NamePart::from_word("Ng", true, Location::End).category);
        assert_eq!(Category::Name,
                   NamePart::from_word("NG", false, Location::End).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("NG", true, Location::End).category);
    }

    #[test]
    fn word() {
        assert_eq!(Category::Initials,
                   NamePart::from_word("JEM", true, Location::Start).category);
        assert_eq!(Category::Name,
                   NamePart::from_word("Jem", true, Location::Start).category);
        assert_eq!(Category::Name,
                   NamePart::from_word("JEM", false, Location::Start).category);
    }

    #[test]
    fn two_letters() {
        assert_eq!(Category::Name,
                   NamePart::from_word("Al", true, Location::Start).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("AL", true, Location::Start).category);
        assert_eq!(Category::Name,
                   NamePart::from_word("AL", false, Location::Start).category);
        assert_eq!(Category::Name,
                   NamePart::from_word("At", true, Location::Start).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("AT", true, Location::Start).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("AT", false, Location::Start).category);
    }
}

// Everything with a vowel reasonably popular in the Social Security data:
// https://www.ssa.gov/oact/babynames/limits.html
static TWO_LETTER_GIVEN_NAMES: phf::Set<&'static str> = phf_set! {
    "Jo",
    "JO",
    "jo",
    "Ty",
    "TY",
    "ty",
    "Ed",
    "ED",
    "ed",
    "Al",
    "AL",
    "al",
    "Bo",
    "BO",
    "bo",
    "Lu",
    "LU",
    "lu",
    "Cy",
    "CY",
    "cy",
    "An",
    "AN",
    "an",
    "La",
    "LA",
    "la",
    "Aj",
    "AJ",
    "aj",
    "Le",
    "LE",
    "le",
    "Om",
    "OM",
    "om",
    "Pa",
    "PA",
    "pa",
    "De",
    "DE",
    "de",
    "Ky",
    "KY",
    "ky",
    "My",
    "MY",
    "my",
    "Vy",
    "VY",
    "vy",
    "Vi",
    "VI",
    "vi",
    "Ka",
    "KA",
    "ka",
    "Sy",
    "SY",
    "sy",
    "Vu",
    "VU",
    "vu",
    "Yu",
    "YU",
    "yu",
    "Mi",
    "MI",
    "mi",
    "Su",
    "SU",
    "su",
    "Ma",
    "MA",
    "ma",
    "Ha",
    "HA",
    "ha",
    "Ki",
    "KI",
    "ki",
    "Tu",
    "TU",
    "tu",
    "Ji",
    "JI",
    "ji",
    "Ja",
    "JA",
    "ja",
    "Ly",
    "LY",
    "ly",
    "Li",
    "LI",
    "li",
    "Ai",
    "AI",
    "ai",
    "Ry",
    "RY",
    "ry",
    "Ab",
    "AB",
    "ab",
    "Ho",
    "HO",
    "ho",
    "Da",
    "DA",
    "da",
    "Oz",
    "OZ",
    "oz",
    "El",
    "EL",
    "el",
    "Na",
    "NA",
    "na",
    "Yi",
    "YI",
    "yi",
    "Em",
    "EM",
    "em",
    "Di",
    "DI",
    "di",
    "Go",
    "GO",
    "go",
    "Ev",
    "EV",
    "ev",
    "Ho",
    "HO",
    "ho",
    "Mo",
    "MO",
    "mo",
    "Lo",
    "LO",
    "lo",
    "Ra",
    "RA",
    "ra",
    "Do",
    "DO",
    "do",
    "Gi",
    "GI",
    "gi",
};
<commit_msg>Remove duplicate two-letter name<commit_after>use super::utils::*;
use super::surname;
use super::namecase;
use std::borrow::Cow;
use std::ascii::AsciiExt;
use phf;
use unicode_segmentation::UnicodeSegmentation;

// If Start and End overlap, use End
#[derive(Eq,PartialEq,Debug)]
pub enum Location {
    Start,
    Middle,
    End,
}

pub struct NameParts<'a> {
    text: &'a str,
    trust_capitalization: bool,
    location: Location,
}

impl <'a>NameParts<'a> {
    fn next_location(&mut self) -> Location {
        if self.location == Location::Middle {
            // If the whole section is in the middle, so are all parts
            Location::Middle
        } else if self.location == Location::Start {
            self.location = Location::Middle;
            Location::Start
        } else if self.text.chars().find(|c| c.is_alphabetic()).is_none() {
            Location::End
        } else {
            Location::Middle
        }
    }
}

impl <'a>Iterator for NameParts<'a> {
    type Item = NamePart<'a>;

    fn next(&mut self) -> Option<NamePart<'a>> {
        // Skip any leading whitespace
        self.text = self.text.trim_left();

        if self.text.is_empty() {
            return None;
        }

        // Now look for the next whitespace that remains
        let next_whitespace = self.text.find(char::is_whitespace).unwrap_or(self.text.len());
        let next_inner_period = self.text[0..next_whitespace].find('.');
        let next_boundary = match next_inner_period {
            Some(i) => i + 1,
            None => next_whitespace,
        };

        let word = &self.text[0..next_boundary];

        if word == "&" {
            // Special case: only allowed word without alphabetical characters
            self.text = &self.text[next_boundary..];
            Some(NamePart {
                word: word,
                chars: 1,
                category: Category::Other,
                namecased: Cow::Borrowed(word),
            })
        } else if !word.chars().any(char::is_alphabetic) {
            // Not a word, skip it by recursing
            self.text = &self.text[next_boundary..];
            self.next()
        } else if !word.chars().any(|c| c.is_ascii()) {
            // For non-ASCII, we defer to the unicode_segmentation library
            let (next_word_boundary, subword) = word.split_word_bound_indices()
                                                    .find(|&(_, subword)| {
                                                        subword.chars().any(char::is_alphabetic)
                                                    })
                                                    .unwrap();
            self.text = &self.text[next_word_boundary + subword.len()..];
            Some(NamePart::from_word(subword, self.trust_capitalization, self.next_location()))
        } else {
            // For ASCII, we split on whitespace and periods only
            self.text = &self.text[next_boundary..];
            Some(NamePart::from_word(word, self.trust_capitalization, self.next_location()))
        }
    }
}

#[derive(Eq,PartialEq,Debug)]
pub enum Category {
    Name,
    Initials,
    Abbreviation,
    Other,
}

#[derive(Debug)]
pub struct NamePart<'a> {
    pub word: &'a str,
    pub chars: usize,
    pub category: Category,
    pub namecased: Cow<'a, str>,
}

impl <'a>NamePart<'a> {

    pub fn all_from_text(text: &str, trust_capitalization: bool, location: Location) -> NameParts {
        NameParts {
            text: text,
            trust_capitalization: trust_capitalization,
            location: location,
        }
    }

    pub fn from_word(word: &str, trust_capitalization: bool, location: Location) -> NamePart {
        let chars = word.chars().count();
        let ascii = word.chars().all(|c| c.is_ascii());

        let category = if chars == 1 && ascii {
            Category::Initials
        } else if chars == 1 {
            Category::Name
        } else if word.ends_with('.') {
            if chars > 2 && has_sequential_alphas(word) {
                Category::Abbreviation
            } else {
                Category::Initials
            }
        } else if word.chars()
                              .filter(|c| !c.is_alphabetic() && !is_combining(*c))
                              .count() > 2 {
            Category::Other
        } else if is_missing_vowels(word) {
            if trust_capitalization &&
               word.chars().all(|c| !c.is_alphabetic() || c.is_uppercase()) {
                Category::Initials
            } else if location == Location::End &&
               surname::is_vowelless_surname(word, trust_capitalization) {
                Category::Name
            } else if chars <= 5 {
                Category::Initials
            } else {
                Category::Other
            }
        } else {
            if chars <= 5 && trust_capitalization &&
               word.chars().all(|c| !c.is_alphabetic() || c.is_uppercase()) {
                Category::Initials
            } else if chars == 2 && !trust_capitalization && !TWO_LETTER_GIVEN_NAMES.contains(word) {
                Category::Initials
            } else {
                Category::Name
            }
        };

        let namecased = if trust_capitalization && ascii && is_capitalized(word) {
            Cow::Borrowed(word)
        } else {
            let might_be_particle = location == Location::Middle;
            Cow::Owned(namecase::namecase(word, might_be_particle))
        };

        NamePart {
            word: word,
            chars: chars,
            category: category,
            namecased: namecased,
        }
    }

    #[inline]
    pub fn is_initials(&self) -> bool {
        self.category == Category::Initials
    }

    #[inline]
    pub fn is_namelike(&self) -> bool {
        self.category == Category::Name
    }

    #[inline]
    pub fn is_abbreviation(&self) -> bool {
        self.category == Category::Abbreviation
    }
}

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

    #[test]
    fn one_word() {
        assert_eq!(1,
                   NamePart::all_from_text("John", true, Location::Start).count());
    }

    #[test]
    fn two_words() {
        assert_eq!(2,
                   NamePart::all_from_text("&* John Doe! ☃", true, Location::Start).count());
    }

    #[test]
    fn only_junk() {
        assert_eq!(0,
                   NamePart::all_from_text(" ... 23 ", true, Location::Start).count());
    }

    #[test]
    fn single_ascii() {
        assert_eq!(Category::Initials,
                   NamePart::from_word("I", true, Location::Start).category);
    }

    #[test]
    fn single_han() {
        assert_eq!(Category::Name,
                   NamePart::from_word("鄭", true, Location::Start).category);
    }

    #[test]
    fn abbreviated_ascii() {
        assert_eq!(Category::Initials,
                   NamePart::from_word("I.", true, Location::Start).category);
    }

    #[test]
    fn abbreviated_double_ascii() {
        assert_eq!(Category::Abbreviation,
                   NamePart::from_word("MI.", true, Location::Start).category);
    }

    #[test]
    fn double_abbreviated_double_ascii() {
        assert_eq!(Category::Initials,
                   NamePart::from_word("M.I.", true, Location::Start).category);
    }

    #[test]
    fn junk() {
        assert_eq!(Category::Other,
                   NamePart::from_word("503(a)", true, Location::Start).category);
    }

    #[test]
    fn no_vowels() {
        assert_eq!(Category::Initials,
                   NamePart::from_word("JM", true, Location::Start).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("jm", true, Location::Start).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("JM", false, Location::Start).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("JMMMMM", true, Location::Start).category);
        assert_eq!(Category::Other,
                   NamePart::from_word("jmmmmm", true, Location::Start).category);
        assert_eq!(Category::Other,
                   NamePart::from_word("JMMMMM", false, Location::Start).category);
    }

    #[test]
    fn vowelless_surname() {
        assert_eq!(Category::Initials,
                   NamePart::from_word("NG", true, Location::Start).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("Ng", true, Location::Start).category);
        assert_eq!(Category::Name,
                   NamePart::from_word("Ng", true, Location::End).category);
        assert_eq!(Category::Name,
                   NamePart::from_word("NG", false, Location::End).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("NG", true, Location::End).category);
    }

    #[test]
    fn word() {
        assert_eq!(Category::Initials,
                   NamePart::from_word("JEM", true, Location::Start).category);
        assert_eq!(Category::Name,
                   NamePart::from_word("Jem", true, Location::Start).category);
        assert_eq!(Category::Name,
                   NamePart::from_word("JEM", false, Location::Start).category);
    }

    #[test]
    fn two_letters() {
        assert_eq!(Category::Name,
                   NamePart::from_word("Al", true, Location::Start).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("AL", true, Location::Start).category);
        assert_eq!(Category::Name,
                   NamePart::from_word("AL", false, Location::Start).category);
        assert_eq!(Category::Name,
                   NamePart::from_word("At", true, Location::Start).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("AT", true, Location::Start).category);
        assert_eq!(Category::Initials,
                   NamePart::from_word("AT", false, Location::Start).category);
    }
}

// Everything with a vowel reasonably popular in the Social Security data:
// https://www.ssa.gov/oact/babynames/limits.html
static TWO_LETTER_GIVEN_NAMES: phf::Set<&'static str> = phf_set! {
    "Jo",
    "JO",
    "jo",
    "Ty",
    "TY",
    "ty",
    "Ed",
    "ED",
    "ed",
    "Al",
    "AL",
    "al",
    "Bo",
    "BO",
    "bo",
    "Lu",
    "LU",
    "lu",
    "Cy",
    "CY",
    "cy",
    "An",
    "AN",
    "an",
    "La",
    "LA",
    "la",
    "Aj",
    "AJ",
    "aj",
    "Le",
    "LE",
    "le",
    "Om",
    "OM",
    "om",
    "Pa",
    "PA",
    "pa",
    "De",
    "DE",
    "de",
    "Ky",
    "KY",
    "ky",
    "My",
    "MY",
    "my",
    "Vy",
    "VY",
    "vy",
    "Vi",
    "VI",
    "vi",
    "Ka",
    "KA",
    "ka",
    "Sy",
    "SY",
    "sy",
    "Vu",
    "VU",
    "vu",
    "Yu",
    "YU",
    "yu",
    "Mi",
    "MI",
    "mi",
    "Su",
    "SU",
    "su",
    "Ma",
    "MA",
    "ma",
    "Ha",
    "HA",
    "ha",
    "Ki",
    "KI",
    "ki",
    "Tu",
    "TU",
    "tu",
    "Ji",
    "JI",
    "ji",
    "Ja",
    "JA",
    "ja",
    "Ly",
    "LY",
    "ly",
    "Li",
    "LI",
    "li",
    "Ai",
    "AI",
    "ai",
    "Ry",
    "RY",
    "ry",
    "Ab",
    "AB",
    "ab",
    "Ho",
    "HO",
    "ho",
    "Da",
    "DA",
    "da",
    "Oz",
    "OZ",
    "oz",
    "El",
    "EL",
    "el",
    "Na",
    "NA",
    "na",
    "Yi",
    "YI",
    "yi",
    "Em",
    "EM",
    "em",
    "Di",
    "DI",
    "di",
    "Go",
    "GO",
    "go",
    "Ev",
    "EV",
    "ev",
    "Mo",
    "MO",
    "mo",
    "Lo",
    "LO",
    "lo",
    "Ra",
    "RA",
    "ra",
    "Do",
    "DO",
    "do",
    "Gi",
    "GI",
    "gi",
};
<|endoftext|>


<commit_before>use std;
use std::num::One;

/// Calculate ceil(a / b).
pub fn div_ceil<T>(a: T, b: T) -> T where
    T: std::ops::Add<T, Output = T> + std::ops::Sub<T, Output = T> +
       std::ops::Div<T, Output = T> + std::num::One + Copy
{
    (a + b - T::one()) / b
}

pub trait CollectSlice: Iterator {
    /// Loop through the iterator, writing items into the given slice until either the
    /// iterator runs out or the slice fills up. Return the number of items written.
    fn collect_slice(&mut self, slice: &mut [Self::Item]) -> usize;
}

impl<T, I: Iterator<Item = T>> CollectSlice for I {
    fn collect_slice(&mut self, slice: &mut [Self::Item]) -> usize {
        slice.iter_mut().zip(self).fold(0, |count, (s, i)| {
            *s = i;
            count + 1
        })
    }
}

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

    #[test]
    fn test_div_ceil() {
        assert_eq!(div_ceil(13, 12), 2);
        assert_eq!(div_ceil(1, 2), 1);
        assert_eq!(div_ceil(0, 3), 0);
    }

    #[test]
    fn test_collect_slice() {
        {
            let mut buf = [0; 5];

            (0..5).map(|i| {
                i + 1
            }).collect_slice(&mut buf[..]);

            assert_eq!(buf[0], 1);
            assert_eq!(buf[1], 2);
            assert_eq!(buf[2], 3);
            assert_eq!(buf[3], 4);
            assert_eq!(buf[4], 5);
        }

        {
            let mut buf = [0; 5];

            (0..3).map(|i| {
                i + 1
            }).collect_slice(&mut buf[..]);

            assert_eq!(buf[0], 1);
            assert_eq!(buf[1], 2);
            assert_eq!(buf[2], 3);
            assert_eq!(buf[3], 0);
            assert_eq!(buf[4], 0);
        }

        {
            let mut buf = [0; 5];

            let mut iter = (0..3).map(|i| {
                i + 1
            });

            iter.collect_slice(&mut buf[2..]);

            assert_eq!(buf[0], 0);
            assert_eq!(buf[1], 0);
            assert_eq!(buf[2], 1);
            assert_eq!(buf[3], 2);
            assert_eq!(buf[4], 3);
        }

        {
            let mut buf = [0; 3];

            let mut iter = (0..5).map(|i| {
                i + 1
            });

            iter.collect_slice(&mut buf[..]);

            assert_eq!(buf[0], 1);
            assert_eq!(buf[1], 2);
            assert_eq!(buf[2], 3);

            assert_eq!(iter.next().unwrap(), 4);
            assert_eq!(iter.next().unwrap(), 5);
        }
    }
}
<commit_msg>Add collect_slice_checked<commit_after>use std;
use std::num::One;

/// Calculate ceil(a / b).
pub fn div_ceil<T>(a: T, b: T) -> T where
    T: std::ops::Add<T, Output = T> + std::ops::Sub<T, Output = T> +
       std::ops::Div<T, Output = T> + std::num::One + Copy
{
    (a + b - T::one()) / b
}

pub trait CollectSlice: Iterator {
    /// Loop through the iterator, writing items into the given slice until either the
    /// iterator runs out or the slice fills up. Return the number of items written.
    fn collect_slice(&mut self, slice: &mut [Self::Item]) -> usize;

    /// Perform `collect_slice()` and panic if there weren't enough elements to fill up
    /// the buffer.
    fn collect_slice_checked(&mut self, slice: &mut [Self::Item]);
}

impl<T, I: Iterator<Item = T>> CollectSlice for I {
    fn collect_slice(&mut self, slice: &mut [Self::Item]) -> usize {
        slice.iter_mut().zip(self).fold(0, |count, (s, i)| {
            *s = i;
            count + 1
        })
    }

    fn collect_slice_checked(&mut self, slice: &mut [Self::Item]) {
        assert_eq!(self.collect_slice(slice), slice.len());
    }
}

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

    #[test]
    fn test_div_ceil() {
        assert_eq!(div_ceil(13, 12), 2);
        assert_eq!(div_ceil(1, 2), 1);
        assert_eq!(div_ceil(0, 3), 0);
    }

    #[test]
    fn test_collect_slice() {
        {
            let mut buf = [0; 5];

            (0..5).map(|i| {
                i + 1
            }).collect_slice(&mut buf[..]);

            assert_eq!(buf[0], 1);
            assert_eq!(buf[1], 2);
            assert_eq!(buf[2], 3);
            assert_eq!(buf[3], 4);
            assert_eq!(buf[4], 5);
        }

        {
            let mut buf = [0; 5];

            let mut iter = (0..3).map(|i| {
                i + 1
            });

            iter.collect_slice(&mut buf[2..]);

            assert_eq!(buf[0], 0);
            assert_eq!(buf[1], 0);
            assert_eq!(buf[2], 1);
            assert_eq!(buf[3], 2);
            assert_eq!(buf[4], 3);
        }

        {
            let mut buf = [0; 3];

            let mut iter = (0..5).map(|i| {
                i + 1
            });

            iter.collect_slice(&mut buf[..]);

            assert_eq!(buf[0], 1);
            assert_eq!(buf[1], 2);
            assert_eq!(buf[2], 3);

            assert_eq!(iter.next().unwrap(), 4);
            assert_eq!(iter.next().unwrap(), 5);
        }
    }

    #[test]
    #[should_panic]
    fn test_collect_slice_checked() {
        let mut buf = [0; 5];

        (0..3).map(|i| {
            i + 1
        }).collect_slice_checked(&mut buf[..]);
    }
}
<|endoftext|>


<commit_before>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
//! Definitions for interfacing *PICC* (Proximity Integrated Circuit Card) - A card or tag using the ISO 14443A interface, eg. Mifare or NTAG203.

pub mod uid;
pub mod atqa;

pub use self::uid::UID;
pub use self::atqa::ATQA;

/// Cascade Tag Type A.
/// Used during anti collision.
pub const CT: u8 = 0x88;

/// Commands sent to the PICC.
#[allow(non_camel_case_types)]
#[derive(Copy,Clone)]
#[cfg_attr(not(feature = "ndebug"), derive(Debug))]
#[repr(u8)]
pub enum Cmd {
	/// The commands used by the PCD to manage communication with several PICCs (ISO 14443-3, Type A, section 6.4)
	/// REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
	REQA			= 0x26,
	/// Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and prepare for anticollision or selection. 7 bit frame.
	WUPA			= 0x52,
	/// Anti collision/Select, Cascade Level 1
	SEL_CL1			= 0x93,
	/// Anti collision/Select, Cascade Level 2
	SEL_CL2			= 0x95,
	/// Anti collision/Select, Cascade Level 3
	SEL_CL3			= 0x97,
	/// HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
	HLTA			= 0x50,
	/// The commands used for MIFARE Classic (from http://www.mouser.com/ds/2/302/MF1S503x-89574.pdf, Section 9)
	///
	/// Use PCD_MFAuthent to authenticate access to a sector, then use these commands to read/write/modify the blocks on the sector.	///
	/// The read/write commands can also be used for MIFARE Ultralight.
	///
	/// Perform authentication with Key A
	MF_AUTH_KEY_A	= 0x60,
	/// Perform authentication with Key B
	MF_AUTH_KEY_B	= 0x61,
	/// Reads one 16 byte block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
	MF_READ			= 0x30,
	/// Writes one 16 byte block to the authenticated sector of the PICC. Called "COMPATIBILITY WRITE" for MIFARE Ultralight.
	MF_WRITE		= 0xA0,
	/// Decrements the contents of a block and stores the result in the internal data register.
	MF_DECREMENT	= 0xC0,
	/// Increments the contents of a block and stores the result in the internal data register.
	MF_INCREMENT	= 0xC1,
	/// Reads the contents of a block into the internal data register.
	MF_RESTORE		= 0xC2,
	/// Writes the contents of the internal data register to a block.
	MF_TRANSFER		= 0xB0,
	/// The commands used for MIFARE Ultralight (from http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf, Section 8.6)
	///
	/// The `MF_READ` and `MF_WRITE` can also be used for MIFARE Ultralight.
	/// Writes one 4 byte page to the PICC.
	UL_WRITE		= 0xA2,
}

/// PICC types we can detect.
#[allow(non_camel_case_types)]
#[derive(Copy,Clone,Eq,PartialEq)]
#[cfg_attr(not(feature = "ndebug"), derive(Debug))]
pub enum Type {
	/// Unknown PICC type
	Unknown,
	/// SAK indicates UID is not complete
	Incomplete,
	/// PICC compliant with ISO/IEC 14443-4
	ISO_14443_4,
	/// PICC compliant with ISO/IEC 18092 (NFC)
	ISO_18092,
	/// MIFARE Classic protocol, 320 bytes
	MIFARE_MINI,
	/// MIFARE Classic protocol, 1KB
	MIFARE_1K,
	/// MIFARE Classic protocol, 4KB
	MIFARE_4K,
	/// MIFARE Ultralight or Ultralight C
	MIFARE_UL,
	/// MIFARE Plus
	MIFARE_PLUS,
	/// Only mentioned in NXP AN 10833 MIFARE Type Identification Procedure
	TNP3XXX,
}

impl Type {

	/// Get picc::Type from SAK byte.
	pub fn from_sak(sak: u8) -> Self {
		use self::Type::*;

		// http://www.nxp.com/documents/application_note/AN10833.pdf
		// 3.2 Coding of Select Acknowledge (SAK)
		// ignore 8-bit (iso14443 starts with LSBit = bit 1)
		// fixes wrong type for manufacturer Infineon (http://nfc-tools.org/index.php?title=ISO14443A)
		match sak & 0x7F {
			0x04 => Incomplete,
			0x09 => MIFARE_MINI,
			0x08 => MIFARE_1K,
			0x18 => MIFARE_4K,
			0x00 => MIFARE_UL,

			0x10 |
			0x11 => MIFARE_PLUS,

			0x20 => ISO_14443_4,
			0x40 => ISO_18092,
			0x01 => TNP3XXX,

			_ => Unknown,
		}
	}
}

pub mod mifare {
	//! MIFARE PICC definitions.

	/// Default key on factory outlet.
	pub const FACTORY_KEY: Key = Key([0xFF; 6]);

	/// MIFARE Crypto1 Key.
	#[derive(Copy,Clone,Eq,PartialEq)]
	#[cfg_attr(not(feature = "ndebug"), derive(Debug))]
	pub struct Key([u8; 6]);

	impl Default for Key {
		#[inline]
		fn default() -> Self {
			Key([0; 6])
		}
	}

	impl Key {
		#[inline]
		pub fn len(&self) -> usize {
			self.0.len()
		}
	}

	impl AsRef<[u8]> for Key {
		#[inline]
		fn as_ref(&self) -> &[u8] {
			self.0.as_ref()
		}
	}

	impl AsMut<[u8]> for Key {
		#[inline]
		fn as_mut(&mut self) -> &mut [u8] {
			self.0.as_mut()
		}
	}
}
<commit_msg>Add From implementations for picc::mifare::Key.<commit_after>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
//! Definitions for interfacing *PICC* (Proximity Integrated Circuit Card) - A card or tag using the ISO 14443A interface, eg. Mifare or NTAG203.

pub mod uid;
pub mod atqa;

pub use self::uid::UID;
pub use self::atqa::ATQA;

/// Cascade Tag Type A.
/// Used during anti collision.
pub const CT: u8 = 0x88;

/// Commands sent to the PICC.
#[allow(non_camel_case_types)]
#[derive(Copy,Clone)]
#[cfg_attr(not(feature = "ndebug"), derive(Debug))]
#[repr(u8)]
pub enum Cmd {
	/// The commands used by the PCD to manage communication with several PICCs (ISO 14443-3, Type A, section 6.4)
	/// REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
	REQA			= 0x26,
	/// Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and prepare for anticollision or selection. 7 bit frame.
	WUPA			= 0x52,
	/// Anti collision/Select, Cascade Level 1
	SEL_CL1			= 0x93,
	/// Anti collision/Select, Cascade Level 2
	SEL_CL2			= 0x95,
	/// Anti collision/Select, Cascade Level 3
	SEL_CL3			= 0x97,
	/// HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
	HLTA			= 0x50,
	/// The commands used for MIFARE Classic (from http://www.mouser.com/ds/2/302/MF1S503x-89574.pdf, Section 9)
	///
	/// Use PCD_MFAuthent to authenticate access to a sector, then use these commands to read/write/modify the blocks on the sector.	///
	/// The read/write commands can also be used for MIFARE Ultralight.
	///
	/// Perform authentication with Key A
	MF_AUTH_KEY_A	= 0x60,
	/// Perform authentication with Key B
	MF_AUTH_KEY_B	= 0x61,
	/// Reads one 16 byte block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
	MF_READ			= 0x30,
	/// Writes one 16 byte block to the authenticated sector of the PICC. Called "COMPATIBILITY WRITE" for MIFARE Ultralight.
	MF_WRITE		= 0xA0,
	/// Decrements the contents of a block and stores the result in the internal data register.
	MF_DECREMENT	= 0xC0,
	/// Increments the contents of a block and stores the result in the internal data register.
	MF_INCREMENT	= 0xC1,
	/// Reads the contents of a block into the internal data register.
	MF_RESTORE		= 0xC2,
	/// Writes the contents of the internal data register to a block.
	MF_TRANSFER		= 0xB0,
	/// The commands used for MIFARE Ultralight (from http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf, Section 8.6)
	///
	/// The `MF_READ` and `MF_WRITE` can also be used for MIFARE Ultralight.
	/// Writes one 4 byte page to the PICC.
	UL_WRITE		= 0xA2,
}

/// PICC types we can detect.
#[allow(non_camel_case_types)]
#[derive(Copy,Clone,Eq,PartialEq)]
#[cfg_attr(not(feature = "ndebug"), derive(Debug))]
pub enum Type {
	/// Unknown PICC type
	Unknown,
	/// SAK indicates UID is not complete
	Incomplete,
	/// PICC compliant with ISO/IEC 14443-4
	ISO_14443_4,
	/// PICC compliant with ISO/IEC 18092 (NFC)
	ISO_18092,
	/// MIFARE Classic protocol, 320 bytes
	MIFARE_MINI,
	/// MIFARE Classic protocol, 1KB
	MIFARE_1K,
	/// MIFARE Classic protocol, 4KB
	MIFARE_4K,
	/// MIFARE Ultralight or Ultralight C
	MIFARE_UL,
	/// MIFARE Plus
	MIFARE_PLUS,
	/// Only mentioned in NXP AN 10833 MIFARE Type Identification Procedure
	TNP3XXX,
}

impl Type {

	/// Get picc::Type from SAK byte.
	pub fn from_sak(sak: u8) -> Self {
		use self::Type::*;

		// http://www.nxp.com/documents/application_note/AN10833.pdf
		// 3.2 Coding of Select Acknowledge (SAK)
		// ignore 8-bit (iso14443 starts with LSBit = bit 1)
		// fixes wrong type for manufacturer Infineon (http://nfc-tools.org/index.php?title=ISO14443A)
		match sak & 0x7F {
			0x04 => Incomplete,
			0x09 => MIFARE_MINI,
			0x08 => MIFARE_1K,
			0x18 => MIFARE_4K,
			0x00 => MIFARE_UL,

			0x10 |
			0x11 => MIFARE_PLUS,

			0x20 => ISO_14443_4,
			0x40 => ISO_18092,
			0x01 => TNP3XXX,

			_ => Unknown,
		}
	}
}

pub mod mifare {
	//! MIFARE PICC definitions.

	/// Default key on factory outlet.
	pub const FACTORY_KEY: Key = Key([0xFF; 6]);

	/// MIFARE Crypto1 Key.
	#[derive(Copy,Clone,Eq,PartialEq)]
	#[cfg_attr(not(feature = "ndebug"), derive(Debug))]
	pub struct Key([u8; 6]);

	impl Default for Key {
		#[inline]
		fn default() -> Self {
			Key([0; 6])
		}
	}

	impl Key {
		#[inline]
		pub fn len(&self) -> usize {
			self.0.len()
		}
	}

	impl AsRef<[u8]> for Key {
		#[inline]
		fn as_ref(&self) -> &[u8] {
			self.0.as_ref()
		}
	}

	impl AsMut<[u8]> for Key {
		#[inline]
		fn as_mut(&mut self) -> &mut [u8] {
			self.0.as_mut()
		}
	}

	impl From<[u8; 6]> for Key {
		#[inline]
		fn from(bytes: [u8; 6]) -> Self {
			Key(bytes)
		}
	}

	/// Constructs `Key` from 48 lower bits (6 lower bytes) of `u64`.
	impl From<u64> for Key {
		fn from(bits: u64) -> Self {
			let bytes = [
				(bits >> 40) as u8,
				(bits >> 32) as u8,
				(bits >> 24) as u8,
				(bits >> 16) as u8,
				(bits >>  8) as u8,
				bits as u8
			];

			Key::from(bytes)
		}
	}

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

		#[test]
		fn test_key_from_u48() {
			let key_bits: u64 = 0x112233445566;
			let key = Key::from(key_bits);

			assert_eq!(key.as_ref(), &[0x11, 0x22, 0x33, 0x44, 0x55, 0x66]);
		}

		#[test]
		fn test_key_from_u64() {
			let key_bits: u64 = 0x1122334455667788;
			let key = Key::from(key_bits);

			assert_eq!(key.as_ref(), &[0x33, 0x44, 0x55, 0x66, 0x77, 0x88]);
		}
	}
}
<|endoftext|>


<commit_before>use summary::Summary;

struct BoxWhiskerData {
    box_lo: f64,
    box_mid: f64,
    box_hi: f64,
    wh_lo: f64,
    wh_hi: f64,
}

impl BoxWhiskerData {
    fn from_summary(summary: &Summary) -> Self {
        BoxWhiskerData {
            box_lo: summary.percentile(0.25).unwrap(),
            box_mid: summary.median(),
            box_hi: summary.percentile(0.75).unwrap(),
            wh_lo: summary.min(),
            wh_hi: summary.max(),
        }
    }
}

struct BoxWhiskerCols {
    box_lo: usize,
    box_mid: usize,
    box_hi: usize,
    wh_lo: usize,
    wh_hi: usize,
}

impl BoxWhiskerCols {
    fn new(data: &BoxWhiskerData, width: usize) -> Self {
        let max_col = width - 1;
        let range = data.wh_hi - data.wh_lo;
        let normalize = |x| (x - data.wh_lo) / range;
        let scale = |x| (normalize(x) * (max_col as f64)) as f64;
        let to_col = |x| scale(x).floor() as usize;

        BoxWhiskerCols {
            box_lo: to_col(data.box_lo),
            box_mid: to_col(data.box_mid),
            box_hi: to_col(data.box_hi),
            wh_lo: to_col(data.wh_lo),
            wh_hi: to_col(data.wh_hi),
        }
    }
}

struct RowChars {
    wh_lo: &'static str,
    wh_lo_box_lo_fill: &'static str,
    box_lo: &'static str,
    box_lo_box_mid_fill: &'static str,
    box_mid: &'static str,
    box_mid_box_hi_fill: &'static str,
    box_hi: &'static str,
    box_hi_wh_hi_fill: &'static str,
    wh_hi: &'static str,
}

impl RowChars {
    pub fn render(&self, row: &mut Vec<String>, cols: &BoxWhiskerCols) {
        row[cols.wh_lo] = self.wh_lo.to_string();
        for i in (cols.wh_lo + 1)..cols.box_lo {
            row[i] = self.wh_lo_box_lo_fill.to_string();
        }
        row[cols.box_lo] = self.box_lo.to_string();
        for i in (cols.box_lo + 1)..cols.box_mid {
            row[i] = self.box_lo_box_mid_fill.to_string();
        }
        row[cols.box_mid] = self.box_mid.to_string();
        for i in (cols.box_mid + 1)..cols.box_hi {
            row[i] = self.box_mid_box_hi_fill.to_string();
        }
        row[cols.box_hi] = self.box_hi.to_string();
        for i in (cols.box_hi + 1)..cols.wh_hi {
            row[i] = self.box_hi_wh_hi_fill.to_string();
        }
        row[cols.wh_hi] = self.wh_hi.to_string();
    }
}

struct CharSet(RowChars, RowChars, RowChars);

static ASCII_CHARS: CharSet = CharSet(
    RowChars {
        wh_lo: " ",
        wh_lo_box_lo_fill: " ",
        box_lo: "+",
        box_lo_box_mid_fill: "-",
        box_mid: "+",
        box_mid_box_hi_fill: "-",
        box_hi: "+",
        box_hi_wh_hi_fill: " ",
        wh_hi: " ",
    },
    RowChars {
        wh_lo: "|",
        wh_lo_box_lo_fill: "-",
        box_lo: "|",
        box_lo_box_mid_fill: " ",
        box_mid: "|",
        box_mid_box_hi_fill: " ",
        box_hi: "|",
        box_hi_wh_hi_fill: "-",
        wh_hi: "|",
    },
    RowChars {
        wh_lo: " ",
        wh_lo_box_lo_fill: " ",
        box_lo: "+",
        box_lo_box_mid_fill: "-",
        box_mid: "+",
        box_mid_box_hi_fill: "-",
        box_hi: "+",
        box_hi_wh_hi_fill: " ",
        wh_hi: " ",
    },
);

static UNICODE_CHARS: CharSet = CharSet(
    RowChars {
        wh_lo: "┬",
        wh_lo_box_lo_fill: " ",
        box_lo: "┌",
        box_lo_box_mid_fill: "─",
        box_mid: "┬",
        box_mid_box_hi_fill: "─",
        box_hi: "┐",
        box_hi_wh_hi_fill: " ",
        wh_hi: "┬",
    },
    RowChars {
        wh_lo: "├",
        wh_lo_box_lo_fill: "─",
        box_lo: "┤",
        box_lo_box_mid_fill: " ",
        box_mid: "│",
        box_mid_box_hi_fill: " ",
        box_hi: "├",
        box_hi_wh_hi_fill: "─",
        wh_hi: "┤",
    },
    RowChars {
        wh_lo: "┴",
        wh_lo_box_lo_fill: " ",
        box_lo: "└",
        box_lo_box_mid_fill: "─",
        box_mid: "┴",
        box_mid_box_hi_fill: "─",
        box_hi: "┘",
        box_hi_wh_hi_fill: " ",
        wh_hi: "┴",
    },
);

fn make_row(width: usize) -> Vec<String> {
    use std::iter::repeat;

    let mut row = vec![];
    row.extend(repeat(String::from("")).take(width));

    row
}

struct Plot(Vec<String>, Vec<String>, Vec<String>);

impl Plot {
    fn new(width: usize) -> Self {
        Plot(make_row(width), make_row(width), make_row(width))
    }

    fn render(&self) -> String {
        let rows = vec![
            self.0.join(""),
            self.1.join(""),
            self.2.join(""),
        ];

        rows.join("\n")
    }
}

pub fn ascii_summary_plot(summary: &Summary, width: usize) -> String {
    let data = BoxWhiskerData::from_summary(summary);
    let cols = BoxWhiskerCols::new(&data, width);

    let mut plot = Plot::new(width);

    ASCII_CHARS.0.render(&mut plot.0, &cols);
    ASCII_CHARS.1.render(&mut plot.1, &cols);
    ASCII_CHARS.2.render(&mut plot.2, &cols);

    plot.render()
}

pub fn summary_plot(summary: &Summary, width: usize) -> String {
    let data = BoxWhiskerData::from_summary(summary);
    let cols = BoxWhiskerCols::new(&data, width);

    let mut plot = Plot::new(width);

    UNICODE_CHARS.0.render(&mut plot.0, &cols);
    UNICODE_CHARS.1.render(&mut plot.1, &cols);
    UNICODE_CHARS.2.render(&mut plot.2, &cols);

    plot.render()
}

fn make_padding(cols: usize) -> String {
    use std::iter::{FromIterator, repeat};

    String::from_iter(repeat(String::from(" ")).take(cols))
}

fn pad(s: &String, cols: usize) -> String {
    let padding = make_padding(cols);

    let padded: Vec<String> = s
        .split("\n")
        .map(|l| format!("{}{}", padding, l))
        .collect();

    padded.join("\n")
}

pub fn comparison_plot(
    summary1: &Summary,
    summary2: &Summary,
    width: usize,
    ascii: bool,
) -> String {
    let min = summary1.min().min(summary2.min());
    let max = summary1.max().max(summary2.max());

    let range = max - min;
    let range1 = summary1.max() - summary1.min();
    let range2 = summary2.max() - summary2.min();

    let proportion1 = range1 / range;
    let proportion2 = range2 / range;

    let width1 = (proportion1 * (width as f64)).floor() as usize;
    let width2 = (proportion2 * (width as f64)).floor() as usize;

    let offset1 = {
        let neg_proportion = (summary1.min() - min) / range;
        (neg_proportion * (width as f64)).floor() as usize
    };
    let offset2 = {
        let neg_proportion = (summary2.min() - min) / range;
        (neg_proportion * (width as f64)).floor() as usize
    };

    let (plot1, plot2) = if ascii {
        let plot1 = ascii_summary_plot(&summary1, width1);
        let plot2 = ascii_summary_plot(&summary2, width2);
        (plot1, plot2)
    } else {
        let plot1 = summary_plot(&summary1, width1);
        let plot2 = summary_plot(&summary2, width2);
        (plot1, plot2)
    };

    format!("{}\n{}", pad(&plot1, offset1), pad(&plot2, offset2))
}
<commit_msg>Add `plot()` method to `CharSet`, use in top-level funcs<commit_after>use summary::Summary;

struct BoxWhiskerData {
    box_lo: f64,
    box_mid: f64,
    box_hi: f64,
    wh_lo: f64,
    wh_hi: f64,
}

impl BoxWhiskerData {
    fn from_summary(summary: &Summary) -> Self {
        BoxWhiskerData {
            box_lo: summary.percentile(0.25).unwrap(),
            box_mid: summary.median(),
            box_hi: summary.percentile(0.75).unwrap(),
            wh_lo: summary.min(),
            wh_hi: summary.max(),
        }
    }
}

struct BoxWhiskerCols {
    box_lo: usize,
    box_mid: usize,
    box_hi: usize,
    wh_lo: usize,
    wh_hi: usize,
}

impl BoxWhiskerCols {
    fn new(data: &BoxWhiskerData, width: usize) -> Self {
        let max_col = width - 1;
        let range = data.wh_hi - data.wh_lo;
        let normalize = |x| (x - data.wh_lo) / range;
        let scale = |x| (normalize(x) * (max_col as f64)) as f64;
        let to_col = |x| scale(x).floor() as usize;

        BoxWhiskerCols {
            box_lo: to_col(data.box_lo),
            box_mid: to_col(data.box_mid),
            box_hi: to_col(data.box_hi),
            wh_lo: to_col(data.wh_lo),
            wh_hi: to_col(data.wh_hi),
        }
    }
}

struct RowChars {
    wh_lo: &'static str,
    wh_lo_box_lo_fill: &'static str,
    box_lo: &'static str,
    box_lo_box_mid_fill: &'static str,
    box_mid: &'static str,
    box_mid_box_hi_fill: &'static str,
    box_hi: &'static str,
    box_hi_wh_hi_fill: &'static str,
    wh_hi: &'static str,
}

impl RowChars {
    pub fn render(&self, row: &mut Vec<String>, cols: &BoxWhiskerCols) {
        row[cols.wh_lo] = self.wh_lo.to_string();
        for i in (cols.wh_lo + 1)..cols.box_lo {
            row[i] = self.wh_lo_box_lo_fill.to_string();
        }
        row[cols.box_lo] = self.box_lo.to_string();
        for i in (cols.box_lo + 1)..cols.box_mid {
            row[i] = self.box_lo_box_mid_fill.to_string();
        }
        row[cols.box_mid] = self.box_mid.to_string();
        for i in (cols.box_mid + 1)..cols.box_hi {
            row[i] = self.box_mid_box_hi_fill.to_string();
        }
        row[cols.box_hi] = self.box_hi.to_string();
        for i in (cols.box_hi + 1)..cols.wh_hi {
            row[i] = self.box_hi_wh_hi_fill.to_string();
        }
        row[cols.wh_hi] = self.wh_hi.to_string();
    }
}

struct CharSet(RowChars, RowChars, RowChars);

impl CharSet {
    pub fn plot(&self, summary: &Summary, width: usize) -> String {
        let data = BoxWhiskerData::from_summary(summary);
        let cols = BoxWhiskerCols::new(&data, width);

        let mut plot = Plot::new(width);

        self.0.render(&mut plot.0, &cols);
        self.1.render(&mut plot.1, &cols);
        self.2.render(&mut plot.2, &cols);

        plot.render()
    }
}

static ASCII_CHARS: CharSet = CharSet(
    RowChars {
        wh_lo: " ",
        wh_lo_box_lo_fill: " ",
        box_lo: "+",
        box_lo_box_mid_fill: "-",
        box_mid: "+",
        box_mid_box_hi_fill: "-",
        box_hi: "+",
        box_hi_wh_hi_fill: " ",
        wh_hi: " ",
    },
    RowChars {
        wh_lo: "|",
        wh_lo_box_lo_fill: "-",
        box_lo: "|",
        box_lo_box_mid_fill: " ",
        box_mid: "|",
        box_mid_box_hi_fill: " ",
        box_hi: "|",
        box_hi_wh_hi_fill: "-",
        wh_hi: "|",
    },
    RowChars {
        wh_lo: " ",
        wh_lo_box_lo_fill: " ",
        box_lo: "+",
        box_lo_box_mid_fill: "-",
        box_mid: "+",
        box_mid_box_hi_fill: "-",
        box_hi: "+",
        box_hi_wh_hi_fill: " ",
        wh_hi: " ",
    },
);

static UNICODE_CHARS: CharSet = CharSet(
    RowChars {
        wh_lo: "┬",
        wh_lo_box_lo_fill: " ",
        box_lo: "┌",
        box_lo_box_mid_fill: "─",
        box_mid: "┬",
        box_mid_box_hi_fill: "─",
        box_hi: "┐",
        box_hi_wh_hi_fill: " ",
        wh_hi: "┬",
    },
    RowChars {
        wh_lo: "├",
        wh_lo_box_lo_fill: "─",
        box_lo: "┤",
        box_lo_box_mid_fill: " ",
        box_mid: "│",
        box_mid_box_hi_fill: " ",
        box_hi: "├",
        box_hi_wh_hi_fill: "─",
        wh_hi: "┤",
    },
    RowChars {
        wh_lo: "┴",
        wh_lo_box_lo_fill: " ",
        box_lo: "└",
        box_lo_box_mid_fill: "─",
        box_mid: "┴",
        box_mid_box_hi_fill: "─",
        box_hi: "┘",
        box_hi_wh_hi_fill: " ",
        wh_hi: "┴",
    },
);

fn make_row(width: usize) -> Vec<String> {
    use std::iter::repeat;

    let mut row = vec![];
    row.extend(repeat(String::from("")).take(width));

    row
}

struct Plot(Vec<String>, Vec<String>, Vec<String>);

impl Plot {
    fn new(width: usize) -> Self {
        Plot(make_row(width), make_row(width), make_row(width))
    }

    fn render(&self) -> String {
        let rows = vec![
            self.0.join(""),
            self.1.join(""),
            self.2.join(""),
        ];

        rows.join("\n")
    }
}

pub fn ascii_summary_plot(summary: &Summary, width: usize) -> String {
    ASCII_CHARS.plot(summary, width)
}

pub fn summary_plot(summary: &Summary, width: usize) -> String {
    UNICODE_CHARS.plot(summary, width)
}

fn make_padding(cols: usize) -> String {
    use std::iter::{FromIterator, repeat};

    String::from_iter(repeat(String::from(" ")).take(cols))
}

fn pad(s: &String, cols: usize) -> String {
    let padding = make_padding(cols);

    let padded: Vec<String> = s
        .split("\n")
        .map(|l| format!("{}{}", padding, l))
        .collect();

    padded.join("\n")
}

pub fn comparison_plot(
    summary1: &Summary,
    summary2: &Summary,
    width: usize,
    ascii: bool,
) -> String {
    let min = summary1.min().min(summary2.min());
    let max = summary1.max().max(summary2.max());

    let range = max - min;
    let range1 = summary1.max() - summary1.min();
    let range2 = summary2.max() - summary2.min();

    let proportion1 = range1 / range;
    let proportion2 = range2 / range;

    let width1 = (proportion1 * (width as f64)).floor() as usize;
    let width2 = (proportion2 * (width as f64)).floor() as usize;

    let offset1 = {
        let neg_proportion = (summary1.min() - min) / range;
        (neg_proportion * (width as f64)).floor() as usize
    };
    let offset2 = {
        let neg_proportion = (summary2.min() - min) / range;
        (neg_proportion * (width as f64)).floor() as usize
    };

    let (plot1, plot2) = if ascii {
        let plot1 = ascii_summary_plot(&summary1, width1);
        let plot2 = ascii_summary_plot(&summary2, width2);
        (plot1, plot2)
    } else {
        let plot1 = summary_plot(&summary1, width1);
        let plot2 = summary_plot(&summary2, width2);
        (plot1, plot2)
    };

    format!("{}\n{}", pad(&plot1, offset1), pad(&plot2, offset2))
}
<|endoftext|>


<commit_before>pub const BIOS_START_ADDRESS: usize = 0x40000000;
pub const NUM_REGISTERS: usize = 4;
pub const MAX_ADDRESS: usize = 0x8FFFFFFF;
pub const NUM_IVT_ENTRIES: usize = 1;
pub const NUM_FLAGS: usize = 1;
pub const FLAGS_START_ADDRESS: usize = MAX_ADDRESS - NUM_FLAGS;
pub const IVT_START_ADDRESS: usize = FLAGS_START_ADDRESS - NUM_IVT_ENTRIES;
pub const REGISTERS_START_ADDRESS: usize = IVT_START_ADDRESS - NUM_REGISTERS;
pub const STACK_POINTER_ADDRESS: usize = REGISTERS_START_ADDRESS - 1;
pub const CONTROLS_ADDRESS: usize = STACK_POINTER_ADDRESS;

pub const FLAG0_HALTED: usize = 0;
pub const FLAG0_BIOS_DONE: usize = 1;
<commit_msg>fix(address): MAX_ADDRESS was wrong lol<commit_after>pub const BIOS_START_ADDRESS: usize = 0x40000000;
pub const NUM_REGISTERS: usize = 4;
pub const MAX_ADDRESS: usize = 0x7FFFFFFF;
pub const NUM_IVT_ENTRIES: usize = 1;
pub const NUM_FLAGS: usize = 1;
pub const FLAGS_START_ADDRESS: usize = MAX_ADDRESS - NUM_FLAGS;
pub const IVT_START_ADDRESS: usize = FLAGS_START_ADDRESS - NUM_IVT_ENTRIES;
pub const REGISTERS_START_ADDRESS: usize = IVT_START_ADDRESS - NUM_REGISTERS;
pub const STACK_POINTER_ADDRESS: usize = REGISTERS_START_ADDRESS - 1;
pub const CONTROLS_ADDRESS: usize = STACK_POINTER_ADDRESS;

pub const FLAG0_HALTED: usize = 0;
pub const FLAG0_BIOS_DONE: usize = 1;
<|endoftext|>


<commit_before>use rand;
use rand::distributions::{IndependentSample, Range};

use rayon::prelude::*;

#[derive(Debug, Clone)]
pub struct NQueens {
    queens: Vec<Option<usize>>,
}

impl NQueens {
    /// Creates a new board of size `usize` with None in each position
    pub fn new_empty(size: usize) -> NQueens {
        let mut queens = Vec::new();
        for _ in 0..size {
            queens.push(None);
        }

        NQueens {
            queens: queens,
        }
    }

    /// Creates a new board of size `usize` with each queen's position selected uniformly at random
    pub fn new_random(size: usize) -> NQueens {
        let mut queens = Vec::new();

        let mut rng = rand::thread_rng();
        for _ in 0..size {
            queens.push(Some(Range::new(0, size).ind_sample(&mut rng)));
        }

        NQueens {
            queens: queens,
        }
    }

    /// Returns the size of the board i.e. the width and height, which are equal
    pub fn size(&self) -> usize {
        self.queens.len()
    }

    /// Returns true if queen's position is set in the given column
    pub fn is_set(&self, column: usize) -> bool {
        assert!(column < self.size());
        self.queens[column].is_some()
    }

    /// Returns the position of the queen in the given column. Panics if queen is not set in that
    /// column
    pub fn get(&self, column: usize) -> usize {
        assert!(column < self.size());
        self.queens[column].unwrap()
    }

    /// Returns a reference to the position of the queen in the given column. Panics if queen is
    /// not set in that column
    pub fn get_ref(&self, column: usize) -> &usize {
        assert!(column < self.size());
        self.queens[column].as_ref().unwrap()
    }

    /// Returns an Option contains the position of the queen in the given column
    pub fn get_option(&self, column: usize) -> Option<usize> {
        assert!(column < self.size());
        self.queens[column]
    }

    /// Sets the queen in the given column to the value of `row`.
    pub fn set(&mut self, column: usize, row: usize) {
        assert!(column < self.size());
        assert!(row < self.size());

        self.queens[column] = Some(row);
    }

    /// Sets the queen in the given column to a position selected uniformly at random
    pub fn set_random(&mut self, column: usize) {
        let mut rng = rand::thread_rng();

        let size = self.size();
        self.set(column, Range::new(0, size).ind_sample(&mut rng));
    }

    /// Creates a struct that implements `Iterator` which provides all possible successors of the
    /// current board configuration. A successor is created by moving or placing a queen in a
    /// single column.
    ///
    /// E.g. if all queens are filled on an 8 by 8 board, the iterator will return 56 boards,
    /// while if no queens are filled the iterator will iterate over 64 boards.
    //pub fn to_successors_iter(&self) -> NQueensSuccessorIter {
    //    NQueensSuccessorIter::new(&self)
    //}

    /// Checks if the current configuration of the board is a valid solution
    pub fn is_valid(&self) -> bool {
        // Check if all entries are not None; this lets us use unwrap everywhere and provides a
        // quick exit.
        let full_board = self.queens.par_iter()
                             .all(|q| !q.is_none());
        if !full_board {
            return false;
        }

        // do not need to check columns because by definition of our struct we only have one queen
        // per column

        // check rows
        let all_rows_distinct = self.queens.par_iter().enumerate().all( |(i,q)| {
            let q = q.unwrap();
            self.queens[i+1..].par_iter().all( |q2| {
                let q2 = q2.unwrap();
                q != q2
            })
        } );

        if !all_rows_distinct {
            return false;
        }

        // check diagonals
        // This "row+column are all distinct" test works because if you imagine an addition table,
        // all the elements on a rising diagonal are the same. Similarly, all the elements on a
        // falling diagonal are the same in a subtraction table. Additionally, they are symmetric
        // (up to sign, see below) so we only have to do the computations for (i,j) pairs and not
        // (j,i) as well.
        let all_diagonals_distinct = self.queens.par_iter().enumerate().all( |(i, q)| {
            let q = q.unwrap();
            // optimization so we don't compare (i,j) and (j,i) as noted above
            self.queens[i+1..].par_iter().enumerate().all( |(j, q2)| {
                let q2 = q2.unwrap();
                // The i+1 term appears to account for the shifting that we did in the second
                // enumeration.

                // This should be correct for all useful inputs. We don't actually need the signed
                // answer; we just don't want them to be equal. If the numbers are too large we may
                // be incorrect (i.e. if things are around USIZE_MAX, USIZE_MAX/2 etc.) but that
                // would be way too many queens.
                (i+q != i+1+j+q2) && (i.wrapping_sub(q) != (i+1+j).wrapping_sub(q2))
            })
        });

        if !all_diagonals_distinct {
            return false;
        }

        // if above checks pass, this is a valid solution and we return true
        return true;
    }
}

use std::ops::Index;
impl Index<usize> for NQueens {
    type Output = usize;

    fn index(&self, column: usize) -> &usize {
        self.get_ref(column)
    }
}

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

    // Note that the set(x, y) function is (column, row), so the Q in a diagram on the same line
    // as a set call is not necessarily being set by that call.

    #[test]
    pub fn test_valid_1() {
        let mut q = NQueens::new_empty(4);
        q.set(0, 1); // X X Q X
        q.set(1, 3); // Q X X X
        q.set(2, 0); // X X X Q
        q.set(3, 2); // X Q X X

        assert!(q.is_valid() == true);
    }

    #[test]
    pub fn test_valid_2() {
        let mut q = NQueens::new_empty(4);
        q.set(0, 2); // X Q X X
        q.set(1, 0); // X X X Q
        q.set(2, 3); // Q X X X
        q.set(3, 1); // X X Q X

        assert!(q.is_valid() == true);
    }

    #[test]
    pub fn test_valid_3() {
        let mut q = NQueens::new_empty(5);
        q.set(0, 2); // X Q X X X
        q.set(1, 0); // X X X Q X
        q.set(2, 3); // Q X X X X
        q.set(3, 1); // X X Q X X
        q.set(4, 4); // X X X X Q

        assert!(q.is_valid() == true);
    }

    #[test]
    pub fn test_valid_4() {
        let mut q = NQueens::new_empty(5);
        q.set(0, 1); // X X X Q X
        q.set(1, 4); // Q X X X X
        q.set(2, 2); // X X Q X X
        q.set(3, 0); // X X X X Q
        q.set(4, 3); // X Q X X X

        assert!(q.is_valid() == true);
    }

    // of course we have to test an actual 8 queens
    #[test]
    pub fn test_valid_5() {
        let mut q = NQueens::new_empty(8);
        q.set(0, 3); // X X X X X Q X X
        q.set(1, 5); // X X X Q X X X X
        q.set(2, 7); // X X X X X X Q X
        q.set(3, 1); // Q X X X X X X X
        q.set(4, 6); // X X X X X X X Q
        q.set(5, 0); // X Q X X X X X X
        q.set(6, 2); // X X X X Q X X X
        q.set(7, 4); // X X Q X X X X X

        assert!(q.is_valid() == true);
    }

    // and another nonsymmetric one
    #[test]
    pub fn test_valid_6() {
        let mut q = NQueens::new_empty(8);
        q.set(0, 7); // X X X X Q X X X
        q.set(1, 1); // X Q X X X X X X
        q.set(2, 4); // X X X Q X X X X
        q.set(3, 2); // X X X X X X Q X
        q.set(4, 0); // X X Q X X X X X
        q.set(5, 6); // X X X X X X X Q
        q.set(6, 3); // X X X X X Q X X
        q.set(7, 5); // Q X X X X X X X

        assert!(q.is_valid() == true);
    }

    #[test]
    pub fn test_horizontals_1() {
        let mut q = NQueens::new_empty(2);
        q.set(0, 0); // Q Q
        q.set(1, 0); // X X
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_horizontals_2() {
        let mut q = NQueens::new_empty(2);
        q.set(0, 0); // X X
        q.set(1, 0); // Q Q
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_horizontals_3() {
        let mut q = NQueens::new_empty(3);
        q.set(0, 0); // Q X Q
        q.set(1, 2); // X X X
        q.set(2, 0); // X Q X
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_horizontals_4() {
        let mut q = NQueens::new_empty(6);
        q.set(0, 0); // X X Q X X X
        q.set(1, 2); // Q X X X Q X
        q.set(2, 0); // X X X X X X
        q.set(2, 0); // X Q X X X X
        q.set(2, 0); // X X X X X Q
        q.set(2, 0); // X X X Q X X
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_diagonals_1() {
        let mut q = NQueens::new_empty(2);
        q.set(0, 0); // Q X
        q.set(1, 1); // X Q
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_diagonals_2() {
        let mut q = NQueens::new_empty(2);
        q.set(0, 1); // X Q
        q.set(1, 0); // Q X
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_diagonals_3() {
        let mut q = NQueens::new_empty(3);
        q.set(0, 0); // Q X X
        q.set(1, 2); // X X Q
        q.set(2, 1); // X Q X
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_diagonals_4() {
        let mut q = NQueens::new_empty(5);
        q.set(0, 2); // X Q X X X
        q.set(1, 0); // X X X Q X
        q.set(2, 4); // Q X X X X
        q.set(3, 1); // X X X X Q
        q.set(3, 3); // X X Q X X
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_diagonals_5() {
        let mut q = NQueens::new_empty(5);
        q.set(0, 3); // X X X Q X
        q.set(1, 1); // X Q X X X
        q.set(2, 4); // X X X X Q
        q.set(3, 0); // Q X X X X
        q.set(3, 2); // X X Q X X
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_none_1() {
        let q = NQueens::new_empty(3);
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_none_2() {
        let mut q = NQueens::new_empty(3);
        q.set(0, 0); // Q X X
        q.set(1, 2); // X X X
                     // X Q X

        assert!(q.is_valid() == false);
    }
}
<commit_msg>Implement Iterator traits for NQueens<commit_after>use std::iter::IntoIterator;
use std::slice::{Iter, IterMut};

use rand;
use rand::distributions::{IndependentSample, Range};

use rayon::prelude::*;

#[derive(Debug, Clone)]
pub struct NQueens {
    queens: Vec<Option<usize>>,
}

impl NQueens {
    /// Creates a new board of size `usize` with None in each position
    pub fn new_empty(size: usize) -> NQueens {
        let mut queens = Vec::new();
        for _ in 0..size {
            queens.push(None);
        }

        NQueens {
            queens: queens,
        }
    }

    /// Creates a new board of size `usize` with each queen's position selected uniformly at random
    pub fn new_random(size: usize) -> NQueens {
        let mut queens = Vec::new();

        let mut rng = rand::thread_rng();
        for _ in 0..size {
            queens.push(Some(Range::new(0, size).ind_sample(&mut rng)));
        }

        NQueens {
            queens: queens,
        }
    }

    /// Returns the size of the board i.e. the width and height, which are equal
    pub fn size(&self) -> usize {
        self.queens.len()
    }

    /// Returns true if queen's position is set in the given column
    pub fn is_set(&self, column: usize) -> bool {
        assert!(column < self.size());
        self.queens[column].is_some()
    }

    /// Returns the position of the queen in the given column. Panics if queen is not set in that
    /// column
    pub fn get(&self, column: usize) -> usize {
        assert!(column < self.size());
        self.queens[column].unwrap()
    }

    /// Returns a reference to the position of the queen in the given column. Panics if queen is
    /// not set in that column
    pub fn get_ref(&self, column: usize) -> &usize {
        assert!(column < self.size());
        self.queens[column].as_ref().unwrap()
    }

    /// Returns an Option containing the position of the queen in the given column
    pub fn get_option(&self, column: usize) -> Option<usize> {
        assert!(column < self.size());
        self.queens[column]
    }

    /// Returns a reference to an Option containing the position of the queen in the given column
    pub fn get_option_ref(&self, column: usize) -> &Option<usize> {
        assert!(column < self.size());
        &self.queens[column]
    }

    /// Sets the queen in the given column to the value of `row`.
    pub fn set(&mut self, column: usize, row: usize) {
        assert!(column < self.size());
        assert!(row < self.size());

        self.queens[column] = Some(row);
    }

    /// Sets the queen in the given column to a position selected uniformly at random
    pub fn set_random(&mut self, column: usize) {
        let mut rng = rand::thread_rng();

        let size = self.size();
        self.set(column, Range::new(0, size).ind_sample(&mut rng));
    }

    /// Returns an iterator over the columns of the board
    pub fn iter(&self) -> Iter<Option<usize>> {
        self.queens.iter()
    }

    /// Returns a mutable iterator over the columns of the board
    pub fn iter_mut(&mut self) -> IterMut<Option<usize>> {
        self.queens.iter_mut()
    }

    /// Creates a struct that implements `Iterator` which provides all possible successors of the
    /// current board configuration. A successor is created by moving or placing a queen in a
    /// single column.
    ///
    /// E.g. if all queens are filled on an 8 by 8 board, the iterator will return 56 boards,
    /// while if no queens are filled the iterator will iterate over 64 boards.
    //pub fn to_successors_iter(&self) -> NQueensSuccessorIter {
    //    NQueensSuccessorIter::new(&self)
    //}

    /// Checks if the current configuration of the board is a valid solution
    pub fn is_valid(&self) -> bool {
        // Check if all entries are not None; this lets us use unwrap everywhere and provides a
        // quick exit.
        let full_board = self.queens.par_iter()
                             .all(|q| !q.is_none());
        if !full_board {
            return false;
        }

        // do not need to check columns because by definition of our struct we only have one queen
        // per column

        // check rows
        let all_rows_distinct = self.queens.par_iter().enumerate().all( |(i,q)| {
            let q = q.unwrap();
            self.queens[i+1..].par_iter().all( |q2| {
                let q2 = q2.unwrap();
                q != q2
            })
        } );

        if !all_rows_distinct {
            return false;
        }

        // check diagonals
        // This "row+column are all distinct" test works because if you imagine an addition table,
        // all the elements on a rising diagonal are the same. Similarly, all the elements on a
        // falling diagonal are the same in a subtraction table. Additionally, they are symmetric
        // (up to sign, see below) so we only have to do the computations for (i,j) pairs and not
        // (j,i) as well.
        let all_diagonals_distinct = self.queens.par_iter().enumerate().all( |(i, q)| {
            let q = q.unwrap();
            // optimization so we don't compare (i,j) and (j,i) as noted above
            self.queens[i+1..].par_iter().enumerate().all( |(j, q2)| {
                let q2 = q2.unwrap();
                // The i+1 term appears to account for the shifting that we did in the second
                // enumeration.

                // This should be correct for all useful inputs. We don't actually need the signed
                // answer; we just don't want them to be equal. If the numbers are too large we may
                // be incorrect (i.e. if things are around USIZE_MAX, USIZE_MAX/2 etc.) but that
                // would be way too many queens.
                (i+q != i+1+j+q2) && (i.wrapping_sub(q) != (i+1+j).wrapping_sub(q2))
            })
        });

        if !all_diagonals_distinct {
            return false;
        }

        // if above checks pass, this is a valid solution and we return true
        return true;
    }
}

use std::ops::Index;
impl Index<usize> for NQueens {
    type Output = usize;

    fn index(&self, column: usize) -> &usize {
        self.get_ref(column)
    }
}

// no `impl IntoIter for NQueens` (i.e. without ref) because it seems useless

impl<'board> IntoIterator for &'board NQueens {
    type Item = &'board Option<usize>;
    type IntoIter = Iter<'board, Option<usize>>;

    fn into_iter(self) -> Iter<'board, Option<usize>> {
        self.queens.iter()
    }
}

impl<'board> IntoIterator for &'board mut NQueens {
    type Item = &'board mut Option<usize>;
    type IntoIter = IterMut<'board, Option<usize>>;

    fn into_iter(self) -> IterMut<'board, Option<usize>> {
        self.queens.iter_mut()
    }
}

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

    // Note that the set(x, y) function is (column, row), so the Q in a diagram on the same line
    // as a set call is not necessarily being set by that call.

    #[test]
    pub fn test_valid_1() {
        let mut q = NQueens::new_empty(4);
        q.set(0, 1); // X X Q X
        q.set(1, 3); // Q X X X
        q.set(2, 0); // X X X Q
        q.set(3, 2); // X Q X X

        assert!(q.is_valid() == true);
    }

    #[test]
    pub fn test_valid_2() {
        let mut q = NQueens::new_empty(4);
        q.set(0, 2); // X Q X X
        q.set(1, 0); // X X X Q
        q.set(2, 3); // Q X X X
        q.set(3, 1); // X X Q X

        assert!(q.is_valid() == true);
    }

    #[test]
    pub fn test_valid_3() {
        let mut q = NQueens::new_empty(5);
        q.set(0, 2); // X Q X X X
        q.set(1, 0); // X X X Q X
        q.set(2, 3); // Q X X X X
        q.set(3, 1); // X X Q X X
        q.set(4, 4); // X X X X Q

        assert!(q.is_valid() == true);
    }

    #[test]
    pub fn test_valid_4() {
        let mut q = NQueens::new_empty(5);
        q.set(0, 1); // X X X Q X
        q.set(1, 4); // Q X X X X
        q.set(2, 2); // X X Q X X
        q.set(3, 0); // X X X X Q
        q.set(4, 3); // X Q X X X

        assert!(q.is_valid() == true);
    }

    // of course we have to test an actual 8 queens
    #[test]
    pub fn test_valid_5() {
        let mut q = NQueens::new_empty(8);
        q.set(0, 3); // X X X X X Q X X
        q.set(1, 5); // X X X Q X X X X
        q.set(2, 7); // X X X X X X Q X
        q.set(3, 1); // Q X X X X X X X
        q.set(4, 6); // X X X X X X X Q
        q.set(5, 0); // X Q X X X X X X
        q.set(6, 2); // X X X X Q X X X
        q.set(7, 4); // X X Q X X X X X

        assert!(q.is_valid() == true);
    }

    // and another nonsymmetric one
    #[test]
    pub fn test_valid_6() {
        let mut q = NQueens::new_empty(8);
        q.set(0, 7); // X X X X Q X X X
        q.set(1, 1); // X Q X X X X X X
        q.set(2, 4); // X X X Q X X X X
        q.set(3, 2); // X X X X X X Q X
        q.set(4, 0); // X X Q X X X X X
        q.set(5, 6); // X X X X X X X Q
        q.set(6, 3); // X X X X X Q X X
        q.set(7, 5); // Q X X X X X X X

        assert!(q.is_valid() == true);
    }

    #[test]
    pub fn test_horizontals_1() {
        let mut q = NQueens::new_empty(2);
        q.set(0, 0); // Q Q
        q.set(1, 0); // X X
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_horizontals_2() {
        let mut q = NQueens::new_empty(2);
        q.set(0, 0); // X X
        q.set(1, 0); // Q Q
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_horizontals_3() {
        let mut q = NQueens::new_empty(3);
        q.set(0, 0); // Q X Q
        q.set(1, 2); // X X X
        q.set(2, 0); // X Q X
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_horizontals_4() {
        let mut q = NQueens::new_empty(6);
        q.set(0, 0); // X X Q X X X
        q.set(1, 2); // Q X X X Q X
        q.set(2, 0); // X X X X X X
        q.set(2, 0); // X Q X X X X
        q.set(2, 0); // X X X X X Q
        q.set(2, 0); // X X X Q X X
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_diagonals_1() {
        let mut q = NQueens::new_empty(2);
        q.set(0, 0); // Q X
        q.set(1, 1); // X Q
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_diagonals_2() {
        let mut q = NQueens::new_empty(2);
        q.set(0, 1); // X Q
        q.set(1, 0); // Q X
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_diagonals_3() {
        let mut q = NQueens::new_empty(3);
        q.set(0, 0); // Q X X
        q.set(1, 2); // X X Q
        q.set(2, 1); // X Q X
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_diagonals_4() {
        let mut q = NQueens::new_empty(5);
        q.set(0, 2); // X Q X X X
        q.set(1, 0); // X X X Q X
        q.set(2, 4); // Q X X X X
        q.set(3, 1); // X X X X Q
        q.set(3, 3); // X X Q X X
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_diagonals_5() {
        let mut q = NQueens::new_empty(5);
        q.set(0, 3); // X X X Q X
        q.set(1, 1); // X Q X X X
        q.set(2, 4); // X X X X Q
        q.set(3, 0); // Q X X X X
        q.set(3, 2); // X X Q X X
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_none_1() {
        let q = NQueens::new_empty(3);
        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_none_2() {
        let mut q = NQueens::new_empty(3);
        q.set(0, 0); // Q X X
        q.set(1, 2); // X X X
                     // X Q X

        assert!(q.is_valid() == false);
    }

    #[test]
    pub fn test_iter_empty() {
        let q = NQueens::new_empty(0);
        assert!(q.iter().next() == None);
    }

    #[test]
    pub fn test_iter_1() {
        let mut q = NQueens::new_empty(4);
        q.set(0, 2);
        q.set(1, 0);
        q.set(2, 3);
        q.set(3, 1);

        let mut qiter = q.iter();
        assert!(qiter.next() == Some(q.get_option_ref(0)));
        assert!(qiter.next() == Some(q.get_option_ref(1)));
        assert!(qiter.next() == Some(q.get_option_ref(2)));
        assert!(qiter.next() == Some(q.get_option_ref(3)));
        assert!(qiter.next() == None);

        let mut qiter = q.iter();
        assert!(qiter.next().unwrap().unwrap() == 2);
        assert!(qiter.next().unwrap().unwrap() == 0);
        assert!(qiter.next().unwrap().unwrap() == 3);
        assert!(qiter.next().unwrap().unwrap() == 1);
        assert!(qiter.next() == None);
    }

    #[test]
    pub fn test_iter_mut_1() {
        let mut b = NQueens::new_empty(4);

        for (i, q) in b.iter_mut().enumerate() {
            *q = Some(4-i);
        }

        assert!(b.get(0) == 4);
        assert!(b.get(1) == 3);
        assert!(b.get(2) == 2);
        assert!(b.get(3) == 1);
    }

    #[test]
    pub fn test_intoiter() {
        let b = NQueens::new_random(4);

        let mut i = 0;
        for q in &b {
            assert!(q.unwrap() == b.get(i));
            i += 1;
        }
    }

    #[test]
    pub fn test_intoiter_mut() {
        let mut b = NQueens::new_empty(4);

        let mut i = 0;
        for q in &mut b {
            *q = Some(i);
            i += 1
        }

        i = 0;
        for q in &b {
            assert!(q.unwrap() == b.get(i));
            i += 1;
        }
    }
}
<|endoftext|>


<commit_before>//! Useful stuff related to the spaceapi.

/// An ``Optional`` can contain ``Optional::Value<T>`` or ``Optional::Absent``.
/// It is similar to an ``Option``, but ``Optional::Absent`` means it will be
/// omitted when serialized, while ``None`` will be serialized to ``null``.
#[derive(Debug, Copy, Clone)]
pub enum Optional<T> {
    Value(T),
    Absent,
}

impl<T> Optional<T> {

    /// Applies a function to the contained value or returns a default.  see
    /// [`std::option::Option<T>::map_or`](http://doc.rust-lang.org/std/option/enum.Option.html#method.map_or)
    pub fn map_or<U, F: FnOnce(T) -> U>(self, def: U, f: F) -> U {
        match self {
            Optional::Value(v) => f(v),
            Optional::Absent => def,
        }
    }

    /// Converts from `Optional<T>` to `Optional<&mut T>`
    pub fn as_mut<'r>(&'r mut self) -> Optional<&'r mut T> {
        match *self {
            Optional::Value(ref mut x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }

    /// Converts from `Optional<T>` to `Optional<&T>`
    pub fn as_ref<'r>(&'r self) -> Optional<&'r T> {
        match *self {
            Optional::Value(ref x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }

    /// Returns `true` if the optional is a `Absent` value
    ///
    /// # Examples
    ///
    /// ```
    /// # use spaceapi::utils::Optional;
    /// # use spaceapi::utils::Optional::{Value,Absent};
    /// let x: Optional<u32> = Value(2);
    /// assert_eq!(x.is_absent(), false);
    ///
    /// let x: Optional<u32> = Absent;
    /// assert_eq!(x.is_absent(), true);
    /// ```
    pub fn is_absent(&self) -> bool {
        match *self {
            Optional::Absent => true,
            _ => false
        }
    }

}
<commit_msg>spaceapi: Add unwrap_or_else to Optional<commit_after>//! Useful stuff related to the spaceapi.

/// An ``Optional`` can contain ``Optional::Value<T>`` or ``Optional::Absent``.
/// It is similar to an ``Option``, but ``Optional::Absent`` means it will be
/// omitted when serialized, while ``None`` will be serialized to ``null``.
#[derive(Debug, Copy, Clone)]
pub enum Optional<T> {
    Value(T),
    Absent,
}

impl<T> Optional<T> {

    /// Returns the contained value or computes it from a closure.
    ///
    /// # Examples
    ///
    /// ```
    /// # use spaceapi::utils::Optional;
    /// # use spaceapi::utils::Optional::{Value,Absent};
    /// let k = 10;
    /// assert_eq!(Value(4).unwrap_or_else(|| 2 * k), 4);
    /// assert_eq!(Absent.unwrap_or_else(|| 2 * k), 20);
    /// ```
    pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
        match self {
            Optional::Value(x) => x,
            Optional::Absent => f()
        }
    }

    /// Applies a function to the contained value or returns a default.  see
    /// [`std::option::Option<T>::map_or`](http://doc.rust-lang.org/std/option/enum.Option.html#method.map_or)
    pub fn map_or<U, F: FnOnce(T) -> U>(self, def: U, f: F) -> U {
        match self {
            Optional::Value(v) => f(v),
            Optional::Absent => def,
        }
    }

    /// Converts from `Optional<T>` to `Optional<&mut T>`
    pub fn as_mut<'r>(&'r mut self) -> Optional<&'r mut T> {
        match *self {
            Optional::Value(ref mut x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }

    /// Converts from `Optional<T>` to `Optional<&T>`
    pub fn as_ref<'r>(&'r self) -> Optional<&'r T> {
        match *self {
            Optional::Value(ref x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }

    /// Returns `true` if the optional is a `Absent` value
    ///
    /// # Examples
    ///
    /// ```
    /// # use spaceapi::utils::Optional;
    /// # use spaceapi::utils::Optional::{Value,Absent};
    /// let x: Optional<u32> = Value(2);
    /// assert_eq!(x.is_absent(), false);
    ///
    /// let x: Optional<u32> = Absent;
    /// assert_eq!(x.is_absent(), true);
    /// ```
    pub fn is_absent(&self) -> bool {
        match *self {
            Optional::Absent => true,
            _ => false
        }
    }

}
<|endoftext|>


<commit_before>use cocoa::base::id;
use cocoa::foundation::NSString;
use std::borrow::Cow;
use std::convert::{From, Into};
use std::ffi::CStr;
use sys::{MTLFunction, MTLFunctionType};

pub struct Function(id);

impl Function {
    pub fn name(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(self.0.name().UTF8String()).to_string_lossy() }
    }

    pub fn function_type(&self) -> FunctionType {
        unsafe { From::from(self.0.functionType()) }
    }

    // TODO(George): Model this correctly
    pub fn vertex_attributes(&self) -> ! {
        unimplemented!();
    }
}

impl_from_into_raw!(Function, of protocol "MTLFunction");

convertible_enum! {
    #[derive(Clone, Copy, Eq, Hash, PartialEq)]
    enum FunctionType: MTLFunctionType {
        Vertex => MTLFunctionTypeVertex,
        Fragment => MTLFunctionTypeFragment,
        Kernel => MTLFunctionTypeKernel
    }
}
<commit_msg>Remove unused import<commit_after>use cocoa::base::id;
use cocoa::foundation::NSString;
use std::borrow::Cow;
use std::convert::From;
use std::ffi::CStr;
use sys::{MTLFunction, MTLFunctionType};

pub struct Function(id);

impl Function {
    pub fn name(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(self.0.name().UTF8String()).to_string_lossy() }
    }

    pub fn function_type(&self) -> FunctionType {
        unsafe { From::from(self.0.functionType()) }
    }

    // TODO(George): Model this correctly
    pub fn vertex_attributes(&self) -> ! {
        unimplemented!();
    }
}

impl_from_into_raw!(Function, of protocol "MTLFunction");

convertible_enum! {
    #[derive(Clone, Copy, Eq, Hash, PartialEq)]
    enum FunctionType: MTLFunctionType {
        Vertex => MTLFunctionTypeVertex,
        Fragment => MTLFunctionTypeFragment,
        Kernel => MTLFunctionTypeKernel
    }
}
<|endoftext|>