<commit_before>//! Quick Csv reader which performs **very** well.
//!
//! ## Example
//!
//! First, create a `Csv` from a `BufRead` reader, a file or a string
//!
//! ```rust
//! extern crate quick_csv;
//!
//! fn main() {
//!     let data = "a,b\r\nc,d\r\ne,f";
//!     let csv = quick_csv::Csv::from_string(data);
//!     for row in csv.into_iter() {
//!         // work on csv row ...
//!         if let Ok(_) = row {
//!             println!("new row!");
//!         } else {
//!             println!("cannot read next line");
//!         }
//!     }
//! }
//! ```
//!
//! `Row` is on the other hand provides 3 methods to access csv columns:
//! - `columns`:
//!   - iterator over columns.
//!   - Iterator item is a `&str`, which means you only have to `parse()` it to the needed type and you're done
//!
//!   ```rust
//!   # let row = quick_csv::Csv::from_string("a,b,c,d,e,38,f").next().unwrap().unwrap();
//!   let mut cols = row.columns().expect("cannot convert to utf8");
//!   let fifth = cols.nth(5).unwrap().parse::<f64>().unwrap();
//!   println!("Doubled fifth column: {}", fifth * 2.0);
//!   ```
//!
//! - `decode`:
//!   - deserialize into you `Decodable` struct, a-la rust-csv.
//!   - most convenient way to deal with your csv data
//!
//!   ```rust
//!   let row = quick_csv::Csv::from_string("a,b,54").next().unwrap().unwrap();
//!   if let Ok((col1, col2, col3)) = row.decode::<(String, u64, f64)>() {
//!       println!("col1: '{}', col2: {}, col3: {}", col1, col2, col3);
//!   }
//!   ```
//!
//! - `bytes_columns`:
//!   - similar to `columns` but columns are of type `&[u8]`, which means you may want to convert it to &str first
//!   - performance gain compared to `columns` is minimal, use it only if you *really* need to as it is less convenient

#![deny(missing_docs)]

extern crate rustc_serialize;

pub mod columns;
pub mod error;

use self::columns::{Columns, BytesColumns};
use std::fs::File;
use std::io::{self, BufRead, BufReader, Write};
use std::iter::Iterator;
use std::path::Path;

use error::{Error, Result};
use rustc_serialize::Decodable;

#[cfg(test)] mod test;

/// Csv reader
///
/// Iterates over the rows of the csv
///
/// # Example
///
/// ```rust
/// let csv = quick_csv::Csv::from_file("./examples/data/bench.csv").unwrap();
/// for row in csv.into_iter() {
///     let row = row.unwrap(); // unwrap result, panic if not utf8
///     {
///         // either use columns iterator directly (Item = &str)
///         if let Ok(mut columns) = row.columns() {
///             println!("Column 1: '{:?}', Column 2: '{:?}'", columns.next(), columns.next());
///         }
///     }
///
///     {
///         // or decode it directly into something simpler
///         if let Ok((col1, col2)) = row.decode::<(String, u64)>() {
///             println!("Column 1: '{:?}', Column 2: '{:?}'", &col1, &col2);
///         }
///     }
///
/// }
/// ```
pub struct Csv<B: BufRead> {
    /// delimiter
    delimiter: u8,
    /// reader
    reader: B,
    /// header
    has_header: bool,
    /// header
    headers: Option<Vec<String>>,
    /// flexible column count
    flexible: bool,
    /// column count
    len: Option<usize>,
    /// if was error, exit next
    exit: bool,
    /// line count
    current_line: usize,
}

impl<B: BufRead> Csv<B> {

    /// Creates a Csv from a generic BufReader
    ///
    /// Note: default delimiter = ','
    pub fn from_reader(reader: B) -> Csv<B> {
        Csv {
            reader: reader,
            delimiter: b',',
            has_header: false,
            headers: None,
            flexible: false,
            len: None,
            exit: false,
            current_line: 0,
        }
    }

    /// Sets a new delimiter
    pub fn delimiter(mut self, delimiter: u8) -> Csv<B> {
        self.delimiter = delimiter;
        self
    }

    /// Sets flexible columns
    pub fn flexible(mut self, flexible: bool) -> Csv<B> {
        self.flexible = flexible;
        self
    }

    /// Defines whether there is a header or not
    pub fn has_header(mut self, has_header: bool) -> Csv<B> {
        self.has_header = has_header;
        let _ = self.headers();
        self
    }

   /// gets first row as Vec<String>
    pub fn headers(&mut self) -> Vec<String> {
        if let Some(ref h) = self.headers {
            return h.clone();
        }
        if self.has_header {
            if let Some(r) = self.next() {
                if let Ok(r) = r {
                    let h = r.decode().ok().unwrap_or_else(Vec::new);
                    self.headers = Some(h.clone());
                    return h;
                }
            }
        }
        Vec::new()
    }

    /// Get column count
    pub fn column_count(&self) -> Option<usize> {
        self.len
    }

    /// Gets the current line number
    ///
    /// Useful if you get an error and want to investigate the source
    pub fn current_line(&self) -> usize {
        self.current_line
    }

}

impl Csv<BufReader<File>> {
    /// Creates a csv from a file path
    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Csv<BufReader<File>>>
    {
        let reader = BufReader::new(try!(File::open(path)));
        Ok(Csv::from_reader(reader))
    }
}

impl<'a> Csv<&'a [u8]> {
    /// Creates a CSV reader for an in memory string buffer.
    pub fn from_string(s: &'a str) -> Csv<&'a [u8]> {
        Csv::from_reader(s.as_bytes())
    }
}

/// Iterator on csv `Row`s
impl<B: BufRead> Iterator for Csv<B> {
    type Item = Result<Row>;
    fn next(&mut self) -> Option<Result<Row>> {
        if self.exit { return None; }
        let mut buf = Vec::new();
        let mut cols = self.len.map_or_else(Vec::new, Vec::with_capacity);
        match read_line(&mut self.reader, &mut buf, self.delimiter, &mut cols) {
            Ok(0) => None,
            Ok(_n) => {
                if buf.ends_with(&[b'\r']) {
                    buf.pop();
                }
                cols.push(buf.len());
                let c = cols.len();
                if let Some(n) = self.len {
                    if n != c && !self.flexible {
                        self.exit = true;
                        return Some(Err(Error::ColumnMismatch(n, c)));
                    }
                } else {
                    self.len = Some(c);
                }
                self.current_line += 1;
                Some(Ok(Row {
                    line: buf,
                    cols: cols,
                }))
            }
            Err(e) => {
                self.exit = true;
                Some(Err(e))
            },
        }
    }
}

/// Row struct used as Csv iterator Item
///
/// Row can be decoded into a Result<T: Decodable>
pub struct Row {
    line: Vec<u8>,
    cols: Vec<usize>,
}

impl Row {

    /// Gets an iterator over columns
    pub fn columns(&self) -> Result<Columns> {
        match ::std::str::from_utf8(&self.line) {
            Err(_) => Err(Error::Io(io::Error::new(io::ErrorKind::InvalidData,
                                    "stream did not contain valid UTF-8"))),
            Ok(s) => Ok(Columns::new(s, &self.cols)),
        }
    }

    ///  Creates a new BytesColumns iterator over &[u8]
    pub fn bytes_columns(&self) -> BytesColumns {
        BytesColumns::new(&self.line, &self.cols)
    }

    /// Decode row into custom decodable type
    pub fn decode<T: Decodable>(&self) -> Result<T> {
        let mut columns = try!(self.columns());
        Decodable::decode(&mut columns)
    }

    /// Gets columns count
    pub fn len(&self) -> usize {
        self.cols.len()
    }

    /// `Row` is empty if there is no columns
    pub fn is_empty(&self) -> bool {
        self.cols.is_empty()
    }

}

/// Consumes bytes as long as they are within quotes
/// manages "" as quote escape
/// returns
/// - Ok(true) if entirely consumed
/// - Ok(false) if no issue but it reached end of buffer
/// - Err(Error::UnescapeQuote) if a quote if found within the column
macro_rules! consume_quote {
    ($bytes: expr, $delimiter: expr, $in_quote: expr,
     $start: expr, $buf: expr, $available: expr, $quote_count: expr) => {
        $in_quote = false;
        loop {
            match $bytes.next() {
                Some((_, &b'\"')) => {
                    match $bytes.clone().next() {
                        Some((i, &b'\"')) => {
                            $bytes.next(); // escaping quote
                            let _ = $buf.write(&$available[$start..i]);
                            $start = i + 1;
                            $quote_count += 1;
                        },
                        None | Some((_, &b'\r')) | Some((_, &b'\n')) => break,
                        Some((_, d)) if *d == $delimiter => break,
                        Some((_, _)) => return Err(Error::UnescapedQuote),
                    }
                },
                None => {
                    $in_quote = true;
                    break;
                },
                _ => (),
            }
        }
    }
}

fn read_line<R: BufRead>(r: &mut R, buf: &mut Vec<u8>,
    delimiter: u8, cols: &mut Vec<usize>) -> Result<usize>
{
    let mut read = 0;
    let mut in_quote = false;
    let mut done = false;
    let mut quote_count = 0;
    while !done {
        let used = {
            let available = match r.fill_buf() {
                Ok(n) if n.is_empty() => return Ok(read),
                Ok(n) => n,
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
                Err(e) => return Err(Error::from(e)),
            };

            let mut bytes = available.iter().enumerate();
            let mut start = 0;

            // previous buffer was exhausted without exiting from quotes
            if in_quote {
                consume_quote!(bytes, delimiter, in_quote, start, buf, available, quote_count);
            }

            // use a simple loop instead of for loop to allow nested loop
            let used: usize;
            loop {
                match bytes.next() {
                    Some((i, &b'\"')) => {
                        if i == 0 || available[i - 1] == delimiter {
                            consume_quote!(bytes, delimiter, in_quote, start, buf, available, quote_count);
                        } else {
                            return Err(Error::UnexpextedQuote);
                        }
                    },
                    Some((i, &b'\n')) => {
                        done = true;
                        used = i + 1;
                        let _ = buf.write(&available[start..i]);
                        break;
                    },
                    Some((i, &d)) => {
                        if d == delimiter { cols.push(read + i - quote_count); }
                    },
                    None => {
                        used = available.len();
                        let _ = buf.write(&available[start..used]);
                        break;
                    },
                }
            }
            used
        };
        r.consume(used);
        read += used;
    }
    Ok(read)
}
<commit_msg>remove std::io::Write import<commit_after>//! Quick Csv reader which performs **very** well.
//!
//! ## Example
//!
//! First, create a `Csv` from a `BufRead` reader, a file or a string
//!
//! ```rust
//! extern crate quick_csv;
//!
//! fn main() {
//!     let data = "a,b\r\nc,d\r\ne,f";
//!     let csv = quick_csv::Csv::from_string(data);
//!     for row in csv.into_iter() {
//!         // work on csv row ...
//!         if let Ok(_) = row {
//!             println!("new row!");
//!         } else {
//!             println!("cannot read next line");
//!         }
//!     }
//! }
//! ```
//!
//! `Row` is on the other hand provides 3 methods to access csv columns:
//! - `columns`:
//!   - iterator over columns.
//!   - Iterator item is a `&str`, which means you only have to `parse()` it to the needed type and you're done
//!
//!   ```rust
//!   # let row = quick_csv::Csv::from_string("a,b,c,d,e,38,f").next().unwrap().unwrap();
//!   let mut cols = row.columns().expect("cannot convert to utf8");
//!   let fifth = cols.nth(5).unwrap().parse::<f64>().unwrap();
//!   println!("Doubled fifth column: {}", fifth * 2.0);
//!   ```
//!
//! - `decode`:
//!   - deserialize into you `Decodable` struct, a-la rust-csv.
//!   - most convenient way to deal with your csv data
//!
//!   ```rust
//!   let row = quick_csv::Csv::from_string("a,b,54").next().unwrap().unwrap();
//!   if let Ok((col1, col2, col3)) = row.decode::<(String, u64, f64)>() {
//!       println!("col1: '{}', col2: {}, col3: {}", col1, col2, col3);
//!   }
//!   ```
//!
//! - `bytes_columns`:
//!   - similar to `columns` but columns are of type `&[u8]`, which means you may want to convert it to &str first
//!   - performance gain compared to `columns` is minimal, use it only if you *really* need to as it is less convenient

#![deny(missing_docs)]

extern crate rustc_serialize;

pub mod columns;
pub mod error;

use self::columns::{Columns, BytesColumns};
use std::fs::File;
use std::io::{self, BufRead, BufReader};
use std::iter::Iterator;
use std::path::Path;

use error::{Error, Result};
use rustc_serialize::Decodable;

#[cfg(test)] mod test;

/// Csv reader
///
/// Iterates over the rows of the csv
///
/// # Example
///
/// ```rust
/// let csv = quick_csv::Csv::from_file("./examples/data/bench.csv").unwrap();
/// for row in csv.into_iter() {
///     let row = row.unwrap(); // unwrap result, panic if not utf8
///     {
///         // either use columns iterator directly (Item = &str)
///         if let Ok(mut columns) = row.columns() {
///             println!("Column 1: '{:?}', Column 2: '{:?}'", columns.next(), columns.next());
///         }
///     }
///
///     {
///         // or decode it directly into something simpler
///         if let Ok((col1, col2)) = row.decode::<(String, u64)>() {
///             println!("Column 1: '{:?}', Column 2: '{:?}'", &col1, &col2);
///         }
///     }
///
/// }
/// ```
pub struct Csv<B: BufRead> {
    /// delimiter
    delimiter: u8,
    /// reader
    reader: B,
    /// header
    has_header: bool,
    /// header
    headers: Option<Vec<String>>,
    /// flexible column count
    flexible: bool,
    /// column count
    len: Option<usize>,
    /// if was error, exit next
    exit: bool,
    /// line count
    current_line: usize,
}

impl<B: BufRead> Csv<B> {

    /// Creates a Csv from a generic BufReader
    ///
    /// Note: default delimiter = ','
    pub fn from_reader(reader: B) -> Csv<B> {
        Csv {
            reader: reader,
            delimiter: b',',
            has_header: false,
            headers: None,
            flexible: false,
            len: None,
            exit: false,
            current_line: 0,
        }
    }

    /// Sets a new delimiter
    pub fn delimiter(mut self, delimiter: u8) -> Csv<B> {
        self.delimiter = delimiter;
        self
    }

    /// Sets flexible columns
    pub fn flexible(mut self, flexible: bool) -> Csv<B> {
        self.flexible = flexible;
        self
    }

    /// Defines whether there is a header or not
    pub fn has_header(mut self, has_header: bool) -> Csv<B> {
        self.has_header = has_header;
        let _ = self.headers();
        self
    }

   /// gets first row as Vec<String>
    pub fn headers(&mut self) -> Vec<String> {
        if let Some(ref h) = self.headers {
            return h.clone();
        }
        if self.has_header {
            if let Some(r) = self.next() {
                if let Ok(r) = r {
                    let h = r.decode().ok().unwrap_or_else(Vec::new);
                    self.headers = Some(h.clone());
                    return h;
                }
            }
        }
        Vec::new()
    }

    /// Get column count
    pub fn column_count(&self) -> Option<usize> {
        self.len
    }

    /// Gets the current line number
    ///
    /// Useful if you get an error and want to investigate the source
    pub fn current_line(&self) -> usize {
        self.current_line
    }

}

impl Csv<BufReader<File>> {
    /// Creates a csv from a file path
    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Csv<BufReader<File>>>
    {
        let reader = BufReader::new(try!(File::open(path)));
        Ok(Csv::from_reader(reader))
    }
}

impl<'a> Csv<&'a [u8]> {
    /// Creates a CSV reader for an in memory string buffer.
    pub fn from_string(s: &'a str) -> Csv<&'a [u8]> {
        Csv::from_reader(s.as_bytes())
    }
}

/// Iterator on csv `Row`s
impl<B: BufRead> Iterator for Csv<B> {
    type Item = Result<Row>;
    fn next(&mut self) -> Option<Result<Row>> {
        if self.exit { return None; }
        let mut buf = Vec::new();
        let mut cols = self.len.map_or_else(Vec::new, Vec::with_capacity);
        match read_line(&mut self.reader, &mut buf, self.delimiter, &mut cols) {
            Ok(0) => None,
            Ok(_n) => {
                if buf.ends_with(&[b'\r']) {
                    buf.pop();
                }
                cols.push(buf.len());
                let c = cols.len();
                if let Some(n) = self.len {
                    if n != c && !self.flexible {
                        self.exit = true;
                        return Some(Err(Error::ColumnMismatch(n, c)));
                    }
                } else {
                    self.len = Some(c);
                }
                self.current_line += 1;
                Some(Ok(Row {
                    line: buf,
                    cols: cols,
                }))
            }
            Err(e) => {
                self.exit = true;
                Some(Err(e))
            },
        }
    }
}

/// Row struct used as Csv iterator Item
///
/// Row can be decoded into a Result<T: Decodable>
pub struct Row {
    line: Vec<u8>,
    cols: Vec<usize>,
}

impl Row {

    /// Gets an iterator over columns
    pub fn columns(&self) -> Result<Columns> {
        match ::std::str::from_utf8(&self.line) {
            Err(_) => Err(Error::Io(io::Error::new(io::ErrorKind::InvalidData,
                                    "stream did not contain valid UTF-8"))),
            Ok(s) => Ok(Columns::new(s, &self.cols)),
        }
    }

    ///  Creates a new BytesColumns iterator over &[u8]
    pub fn bytes_columns(&self) -> BytesColumns {
        BytesColumns::new(&self.line, &self.cols)
    }

    /// Decode row into custom decodable type
    pub fn decode<T: Decodable>(&self) -> Result<T> {
        let mut columns = try!(self.columns());
        Decodable::decode(&mut columns)
    }

    /// Gets columns count
    pub fn len(&self) -> usize {
        self.cols.len()
    }

    /// `Row` is empty if there is no columns
    pub fn is_empty(&self) -> bool {
        self.cols.is_empty()
    }

}

/// Consumes bytes as long as they are within quotes
/// manages "" as quote escape
/// returns
/// - Ok(true) if entirely consumed
/// - Ok(false) if no issue but it reached end of buffer
/// - Err(Error::UnescapeQuote) if a quote if found within the column
macro_rules! consume_quote {
    ($bytes: expr, $delimiter: expr, $in_quote: expr,
     $start: expr, $buf: expr, $available: expr, $quote_count: expr) => {
        $in_quote = false;
        loop {
            match $bytes.next() {
                Some((_, &b'\"')) => {
                    match $bytes.clone().next() {
                        Some((i, &b'\"')) => {
                            $bytes.next(); // escaping quote
                            $buf.extend_from_slice(&$available[$start..i]);
                            $start = i + 1;
                            $quote_count += 1;
                        },
                        None | Some((_, &b'\r')) | Some((_, &b'\n')) => break,
                        Some((_, d)) if *d == $delimiter => break,
                        Some((_, _)) => return Err(Error::UnescapedQuote),
                    }
                },
                None => {
                    $in_quote = true;
                    break;
                },
                _ => (),
            }
        }
    }
}

/// Reads an entire line into memory
fn read_line<R: BufRead>(r: &mut R, buf: &mut Vec<u8>,
    delimiter: u8, cols: &mut Vec<usize>) -> Result<usize>
{
    let mut read = 0;
    let mut in_quote = false;
    let mut done = false;
    let mut quote_count = 0;
    while !done {
        let used = {
            let available = match r.fill_buf() {
                Ok(n) if n.is_empty() => return Ok(read),
                Ok(n) => n,
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
                Err(e) => return Err(Error::from(e)),
            };

            let mut bytes = available.iter().enumerate();
            let mut start = 0;

            // previous buffer was exhausted without exiting from quotes
            if in_quote {
                consume_quote!(bytes, delimiter, in_quote, start, buf, available, quote_count);
            }

            // use a simple loop instead of for loop to allow nested loop
            let used: usize;
            loop {
                match bytes.next() {
                    Some((i, &b'\"')) => {
                        if i == 0 || available[i - 1] == delimiter {
                            consume_quote!(bytes, delimiter, in_quote, start, buf, available, quote_count);
                        } else {
                            return Err(Error::UnexpextedQuote);
                        }
                    },
                    Some((i, &b'\n')) => {
                        done = true;
                        used = i + 1;
                        buf.extend_from_slice(&available[start..i]);
                        break;
                    },
                    Some((i, &d)) => {
                        if d == delimiter { cols.push(read + i - quote_count); }
                    },
                    None => {
                        used = available.len();
                        buf.extend_from_slice(&available[start..used]);
                        break;
                    },
                }
            }
            used
        };
        r.consume(used);
        read += used;
    }
    Ok(read)
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

pub fn puzzle(input: &str) -> String {
    let mut lines = input.lines();
    let first_line = lines.next().expect("There were no lines!");

    let mut columns: Vec<Column> = first_line.chars().map(|ch| {
        let mut c = Column { freqs: HashMap::new() };
        c.add_char(ch);
        c
    }).collect();

    for line in lines {
        for (i, ch) in line.chars().enumerate() {
            columns[i].add_char(ch);
        }
    }

    let mut answer = String::new();
    for col in columns {
        answer.push(col.most_common_char())
    }
    answer
}

pub struct Column {
    freqs: HashMap<char, u32>,
}

impl Column {
    fn add_char(&mut self, ch: char) {
        let count = self.freqs.entry(ch).or_insert(0);
        *count += 1;
    }

    fn most_common_char(&self) -> char {
        let mut f: Vec<(&char, &u32)> = self.freqs.iter().collect();
        f.sort_by(|a, b| b.1.cmp(&a.1));
        *f[0].0
    }
}

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

    #[test]
    fn most_common_char_seen_in_column() {
        let mut c = Column { freqs: HashMap::new() };
        c.add_char('a');
        c.add_char('b');
        c.add_char('a');
        assert_eq!(c.most_common_char(), 'a');
    }

    #[test]
    fn sample() {
        let input = "\
eedadn
drvtee
eandsr
raavrd
atevrs
tsrnev
sdttsa
rasrtv
nssdts
ntnada
svetve
tesnvt
vntsnd
vrdear
dvrsen
enarar";
        assert_eq!(puzzle(input), String::from("easter"));
    }
}
<commit_msg>Change most to least...<commit_after>use std::collections::HashMap;

pub fn puzzle(input: &str) -> String {
    let mut lines = input.lines();
    let first_line = lines.next().expect("There were no lines!");

    let mut columns: Vec<Column> = first_line.chars().map(|ch| {
        let mut c = Column { freqs: HashMap::new() };
        c.add_char(ch);
        c
    }).collect();

    for line in lines {
        for (i, ch) in line.chars().enumerate() {
            columns[i].add_char(ch);
        }
    }

    let mut answer = String::new();
    for col in columns {
        answer.push(col.least_common_char())
    }
    answer
}

pub struct Column {
    freqs: HashMap<char, u32>,
}

impl Column {
    fn add_char(&mut self, ch: char) {
        let count = self.freqs.entry(ch).or_insert(0);
        *count += 1;
    }

    fn least_common_char(&self) -> char {
        let mut f: Vec<(&char, &u32)> = self.freqs.iter().collect();
        f.sort_by(|a, b| a.1.cmp(&b.1));
        *f[0].0
    }
}

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

    #[test]
    fn least_common_char_seen_in_column() {
        let mut c = Column { freqs: HashMap::new() };
        c.add_char('a');
        c.add_char('b');
        c.add_char('a');
        assert_eq!(c.least_common_char(), 'b');
    }

    #[test]
    fn sample() {
        let input = "\
eedadn
drvtee
eandsr
raavrd
atevrs
tsrnev
sdttsa
rasrtv
nssdts
ntnada
svetve
tesnvt
vntsnd
vrdear
dvrsen
enarar";
        assert_eq!(puzzle(input), String::from("advent"));
    }
}
<|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/. */

#![feature(slicing_syntax)]

use std::slice::bytes::copy_memory;

pub static SBOX: [u8, ..256] = [
  0x29, 0x2e, 0x43, 0xc9, 0xa2, 0xd8, 0x7c, 0x01, 0x3d, 0x36, 0x54, 0xa1, 0xec, 0xf0, 0x06, 0x13,
  0x62, 0xa7, 0x05, 0xf3, 0xc0, 0xc7, 0x73, 0x8c, 0x98, 0x93, 0x2b, 0xd9, 0xbc, 0x4c, 0x82, 0xca,
  0x1e, 0x9b, 0x57, 0x3c, 0xfd, 0xd4, 0xe0, 0x16, 0x67, 0x42, 0x6f, 0x18, 0x8a, 0x17, 0xe5, 0x12,
  0xbe, 0x4e, 0xc4, 0xd6, 0xda, 0x9e, 0xde, 0x49, 0xa0, 0xfb, 0xf5, 0x8e, 0xbb, 0x2f, 0xee, 0x7a,
  0xa9, 0x68, 0x79, 0x91, 0x15, 0xb2, 0x07, 0x3f, 0x94, 0xc2, 0x10, 0x89, 0x0b, 0x22, 0x5f, 0x21,
  0x80, 0x7f, 0x5d, 0x9a, 0x5a, 0x90, 0x32, 0x27, 0x35, 0x3e, 0xcc, 0xe7, 0xbf, 0xf7, 0x97, 0x03,
  0xff, 0x19, 0x30, 0xb3, 0x48, 0xa5, 0xb5, 0xd1, 0xd7, 0x5e, 0x92, 0x2a, 0xac, 0x56, 0xaa, 0xc6,
  0x4f, 0xb8, 0x38, 0xd2, 0x96, 0xa4, 0x7d, 0xb6, 0x76, 0xfc, 0x6b, 0xe2, 0x9c, 0x74, 0x04, 0xf1,
  0x45, 0x9d, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5b, 0xcf, 0x65, 0xe6, 0x2d, 0xa8, 0x02,
  0x1b, 0x60, 0x25, 0xad, 0xae, 0xb0, 0xb9, 0xf6, 0x1c, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7e, 0x0f,
  0x55, 0x47, 0xa3, 0x23, 0xdd, 0x51, 0xaf, 0x3a, 0xc3, 0x5c, 0xf9, 0xce, 0xba, 0xc5, 0xea, 0x26,
  0x2c, 0x53, 0x0d, 0x6e, 0x85, 0x28, 0x84, 0x09, 0xd3, 0xdf, 0xcd, 0xf4, 0x41, 0x81, 0x4d, 0x52,
  0x6a, 0xdc, 0x37, 0xc8, 0x6c, 0xc1, 0xab, 0xfa, 0x24, 0xe1, 0x7b, 0x08, 0x0c, 0xbd, 0xb1, 0x4a,
  0x78, 0x88, 0x95, 0x8b, 0xe3, 0x63, 0xe8, 0x6d, 0xe9, 0xcb, 0xd5, 0xfe, 0x3b, 0x00, 0x1d, 0x39,
  0xf2, 0xef, 0xb7, 0x0e, 0x66, 0x58, 0xd0, 0xe4, 0xa6, 0x77, 0x72, 0xf8, 0xeb, 0x75, 0x4b, 0x0a,
  0x31, 0x44, 0x50, 0xb4, 0x8f, 0xed, 0x1f, 0x1a, 0xdb, 0x99, 0x8d, 0x33, 0x9f, 0x11, 0x83, 0x14
];

pub static SBOXI: [u8, ..256] = [
  0xdd, 0x07, 0x8f, 0x5f, 0x7e, 0x12, 0x0e, 0x46, 0xcb, 0xb7, 0xef, 0x4c, 0xcc, 0xb2, 0xe3, 0x9f,
  0x4a, 0xfd, 0x2f, 0x0f, 0xff, 0x44, 0x27, 0x2d, 0x2b, 0x61, 0xf7, 0x90, 0x98, 0xde, 0x20, 0xf6,
  0x87, 0x4f, 0x4d, 0xa3, 0xc8, 0x92, 0xaf, 0x57, 0xb5, 0x00, 0x6b, 0x1a, 0xb0, 0x8d, 0x01, 0x3d,
  0x62, 0xf0, 0x56, 0xfb, 0x9c, 0x58, 0x09, 0xc2, 0x72, 0xdf, 0xa7, 0xdc, 0x23, 0x08, 0x59, 0x47,
  0x9d, 0xbc, 0x29, 0x02, 0xf1, 0x80, 0x99, 0xa1, 0x64, 0x37, 0xcf, 0xee, 0x1d, 0xbe, 0x31, 0x70,
  0xf2, 0xa5, 0xbf, 0xb1, 0x0a, 0xa0, 0x6d, 0x22, 0xe5, 0x83, 0x54, 0x89, 0xa9, 0x52, 0x69, 0x4e,
  0x91, 0x9a, 0x10, 0xd5, 0x84, 0x8b, 0xe4, 0x28, 0x41, 0x9b, 0xc0, 0x7a, 0xc4, 0xd7, 0xb3, 0x2a,
  0x82, 0x85, 0xea, 0x16, 0x7d, 0xed, 0x78, 0xe9, 0xd0, 0x42, 0x3f, 0xca, 0x06, 0x76, 0x9e, 0x51,
  0x50, 0xbd, 0x1e, 0xfe, 0xb6, 0xb4, 0x88, 0x86, 0xd1, 0x4b, 0x2c, 0xd3, 0x17, 0xfa, 0x3b, 0xf4,
  0x55, 0x43, 0x6a, 0x19, 0x48, 0xd2, 0x74, 0x5e, 0x18, 0xf9, 0x53, 0x21, 0x7c, 0x81, 0x35, 0xfc,
  0x38, 0x0b, 0x04, 0xa2, 0x75, 0x65, 0xe8, 0x11, 0x8e, 0x40, 0x6e, 0xc6, 0x6c, 0x93, 0x94, 0xa6,
  0x95, 0xce, 0x45, 0x63, 0xf3, 0x66, 0x77, 0xe2, 0x71, 0x96, 0xac, 0x3c, 0x1c, 0xcd, 0x30, 0x5c,
  0x14, 0xc5, 0x49, 0xa8, 0x32, 0xad, 0x6f, 0x15, 0xc3, 0x03, 0x1f, 0xd9, 0x5a, 0xba, 0xab, 0x8a,
  0xe6, 0x67, 0x73, 0xb8, 0x25, 0xda, 0x33, 0x68, 0x05, 0x1b, 0x34, 0xf8, 0xc1, 0xa4, 0x36, 0xb9,
  0x26, 0xc9, 0x7b, 0xd4, 0xe7, 0x2e, 0x8c, 0x5b, 0xd6, 0xd8, 0xae, 0xec, 0x0c, 0xf5, 0x3e, 0xe1,
  0x0d, 0x7f, 0xe0, 0x13, 0xbb, 0x3a, 0x97, 0x5d, 0xeb, 0xaa, 0xc7, 0x39, 0x79, 0x24, 0xdb, 0x60
];

fn pad(msg: &[u8]) -> Vec<u8> {
  let mut msg = msg.to_vec();
  let pad = 16 - msg.len() % 16;
  msg.grow_fn(pad, |_| pad as u8);
  msg
}

fn checksum(msg: &[u8]) -> [u8, ..16] {
  // Message must be padded.
  assert!(msg.len() % 16 == 0);

  let mut checksum = [0u8, ..16];
  let mut last = 0u8;

  for chunk in msg.chunks(16) {
    for (mbyte, cbyte) in chunk.iter().zip(checksum.iter_mut()) {
      *cbyte ^= SBOX[(*mbyte ^ last) as uint];
      last = *cbyte;
    }
  }

  checksum
}

pub fn compress(state: &[u8], msg: &[u8]) -> [u8, ..16] {
  // Two 128 bit blocks in.
  assert!(state.len() == 16 && msg.len() == 16);

  // Copy over the current state and the message block.
  let mut x = [0u8, ..48];
  copy_memory(x[mut ..16], state);
  copy_memory(x[mut 16..32], msg);

  // XOR the previous state and the message block.
  for (i, byte) in msg.iter().enumerate() {
    x[32 + i] = *byte ^ x[i];
  }

  // Encrypt block (18 rounds).
  let mut t = 0u8;
  for i in range(0, 18) {
    for byte in x.iter_mut() {
      *byte ^= SBOX[t as uint];
      t = *byte;
    }
    t += i;
  }

  // Extract the result.
  let mut result = [0u8, ..16];
  copy_memory(&mut result, x[..16]);
  result
}

pub fn digest(msg: &[u8]) -> [u8, ..16] {
  // Pad the message to be a multiple of 16 bytes long.
  let msg = pad(msg);

  // Compress all message blocks.
  let state = msg.chunks(16).fold([0u8, ..16], |s, m| compress(&s, m));

  // Compute the checksum and merge it into the state.
  compress(&state, &checksum(msg[]))
}

#[cfg(test)]
mod test {
  use digest;

  fn check(exp: &str, msg: &str) {
    let hash = digest(msg.as_bytes());
    let hex = hash.iter().fold(String::new(), |a, &b| format!("{}{:02x}", a, b));
    assert_eq!(exp.to_string(), hex);
  }

  #[test]
  fn test() {
    check("8350e5a3e24c153df2275c9f80692773", "");
    check("32ec01ec4a6dac72c0ab96fb34c0b5d1", "a");
    check("da853b0d3f88d99b30283a69e6ded6bb", "abc");
    check("ab4f496bfb2a530b219ff33031fe06b0", "message digest");
    check("4e8ddff3650292ab5a4108c3aa47940b", "abcdefghijklmnopqrstuvwxyz");
    check("da33def2a42df13975352846c30338cd", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
    check("d5976f79d83d3a0dc9806c3c66f3efd8", "12345678901234567890123456789012345678901234567890123456789012345678901234567890");
  }
}
<commit_msg>fix license header<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/. */

#![feature(slicing_syntax)]

use std::slice::bytes::copy_memory;

pub static SBOX: [u8, ..256] = [
  0x29, 0x2e, 0x43, 0xc9, 0xa2, 0xd8, 0x7c, 0x01, 0x3d, 0x36, 0x54, 0xa1, 0xec, 0xf0, 0x06, 0x13,
  0x62, 0xa7, 0x05, 0xf3, 0xc0, 0xc7, 0x73, 0x8c, 0x98, 0x93, 0x2b, 0xd9, 0xbc, 0x4c, 0x82, 0xca,
  0x1e, 0x9b, 0x57, 0x3c, 0xfd, 0xd4, 0xe0, 0x16, 0x67, 0x42, 0x6f, 0x18, 0x8a, 0x17, 0xe5, 0x12,
  0xbe, 0x4e, 0xc4, 0xd6, 0xda, 0x9e, 0xde, 0x49, 0xa0, 0xfb, 0xf5, 0x8e, 0xbb, 0x2f, 0xee, 0x7a,
  0xa9, 0x68, 0x79, 0x91, 0x15, 0xb2, 0x07, 0x3f, 0x94, 0xc2, 0x10, 0x89, 0x0b, 0x22, 0x5f, 0x21,
  0x80, 0x7f, 0x5d, 0x9a, 0x5a, 0x90, 0x32, 0x27, 0x35, 0x3e, 0xcc, 0xe7, 0xbf, 0xf7, 0x97, 0x03,
  0xff, 0x19, 0x30, 0xb3, 0x48, 0xa5, 0xb5, 0xd1, 0xd7, 0x5e, 0x92, 0x2a, 0xac, 0x56, 0xaa, 0xc6,
  0x4f, 0xb8, 0x38, 0xd2, 0x96, 0xa4, 0x7d, 0xb6, 0x76, 0xfc, 0x6b, 0xe2, 0x9c, 0x74, 0x04, 0xf1,
  0x45, 0x9d, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5b, 0xcf, 0x65, 0xe6, 0x2d, 0xa8, 0x02,
  0x1b, 0x60, 0x25, 0xad, 0xae, 0xb0, 0xb9, 0xf6, 0x1c, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7e, 0x0f,
  0x55, 0x47, 0xa3, 0x23, 0xdd, 0x51, 0xaf, 0x3a, 0xc3, 0x5c, 0xf9, 0xce, 0xba, 0xc5, 0xea, 0x26,
  0x2c, 0x53, 0x0d, 0x6e, 0x85, 0x28, 0x84, 0x09, 0xd3, 0xdf, 0xcd, 0xf4, 0x41, 0x81, 0x4d, 0x52,
  0x6a, 0xdc, 0x37, 0xc8, 0x6c, 0xc1, 0xab, 0xfa, 0x24, 0xe1, 0x7b, 0x08, 0x0c, 0xbd, 0xb1, 0x4a,
  0x78, 0x88, 0x95, 0x8b, 0xe3, 0x63, 0xe8, 0x6d, 0xe9, 0xcb, 0xd5, 0xfe, 0x3b, 0x00, 0x1d, 0x39,
  0xf2, 0xef, 0xb7, 0x0e, 0x66, 0x58, 0xd0, 0xe4, 0xa6, 0x77, 0x72, 0xf8, 0xeb, 0x75, 0x4b, 0x0a,
  0x31, 0x44, 0x50, 0xb4, 0x8f, 0xed, 0x1f, 0x1a, 0xdb, 0x99, 0x8d, 0x33, 0x9f, 0x11, 0x83, 0x14
];

pub static SBOXI: [u8, ..256] = [
  0xdd, 0x07, 0x8f, 0x5f, 0x7e, 0x12, 0x0e, 0x46, 0xcb, 0xb7, 0xef, 0x4c, 0xcc, 0xb2, 0xe3, 0x9f,
  0x4a, 0xfd, 0x2f, 0x0f, 0xff, 0x44, 0x27, 0x2d, 0x2b, 0x61, 0xf7, 0x90, 0x98, 0xde, 0x20, 0xf6,
  0x87, 0x4f, 0x4d, 0xa3, 0xc8, 0x92, 0xaf, 0x57, 0xb5, 0x00, 0x6b, 0x1a, 0xb0, 0x8d, 0x01, 0x3d,
  0x62, 0xf0, 0x56, 0xfb, 0x9c, 0x58, 0x09, 0xc2, 0x72, 0xdf, 0xa7, 0xdc, 0x23, 0x08, 0x59, 0x47,
  0x9d, 0xbc, 0x29, 0x02, 0xf1, 0x80, 0x99, 0xa1, 0x64, 0x37, 0xcf, 0xee, 0x1d, 0xbe, 0x31, 0x70,
  0xf2, 0xa5, 0xbf, 0xb1, 0x0a, 0xa0, 0x6d, 0x22, 0xe5, 0x83, 0x54, 0x89, 0xa9, 0x52, 0x69, 0x4e,
  0x91, 0x9a, 0x10, 0xd5, 0x84, 0x8b, 0xe4, 0x28, 0x41, 0x9b, 0xc0, 0x7a, 0xc4, 0xd7, 0xb3, 0x2a,
  0x82, 0x85, 0xea, 0x16, 0x7d, 0xed, 0x78, 0xe9, 0xd0, 0x42, 0x3f, 0xca, 0x06, 0x76, 0x9e, 0x51,
  0x50, 0xbd, 0x1e, 0xfe, 0xb6, 0xb4, 0x88, 0x86, 0xd1, 0x4b, 0x2c, 0xd3, 0x17, 0xfa, 0x3b, 0xf4,
  0x55, 0x43, 0x6a, 0x19, 0x48, 0xd2, 0x74, 0x5e, 0x18, 0xf9, 0x53, 0x21, 0x7c, 0x81, 0x35, 0xfc,
  0x38, 0x0b, 0x04, 0xa2, 0x75, 0x65, 0xe8, 0x11, 0x8e, 0x40, 0x6e, 0xc6, 0x6c, 0x93, 0x94, 0xa6,
  0x95, 0xce, 0x45, 0x63, 0xf3, 0x66, 0x77, 0xe2, 0x71, 0x96, 0xac, 0x3c, 0x1c, 0xcd, 0x30, 0x5c,
  0x14, 0xc5, 0x49, 0xa8, 0x32, 0xad, 0x6f, 0x15, 0xc3, 0x03, 0x1f, 0xd9, 0x5a, 0xba, 0xab, 0x8a,
  0xe6, 0x67, 0x73, 0xb8, 0x25, 0xda, 0x33, 0x68, 0x05, 0x1b, 0x34, 0xf8, 0xc1, 0xa4, 0x36, 0xb9,
  0x26, 0xc9, 0x7b, 0xd4, 0xe7, 0x2e, 0x8c, 0x5b, 0xd6, 0xd8, 0xae, 0xec, 0x0c, 0xf5, 0x3e, 0xe1,
  0x0d, 0x7f, 0xe0, 0x13, 0xbb, 0x3a, 0x97, 0x5d, 0xeb, 0xaa, 0xc7, 0x39, 0x79, 0x24, 0xdb, 0x60
];

fn pad(msg: &[u8]) -> Vec<u8> {
  let mut msg = msg.to_vec();
  let pad = 16 - msg.len() % 16;
  msg.grow_fn(pad, |_| pad as u8);
  msg
}

fn checksum(msg: &[u8]) -> [u8, ..16] {
  // Message must be padded.
  assert!(msg.len() % 16 == 0);

  let mut checksum = [0u8, ..16];
  let mut last = 0u8;

  for chunk in msg.chunks(16) {
    for (mbyte, cbyte) in chunk.iter().zip(checksum.iter_mut()) {
      *cbyte ^= SBOX[(*mbyte ^ last) as uint];
      last = *cbyte;
    }
  }

  checksum
}

pub fn compress(state: &[u8], msg: &[u8]) -> [u8, ..16] {
  // Two 128 bit blocks in.
  assert!(state.len() == 16 && msg.len() == 16);

  // Copy over the current state and the message block.
  let mut x = [0u8, ..48];
  copy_memory(x[mut ..16], state);
  copy_memory(x[mut 16..32], msg);

  // XOR the previous state and the message block.
  for (i, byte) in msg.iter().enumerate() {
    x[32 + i] = *byte ^ x[i];
  }

  // Encrypt block (18 rounds).
  let mut t = 0u8;
  for i in range(0, 18) {
    for byte in x.iter_mut() {
      *byte ^= SBOX[t as uint];
      t = *byte;
    }
    t += i;
  }

  // Extract the result.
  let mut result = [0u8, ..16];
  copy_memory(&mut result, x[..16]);
  result
}

pub fn digest(msg: &[u8]) -> [u8, ..16] {
  // Pad the message to be a multiple of 16 bytes long.
  let msg = pad(msg);

  // Compress all message blocks.
  let state = msg.chunks(16).fold([0u8, ..16], |s, m| compress(&s, m));

  // Compute the checksum and merge it into the state.
  compress(&state, &checksum(msg[]))
}

#[cfg(test)]
mod test {
  use digest;

  fn check(exp: &str, msg: &str) {
    let hash = digest(msg.as_bytes());
    let hex = hash.iter().fold(String::new(), |a, &b| format!("{}{:02x}", a, b));
    assert_eq!(exp.to_string(), hex);
  }

  #[test]
  fn test() {
    check("8350e5a3e24c153df2275c9f80692773", "");
    check("32ec01ec4a6dac72c0ab96fb34c0b5d1", "a");
    check("da853b0d3f88d99b30283a69e6ded6bb", "abc");
    check("ab4f496bfb2a530b219ff33031fe06b0", "message digest");
    check("4e8ddff3650292ab5a4108c3aa47940b", "abcdefghijklmnopqrstuvwxyz");
    check("da33def2a42df13975352846c30338cd", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
    check("d5976f79d83d3a0dc9806c3c66f3efd8", "12345678901234567890123456789012345678901234567890123456789012345678901234567890");
  }
}
<|endoftext|>


<commit_before>//! An implementation of [FLAC](https://xiph.org/flac), free lossless audio
//! codec, written in Rust.
//!
//! # Examples
//!
//! Basic decoding from a file.
//!
//! ```
//! match flac::Stream::from_file("path/to/file.flac") {
//!   Ok(mut stream) => {
//!     // Copy of `StreamInfo` to help convert to a different audio format.
//!     let info = stream.info();
//!
//!     for sample in stream.iter() {
//!       // Iterate over each decoded sample
//!     }
//!   }
//!   Err(error)     => println!("{}", error),
//! }
//! ```

#[macro_use]
extern crate nom;

#[macro_use]
mod utility;
pub mod metadata;
mod frame;
mod subframe;
pub mod stream;

pub use metadata::Metadata;
pub use stream::Stream;
<commit_msg>Re-order the public and private modules<commit_after>//! An implementation of [FLAC](https://xiph.org/flac), free lossless audio
//! codec, written in Rust.
//!
//! # Examples
//!
//! Basic decoding from a file.
//!
//! ```
//! match flac::Stream::from_file("path/to/file.flac") {
//!   Ok(mut stream) => {
//!     // Copy of `StreamInfo` to help convert to a different audio format.
//!     let info = stream.info();
//!
//!     for sample in stream.iter() {
//!       // Iterate over each decoded sample
//!     }
//!   }
//!   Err(error)     => println!("{}", error),
//! }
//! ```

#[macro_use]
extern crate nom;

#[macro_use]
mod utility;
mod frame;
mod subframe;
pub mod metadata;
pub mod stream;

pub use metadata::Metadata;
pub use stream::Stream;
<|endoftext|>


<commit_before>extern crate regex;

#[macro_use]
extern crate lazy_static;

mod suffix;
mod nickname;
mod title;

pub struct Name {
  raw: String,
  pub given_name: String,
  pub surname: String,
  pub middle_names: String,
}

impl Name {
    pub fn parse(name: &str) -> Option<Name> {
        let mut words: Vec<&str> = Vec::new();

        // Strip suffixes and nicknames, and then flip remaining words around
        // (remaining) comma (for formats like "Smith, John"; but suffixes may
        // also contain commas, e.g. "John Smith, esq.")
        let mut parts = name.rsplit(',').peekable();
        loop {
            match parts.next() {
                Some(part) => {
                    let is_first_part = parts.peek().is_none();
                    if is_first_part || !suffix::is_suffix(part) {
                        for word in part.split_whitespace() {
                            if !nickname::is_nickname(word) {
                                words.push(word);
                            }
                        }
                    }
                }
                None => { break }
            }
        }

        // Check for non-comma-separated suffix
        if words.len() > 1 && suffix::is_suffix(words.last().unwrap()) {
            words.pop();
        }

        // Check for title as prefix
        let mut prefix_len = words.len() - 1;
        while prefix_len > 0 {
            if title::is_title(&words[0..prefix_len]) {
                for _ in 0..prefix_len {
                    words.remove(0);
                }
                break;
            }
            prefix_len -= 1;
        }

        // We need at least a first and last name, or we can't tell which we have
        if words.len() < 2 {
            return None;
        }

        // TODO Check if last word is suffix

        let parsed = Name {
            raw: name.to_string(),
            given_name: words[0].to_string(),
            surname: words[1..].join(" "),
            middle_names: "".to_string(), // TODO
        };
        return Some(parsed);
    }

    pub fn display(&self) -> String {
        return format!("{} {}", self.given_name, self.surname);
    }

}
<commit_msg>Remove outdated TODO<commit_after>extern crate regex;

#[macro_use]
extern crate lazy_static;

mod suffix;
mod nickname;
mod title;

pub struct Name {
  raw: String,
  pub given_name: String,
  pub surname: String,
  pub middle_names: String,
}

impl Name {
    pub fn parse(name: &str) -> Option<Name> {
        let mut words: Vec<&str> = Vec::new();

        // Strip suffixes and nicknames, and then flip remaining words around
        // (remaining) comma (for formats like "Smith, John"; but suffixes may
        // also contain commas, e.g. "John Smith, esq.")
        let mut parts = name.rsplit(',').peekable();
        loop {
            match parts.next() {
                Some(part) => {
                    let is_first_part = parts.peek().is_none();
                    if is_first_part || !suffix::is_suffix(part) {
                        for word in part.split_whitespace() {
                            if !nickname::is_nickname(word) {
                                words.push(word);
                            }
                        }
                    }
                }
                None => { break }
            }
        }

        // Check for non-comma-separated suffix
        if words.len() > 1 && suffix::is_suffix(words.last().unwrap()) {
            words.pop();
        }

        // Check for title as prefix
        let mut prefix_len = words.len() - 1;
        while prefix_len > 0 {
            if title::is_title(&words[0..prefix_len]) {
                for _ in 0..prefix_len {
                    words.remove(0);
                }
                break;
            }
            prefix_len -= 1;
        }

        // We need at least a first and last name, or we can't tell which we have
        if words.len() < 2 {
            return None;
        }

        let parsed = Name {
            raw: name.to_string(),
            given_name: words[0].to_string(),
            surname: words[1..].join(" "),
            middle_names: "".to_string(), // TODO
        };
        return Some(parsed);
    }

    pub fn display(&self) -> String {
        return format!("{} {}", self.given_name, self.surname);
    }

}
<|endoftext|>


<commit_before>
#![feature(phase)]

pub fn xor(source: &[u8], key: &[u8]) -> Vec<u8> {
    if source.len() == 0 || key.len() == 0 {
        return source.to_vec();
    }
    let key_iter = InfiniteByteIterator::new(key);
    source.iter().zip(key_iter).map(|(&a, b)| a ^ b).collect()
}

struct InfiniteByteIterator<'a> {
    bytes: &'a [u8],
    index: uint
}

impl<'a> InfiniteByteIterator<'a> {
    pub fn new(bytes: &'a [u8]) -> InfiniteByteIterator<'a> {
        InfiniteByteIterator {
            bytes: bytes,
            index: 0
        }
    }
}

impl<'a> Iterator<u8> for InfiniteByteIterator<'a> {
    fn next(&mut self) -> Option<u8> {
        if self.bytes.len() == 1 {
            Some(self.bytes[0])
        } else {
            let byte = self.bytes[self.index];
            self.index = next_index(self.index, self.bytes.len());
            Some(byte)
        }
    }
}

fn next_index(index: uint, count: uint) -> uint {
    if index + 1 < count { index + 1 } else { 0 }
}

#[cfg(test)]
mod test {
    #[phase(plugin)] extern crate stainless;
    pub use super::xor;

    describe! xor {
        it "should return right result" {
            let source = [0, 1, 2, 3];
            let key = [34, 52];
            assert!(xor(source, key).as_slice() == [34, 53, 32, 55]);
        }

        it "should return right result with one byte xor" {
            let source = [0, 1, 2, 3];
            let key = [47];
            assert!(xor(source, key).as_slice() == [47, 46, 45, 44]);
        }

        it "should return source if key is empty" {
            let source = [0, 1, 2, 3];
            let key = [];
            assert!(xor(source, key).as_slice() == [0, 1, 2, 3]);
        }

        it "should return empty result if source is empty" {
            let source = [];
            let key = [45, 32, 56];
            assert!(xor(source, key).as_slice() == []);
        }
    }
}
<commit_msg>Minor refactoring.<commit_after>
#![feature(phase)]

pub fn xor(source: &[u8], key: &[u8]) -> Vec<u8> {
    match key.len() {
        0 => source.to_vec(),
        1 => xor_byte(source, key[0]),
        _ => xor_sequence(source, key),
    }
}

fn xor_byte(source: &[u8], byte: u8) -> Vec<u8> {
    source.iter().map(|&a| a ^ byte).collect()
}

fn xor_sequence(source: &[u8], key: &[u8]) -> Vec<u8> {
    let key_iter = InfiniteByteIterator::new(key);
    source.iter().zip(key_iter).map(|(&a, b)| a ^ b).collect()
}

struct InfiniteByteIterator<'a> {
    bytes: &'a [u8],
    index: uint
}

impl<'a> InfiniteByteIterator<'a> {
    pub fn new(bytes: &'a [u8]) -> InfiniteByteIterator<'a> {
        InfiniteByteIterator {
            bytes: bytes,
            index: 0
        }
    }
}

impl<'a> Iterator<u8> for InfiniteByteIterator<'a> {
    fn next(&mut self) -> Option<u8> {
        let byte = self.bytes[self.index];
        self.index = next_index(self.index, self.bytes.len());
        Some(byte)
    }
}

fn next_index(index: uint, count: uint) -> uint {
    if index + 1 < count { index + 1 } else { 0 }
}

#[cfg(test)]
mod test {
    #[phase(plugin)] extern crate stainless;
    pub use super::xor;

    describe! xor {
        it "should return right result" {
            let source = [0, 1, 2, 3];
            let key = [34, 52];
            assert!(xor(source, key).as_slice() == [34, 53, 32, 55]);
        }

        it "should return right result with one byte xor" {
            let source = [0, 1, 2, 3];
            let key = [47];
            assert!(xor(source, key).as_slice() == [47, 46, 45, 44]);
        }

        it "should return source if key is empty" {
            let source = [0, 1, 2, 3];
            let key = [];
            assert!(xor(source, key).as_slice() == [0, 1, 2, 3]);
        }

        it "should return empty result if source is empty" {
            let source = [];
            let key = [45, 32, 56];
            assert!(xor(source, key).as_slice() == []);
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Write};
use std::f32::consts::PI;
use std::ops::{Add, Neg};

#[derive(Copy, Clone, Debug)]
pub struct Position(f32, f32);

impl Position {
    pub fn origin() -> Position {
        Position(0.0, 0.0)
    }

    pub fn min(&self, other: &Position) -> Position {
        Position(self.0.min(other.0), self.1.min(other.1))
    }

    pub fn max(&self, other: &Position) -> Position {
        Position(self.0.max(other.0), self.1.max(other.1))
    }

    pub fn min_max(&self, min_max: &(Position, Position)) -> (Position, Position) {
        (self.min(&min_max.0), self.max(&min_max.1))
    }
}

struct Bounds {
    min_max: Option<(Position, Position)>,
}

impl Bounds {
    fn new() -> Bounds {
        Bounds { min_max: None }
    }

    fn add_position(&mut self, pos: Position) {
        let mm = match self.min_max {
            None => (pos, pos),
            Some(ref a) => pos.min_max(a),
        };

        self.min_max = Some(mm);
    }

    fn is_bounded(&self) -> bool {
        self.min_max.is_some()
    }

    fn width(&self) -> f32 {
        let (min, max) = self.min_max.unwrap();
        (max.0 - min.0).abs()
    }

    fn height(&self) -> f32 {
        let (min, max) = self.min_max.unwrap();
        (max.1 - min.1).abs()
    }

    fn min_x(&self) -> f32 {
        let (min, _) = self.min_max.unwrap();
        min.0
    }
    fn min_y(&self) -> f32 {
        let (min, _) = self.min_max.unwrap();
        min.1
    }

    fn max_x(&self) -> f32 {
        let (_, max) = self.min_max.unwrap();
        max.0
    }
    fn max_y(&self) -> f32 {
        let (_, max) = self.min_max.unwrap();
        max.1
    }
}

impl Add<Position> for Position {
    type Output = Position;
    fn add(self, other: Position) -> Self::Output {
        Position(self.0 + other.0, self.1 + other.1)
    }
}

#[derive(Copy, Clone, Debug)]
pub struct Degree(pub f32);

#[derive(Copy, Clone, Debug)]
pub struct Radiant(pub f32);

impl Into<Degree> for Radiant {
    fn into(self) -> Degree {
        Degree(self.0 * 180.0 / PI)
    }
}

impl Into<Degree> for f32 {
    fn into(self) -> Degree {
        Degree(self)
    }
}

impl Into<Radiant> for Degree {
    fn into(self) -> Radiant {
        Radiant(self.0 * PI / 180.0)
    }
}

#[derive(Copy, Clone, Debug)]
pub struct Distance(f32);

impl Into<Distance> for f32 {
    fn into(self) -> Distance {
        Distance(self)
    }
}

impl Neg for Distance {
    type Output = Distance;
    fn neg(self) -> Self::Output {
        Distance(-self.0)
    }
}

impl Neg for Degree {
    type Output = Degree;
    fn neg(self) -> Self::Output {
        Degree(-self.0)
    }
}

pub trait Turtle {
    /// Move turtle forward by specified `distance`.
    fn forward<T: Into<Distance>>(&mut self, distance: T);

    /// Move turtle backward by specified `distance`.
    fn backward<T: Into<Distance>>(&mut self, distance: T) {
        self.forward(-distance.into())
    }

    /// Move turtle forward by specified `distance` *without* drawing.
    fn move_forward<T: Into<Distance>>(&mut self, distance: T);

    /// Rotate around `angle`. If `angle` is positive,
    /// the turtle is turned to the left, if negative,
    /// to the right.
    fn rotate<T: Into<Degree>>(&mut self, angle: T);

    /// Turn turtle right by `angle` degree.
    fn right<T: Into<Degree>>(&mut self, angle: T) {
        self.rotate(-angle.into());
    }

    /// Turn turtle left by `angle` degree.
    fn left<T: Into<Degree>>(&mut self, angle: T) {
        self.rotate(angle.into());
    }

    /// Returns `true` if pen is down.
    fn is_pen_down(&self) -> bool;

    /// Returns `true` if pen is up.
    fn is_pen_up(&self) -> bool {
        !self.is_pen_down()
    }

    /// Put the pen down.
    fn pen_down(&mut self);

    /// Put the pen up.
    fn pen_up(&mut self);

    fn goto(&mut self, pos: Position);

    fn home(&mut self) {
        self.goto(Position::origin());
    }

    /// Push current turtle state on stack.
    fn push(&mut self);

    /// Restore previously saved turtle state.
    fn pop(&mut self);
}

#[derive(Clone)]
struct TurtleState {
    pos: Position,
    angle: Degree,
    pendown: bool,
}

pub struct Canvas {
    states: Vec<TurtleState>,
    paths: Vec<Vec<Position>>,
}

impl Canvas {
    pub fn new() -> Canvas {
        let init_pos = Position::origin();
        let init_state = TurtleState {
            pos: init_pos,
            // The coordinate system we use: x from left to right. y from bottom to top.
            angle: Degree(0.0), // points upwards
            pendown: true, /* start with pen down */
        };
        Canvas {
            states: vec![init_state],
            paths: vec![vec![init_pos]],
        }
    }

    #[inline]
    fn current_state_mut(&mut self) -> &mut TurtleState {
        self.states.last_mut().unwrap()
    }

    #[inline]
    fn current_state(&self) -> &TurtleState {
        self.states.last().unwrap()
    }

    #[inline]
    fn direction(&self, distance: Distance) -> (f32, f32) {
        let state = self.current_state();
        let rad: Radiant = state.angle.into();
        let (sin, cos) = rad.0.sin_cos();
        let dx = -sin * distance.0;
        let dy = cos * distance.0;
        (dx, dy)
    }

    fn line_to(&mut self, dst: Position) {
        self.paths.last_mut().unwrap().push(dst);
    }

    fn move_to(&mut self, dst: Position) {
        if self.paths.is_empty() {
            self.paths.push(vec![dst]);
        } else {
            let begin_new_path = self.paths.last().unwrap().len() > 1;
            if begin_new_path {
                self.paths.push(vec![dst]);
            } else {
                // Replace first path element with current position
                self.paths.last_mut().unwrap()[0] = dst;
            }
        }
    }

    fn foreach_position<F: FnMut(Position)>(&self, mut f: F, scale_x: f32, scale_y: f32) {
        for path in self.paths.iter() {
            for pos in path.iter() {
                f(Position(pos.0 * scale_x, pos.1 * scale_y));
            }
        }
    }

    /// Saves the turtle graphic as Embedded Postscript (EPS)
    pub fn save_eps<W: Write>(&self, wr: &mut W) -> io::Result<()> {
        // Determine extend of canvas
        let mut bounds = Bounds::new();

        // The EPS coordinates are from bottom to top, like turtle coordinates.
        self.foreach_position(|pos| bounds.add_position(pos), 1.0, 1.0);

        let (min_width, min_height) = (100.0, 100.0);
        let width = bounds.width().max(min_width);
        let height = bounds.height().max(min_height);
        let border_percent = 0.1;

        let scale = 1.0 + 2.0 * border_percent;

        try!(writeln!(wr, r#"%%!PS-Adobe-3.0 EPSF-3.0
%%Creator: https://github.com/mneumann/turtle-rs
%%DocumentData: Clean7Bit
%%Origin: 0 0
%%BoundingBox: {} {} {} {}
%%LanguageLevel: 2
%%Pages: 1
%%Page: 1 1
"#,
        bounds.min_x() - border_percent * width,
        bounds.min_y() - border_percent * height,
        bounds.max_x() + border_percent * width,
        bounds.max_y() + border_percent * height));

        // use a stroke width of 0.1% of the width or height of the canvas
        let stroke_width = scale * width.max(height) / 1000.0;
        try!(writeln!(wr,
                      r#"{} setlinewidth"#,
                      stroke_width));

        for path in self.paths.iter() {
            if let Some((head, tail)) = path.split_first() {
                try!(writeln!(wr, "newpath"));
                try!(writeln!(wr, "  {} {} moveto", head.0, head.1));
                for pos in tail {
                    try!(writeln!(wr, r#"  {} {} lineto"#, pos.0, pos.1));
                }
                try!(writeln!(wr, r#"stroke"#));
            }
        }
        writeln!(wr, "%%EOF")
    }

    /// Saves the turtle graphic as Scalable Vector Graphic (SVG).
    pub fn save_svg<W: Write>(&self, wr: &mut W) -> io::Result<()> {
        // Determine extend of canvas
        let mut bounds = Bounds::new();

        // The SVG coordinates are from top to bottom, while turtle coordinates are
        // bottom to
        // top. We have to convert between the two. (multiply `y` by -1.0)
        self.foreach_position(|pos| bounds.add_position(pos), 1.0, -1.0);

        let (min_width, min_height) = (100.0, 100.0);
        let width = bounds.width().max(min_width);
        let height = bounds.height().max(min_height);
        let border_percent = 0.1;

        let top_left = Position(bounds.min_x() - border_percent * width,
                                bounds.min_y() - border_percent * height);

        let scale = 1.0 + 2.0 * border_percent;

        try!(writeln!(wr,
                      r#"<?xml version="1.0" encoding="UTF-8"?>
                <svg xmlns="http://www.w3.org/2000/svg"
                version="1.1" baseProfile="full"
                viewBox="{} {} {} {}">"#,
                      top_left.0,
                      top_left.1,
                      scale * width,
                      scale * height));

        // use a stroke width of 0.1% of the width or height of the canvas
        let stroke_width = scale * width.max(height) / 1000.0;
        try!(writeln!(wr,
                      r#"<g stroke="black" stroke-width="{}" fill="none">"#,
                      stroke_width));

        for path in self.paths.iter() {
            if let Some((head, tail)) = path.split_first() {
                // XXX
                let head = Position(head.0, -1.0 * head.1);

                try!(write!(wr, r#"<path d="M{} {}"#, head.0, head.1));
                for pos in tail {
                    let pos = Position(pos.0, -1.0 * pos.1);
                    try!(write!(wr, r#" L{} {}"#, pos.0, pos.1));
                }
                try!(writeln!(wr, r#"" />"#));
            }
        }
        try!(writeln!(wr, r#"</g>"#));

        writeln!(wr, "</svg>")
    }
}

impl Turtle for Canvas {
    /// Move turtle forward by specified `distance`.
    fn forward<T: Into<Distance>>(&mut self, distance: T) {
        let (dx, dy) = self.direction(distance.into());
        let src: Position = self.current_state().pos;
        let dst = Position(src.0 + dx, src.1 + dy);
        if self.is_pen_down() {
            self.line_to(dst);
        }
        self.current_state_mut().pos = dst;
    }

    fn rotate<T: Into<Degree>>(&mut self, angle: T) {
        let angle: Degree = angle.into();
        self.current_state_mut().angle.0 += angle.0;
    }

    fn move_forward<T: Into<Distance>>(&mut self, distance: T) {
        let (dx, dy) = self.direction(distance.into());
        let src: Position = self.current_state().pos;
        let dst = Position(src.0 + dx, src.1 + dy);
        self.move_to(dst);
        self.current_state_mut().pos = dst;
    }

    fn is_pen_down(&self) -> bool {
        self.current_state().pendown
    }

    /// Put the pen down.
    fn pen_down(&mut self) {
        let pos = self.current_state().pos;
        self.move_to(pos);
        self.current_state_mut().pendown = true;
    }

    /// Put the pen up.
    fn pen_up(&mut self) {
        self.current_state_mut().pendown = false;
    }

    /// Positions the turtle exactly at `position`.
    fn goto(&mut self, position: Position) {
        self.current_state_mut().pos = position;
        self.move_to(position);
    }

    /// Push current turtle state on stack.
    fn push(&mut self) {
        let state = self.current_state_mut().clone();
        self.states.push(state);
    }

    /// Restore previously saved turtle state.
    fn pop(&mut self) {
        self.states.pop();
        let pos = self.current_state().pos;
        self.move_to(pos);
    }
}
<commit_msg>Reformat and silence warning<commit_after>use std::io::{self, Write};
use std::f32::consts::PI;
use std::ops::{Add, Neg};

#[derive(Copy, Clone, Debug)]
pub struct Position(f32, f32);

impl Position {
    pub fn origin() -> Position {
        Position(0.0, 0.0)
    }

    pub fn min(&self, other: &Position) -> Position {
        Position(self.0.min(other.0), self.1.min(other.1))
    }

    pub fn max(&self, other: &Position) -> Position {
        Position(self.0.max(other.0), self.1.max(other.1))
    }

    pub fn min_max(&self, min_max: &(Position, Position)) -> (Position, Position) {
        (self.min(&min_max.0), self.max(&min_max.1))
    }
}

struct Bounds {
    min_max: Option<(Position, Position)>,
}

impl Bounds {
    fn new() -> Bounds {
        Bounds { min_max: None }
    }

    fn add_position(&mut self, pos: Position) {
        let mm = match self.min_max {
            None => (pos, pos),
            Some(ref a) => pos.min_max(a),
        };

        self.min_max = Some(mm);
    }

    #[allow(dead_code)]
    fn is_bounded(&self) -> bool {
        self.min_max.is_some()
    }

    fn width(&self) -> f32 {
        let (min, max) = self.min_max.unwrap();
        (max.0 - min.0).abs()
    }

    fn height(&self) -> f32 {
        let (min, max) = self.min_max.unwrap();
        (max.1 - min.1).abs()
    }

    fn min_x(&self) -> f32 {
        let (min, _) = self.min_max.unwrap();
        min.0
    }
    fn min_y(&self) -> f32 {
        let (min, _) = self.min_max.unwrap();
        min.1
    }

    fn max_x(&self) -> f32 {
        let (_, max) = self.min_max.unwrap();
        max.0
    }
    fn max_y(&self) -> f32 {
        let (_, max) = self.min_max.unwrap();
        max.1
    }
}

impl Add<Position> for Position {
    type Output = Position;
    fn add(self, other: Position) -> Self::Output {
        Position(self.0 + other.0, self.1 + other.1)
    }
}

#[derive(Copy, Clone, Debug)]
pub struct Degree(pub f32);

#[derive(Copy, Clone, Debug)]
pub struct Radiant(pub f32);

impl Into<Degree> for Radiant {
    fn into(self) -> Degree {
        Degree(self.0 * 180.0 / PI)
    }
}

impl Into<Degree> for f32 {
    fn into(self) -> Degree {
        Degree(self)
    }
}

impl Into<Radiant> for Degree {
    fn into(self) -> Radiant {
        Radiant(self.0 * PI / 180.0)
    }
}

#[derive(Copy, Clone, Debug)]
pub struct Distance(f32);

impl Into<Distance> for f32 {
    fn into(self) -> Distance {
        Distance(self)
    }
}

impl Neg for Distance {
    type Output = Distance;
    fn neg(self) -> Self::Output {
        Distance(-self.0)
    }
}

impl Neg for Degree {
    type Output = Degree;
    fn neg(self) -> Self::Output {
        Degree(-self.0)
    }
}

pub trait Turtle {
    /// Move turtle forward by specified `distance`.
    fn forward<T: Into<Distance>>(&mut self, distance: T);

    /// Move turtle backward by specified `distance`.
    fn backward<T: Into<Distance>>(&mut self, distance: T) {
        self.forward(-distance.into())
    }

    /// Move turtle forward by specified `distance` *without* drawing.
    fn move_forward<T: Into<Distance>>(&mut self, distance: T);

    /// Rotate around `angle`. If `angle` is positive,
    /// the turtle is turned to the left, if negative,
    /// to the right.
    fn rotate<T: Into<Degree>>(&mut self, angle: T);

    /// Turn turtle right by `angle` degree.
    fn right<T: Into<Degree>>(&mut self, angle: T) {
        self.rotate(-angle.into());
    }

    /// Turn turtle left by `angle` degree.
    fn left<T: Into<Degree>>(&mut self, angle: T) {
        self.rotate(angle.into());
    }

    /// Returns `true` if pen is down.
    fn is_pen_down(&self) -> bool;

    /// Returns `true` if pen is up.
    fn is_pen_up(&self) -> bool {
        !self.is_pen_down()
    }

    /// Put the pen down.
    fn pen_down(&mut self);

    /// Put the pen up.
    fn pen_up(&mut self);

    fn goto(&mut self, pos: Position);

    fn home(&mut self) {
        self.goto(Position::origin());
    }

    /// Push current turtle state on stack.
    fn push(&mut self);

    /// Restore previously saved turtle state.
    fn pop(&mut self);
}

#[derive(Clone)]
struct TurtleState {
    pos: Position,
    angle: Degree,
    pendown: bool,
}

pub struct Canvas {
    states: Vec<TurtleState>,
    paths: Vec<Vec<Position>>,
}

impl Canvas {
    pub fn new() -> Canvas {
        let init_pos = Position::origin();
        let init_state = TurtleState {
            pos: init_pos,
            // The coordinate system we use: x from left to right. y from bottom to top.
            angle: Degree(0.0), // points upwards
            pendown: true, // start with pen down
        };
        Canvas {
            states: vec![init_state],
            paths: vec![vec![init_pos]],
        }
    }

    #[inline]
    fn current_state_mut(&mut self) -> &mut TurtleState {
        self.states.last_mut().unwrap()
    }

    #[inline]
    fn current_state(&self) -> &TurtleState {
        self.states.last().unwrap()
    }

    #[inline]
    fn direction(&self, distance: Distance) -> (f32, f32) {
        let state = self.current_state();
        let rad: Radiant = state.angle.into();
        let (sin, cos) = rad.0.sin_cos();
        let dx = -sin * distance.0;
        let dy = cos * distance.0;
        (dx, dy)
    }

    fn line_to(&mut self, dst: Position) {
        self.paths.last_mut().unwrap().push(dst);
    }

    fn move_to(&mut self, dst: Position) {
        if self.paths.is_empty() {
            self.paths.push(vec![dst]);
        } else {
            let begin_new_path = self.paths.last().unwrap().len() > 1;
            if begin_new_path {
                self.paths.push(vec![dst]);
            } else {
                // Replace first path element with current position
                self.paths.last_mut().unwrap()[0] = dst;
            }
        }
    }

    fn foreach_position<F: FnMut(Position)>(&self, mut f: F, scale_x: f32, scale_y: f32) {
        for path in self.paths.iter() {
            for pos in path.iter() {
                f(Position(pos.0 * scale_x, pos.1 * scale_y));
            }
        }
    }

    /// Saves the turtle graphic as Embedded Postscript (EPS)
    pub fn save_eps<W: Write>(&self, wr: &mut W) -> io::Result<()> {
        // Determine extend of canvas
        let mut bounds = Bounds::new();

        // The EPS coordinates are from bottom to top, like turtle coordinates.
        self.foreach_position(|pos| bounds.add_position(pos), 1.0, 1.0);

        let (min_width, min_height) = (100.0, 100.0);
        let width = bounds.width().max(min_width);
        let height = bounds.height().max(min_height);
        let border_percent = 0.1;

        let scale = 1.0 + 2.0 * border_percent;

        try!(writeln!(wr,
                      r#"%%!PS-Adobe-3.0 EPSF-3.0
%%Creator: https://github.com/mneumann/turtle-rs
%%DocumentData: Clean7Bit
%%Origin: 0 0
%%BoundingBox: {} {} {} {}
%%LanguageLevel: 2
%%Pages: 1
%%Page: 1 1
"#,
                      bounds.min_x() - border_percent * width,
                      bounds.min_y() - border_percent * height,
                      bounds.max_x() + border_percent * width,
                      bounds.max_y() + border_percent * height));

        // use a stroke width of 0.1% of the width or height of the canvas
        let stroke_width = scale * width.max(height) / 1000.0;
        try!(writeln!(wr, r#"{} setlinewidth"#, stroke_width));

        for path in self.paths.iter() {
            if let Some((head, tail)) = path.split_first() {
                try!(writeln!(wr, "newpath"));
                try!(writeln!(wr, "  {} {} moveto", head.0, head.1));
                for pos in tail {
                    try!(writeln!(wr, r#"  {} {} lineto"#, pos.0, pos.1));
                }
                try!(writeln!(wr, r#"stroke"#));
            }
        }
        writeln!(wr, "%%EOF")
    }

    /// Saves the turtle graphic as Scalable Vector Graphic (SVG).
    pub fn save_svg<W: Write>(&self, wr: &mut W) -> io::Result<()> {
        // Determine extend of canvas
        let mut bounds = Bounds::new();

        // The SVG coordinates are from top to bottom, while turtle coordinates are
        // bottom to
        // top. We have to convert between the two. (multiply `y` by -1.0)
        self.foreach_position(|pos| bounds.add_position(pos), 1.0, -1.0);

        let (min_width, min_height) = (100.0, 100.0);
        let width = bounds.width().max(min_width);
        let height = bounds.height().max(min_height);
        let border_percent = 0.1;

        let top_left = Position(bounds.min_x() - border_percent * width,
                                bounds.min_y() - border_percent * height);

        let scale = 1.0 + 2.0 * border_percent;

        try!(writeln!(wr,
                      r#"<?xml version="1.0" encoding="UTF-8"?>
                <svg xmlns="http://www.w3.org/2000/svg"
                version="1.1" baseProfile="full"
                viewBox="{} {} {} {}">"#,
                      top_left.0,
                      top_left.1,
                      scale * width,
                      scale * height));

        // use a stroke width of 0.1% of the width or height of the canvas
        let stroke_width = scale * width.max(height) / 1000.0;
        try!(writeln!(wr,
                      r#"<g stroke="black" stroke-width="{}" fill="none">"#,
                      stroke_width));

        for path in self.paths.iter() {
            if let Some((head, tail)) = path.split_first() {
                // XXX
                let head = Position(head.0, -1.0 * head.1);

                try!(write!(wr, r#"<path d="M{} {}"#, head.0, head.1));
                for pos in tail {
                    let pos = Position(pos.0, -1.0 * pos.1);
                    try!(write!(wr, r#" L{} {}"#, pos.0, pos.1));
                }
                try!(writeln!(wr, r#"" />"#));
            }
        }
        try!(writeln!(wr, r#"</g>"#));

        writeln!(wr, "</svg>")
    }
}

impl Turtle for Canvas {
    /// Move turtle forward by specified `distance`.
    fn forward<T: Into<Distance>>(&mut self, distance: T) {
        let (dx, dy) = self.direction(distance.into());
        let src: Position = self.current_state().pos;
        let dst = Position(src.0 + dx, src.1 + dy);
        if self.is_pen_down() {
            self.line_to(dst);
        }
        self.current_state_mut().pos = dst;
    }

    fn rotate<T: Into<Degree>>(&mut self, angle: T) {
        let angle: Degree = angle.into();
        self.current_state_mut().angle.0 += angle.0;
    }

    fn move_forward<T: Into<Distance>>(&mut self, distance: T) {
        let (dx, dy) = self.direction(distance.into());
        let src: Position = self.current_state().pos;
        let dst = Position(src.0 + dx, src.1 + dy);
        self.move_to(dst);
        self.current_state_mut().pos = dst;
    }

    fn is_pen_down(&self) -> bool {
        self.current_state().pendown
    }

    /// Put the pen down.
    fn pen_down(&mut self) {
        let pos = self.current_state().pos;
        self.move_to(pos);
        self.current_state_mut().pendown = true;
    }

    /// Put the pen up.
    fn pen_up(&mut self) {
        self.current_state_mut().pendown = false;
    }

    /// Positions the turtle exactly at `position`.
    fn goto(&mut self, position: Position) {
        self.current_state_mut().pos = position;
        self.move_to(position);
    }

    /// Push current turtle state on stack.
    fn push(&mut self) {
        let state = self.current_state_mut().clone();
        self.states.push(state);
    }

    /// Restore previously saved turtle state.
    fn pop(&mut self) {
        self.states.pop();
        let pos = self.current_state().pos;
        self.move_to(pos);
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! A GLFW window back-end for the Piston game engine.

extern crate glfw;
extern crate collections;
extern crate gl;
extern crate event;
extern crate shader_version;
extern crate input;
extern crate current;

// External crates.
use current::{ Get, Modifier, Set };
use collections::RingBuf;
use glfw::Context;
use input::{
    keyboard,
    mouse,
    InputEvent,
};
use event::{
    Window,
    WindowSettings,
};
use event::window::{ ShouldClose, SetShouldClose, Size };
use event::window::{ PollEvent, SwapBuffers };
use event::window::{ CaptureCursor, SetCaptureCursor };
use event::window::{ DrawSize };
use event::window::{ Title, SetTitle };
use shader_version::opengl::OpenGL;

/// Contains stuff for game window.
pub struct GlfwWindow {
    /// The window.
    pub window: glfw::Window,
    /// Receives events from window.
    events: Receiver<(f64, glfw::WindowEvent)>,
    /// GLFW context.
    pub glfw: glfw::Glfw,
    event_queue: RingBuf<input::InputEvent>,
    // Used to compute relative mouse movement.
    last_mouse_pos: Option<(f64, f64)>,
    // The back-end does not remember the title.
    title: String,
    exit_on_esc: bool,
}

impl GlfwWindow {
    /// Create a new game window from an existing GLFW window.
    pub fn from_pieces(win: glfw::Window, glfw: glfw::Glfw,
                       events: Receiver<(f64, glfw::WindowEvent)>,
                       exit_on_esc: bool) -> GlfwWindow {
        win.set_all_polling(true);
        win.make_current();
        let title = "<unknown window title, created from_pieces>";
        GlfwWindow {
            window: win,
            events: events,
            glfw: glfw,
            exit_on_esc: exit_on_esc,
            event_queue: RingBuf::new(),
            last_mouse_pos: None,
            title: title.to_string(),
        }
    }

    /// Creates a new game window for GLFW.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> GlfwWindow {
        use glfw::Context;

        // Initialize GLFW.
        let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

        let (major, minor) = opengl.get_major_minor();

        // Make sure we have the right GL version.
        glfw.window_hint(glfw::ContextVersion(major as u32, minor as u32));
        glfw.window_hint(glfw::OpenglForwardCompat(true));
        glfw.window_hint(glfw::OpenglProfile(glfw::OpenGlCoreProfile));
        glfw.window_hint(glfw::Samples(settings.samples as u32));

        // Create GLFW window.
        let (window, events) = glfw.create_window(
            settings.size[0],
            settings.size[1],
            settings.title.as_slice(), glfw::Windowed
        ).expect("Failed to create GLFW window.");
        window.set_all_polling(true);
        window.make_current();

        // Load the OpenGL function pointers
        gl::load_with(|s| window.get_proc_address(s));

        GlfwWindow {
            window: window,
            events: events,
            glfw: glfw,
            event_queue: RingBuf::new(),
            last_mouse_pos: None,
            title: settings.title,
            exit_on_esc: settings.exit_on_esc,
        }
    }

    fn flush_messages(&mut self) {
        if self.event_queue.len() != 0 {
            return;
        }

        self.glfw.poll_events();
        for (_, event) in glfw::flush_messages(&self.events) {
            match event {
                glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _)
                if self.exit_on_esc => {
                    self.window.set_should_close(true);
                }
                glfw::CharEvent(ch) => {
                    self.event_queue.push_back(input::Text(ch.to_string()));
                }
                glfw::KeyEvent(key, _, glfw::Press, _) => {
                    self.event_queue.push_back(
                        input::Press(input::Keyboard(glfw_map_key(key)))
                    );
                }
                glfw::KeyEvent(key, _, glfw::Release, _) => {
                    self.event_queue.push_back(
                        input::Release(input::Keyboard(glfw_map_key(key)))
                    );
                }
                glfw::MouseButtonEvent(button, glfw::Press, _) => {
                    self.event_queue.push_back(
                        input::Press(input::Mouse(glfw_map_mouse(button)))
                    );
                }
                glfw::MouseButtonEvent(button, glfw::Release, _) => {
                    self.event_queue.push_back(
                        input::Release(input::Mouse(glfw_map_mouse(button)))
                    );
                }
                glfw::CursorPosEvent(x, y) => {
                    self.event_queue.push_back(input::Move(input::MouseCursor(x, y)));
                    match self.last_mouse_pos {
                        Some((lx, ly)) => {
                            self.event_queue.push_back(
                                input::Move(input::MouseRelative(x - lx, y - ly))
                            )
                        }
                        None => {}
                    };
                    self.last_mouse_pos = Some((x, y));
                }
                glfw::ScrollEvent(x, y) => {
                    self.event_queue.push_back(input::Move(input::MouseScroll(x, y)));
                }
                glfw::SizeEvent(w, h) => {
                    self.event_queue.push_back(input::Resize(w as u32, h as u32));
                }
                glfw::FocusEvent(focus) => {
                    self.event_queue.push_back(input::Focus(focus));
                }
                _ => {}
            }
        }
    }
}

impl Get<Size> for GlfwWindow {
    fn get(&self) -> Size {
        let (w, h) = self.window.get_size();
        Size([w as u32, h as u32])
    }
}

impl Get<ShouldClose> for GlfwWindow {
    fn get(&self) -> ShouldClose {
        ShouldClose(self.window.should_close())
    }
}

impl PollEvent<InputEvent> for GlfwWindow {
    fn poll_event(&mut self) -> Option<input::InputEvent> {
        self.flush_messages();

        if self.event_queue.len() != 0 {
            self.event_queue.pop_front()
        } else {
            None
        }
    }
}

impl SwapBuffers for GlfwWindow {
    fn swap_buffers(&mut self) {
        use glfw::Context;

        self.window.swap_buffers();
    }
}

impl Modifier<GlfwWindow> for CaptureCursor {
    fn modify(self, window: &mut GlfwWindow) {
        let CaptureCursor(enabled) = self;
        if enabled {
            window.window.set_cursor_mode(glfw::CursorDisabled)
        } else {
            window.window.set_cursor_mode(glfw::CursorNormal);
            window.last_mouse_pos = None;
        }
    }
}

impl SetCaptureCursor for GlfwWindow {
    fn set_capture_cursor(&mut self, val: CaptureCursor) {
        self.set_mut(val);
    }
}

impl Modifier<GlfwWindow> for ShouldClose {
    fn modify(self, window: &mut GlfwWindow) {
        let ShouldClose(val) = self;
        window.window.set_should_close(val);
    }
}

impl SetShouldClose for GlfwWindow {
    fn set_should_close(&mut self, val: ShouldClose) {
        self.set_mut(val);
    }
}

impl Get<DrawSize> for GlfwWindow {
    fn get(&self) -> DrawSize {
        let (w, h) = self.window.get_framebuffer_size();
        DrawSize([w as u32, h as u32])
    }
}

impl Get<Title> for GlfwWindow {
    fn get(&self) -> Title {
        Title(self.title.clone())
    }
}

impl Modifier<GlfwWindow> for Title {
    fn modify(self, window: &mut GlfwWindow) {
        let Title(val) = self;
        window.window.set_title(val.as_slice())
    }
}

impl SetTitle for GlfwWindow {
    fn set_title(&mut self, val: Title) {
        self.set_mut(val);
    }
}

impl Window for GlfwWindow {}

fn glfw_map_key(keycode: glfw::Key) -> keyboard::Key {
    match keycode {
        glfw::Key0 => keyboard::D0,
        glfw::Key1 => keyboard::D1,
        glfw::Key2 => keyboard::D2,
        glfw::Key3 => keyboard::D3,
        glfw::Key4 => keyboard::D4,
        glfw::Key5 => keyboard::D5,
        glfw::Key6 => keyboard::D6,
        glfw::Key7 => keyboard::D7,
        glfw::Key8 => keyboard::D8,
        glfw::Key9 => keyboard::D9,
        glfw::KeyA => keyboard::A,
        glfw::KeyB => keyboard::B,
        glfw::KeyC => keyboard::C,
        glfw::KeyD => keyboard::D,
        glfw::KeyE => keyboard::E,
        glfw::KeyF => keyboard::F,
        glfw::KeyG => keyboard::G,
        glfw::KeyH => keyboard::H,
        glfw::KeyI => keyboard::I,
        glfw::KeyJ => keyboard::J,
        glfw::KeyK => keyboard::K,
        glfw::KeyL => keyboard::L,
        glfw::KeyM => keyboard::M,
        glfw::KeyN => keyboard::N,
        glfw::KeyO => keyboard::O,
        glfw::KeyP => keyboard::P,
        glfw::KeyQ => keyboard::Q,
        glfw::KeyR => keyboard::R,
        glfw::KeyS => keyboard::S,
        glfw::KeyT => keyboard::T,
        glfw::KeyU => keyboard::U,
        glfw::KeyV => keyboard::V,
        glfw::KeyW => keyboard::W,
        glfw::KeyX => keyboard::X,
        glfw::KeyY => keyboard::Y,
        glfw::KeyZ => keyboard::Z,
        glfw::KeyApostrophe => keyboard::Unknown,
        glfw::KeyBackslash => keyboard::Backslash,
        glfw::KeyBackspace => keyboard::Backspace,
        glfw::KeyCapsLock => keyboard::CapsLock,
        glfw::KeyDelete => keyboard::Delete,
        glfw::KeyComma => keyboard::Comma,
        glfw::KeyDown => keyboard::Down,
        glfw::KeyEnd => keyboard::End,
        glfw::KeyEnter => keyboard::Return,
        glfw::KeyEqual => keyboard::Equals,
        glfw::KeyEscape => keyboard::Escape,
        glfw::KeyF1 => keyboard::F1,
        glfw::KeyF2 => keyboard::F2,
        glfw::KeyF3 => keyboard::F3,
        glfw::KeyF4 => keyboard::F4,
        glfw::KeyF5 => keyboard::F5,
        glfw::KeyF6 => keyboard::F6,
        glfw::KeyF7 => keyboard::F7,
        glfw::KeyF8 => keyboard::F8,
        glfw::KeyF9 => keyboard::F9,
        glfw::KeyF10 => keyboard::F10,
        glfw::KeyF11 => keyboard::F11,
        glfw::KeyF12 => keyboard::F12,
        glfw::KeyF13 => keyboard::F13,
        glfw::KeyF14 => keyboard::F14,
        glfw::KeyF15 => keyboard::F15,
        glfw::KeyF16 => keyboard::F16,
        glfw::KeyF17 => keyboard::F17,
        glfw::KeyF18 => keyboard::F18,
        glfw::KeyF19 => keyboard::F19,
        glfw::KeyF20 => keyboard::F20,
        glfw::KeyF21 => keyboard::F21,
        glfw::KeyF22 => keyboard::F22,
        glfw::KeyF23 => keyboard::F23,
        glfw::KeyF24 => keyboard::F24,
        // Possibly next code.
        glfw::KeyF25 => keyboard::Unknown,
        glfw::KeyKp0 => keyboard::NumPad0,
        glfw::KeyKp1 => keyboard::NumPad1,
        glfw::KeyKp2 => keyboard::NumPad2,
        glfw::KeyKp3 => keyboard::NumPad3,
        glfw::KeyKp4 => keyboard::NumPad4,
        glfw::KeyKp5 => keyboard::NumPad5,
        glfw::KeyKp6 => keyboard::NumPad6,
        glfw::KeyKp7 => keyboard::NumPad7,
        glfw::KeyKp8 => keyboard::NumPad8,
        glfw::KeyKp9 => keyboard::NumPad9,
        glfw::KeyKpDecimal => keyboard::NumPadDecimal,
        glfw::KeyKpDivide => keyboard::NumPadDivide,
        glfw::KeyKpMultiply => keyboard::NumPadMultiply,
        glfw::KeyKpSubtract => keyboard::NumPadMinus,
        glfw::KeyKpAdd => keyboard::NumPadPlus,
        glfw::KeyKpEnter => keyboard::NumPadEnter,
        glfw::KeyKpEqual => keyboard::NumPadEquals,
        glfw::KeyLeftShift => keyboard::LShift,
        glfw::KeyLeftControl => keyboard::LCtrl,
        glfw::KeyLeftAlt => keyboard::LAlt,
        glfw::KeyLeftSuper => keyboard::LGui,
        glfw::KeyRightShift => keyboard::RShift,
        glfw::KeyRightControl => keyboard::RCtrl,
        glfw::KeyRightAlt => keyboard::RAlt,
        glfw::KeyRightSuper => keyboard::RGui,
        // Map to backslash?
        glfw::KeyGraveAccent => keyboard::Unknown,
        glfw::KeyHome => keyboard::Home,
        glfw::KeyInsert => keyboard::Insert,
        glfw::KeyLeft => keyboard::Left,
        glfw::KeyLeftBracket => keyboard::LeftBracket,
        glfw::KeyMenu => keyboard::Menu,
        glfw::KeyMinus => keyboard::Minus,
        glfw::KeyNumLock => keyboard::NumLockClear,
        glfw::KeyPageDown => keyboard::PageDown,
        glfw::KeyPageUp => keyboard::PageUp,
        glfw::KeyPause => keyboard::Pause,
        glfw::KeyPeriod => keyboard::Period,
        glfw::KeyPrintScreen => keyboard::PrintScreen,
        glfw::KeyRight => keyboard::Right,
        glfw::KeyRightBracket => keyboard::RightBracket,
        glfw::KeyScrollLock => keyboard::ScrollLock,
        glfw::KeySemicolon => keyboard::Semicolon,
        glfw::KeySlash => keyboard::Slash,
        glfw::KeySpace => keyboard::Space,
        glfw::KeyTab => keyboard::Tab,
        glfw::KeyUp => keyboard::Up,
        glfw::KeyWorld1 => keyboard::Unknown,
        glfw::KeyWorld2 => keyboard::Unknown,
        // _ => keyboard::Unknown,
    }
}

fn glfw_map_mouse(mouse_button: glfw::MouseButton) -> mouse::Button {
    match mouse_button {
        glfw::MouseButton1 => mouse::Left,
        glfw::MouseButton2 => mouse::Right,
        glfw::MouseButton3 => mouse::Middle,
        glfw::MouseButton4 => mouse::X1,
        glfw::MouseButton5 => mouse::X2,
        glfw::MouseButton6 => mouse::Button6,
        glfw::MouseButton7 => mouse::Button7,
        glfw::MouseButton8 => mouse::Button8,
    }
}
<commit_msg>Upgraded to latest piston-event<commit_after>#![deny(missing_docs)]

//! A GLFW window back-end for the Piston game engine.

extern crate glfw;
extern crate collections;
extern crate gl;
extern crate event;
extern crate shader_version;
extern crate input;
extern crate current;

// External crates.
use current::{ Get, Modifier, Set };
use collections::RingBuf;
use glfw::Context;
use input::{
    keyboard,
    mouse,
    InputEvent,
};
use event::{
    Window,
    WindowSettings,
};
use event::window::{
    ShouldClose, SetShouldClose, Size,
    PollEvent, SwapBuffers,
    CaptureCursor, SetCaptureCursor,
    DrawSize,
    Title, SetTitle,
    ExitOnEsc, SetExitOnEsc,
};
use shader_version::opengl::OpenGL;

/// Contains stuff for game window.
pub struct GlfwWindow {
    /// The window.
    pub window: glfw::Window,
    /// Receives events from window.
    events: Receiver<(f64, glfw::WindowEvent)>,
    /// GLFW context.
    pub glfw: glfw::Glfw,
    event_queue: RingBuf<input::InputEvent>,
    // Used to compute relative mouse movement.
    last_mouse_pos: Option<(f64, f64)>,
    // The back-end does not remember the title.
    title: String,
    exit_on_esc: bool,
}

impl GlfwWindow {
    /// Create a new game window from an existing GLFW window.
    pub fn from_pieces(win: glfw::Window, glfw: glfw::Glfw,
                       events: Receiver<(f64, glfw::WindowEvent)>,
                       exit_on_esc: bool) -> GlfwWindow {
        win.set_all_polling(true);
        win.make_current();
        let title = "<unknown window title, created from_pieces>";
        GlfwWindow {
            window: win,
            events: events,
            glfw: glfw,
            exit_on_esc: exit_on_esc,
            event_queue: RingBuf::new(),
            last_mouse_pos: None,
            title: title.to_string(),
        }
    }

    /// Creates a new game window for GLFW.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> GlfwWindow {
        use glfw::Context;

        // Initialize GLFW.
        let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

        let (major, minor) = opengl.get_major_minor();

        // Make sure we have the right GL version.
        glfw.window_hint(glfw::ContextVersion(major as u32, minor as u32));
        glfw.window_hint(glfw::OpenglForwardCompat(true));
        glfw.window_hint(glfw::OpenglProfile(glfw::OpenGlCoreProfile));
        glfw.window_hint(glfw::Samples(settings.samples as u32));

        // Create GLFW window.
        let (window, events) = glfw.create_window(
            settings.size[0],
            settings.size[1],
            settings.title.as_slice(), glfw::Windowed
        ).expect("Failed to create GLFW window.");
        window.set_all_polling(true);
        window.make_current();

        // Load the OpenGL function pointers
        gl::load_with(|s| window.get_proc_address(s));

        GlfwWindow {
            window: window,
            events: events,
            glfw: glfw,
            event_queue: RingBuf::new(),
            last_mouse_pos: None,
            title: settings.title,
            exit_on_esc: settings.exit_on_esc,
        }
    }

    fn flush_messages(&mut self) {
        if self.event_queue.len() != 0 {
            return;
        }

        self.glfw.poll_events();
        for (_, event) in glfw::flush_messages(&self.events) {
            match event {
                glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _)
                if self.exit_on_esc => {
                    self.window.set_should_close(true);
                }
                glfw::CharEvent(ch) => {
                    self.event_queue.push_back(input::Text(ch.to_string()));
                }
                glfw::KeyEvent(key, _, glfw::Press, _) => {
                    self.event_queue.push_back(
                        input::Press(input::Keyboard(glfw_map_key(key)))
                    );
                }
                glfw::KeyEvent(key, _, glfw::Release, _) => {
                    self.event_queue.push_back(
                        input::Release(input::Keyboard(glfw_map_key(key)))
                    );
                }
                glfw::MouseButtonEvent(button, glfw::Press, _) => {
                    self.event_queue.push_back(
                        input::Press(input::Mouse(glfw_map_mouse(button)))
                    );
                }
                glfw::MouseButtonEvent(button, glfw::Release, _) => {
                    self.event_queue.push_back(
                        input::Release(input::Mouse(glfw_map_mouse(button)))
                    );
                }
                glfw::CursorPosEvent(x, y) => {
                    self.event_queue.push_back(input::Move(input::MouseCursor(x, y)));
                    match self.last_mouse_pos {
                        Some((lx, ly)) => {
                            self.event_queue.push_back(
                                input::Move(input::MouseRelative(x - lx, y - ly))
                            )
                        }
                        None => {}
                    };
                    self.last_mouse_pos = Some((x, y));
                }
                glfw::ScrollEvent(x, y) => {
                    self.event_queue.push_back(input::Move(input::MouseScroll(x, y)));
                }
                glfw::SizeEvent(w, h) => {
                    self.event_queue.push_back(input::Resize(w as u32, h as u32));
                }
                glfw::FocusEvent(focus) => {
                    self.event_queue.push_back(input::Focus(focus));
                }
                _ => {}
            }
        }
    }
}

impl Get<Size> for GlfwWindow {
    fn get(&self) -> Size {
        let (w, h) = self.window.get_size();
        Size([w as u32, h as u32])
    }
}

impl Get<ShouldClose> for GlfwWindow {
    fn get(&self) -> ShouldClose {
        ShouldClose(self.window.should_close())
    }
}

impl PollEvent<InputEvent> for GlfwWindow {
    fn poll_event(&mut self) -> Option<input::InputEvent> {
        self.flush_messages();

        if self.event_queue.len() != 0 {
            self.event_queue.pop_front()
        } else {
            None
        }
    }
}

impl SwapBuffers for GlfwWindow {
    fn swap_buffers(&mut self) {
        use glfw::Context;

        self.window.swap_buffers();
    }
}

impl Modifier<GlfwWindow> for CaptureCursor {
    fn modify(self, window: &mut GlfwWindow) {
        let CaptureCursor(enabled) = self;
        if enabled {
            window.window.set_cursor_mode(glfw::CursorDisabled)
        } else {
            window.window.set_cursor_mode(glfw::CursorNormal);
            window.last_mouse_pos = None;
        }
    }
}

impl SetCaptureCursor for GlfwWindow {
    fn set_capture_cursor(&mut self, val: CaptureCursor) {
        self.set_mut(val);
    }
}

impl Modifier<GlfwWindow> for ShouldClose {
    fn modify(self, window: &mut GlfwWindow) {
        let ShouldClose(val) = self;
        window.window.set_should_close(val);
    }
}

impl SetShouldClose for GlfwWindow {
    fn set_should_close(&mut self, val: ShouldClose) {
        self.set_mut(val);
    }
}

impl Get<DrawSize> for GlfwWindow {
    fn get(&self) -> DrawSize {
        let (w, h) = self.window.get_framebuffer_size();
        DrawSize([w as u32, h as u32])
    }
}

impl Get<Title> for GlfwWindow {
    fn get(&self) -> Title {
        Title(self.title.clone())
    }
}

impl Modifier<GlfwWindow> for Title {
    fn modify(self, window: &mut GlfwWindow) {
        let Title(val) = self;
        window.window.set_title(val.as_slice())
    }
}

impl SetTitle for GlfwWindow {
    fn set_title(&mut self, val: Title) {
        self.set_mut(val);
    }
}

impl Get<ExitOnEsc> for GlfwWindow {
    fn get(&self) -> ExitOnEsc {
        ExitOnEsc(self.exit_on_esc)
    }
}

impl Modifier<GlfwWindow> for ExitOnEsc {
    fn modify(self, window: &mut GlfwWindow) {
        let ExitOnEsc(val) = self;
        window.exit_on_esc = val;
    }
}

impl SetExitOnEsc for GlfwWindow {
    fn set_exit_on_esc(&mut self, val: ExitOnEsc) {
        self.set_mut(val);
    }
}

impl Window for GlfwWindow {}

fn glfw_map_key(keycode: glfw::Key) -> keyboard::Key {
    match keycode {
        glfw::Key0 => keyboard::D0,
        glfw::Key1 => keyboard::D1,
        glfw::Key2 => keyboard::D2,
        glfw::Key3 => keyboard::D3,
        glfw::Key4 => keyboard::D4,
        glfw::Key5 => keyboard::D5,
        glfw::Key6 => keyboard::D6,
        glfw::Key7 => keyboard::D7,
        glfw::Key8 => keyboard::D8,
        glfw::Key9 => keyboard::D9,
        glfw::KeyA => keyboard::A,
        glfw::KeyB => keyboard::B,
        glfw::KeyC => keyboard::C,
        glfw::KeyD => keyboard::D,
        glfw::KeyE => keyboard::E,
        glfw::KeyF => keyboard::F,
        glfw::KeyG => keyboard::G,
        glfw::KeyH => keyboard::H,
        glfw::KeyI => keyboard::I,
        glfw::KeyJ => keyboard::J,
        glfw::KeyK => keyboard::K,
        glfw::KeyL => keyboard::L,
        glfw::KeyM => keyboard::M,
        glfw::KeyN => keyboard::N,
        glfw::KeyO => keyboard::O,
        glfw::KeyP => keyboard::P,
        glfw::KeyQ => keyboard::Q,
        glfw::KeyR => keyboard::R,
        glfw::KeyS => keyboard::S,
        glfw::KeyT => keyboard::T,
        glfw::KeyU => keyboard::U,
        glfw::KeyV => keyboard::V,
        glfw::KeyW => keyboard::W,
        glfw::KeyX => keyboard::X,
        glfw::KeyY => keyboard::Y,
        glfw::KeyZ => keyboard::Z,
        glfw::KeyApostrophe => keyboard::Unknown,
        glfw::KeyBackslash => keyboard::Backslash,
        glfw::KeyBackspace => keyboard::Backspace,
        glfw::KeyCapsLock => keyboard::CapsLock,
        glfw::KeyDelete => keyboard::Delete,
        glfw::KeyComma => keyboard::Comma,
        glfw::KeyDown => keyboard::Down,
        glfw::KeyEnd => keyboard::End,
        glfw::KeyEnter => keyboard::Return,
        glfw::KeyEqual => keyboard::Equals,
        glfw::KeyEscape => keyboard::Escape,
        glfw::KeyF1 => keyboard::F1,
        glfw::KeyF2 => keyboard::F2,
        glfw::KeyF3 => keyboard::F3,
        glfw::KeyF4 => keyboard::F4,
        glfw::KeyF5 => keyboard::F5,
        glfw::KeyF6 => keyboard::F6,
        glfw::KeyF7 => keyboard::F7,
        glfw::KeyF8 => keyboard::F8,
        glfw::KeyF9 => keyboard::F9,
        glfw::KeyF10 => keyboard::F10,
        glfw::KeyF11 => keyboard::F11,
        glfw::KeyF12 => keyboard::F12,
        glfw::KeyF13 => keyboard::F13,
        glfw::KeyF14 => keyboard::F14,
        glfw::KeyF15 => keyboard::F15,
        glfw::KeyF16 => keyboard::F16,
        glfw::KeyF17 => keyboard::F17,
        glfw::KeyF18 => keyboard::F18,
        glfw::KeyF19 => keyboard::F19,
        glfw::KeyF20 => keyboard::F20,
        glfw::KeyF21 => keyboard::F21,
        glfw::KeyF22 => keyboard::F22,
        glfw::KeyF23 => keyboard::F23,
        glfw::KeyF24 => keyboard::F24,
        // Possibly next code.
        glfw::KeyF25 => keyboard::Unknown,
        glfw::KeyKp0 => keyboard::NumPad0,
        glfw::KeyKp1 => keyboard::NumPad1,
        glfw::KeyKp2 => keyboard::NumPad2,
        glfw::KeyKp3 => keyboard::NumPad3,
        glfw::KeyKp4 => keyboard::NumPad4,
        glfw::KeyKp5 => keyboard::NumPad5,
        glfw::KeyKp6 => keyboard::NumPad6,
        glfw::KeyKp7 => keyboard::NumPad7,
        glfw::KeyKp8 => keyboard::NumPad8,
        glfw::KeyKp9 => keyboard::NumPad9,
        glfw::KeyKpDecimal => keyboard::NumPadDecimal,
        glfw::KeyKpDivide => keyboard::NumPadDivide,
        glfw::KeyKpMultiply => keyboard::NumPadMultiply,
        glfw::KeyKpSubtract => keyboard::NumPadMinus,
        glfw::KeyKpAdd => keyboard::NumPadPlus,
        glfw::KeyKpEnter => keyboard::NumPadEnter,
        glfw::KeyKpEqual => keyboard::NumPadEquals,
        glfw::KeyLeftShift => keyboard::LShift,
        glfw::KeyLeftControl => keyboard::LCtrl,
        glfw::KeyLeftAlt => keyboard::LAlt,
        glfw::KeyLeftSuper => keyboard::LGui,
        glfw::KeyRightShift => keyboard::RShift,
        glfw::KeyRightControl => keyboard::RCtrl,
        glfw::KeyRightAlt => keyboard::RAlt,
        glfw::KeyRightSuper => keyboard::RGui,
        // Map to backslash?
        glfw::KeyGraveAccent => keyboard::Unknown,
        glfw::KeyHome => keyboard::Home,
        glfw::KeyInsert => keyboard::Insert,
        glfw::KeyLeft => keyboard::Left,
        glfw::KeyLeftBracket => keyboard::LeftBracket,
        glfw::KeyMenu => keyboard::Menu,
        glfw::KeyMinus => keyboard::Minus,
        glfw::KeyNumLock => keyboard::NumLockClear,
        glfw::KeyPageDown => keyboard::PageDown,
        glfw::KeyPageUp => keyboard::PageUp,
        glfw::KeyPause => keyboard::Pause,
        glfw::KeyPeriod => keyboard::Period,
        glfw::KeyPrintScreen => keyboard::PrintScreen,
        glfw::KeyRight => keyboard::Right,
        glfw::KeyRightBracket => keyboard::RightBracket,
        glfw::KeyScrollLock => keyboard::ScrollLock,
        glfw::KeySemicolon => keyboard::Semicolon,
        glfw::KeySlash => keyboard::Slash,
        glfw::KeySpace => keyboard::Space,
        glfw::KeyTab => keyboard::Tab,
        glfw::KeyUp => keyboard::Up,
        glfw::KeyWorld1 => keyboard::Unknown,
        glfw::KeyWorld2 => keyboard::Unknown,
        // _ => keyboard::Unknown,
    }
}

fn glfw_map_mouse(mouse_button: glfw::MouseButton) -> mouse::Button {
    match mouse_button {
        glfw::MouseButton1 => mouse::Left,
        glfw::MouseButton2 => mouse::Right,
        glfw::MouseButton3 => mouse::Middle,
        glfw::MouseButton4 => mouse::X1,
        glfw::MouseButton5 => mouse::X2,
        glfw::MouseButton6 => mouse::Button6,
        glfw::MouseButton7 => mouse::Button7,
        glfw::MouseButton8 => mouse::Button8,
    }
}
<|endoftext|>