<commit_before>//! # A strongly restrictive color type.

use std::fmt;

/// It is guaranteed that `T` can be and will always be only either `u8` or `f32`.
/// It can also be guaranteed that `Display` is not and will never be implemented
/// for `Color<f32>`.
/// It can also be guaranteed that arithmetics are not and will never be implemented
/// for `Color<u8>`.
///
/// ```
/// assert_fail_to_compile!(Color(0.0, 0.0, 0.0).to_string());
/// assert_fail_to_compile!(println!("{}", Color(0.0, 0.0, 0.0)));
/// assert_fail_to_compile!(Color(0, 0, 0) + Color(1, 1, 1));
/// ```
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Color<T>(T, T, T);

/// `Color888` can only do IO (convert to and from strings), and some simple equality tests.
pub type Color888 = Color<u8>;
/// `Colorf32` can only do arithmetics and convert to/from `Color888`.
pub type Colorf32 = Color<f32>;

impl fmt::Display for Color888 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let Color(r, g, b) = *self;
        write!(f, "{:02x}{:02x}{:02x}", r, g, b)
    }
}

impl Eq for Color888 {}

impl From<Color888> for Colorf32 {
    fn from(color: Color888) -> Self {
        let Color(r, g, b) = color;
        let r = r as f32 / 255f32;
        let g = g as f32 / 255f32;
        let b = b as f32 / 255f32;
        Color(r, g, b)
    }
}

impl Colorf32 {
    fn clamp_to_888(self) -> Color888 {
        let Color(r, g, b) = self.clamp();
        let r = (r * 255f32).min(255f32) as u8;
        let g = (g * 255f32).min(255f32) as u8;
        let b = (b * 255f32).min(255f32) as u8;
        Color(r, g, b)
    }

    fn clamp_with(self, min: f32, max: f32) -> Self {
        let Color(r, g, b) = self;
        let r = r.max(min).min(max);
        let g = g.max(min).min(max);
        let b = b.max(min).min(max);
        Color(r, g, b)
    }

    fn clamp(self) -> Self {
        self.clamp_with(0f32, 1f32)
    }
}

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

    #[test]
    fn lossless_conversion() {
        for i in 0..256 {
            let a = i as u8;
            let color = Color(a, a, a);
            let color2 = Colorf32::from(color).clamp_to_888();
            assert_eq!(color, color2);
        }
    }

    #[test]
    fn clampped_down_conversion() {
        let max = Color(255, 255, 255);
        for i in 256..512 {
            let a = i as f32 / 255f32;
            let color = Color(a, a, a).clamp_to_888();
            assert_eq!(color, max);
        }
    }

    #[test]
    fn clampped_up_conversion() {
        let min = Color(0, 0, 0);
        for i in -256..0 {
            let a = i as f32 / 255f32;
            let color = Color(a, a, a).clamp_to_888();
            assert_eq!(color, min);
        }
    }

    #[test]
    fn display_color888() {
        assert_eq!(Color(0, 0, 0).to_string(), "000000");
        assert_eq!(Color(255, 255, 255).to_string(), "ffffff");
        assert_eq!(Color(1, 254, 10).to_string(), "01fe0a");
    }
}

<commit_msg>use underscore in numbers to make things easier on eyes.<commit_after>//! # A strongly restrictive color type.

use std::fmt;

/// It is guaranteed that `T` can be and will always be only either `u8` or `f32`.
/// It can also be guaranteed that `Display` is not and will never be implemented
/// for `Color<f32>`.
/// It can also be guaranteed that arithmetics are not and will never be implemented
/// for `Color<u8>`.
///
/// ```
/// assert_fail_to_compile!(Color(0.0, 0.0, 0.0).to_string());
/// assert_fail_to_compile!(println!("{}", Color(0.0, 0.0, 0.0)));
/// assert_fail_to_compile!(Color(0, 0, 0) + Color(1, 1, 1));
/// ```
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Color<T>(T, T, T);

/// `Color888` can only do IO (convert to and from strings), and some simple equality tests.
pub type Color888 = Color<u8>;
/// `Colorf32` can only do arithmetics and convert to/from `Color888`.
pub type Colorf32 = Color<f32>;

impl fmt::Display for Color888 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let Color(r, g, b) = *self;
        write!(f, "{:02x}{:02x}{:02x}", r, g, b)
    }
}

impl Eq for Color888 {}

impl From<Color888> for Colorf32 {
    fn from(color: Color888) -> Self {
        let Color(r, g, b) = color;
        let r = r as f32 / 255_f32;
        let g = g as f32 / 255_f32;
        let b = b as f32 / 255_f32;
        Color(r, g, b)
    }
}

impl Colorf32 {
    fn clamp_to_888(self) -> Color888 {
        let Color(r, g, b) = self.clamp();
        let r = (r * 255_f32).min(255_f32) as u8;
        let g = (g * 255_f32).min(255_f32) as u8;
        let b = (b * 255_f32).min(255_f32) as u8;
        Color(r, g, b)
    }

    fn clamp_with(self, min: f32, max: f32) -> Self {
        let Color(r, g, b) = self;
        let r = r.max(min).min(max);
        let g = g.max(min).min(max);
        let b = b.max(min).min(max);
        Color(r, g, b)
    }

    fn clamp(self) -> Self {
        self.clamp_with(0_f32, 1_f32)
    }
}

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

    #[test]
    fn lossless_conversion() {
        for i in 0..256 {
            let a = i as u8;
            let color = Color(a, a, a);
            let color2 = Colorf32::from(color).clamp_to_888();
            assert_eq!(color, color2);
        }
    }

    #[test]
    fn clampped_down_conversion() {
        let max = Color(255, 255, 255);
        for i in 256..512 {
            let a = i as f32 / 255_f32;
            let color = Color(a, a, a).clamp_to_888();
            assert_eq!(color, max);
        }
    }

    #[test]
    fn clampped_up_conversion() {
        let min = Color(0, 0, 0);
        for i in -256..0 {
            let a = i as f32 / 255_f32;
            let color = Color(a, a, a).clamp_to_888();
            assert_eq!(color, min);
        }
    }

    #[test]
    fn display_color888() {
        assert_eq!(Color(0, 0, 0).to_string(), "000000");
        assert_eq!(Color(255, 255, 255).to_string(), "ffffff");
        assert_eq!(Color(1, 254, 10).to_string(), "01fe0a");
    }
}
<|endoftext|>


<commit_before>// DOCS

#![allow(unstable)]
#![feature(plugin)]
#[plugin] #[no_link] extern crate peg_syntax_ext;

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};

pub struct Property {
    /// Parameters.
    pub params: HashMap<String, String>,

    /// Value as unparsed string.
    pub raw_value: String,

    /// Property group. E.g. a contentline like `foo.FN:Markus` would result in the group being
    /// `"foo"`.
    pub prop_group: Option<String>
}

impl Property {
    /// Create property from unescaped string.
    pub fn new(value: &str) -> Property {
        Property {
            params: HashMap::new(),
            raw_value: escape_chars(value),
            prop_group: None
        }
    }

    /// Get value as unescaped string.
    pub fn value_as_string(&self) -> String {
        unescape_chars(self.raw_value.as_slice())
    }
}

pub struct Component {
    /// The name of the component, such as `VCARD` or `VEVENT`.
    pub name: String,

    /// The component's properties.
    pub props: HashMap<String, Vec<Property>>,

    /// The component's child- or sub-components.
    pub subcomponents: Vec<Component>
}

impl Component {
    pub fn new(name: &str) -> Component {
        Component {
            name: name.to_string(),
            props: HashMap::new(),
            subcomponents: vec![]
        }
    }

    /// Retrieve one property (from many) by key. Returns `None` if nothing is found.
    pub fn single_prop(&self, key: &str) -> Option<&Property> {
        match self.props.get(key) {
            Some(x) => {
                match x.len() {
                    1 => Some(&x[0]),
                    _ => None
                }
            },
            None => None
        }
    }

    /// Retrieve a mutable vector of properties for this key. Creates one (and inserts it into the
    /// component) if none exists.
    pub fn all_props_mut(&mut self, key: &str) -> &mut Vec<Property> {
        match self.props.entry(String::from_str(key)) {
            Occupied(values) => values.into_mut(),
            Vacant(values) => values.insert(vec![])
        }
    }

    /// Retrieve properties by key. Returns an empty slice if key doesn't exist.
    pub fn all_props(&self, key: &str) -> &[Property] {
        static EMPTY: &'static [Property] = &[];
        match self.props.get(key) {
            Some(values) => values.as_slice(),
            None => EMPTY
        }
    }
}

peg! parser(r#"
use super::{Component,Property};
use std::collections::HashMap;

components -> Vec<Component>
    = cs:component ** eols __ { cs }

    #[pub]
    component -> Component
        = name:component_begin
          ps:props
          cs:components
          component_end {
            let mut rv = Component::new(name);
            rv.subcomponents = cs;

            for (k, v) in ps.into_iter() {
                rv.all_props_mut(k).push(v);
            };

            rv
        }

    component_begin -> &'input str
        = "BEGIN:" v:value __ { v }

    component_end -> &'input str
        = "END:" v:value __ { v }

props -> Vec<(&'input str, Property)>
    = ps:prop ++ eols __ { ps }

    prop -> (&'input str, Property)
        = !"BEGIN:" !"END:" g:group? k:name p:params ":" v:value {
            (k, Property { params: p, raw_value: v.to_string(), prop_group: g })
        }

    group -> String
        = g:group_name "." { g.to_string() }

        group_name -> &'input str
            = group_char+ { match_str }

    name -> &'input str
        = iana_token+ { match_str }

    params -> HashMap<String, String>
        = ps:(";" p:param {p})* {
            let mut rv: HashMap<String, String> = HashMap::with_capacity(ps.len());
            rv.extend(ps.into_iter().map(|(k, v)| (k.to_string(), v.to_string())));
            rv
        }

        param -> (&'input str, &'input str)
            // FIXME: Doesn't handle comma-separated values
            = k:param_name v:("=" v:param_value { v })? {
                (k, match v {
                    Some(x) => x,
                    None => ""
                })
            }

        param_name -> &'input str
            = iana_token+ { match_str }

        param_value -> &'input str
            = x:(quoted_string / param_text) { x }

        param_text -> &'input str
            = safe_char* { match_str }

    value -> &'input str
        = value_char+ { match_str }

quoted_string -> &'input str
    = dquote x:quoted_content dquote { x }

quoted_content -> &'input str
    = qsafe_char* { match_str }

iana_token = ([a-zA-Z0-9] / "-")+
group_char = ([a-zA-Z0-9] / "-")
qsafe_char = !dquote !ctl value_char
safe_char = !";" !":" qsafe_char

value_char = !eol .

eol = "\r\n" / "\n" / "\r"
dquote = "\""
eols = eol+

// Taken from vCard. vCalendar's is a subset. Together with the definition of "qsafe_char" this
// might reject a bunch of valid iCalendars, but I can't imagine one.
ctl = [\u{00}-\u{1F}] / "\u{7F}"

whitespace = " " / "\t"
__ = (eol / whitespace)*

"#);

/// Parse a component. The error value is a human-readable message.
pub fn parse_component(s: &str) -> Result<Component, String> {
    // XXX: The unfolding should be worked into the PEG
    // See feature request: https://github.com/kevinmehall/rust-peg/issues/26
    let unfolded = unfold_lines(s);
    parser::component(unfolded.as_slice())
}

/// Write a component. The error value is a human-readable message.
pub fn write_component(c: &Component) -> String {
    fn inner(buf: &mut String, c: &Component) {
        buf.push_str("BEGIN:");
        buf.push_str(c.name.as_slice());
        buf.push_str("\r\n");

        for (prop_name, props) in c.props.iter() {
            for prop in props.iter() {
                match prop.prop_group {
                    Some(ref x) => { buf.push_str(x.as_slice()); buf.push('.'); },
                    None => ()
                };
                buf.push_str(prop_name.as_slice());
                for (param_key, param_value) in prop.params.iter() {
                    buf.push(';');
                    buf.push_str(param_key.as_slice());
                    buf.push('=');
                    buf.push_str(param_value.as_slice());
                };
                buf.push(':');
                buf.push_str(fold_line(prop.raw_value.as_slice()).as_slice());
                buf.push_str("\r\n");
            };
        };

        for subcomponent in c.subcomponents.iter() {
            inner(buf, subcomponent);
        };

        buf.push_str("END:");
        buf.push_str(c.name.as_slice());
        buf.push_str("\r\n");
    }

    let mut buf = String::new();
    inner(&mut buf, c);
    buf
}

/// Escape text for a VObject property value.
pub fn escape_chars(s: &str) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\n")
        .replace("\\", "\\\\")
        .replace(";", "\\;")
        .replace(",", "\\,")
        .replace("\r\n", "\\n")
        .replace("\n", "\\n")
}

/// Unescape text from a VObject property value.
pub fn unescape_chars(s: &str) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\\n")
        .replace("\r\n", "\n")
        .replace("\\n", "\n")
        .replace("\\,", ",")
        .replace("\\;", ";")
        .replace("\\\\", "\\")
}

/// Unfold contentline.
pub fn unfold_lines(s: &str) -> String {
    s
        .replace("\r\n ", "").replace("\r\n\t", "")
        .replace("\n ", "").replace("\n\t", "")
        .replace("\r ", "").replace("\r\t", "")
}

/// Fold contentline to 75 chars. This function assumes the input to be unfolded, which means no
/// '\n' or '\r' in it.
pub fn fold_line(s: &str) -> String {
    let mut rv = String::new();
    for (i, c) in s.chars().enumerate() {
        rv.push(c);
        if i != 0 && i % 75 == 0 {
            rv.push_str("\r\n ");
        };
    };
    rv
}
<commit_msg>move peg parser to bottom<commit_after>// DOCS

#![allow(unstable)]
#![feature(plugin)]
#[plugin] #[no_link] extern crate peg_syntax_ext;

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};

pub struct Property {
    /// Parameters.
    pub params: HashMap<String, String>,

    /// Value as unparsed string.
    pub raw_value: String,

    /// Property group. E.g. a contentline like `foo.FN:Markus` would result in the group being
    /// `"foo"`.
    pub prop_group: Option<String>
}

impl Property {
    /// Create property from unescaped string.
    pub fn new(value: &str) -> Property {
        Property {
            params: HashMap::new(),
            raw_value: escape_chars(value),
            prop_group: None
        }
    }

    /// Get value as unescaped string.
    pub fn value_as_string(&self) -> String {
        unescape_chars(self.raw_value.as_slice())
    }
}

pub struct Component {
    /// The name of the component, such as `VCARD` or `VEVENT`.
    pub name: String,

    /// The component's properties.
    pub props: HashMap<String, Vec<Property>>,

    /// The component's child- or sub-components.
    pub subcomponents: Vec<Component>
}

impl Component {
    pub fn new(name: &str) -> Component {
        Component {
            name: name.to_string(),
            props: HashMap::new(),
            subcomponents: vec![]
        }
    }

    /// Retrieve one property (from many) by key. Returns `None` if nothing is found.
    pub fn single_prop(&self, key: &str) -> Option<&Property> {
        match self.props.get(key) {
            Some(x) => {
                match x.len() {
                    1 => Some(&x[0]),
                    _ => None
                }
            },
            None => None
        }
    }

    /// Retrieve a mutable vector of properties for this key. Creates one (and inserts it into the
    /// component) if none exists.
    pub fn all_props_mut(&mut self, key: &str) -> &mut Vec<Property> {
        match self.props.entry(String::from_str(key)) {
            Occupied(values) => values.into_mut(),
            Vacant(values) => values.insert(vec![])
        }
    }

    /// Retrieve properties by key. Returns an empty slice if key doesn't exist.
    pub fn all_props(&self, key: &str) -> &[Property] {
        static EMPTY: &'static [Property] = &[];
        match self.props.get(key) {
            Some(values) => values.as_slice(),
            None => EMPTY
        }
    }
}

/// Parse a component. The error value is a human-readable message.
pub fn parse_component(s: &str) -> Result<Component, String> {
    // XXX: The unfolding should be worked into the PEG
    // See feature request: https://github.com/kevinmehall/rust-peg/issues/26
    let unfolded = unfold_lines(s);
    parser::component(unfolded.as_slice())
}

/// Write a component. The error value is a human-readable message.
pub fn write_component(c: &Component) -> String {
    fn inner(buf: &mut String, c: &Component) {
        buf.push_str("BEGIN:");
        buf.push_str(c.name.as_slice());
        buf.push_str("\r\n");

        for (prop_name, props) in c.props.iter() {
            for prop in props.iter() {
                match prop.prop_group {
                    Some(ref x) => { buf.push_str(x.as_slice()); buf.push('.'); },
                    None => ()
                };
                buf.push_str(prop_name.as_slice());
                for (param_key, param_value) in prop.params.iter() {
                    buf.push(';');
                    buf.push_str(param_key.as_slice());
                    buf.push('=');
                    buf.push_str(param_value.as_slice());
                };
                buf.push(':');
                buf.push_str(fold_line(prop.raw_value.as_slice()).as_slice());
                buf.push_str("\r\n");
            };
        };

        for subcomponent in c.subcomponents.iter() {
            inner(buf, subcomponent);
        };

        buf.push_str("END:");
        buf.push_str(c.name.as_slice());
        buf.push_str("\r\n");
    }

    let mut buf = String::new();
    inner(&mut buf, c);
    buf
}

/// Escape text for a VObject property value.
pub fn escape_chars(s: &str) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\n")
        .replace("\\", "\\\\")
        .replace(";", "\\;")
        .replace(",", "\\,")
        .replace("\r\n", "\\n")
        .replace("\n", "\\n")
}

/// Unescape text from a VObject property value.
pub fn unescape_chars(s: &str) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\\n")
        .replace("\r\n", "\n")
        .replace("\\n", "\n")
        .replace("\\,", ",")
        .replace("\\;", ";")
        .replace("\\\\", "\\")
}

/// Unfold contentline.
pub fn unfold_lines(s: &str) -> String {
    s
        .replace("\r\n ", "").replace("\r\n\t", "")
        .replace("\n ", "").replace("\n\t", "")
        .replace("\r ", "").replace("\r\t", "")
}

/// Fold contentline to 75 chars. This function assumes the input to be unfolded, which means no
/// '\n' or '\r' in it.
pub fn fold_line(s: &str) -> String {
    let mut rv = String::new();
    for (i, c) in s.chars().enumerate() {
        rv.push(c);
        if i != 0 && i % 75 == 0 {
            rv.push_str("\r\n ");
        };
    };
    rv
}

peg! parser(r#"
use super::{Component,Property};
use std::collections::HashMap;

components -> Vec<Component>
    = cs:component ** eols __ { cs }

    #[pub]
    component -> Component
        = name:component_begin
          ps:props
          cs:components
          component_end {
            let mut rv = Component::new(name);
            rv.subcomponents = cs;

            for (k, v) in ps.into_iter() {
                rv.all_props_mut(k).push(v);
            };

            rv
        }

    component_begin -> &'input str
        = "BEGIN:" v:value __ { v }

    component_end -> &'input str
        = "END:" v:value __ { v }

props -> Vec<(&'input str, Property)>
    = ps:prop ++ eols __ { ps }

    prop -> (&'input str, Property)
        = !"BEGIN:" !"END:" g:group? k:name p:params ":" v:value {
            (k, Property { params: p, raw_value: v.to_string(), prop_group: g })
        }

    group -> String
        = g:group_name "." { g.to_string() }

        group_name -> &'input str
            = group_char+ { match_str }

    name -> &'input str
        = iana_token+ { match_str }

    params -> HashMap<String, String>
        = ps:(";" p:param {p})* {
            let mut rv: HashMap<String, String> = HashMap::with_capacity(ps.len());
            rv.extend(ps.into_iter().map(|(k, v)| (k.to_string(), v.to_string())));
            rv
        }

        param -> (&'input str, &'input str)
            // FIXME: Doesn't handle comma-separated values
            = k:param_name v:("=" v:param_value { v })? {
                (k, match v {
                    Some(x) => x,
                    None => ""
                })
            }

        param_name -> &'input str
            = iana_token+ { match_str }

        param_value -> &'input str
            = x:(quoted_string / param_text) { x }

        param_text -> &'input str
            = safe_char* { match_str }

    value -> &'input str
        = value_char+ { match_str }

quoted_string -> &'input str
    = dquote x:quoted_content dquote { x }

quoted_content -> &'input str
    = qsafe_char* { match_str }

iana_token = ([a-zA-Z0-9] / "-")+
group_char = ([a-zA-Z0-9] / "-")
qsafe_char = !dquote !ctl value_char
safe_char = !";" !":" qsafe_char

value_char = !eol .

eol = "\r\n" / "\n" / "\r"
dquote = "\""
eols = eol+

// Taken from vCard. vCalendar's is a subset. Together with the definition of "qsafe_char" this
// might reject a bunch of valid iCalendars, but I can't imagine one.
ctl = [\u{00}-\u{1F}] / "\u{7F}"

whitespace = " " / "\t"
__ = (eol / whitespace)*

"#);
<|endoftext|>


<commit_before>// Copyright 2013-2014 Jeffery Olson
//
// Licensed under the 3-Clause BSD License, see LICENSE.txt
// at the top-level of this repository.
// This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id="http://olsonjeffery.github.io#schemers:0.0.1"]
#![desc = "Simple Scheme Interpreter"]
#![license = "3-Clause BSD"]

extern crate collections = "collections";

use std::from_str::FromStr;
use collections::hashmap::HashMap;

// this is starting out as a straight port of Peter Norvig's
// lis.py (the first iteration) to Rust

#[cfg(not(test))]
fn main() {
    use std::os::args;
    let args: Vec<~str> = args().move_iter().skip(1).collect();
    if args.len() == 0 {
        fail!("no program provided");
    }
    let program: ~str = args.move_iter()
        .fold(~"", |memo, arg| memo + arg + " ").trim().to_owned();
    let parsed_items = parse_str(program);
    println!("{}", parsed_items.print());
}

pub struct Env {
    entries: HashMap<~str, Expr>,
    outer: Option<~Env>
}

#[deriving(Eq, Show, Clone)]
pub enum Expr {
    Atom(AtomVal),
    List(Vec<~Expr>)
}

#[deriving(Eq, Show, Clone)]
pub enum AtomVal {
    Symbol(~str),
    Integer(i64),
    Float(f64)
}

fn eval(expr: Expr, env: Env) -> (Expr, Env) {
    match expr {
        Atom(Symbol(ref var_name)) => (env.find(var_name), env),
        _ => fail!("un-implemented case")
    }
}

fn parse_str(input: ~str) -> Expr {
    parse(&mut tokenize(input))
}

fn pad_input(input: ~str) -> ~str {
    input.replace("(", " ( ").replace(")", " ) ")
}

fn tokenize(input: ~str) -> Vec<~str> {
    pad_input(input).split_str(" ")
        .filter(|i| *i != "").map(|i| i.to_owned()).collect()
}

fn parse(tokens: &mut Vec<~str>) -> Expr {
    let current_token =
        tokens.shift().expect("calling parse() w/ empty token list; shouldn't happen");
    match current_token {
        ref x if *x == ~"(" => {
            let mut list = Vec::new();
            while *tokens.get(0) != ~")" {
                list.push(box parse(tokens));
            }
            tokens.shift();
            List(list)
        },
        ref x if *x == ~")" => fail!("hit ) token; shouldn't happen"),
        x => Expr::new_atom(x)
    }
}

impl Env {
    pub fn new(params: Option<Vec<~str>>, args: Option<Vec<Expr>>, outer: Option<~Env>) -> Env {
        let mut entries = HashMap::new();
        if params.is_some() && args.is_some() {
            let params = params.expect("params should be a value");
            let args = args.expect("args should be a value");
            if params.len() == args.len() {
                for ctr in range(0,params.len()) {
                    entries.insert(params.get(ctr).to_owned(),
                                   args.get(ctr).clone());
                }
            } else {
                fail!("params and args length doesn't match")
            }
        }
        else if params.is_none() && args.is_none() {
            // do nothing!
        } else {
            fail!("cannot have params & args unset")
        }
        Env { entries: entries, outer: outer }
    }

    pub fn find(&self, symbol: &~str) -> Expr {
        match self.entries.find(symbol) {
            Some(expr) => expr.clone(),
            None => {
                match &self.outer {
                    &Some(ref outer_env) => outer_env.find(symbol),
                    &None => fail!("No variable named {} defined in the environment."
                                  , *symbol)
                }
            }
        }
    }
}

impl Expr {
    pub fn new_atom(input: ~str) -> Expr {
        let first_char = input.char_at(0);
        match first_char {
            '0' | '1' | '2' | '3' | '4' | '5' |
            '6' | '7' | '8' | '9' => {
                match input.contains(".") {
                    true => {
                        match FromStr::from_str(input) {
                            Some(val) => Atom(Float(val)),
                            None => fail!("Cannot parse number-like input of: {}", input)
                        }
                    },
                    false => {
                        match FromStr::from_str(input) {
                            Some(val) => Atom(Integer(val)),
                            None => fail!("Cannot parse number-like input of: {}", input)
                        }
                    }
                }
            },
            _ => Atom(Symbol(input))
        }
    }

    pub fn is_atom(&self) -> bool {
        match *self {
            Atom(_) => true,
            _ => false
        }
    }

    pub fn print(&self) -> ~str {
        match self {
            &List(ref items) => {
                let out = items.iter().map(|i| i.print())
                    .fold(~"(", |m, v| m + v + " ");
                out.trim() + ")"
            },
            &Atom(ref v) => v.print()
        }
    }
    pub fn un_cons(self) -> (Expr, Option<Expr>) {
        match self {
            Atom(v) => (Atom(v), None),
            List(mut items) => {
                if items.len() == 0 {
                    fail!("cannot build car/cdr of empty list");
                }
                let car = items.shift()
                    .expect("at least one item in the least; shouldn't happen");
                (*car, Some(List(items)))
            }
        }
    }
}

impl AtomVal {
    pub fn print(&self) -> ~str {
        match self {
            &Symbol(ref v) => v.to_owned(),
            &Integer(ref v) => v.to_str(),
            &Float(ref v) => v.to_str()
        }
    }
}

#[cfg(test)]
mod parser_test {
    use super::{pad_input, tokenize, parse, Atom, List, Symbol, Integer, Float};

    #[test]
    fn pad_input_should_insert_spaces_before_and_after_parens() {
        assert_eq!(pad_input(~"(x 1 2 3)"), ~" ( x 1 2 3 ) ");
    }

    #[test]
    fn tokenize_string_into_tokens() {
        let tokens = tokenize(~"(foo 12 3)");
        assert_eq!(tokens.len(), 5);
        assert_eq!(tokens.get(0).to_owned(), ~"(");
        assert_eq!(tokens.get(1).to_owned(), ~"foo");
        assert_eq!(tokens.get(2).to_owned(), ~"12");
        assert_eq!(tokens.get(3).to_owned(), ~"3");
        assert_eq!(tokens.get(4).to_owned(), ~")");
    }

    #[test]
    fn should_parse_tokens_consisting_of_a_str_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"bar");
        let parsed_item = parse(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            Atom(Symbol(val)) => {
                assert_eq!(val, ~"bar")
            },
            _ => assert!(false)
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_an_int_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"42");
        let parsed_item = parse(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            Atom(Integer(val)) => {
                assert_eq!(val, 42)
            },
            _ => assert!(false)
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_a_float_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"1.1");
        let parsed_item = parse(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            Atom(Float(val)) => {
                assert_eq!(val, 1.1)
            },
            _ => assert!(false)
        }
    }

    #[test]
    fn should_parse_tokens_consisting_of_a_list_of_atoms_and_parse_it() {
        let tokens = &mut tokenize(~"(bar 12 45)");
        let parsed_item = parse(tokens);
        assert_eq!(parsed_item.is_atom(), false);
        match parsed_item {
            List(items) => {
                let items_len = items.len();
                assert!(3 == items_len);
                assert_eq!(items.get(0).is_atom(), true);
                assert_eq!(*items.get(0), ~Atom(Symbol(~"bar")));
                assert_eq!(items.get(1).is_atom(), true);
                assert_eq!(*items.get(1), ~Atom(Integer(12)));
                assert_eq!(items.get(2).is_atom(), true);
                assert_eq!(*items.get(2), ~Atom(Integer(45)));
            },
            _ => fail!("got back an atom, it seems")
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_a_list_of_atoms_and_a_nested_list() {
        let tokens = &mut tokenize(~"((2 3) bar 12 (hee (hah)))");
        let parsed_item = parse(tokens);
        assert_eq!(parsed_item.is_atom(), false);
        match parsed_item {
            List(items) => {
                let items_len = items.len();
                assert!(4 == items_len);
                match *items.get(0) {
                    ~List(ref items) => {
                        assert_eq!(items.len(), 2);
                        assert_eq!(*items.get(0), ~Atom(Integer(2)));
                        assert_eq!(*items.get(1), ~Atom(Integer(3)));
                    },
                    _ => fail!("shoulda got a list")
                }
                assert_eq!(*items.get(1), ~Atom(Symbol(~"bar")));
                assert_eq!(*items.get(2), ~Atom(Integer(12)));
                match *items.get(3) {
                    ~List(ref items) => {
                        assert_eq!(items.len(), 2);
                        assert_eq!(*items.get(0), ~Atom(Symbol(~"hee")));
                        match *items.get(1) {
                            ~List(ref items) => {
                                assert_eq!(items.len(), 1);
                                assert_eq!(*items.get(0), ~Atom(Symbol(~"hah")));
                            },
                            _ => fail!("shoulda got a list")
                        }
                    },
                    _ => fail!("shoulda got a list")
                }
            },
            _ => fail!("got back an atom, it seems")
        }
    }
    #[test]
    fn parsed_tokens_of_a_list_of_atoms_and_a_nested_list_should_to_str_correctly() {
        let input = ~"((2 3) bar 12 (hee (hah)))";
        let tokens = &mut tokenize(input.to_owned());
        let parsed_item = parse(tokens);
        let output = parsed_item.print();
        assert_eq!(input, output);
    }
}

#[cfg(test)]
mod eval_test {
    mod un_cons {
        use super::super::{parse_str, Atom, List, Symbol, Integer, Env, eval};
        #[test]
        fn an_atom_expr_returns_the_atom_in_the_car_with_none_in_the_cdr() {
            let expr = parse_str(~"x");
            let (car, cdr) = expr.un_cons();
            assert_eq!(car, Atom(Symbol(~"x")));
            assert_eq!(cdr, None);
        }

        #[test]
        fn a_list_with_one_atom_element_returns_an_atom_car_and_an_empty_list_in_the_cdr() {
            let expr = parse_str(~"(x)");
            let (car, cdr) = expr.un_cons();
            assert_eq!(car, Atom(Symbol(~"x")));
            match cdr.expect("should be a value here") {
                List(items) => assert_eq!(items.len(), 0),
                _ => fail!("expected a list")
            }
        }

        #[test]
        fn a_list_with_multiple_elements_returns_the_first_car_and_the_rust_in_the_cdr() {
            let expr = parse_str(~"(y 2 3)");
            let (car, cdr) = expr.un_cons();
            assert_eq!(car, Atom(Symbol(~"y")));
            match cdr.expect("should be a value here") {
                List(items) => {
                    assert_eq!(items.len(), 2)
                },
                _ => fail!("expected a list")
            }
        }

        #[test]
        #[should_fail]
        fn calling_extract_on_an_empty_list_should_fail() {
            let expr = parse_str(~"()");
            expr.un_cons();
        }

        #[test]
        fn given_a_symbol_in_the_env_then_calling_eval_should_return_it() {
            let env = Env::new(
                Some(vec!(~"x")),
                Some(vec!(Atom(Integer(42)))),
                None);
            let in_expr = parse_str(~"x");
            let (out_expr, _) = eval(in_expr, env);
            assert_eq!(out_expr, Atom(Integer(42)));
        }

        #[test]
        #[should_fail]
        fn given_a_symbol_NOT_in_the_env_then_calling_eval_should_fail() {
            let env = Env::new(None, None, None);
            let in_expr = parse_str(~"x");
            eval(in_expr, env);
        }
    }

    mod env_tests {
        use super::super::{Env};

        #[test]
        fn a_new_env_with_no_parent_params_or_vars_should_be_set_up_empty() {
            let _env = Env::new(None, None, None);
        }
    }
}
<commit_msg>eval returns non-symbol Atoms back unchanged<commit_after>// Copyright 2013-2014 Jeffery Olson
//
// Licensed under the 3-Clause BSD License, see LICENSE.txt
// at the top-level of this repository.
// This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id="http://olsonjeffery.github.io#schemers:0.0.1"]
#![desc = "Simple Scheme Interpreter"]
#![license = "3-Clause BSD"]

extern crate collections = "collections";

use std::from_str::FromStr;
use collections::hashmap::HashMap;

// this is starting out as a straight port of Peter Norvig's
// lis.py (the first iteration) to Rust

#[cfg(not(test))]
fn main() {
    use std::os::args;
    let args: Vec<~str> = args().move_iter().skip(1).collect();
    if args.len() == 0 {
        fail!("no program provided");
    }
    let program: ~str = args.move_iter()
        .fold(~"", |memo, arg| memo + arg + " ").trim().to_owned();
    let parsed_items = parse_str(program);
    println!("{}", parsed_items.print());
}

pub struct Env {
    entries: HashMap<~str, Expr>,
    outer: Option<~Env>
}

#[deriving(Eq, Show, Clone)]
pub enum Expr {
    Atom(AtomVal),
    List(Vec<~Expr>)
}

#[deriving(Eq, Show, Clone)]
pub enum AtomVal {
    Symbol(~str),
    Integer(i64),
    Float(f64)
}

fn eval(expr: Expr, env: Env) -> (Expr, Env) {
    match expr {
        Atom(Symbol(ref var_name)) => (env.find(var_name), env),
        val @ Atom(_) => (val, env),
        _ => fail!("un-implemented case")
    }
}

fn parse_str(input: ~str) -> Expr {
    parse(&mut tokenize(input))
}

fn pad_input(input: ~str) -> ~str {
    input.replace("(", " ( ").replace(")", " ) ")
}

fn tokenize(input: ~str) -> Vec<~str> {
    pad_input(input).split_str(" ")
        .filter(|i| *i != "").map(|i| i.to_owned()).collect()
}

fn parse(tokens: &mut Vec<~str>) -> Expr {
    let current_token =
        tokens.shift().expect("calling parse() w/ empty token list; shouldn't happen");
    match current_token {
        ref x if *x == ~"(" => {
            let mut list = Vec::new();
            while *tokens.get(0) != ~")" {
                list.push(box parse(tokens));
            }
            tokens.shift();
            List(list)
        },
        ref x if *x == ~")" => fail!("hit ) token; shouldn't happen"),
        x => Expr::new_atom(x)
    }
}

impl Env {
    pub fn new(params: Option<Vec<~str>>, args: Option<Vec<Expr>>, outer: Option<~Env>) -> Env {
        let mut entries = HashMap::new();
        if params.is_some() && args.is_some() {
            let params = params.expect("params should be a value");
            let args = args.expect("args should be a value");
            if params.len() == args.len() {
                for ctr in range(0,params.len()) {
                    entries.insert(params.get(ctr).to_owned(),
                                   args.get(ctr).clone());
                }
            } else {
                fail!("params and args length doesn't match")
            }
        }
        else if params.is_none() && args.is_none() {
            // do nothing!
        } else {
            fail!("cannot have params & args unset")
        }
        Env { entries: entries, outer: outer }
    }

    pub fn find(&self, symbol: &~str) -> Expr {
        match self.entries.find(symbol) {
            Some(expr) => expr.clone(),
            None => {
                match &self.outer {
                    &Some(ref outer_env) => outer_env.find(symbol),
                    &None => fail!("No variable named {} defined in the environment."
                                  , *symbol)
                }
            }
        }
    }
}

impl Expr {
    pub fn new_atom(input: ~str) -> Expr {
        let first_char = input.char_at(0);
        match first_char {
            '0' | '1' | '2' | '3' | '4' | '5' |
            '6' | '7' | '8' | '9' => {
                match input.contains(".") {
                    true => {
                        match FromStr::from_str(input) {
                            Some(val) => Atom(Float(val)),
                            None => fail!("Cannot parse number-like input of: {}", input)
                        }
                    },
                    false => {
                        match FromStr::from_str(input) {
                            Some(val) => Atom(Integer(val)),
                            None => fail!("Cannot parse number-like input of: {}", input)
                        }
                    }
                }
            },
            _ => Atom(Symbol(input))
        }
    }

    pub fn is_atom(&self) -> bool {
        match *self {
            Atom(_) => true,
            _ => false
        }
    }

    pub fn print(&self) -> ~str {
        match self {
            &List(ref items) => {
                let out = items.iter().map(|i| i.print())
                    .fold(~"(", |m, v| m + v + " ");
                out.trim() + ")"
            },
            &Atom(ref v) => v.print()
        }
    }
    pub fn un_cons(self) -> (Expr, Option<Expr>) {
        match self {
            Atom(v) => (Atom(v), None),
            List(mut items) => {
                if items.len() == 0 {
                    fail!("cannot build car/cdr of empty list");
                }
                let car = items.shift()
                    .expect("at least one item in the least; shouldn't happen");
                (*car, Some(List(items)))
            }
        }
    }
}

impl AtomVal {
    pub fn print(&self) -> ~str {
        match self {
            &Symbol(ref v) => v.to_owned(),
            &Integer(ref v) => v.to_str(),
            &Float(ref v) => v.to_str()
        }
    }
}

#[cfg(test)]
mod parser_test {
    use super::{pad_input, tokenize, parse, Atom, List, Symbol, Integer, Float};

    #[test]
    fn pad_input_should_insert_spaces_before_and_after_parens() {
        assert_eq!(pad_input(~"(x 1 2 3)"), ~" ( x 1 2 3 ) ");
    }

    #[test]
    fn tokenize_string_into_tokens() {
        let tokens = tokenize(~"(foo 12 3)");
        assert_eq!(tokens.len(), 5);
        assert_eq!(tokens.get(0).to_owned(), ~"(");
        assert_eq!(tokens.get(1).to_owned(), ~"foo");
        assert_eq!(tokens.get(2).to_owned(), ~"12");
        assert_eq!(tokens.get(3).to_owned(), ~"3");
        assert_eq!(tokens.get(4).to_owned(), ~")");
    }

    #[test]
    fn should_parse_tokens_consisting_of_a_str_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"bar");
        let parsed_item = parse(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            Atom(Symbol(val)) => {
                assert_eq!(val, ~"bar")
            },
            _ => assert!(false)
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_an_int_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"42");
        let parsed_item = parse(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            Atom(Integer(val)) => {
                assert_eq!(val, 42)
            },
            _ => assert!(false)
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_a_float_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"1.1");
        let parsed_item = parse(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            Atom(Float(val)) => {
                assert_eq!(val, 1.1)
            },
            _ => assert!(false)
        }
    }

    #[test]
    fn should_parse_tokens_consisting_of_a_list_of_atoms_and_parse_it() {
        let tokens = &mut tokenize(~"(bar 12 45)");
        let parsed_item = parse(tokens);
        assert_eq!(parsed_item.is_atom(), false);
        match parsed_item {
            List(items) => {
                let items_len = items.len();
                assert!(3 == items_len);
                assert_eq!(items.get(0).is_atom(), true);
                assert_eq!(*items.get(0), ~Atom(Symbol(~"bar")));
                assert_eq!(items.get(1).is_atom(), true);
                assert_eq!(*items.get(1), ~Atom(Integer(12)));
                assert_eq!(items.get(2).is_atom(), true);
                assert_eq!(*items.get(2), ~Atom(Integer(45)));
            },
            _ => fail!("got back an atom, it seems")
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_a_list_of_atoms_and_a_nested_list() {
        let tokens = &mut tokenize(~"((2 3) bar 12 (hee (hah)))");
        let parsed_item = parse(tokens);
        assert_eq!(parsed_item.is_atom(), false);
        match parsed_item {
            List(items) => {
                let items_len = items.len();
                assert!(4 == items_len);
                match *items.get(0) {
                    ~List(ref items) => {
                        assert_eq!(items.len(), 2);
                        assert_eq!(*items.get(0), ~Atom(Integer(2)));
                        assert_eq!(*items.get(1), ~Atom(Integer(3)));
                    },
                    _ => fail!("shoulda got a list")
                }
                assert_eq!(*items.get(1), ~Atom(Symbol(~"bar")));
                assert_eq!(*items.get(2), ~Atom(Integer(12)));
                match *items.get(3) {
                    ~List(ref items) => {
                        assert_eq!(items.len(), 2);
                        assert_eq!(*items.get(0), ~Atom(Symbol(~"hee")));
                        match *items.get(1) {
                            ~List(ref items) => {
                                assert_eq!(items.len(), 1);
                                assert_eq!(*items.get(0), ~Atom(Symbol(~"hah")));
                            },
                            _ => fail!("shoulda got a list")
                        }
                    },
                    _ => fail!("shoulda got a list")
                }
            },
            _ => fail!("got back an atom, it seems")
        }
    }
    #[test]
    fn parsed_tokens_of_a_list_of_atoms_and_a_nested_list_should_to_str_correctly() {
        let input = ~"((2 3) bar 12 (hee (hah)))";
        let tokens = &mut tokenize(input.to_owned());
        let parsed_item = parse(tokens);
        let output = parsed_item.print();
        assert_eq!(input, output);
    }
}

#[cfg(test)]
mod eval_test {
    mod un_cons {
        use super::super::{parse_str, Atom, List, Symbol, Integer, Float,
                           Env, eval};
        #[test]
        fn an_atom_expr_returns_the_atom_in_the_car_with_none_in_the_cdr() {
            let expr = parse_str(~"x");
            let (car, cdr) = expr.un_cons();
            assert_eq!(car, Atom(Symbol(~"x")));
            assert_eq!(cdr, None);
        }

        #[test]
        fn a_list_with_one_atom_element_returns_an_atom_car_and_an_empty_list_in_the_cdr() {
            let expr = parse_str(~"(x)");
            let (car, cdr) = expr.un_cons();
            assert_eq!(car, Atom(Symbol(~"x")));
            match cdr.expect("should be a value here") {
                List(items) => assert_eq!(items.len(), 0),
                _ => fail!("expected a list")
            }
        }

        #[test]
        fn a_list_with_multiple_elements_returns_the_first_car_and_the_rust_in_the_cdr() {
            let expr = parse_str(~"(y 2 3)");
            let (car, cdr) = expr.un_cons();
            assert_eq!(car, Atom(Symbol(~"y")));
            match cdr.expect("should be a value here") {
                List(items) => {
                    assert_eq!(items.len(), 2)
                },
                _ => fail!("expected a list")
            }
        }

        #[test]
        #[should_fail]
        fn calling_extract_on_an_empty_list_should_fail() {
            let expr = parse_str(~"()");
            expr.un_cons();
        }

        #[test]
        fn given_a_symbol_in_the_env_then_calling_eval_should_resolve_its_value() {
            let env = Env::new(
                Some(vec!(~"x")),
                Some(vec!(Atom(Integer(42)))),
                None);
            let in_expr = parse_str(~"x");
            let (out_expr, _) = eval(in_expr, env);
            assert_eq!(out_expr, Atom(Integer(42)));
        }

        #[test]
        #[should_fail]
        fn given_a_symbol_NOT_in_the_env_then_calling_eval_should_fail() {
            let env = Env::new(None, None, None);
            let in_expr = parse_str(~"x");
            eval(in_expr, env);
        }

        #[test]
        fn given_a_float_literal_then_calling_eval_should_return_it_back() {
            let env = Env::new(None, None, None);
            let in_expr = parse_str(~"34.3");
            let (out_expr, _) = eval(in_expr, env);
            assert_eq!(out_expr, Atom(Float(34.3)));
        }

        #[test]
        fn given_a_integer_literal_then_calling_eval_should_return_it_back() {
            let env = Env::new(None, None, None);
            let in_expr = parse_str(~"34");
            let (out_expr, _) = eval(in_expr, env);
            assert_eq!(out_expr, Atom(Integer(34)));
        }
    }

    mod env_tests {
        use super::super::{Env};

        #[test]
        fn a_new_env_with_no_parent_params_or_vars_should_be_set_up_empty() {
            let _env = Env::new(None, None, None);
        }
    }
}
<|endoftext|>


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

use core::fmt;
use prelude::*;
use serde::{de::{self, SeqAccess, Error}, Deserialize, Deserializer, Serialize, Serializer};
use serde::ser::SerializeTuple;

#[cfg(all(feature = "serde", not(feature = "dense_serde")))]
impl Serialize for Uuid {
    fn serialize<S: Serializer>(
        &self,
        serializer: S,
    ) -> Result<S::Ok, S::Error> {
        if serializer.is_human_readable() {
            serializer
                .serialize_str(&self.to_hyphenated().encode_lower(&mut [0; 36]))
        } else {
            serializer.serialize_bytes(self.as_bytes())
        }
    }
}

#[cfg(feature = "dense_serde")]
impl Serialize for Uuid {
    fn serialize<S: Serializer>(
        &self,
        serializer: S,
    ) -> Result<S::Ok, S::Error> {
        if serializer.is_human_readable() {
            serializer
                .serialize_str(&self.to_hyphenated().encode_lower(&mut [0; 36]))
        } else {
            let mut seq =
                serializer.serialize_tuple(16)?;

            for byte in self.as_bytes() {
                seq.serialize_element(byte)?;
            }

            seq.end()
        }
    }
}

struct UuidStringVisitor;

impl<'vi> de::Visitor<'vi> for UuidStringVisitor {
    type Value = Uuid;

    fn expecting(
        &self,
        formatter: &mut fmt::Formatter,
    ) -> fmt::Result {
        write!(formatter, "a UUID string")
    }

    fn visit_str<E: de::Error>(
        self,
        value: &str,
    ) -> Result<Uuid, E> {
        value.parse::<Uuid>().map_err(E::custom)
    }

    fn visit_bytes<E: de::Error>(
        self,
        value: &[u8],
    ) -> Result<Uuid, E> {
        Uuid::from_slice(value).map_err(E::custom)
    }
}

#[cfg(feature = "dense_serde")]
impl<'de> Deserialize<'de> for Uuid {
    fn deserialize<D: Deserializer<'de>>(
        deserializer: D,
    ) -> Result<Self, D::Error> {
        if deserializer.is_human_readable() {
            deserializer.deserialize_str(UuidStringVisitor)
        } else {
            struct DenseUuidBytesVisitor;

            impl<'vi> de::Visitor<'vi> for DenseUuidBytesVisitor {
                type Value = Uuid;

                fn expecting(
                    &self,
                    formatter: &mut fmt::Formatter,
                ) -> fmt::Result {
                    write!(formatter, "tuple")
                }

                fn visit_seq<A: SeqAccess<'vi>>(
                    self,
                    mut seq: A,
                ) -> Result<Self::Value, A::Error> {
                    if seq.size_hint() == Some(16) {
                        let mut buf = [0; 16];

                        for i in 0..16 {
                            buf[i] = seq.next_element().unwrap().unwrap()
                        }

                        Ok(Uuid::from_bytes(buf))
                    } else {
                        Err(Error::custom("Uuid must be 16 bytes long"))
                    }
                }
            }

            deserializer.deserialize_tuple(16, DenseUuidBytesVisitor)
        }
    }
}

#[cfg(all(feature = "serde", not(feature = "dense_serde")))]
impl<'de> Deserialize<'de> for Uuid {
    fn deserialize<D: Deserializer<'de>>(
        deserializer: D,
    ) -> Result<Self, D::Error> {
        if deserializer.is_human_readable() {
            deserializer.deserialize_str(UuidStringVisitor)
        } else {
            struct UuidBytesVisitor;

            impl<'vi> de::Visitor<'vi> for UuidBytesVisitor {
                type Value = Uuid;

                fn expecting(
                    &self,
                    formatter: &mut fmt::Formatter,
                ) -> fmt::Result {
                    write!(formatter, "bytes")
                }

                fn visit_bytes<E: de::Error>(
                    self,
                    value: &[u8],
                ) -> Result<Uuid, E> {
                    Uuid::from_slice(value).map_err(E::custom)
                }
            }

            deserializer.deserialize_bytes(UuidBytesVisitor)
        }
    }
}

#[cfg(all(test, feature = "serde", not(feature = "dense_serde")))]
mod serde_tests {
    use serde_test;

    use prelude::*;

    #[test]
    fn test_serialize_readable() {
        use serde_test::Configure;

        let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
        let u = Uuid::parse_str(uuid_str).unwrap();
        serde_test::assert_tokens(
            &u.readable(),
            &[serde_test::Token::Str(uuid_str)],
        );
    }

    #[test]
    fn test_serialize_compact() {
        use serde_test::Configure;

        let uuid_bytes = b"F9168C5E-CEB2-4F";
        let u = Uuid::from_slice(uuid_bytes).unwrap();
        serde_test::assert_tokens(
            &u.compact(),
            &[serde_test::Token::Bytes(uuid_bytes)],
        );
    }
}

#[cfg(all(test, feature = "dense_serde"))]
mod dense_serde_tests {
    use serde_test;

    use prelude::*;

    #[test]
    fn test_serialize_readable() {
        use serde_test::Configure;

        let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
        let u = Uuid::parse_str(uuid_str).unwrap();
        serde_test::assert_tokens(
            &u.readable(),
            &[serde_test::Token::Str(uuid_str)],
        );
    }

    #[test]
    fn test_serialize_compact() {
        use serde_test::Configure;

        let uuid_bytes = b"F9168C5E-CEB2-4F";
        let u = Uuid::from_slice(uuid_bytes).unwrap();
        serde_test::assert_tokens(
            &u.compact(),
            &[
                serde_test::Token::Tuple { len: 16 },
                serde_test::Token::U8(uuid_bytes[0]),
                serde_test::Token::U8(uuid_bytes[1]),
                serde_test::Token::U8(uuid_bytes[2]),
                serde_test::Token::U8(uuid_bytes[3]),
                serde_test::Token::U8(uuid_bytes[4]),
                serde_test::Token::U8(uuid_bytes[5]),
                serde_test::Token::U8(uuid_bytes[6]),
                serde_test::Token::U8(uuid_bytes[7]),
                serde_test::Token::U8(uuid_bytes[8]),
                serde_test::Token::U8(uuid_bytes[9]),
                serde_test::Token::U8(uuid_bytes[10]),
                serde_test::Token::U8(uuid_bytes[11]),
                serde_test::Token::U8(uuid_bytes[12]),
                serde_test::Token::U8(uuid_bytes[13]),
                serde_test::Token::U8(uuid_bytes[14]),
                serde_test::Token::U8(uuid_bytes[15]),
                serde_test::Token::TupleEnd
            ],
        )
    }
}
<commit_msg>Fix CI error from unsupported syntax<commit_after>// Copyright 2013-2014 The Rust Project Developers.
// Copyright 2018 The Uuid Project Developers.
//
// See the COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::fmt;
use prelude::*;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::{self, SeqAccess, Error};
use serde::ser::SerializeTuple;

#[cfg(all(feature = "serde", not(feature = "dense_serde")))]
impl Serialize for Uuid {
    fn serialize<S: Serializer>(
        &self,
        serializer: S,
    ) -> Result<S::Ok, S::Error> {
        if serializer.is_human_readable() {
            serializer
                .serialize_str(&self.to_hyphenated().encode_lower(&mut [0; 36]))
        } else {
            serializer.serialize_bytes(self.as_bytes())
        }
    }
}

#[cfg(feature = "dense_serde")]
impl Serialize for Uuid {
    fn serialize<S: Serializer>(
        &self,
        serializer: S,
    ) -> Result<S::Ok, S::Error> {
        if serializer.is_human_readable() {
            serializer
                .serialize_str(&self.to_hyphenated().encode_lower(&mut [0; 36]))
        } else {
            let mut seq =
                serializer.serialize_tuple(16)?;

            for byte in self.as_bytes() {
                seq.serialize_element(byte)?;
            }

            seq.end()
        }
    }
}

struct UuidStringVisitor;

impl<'vi> de::Visitor<'vi> for UuidStringVisitor {
    type Value = Uuid;

    fn expecting(
        &self,
        formatter: &mut fmt::Formatter,
    ) -> fmt::Result {
        write!(formatter, "a UUID string")
    }

    fn visit_str<E: de::Error>(
        self,
        value: &str,
    ) -> Result<Uuid, E> {
        value.parse::<Uuid>().map_err(E::custom)
    }

    fn visit_bytes<E: de::Error>(
        self,
        value: &[u8],
    ) -> Result<Uuid, E> {
        Uuid::from_slice(value).map_err(E::custom)
    }
}

#[cfg(feature = "dense_serde")]
impl<'de> Deserialize<'de> for Uuid {
    fn deserialize<D: Deserializer<'de>>(
        deserializer: D,
    ) -> Result<Self, D::Error> {
        if deserializer.is_human_readable() {
            deserializer.deserialize_str(UuidStringVisitor)
        } else {
            struct DenseUuidBytesVisitor;

            impl<'vi> de::Visitor<'vi> for DenseUuidBytesVisitor {
                type Value = Uuid;

                fn expecting(
                    &self,
                    formatter: &mut fmt::Formatter,
                ) -> fmt::Result {
                    write!(formatter, "tuple")
                }

                fn visit_seq<A: SeqAccess<'vi>>(
                    self,
                    mut seq: A,
                ) -> Result<Self::Value, A::Error> {
                    if seq.size_hint() == Some(16) {
                        let mut buf = [0; 16];

                        for i in 0..16 {
                            buf[i] = seq.next_element().unwrap().unwrap()
                        }

                        Ok(Uuid::from_bytes(buf))
                    } else {
                        Err(Error::custom("Uuid must be 16 bytes long"))
                    }
                }
            }

            deserializer.deserialize_tuple(16, DenseUuidBytesVisitor)
        }
    }
}

#[cfg(all(feature = "serde", not(feature = "dense_serde")))]
impl<'de> Deserialize<'de> for Uuid {
    fn deserialize<D: Deserializer<'de>>(
        deserializer: D,
    ) -> Result<Self, D::Error> {
        if deserializer.is_human_readable() {
            deserializer.deserialize_str(UuidStringVisitor)
        } else {
            struct UuidBytesVisitor;

            impl<'vi> de::Visitor<'vi> for UuidBytesVisitor {
                type Value = Uuid;

                fn expecting(
                    &self,
                    formatter: &mut fmt::Formatter,
                ) -> fmt::Result {
                    write!(formatter, "bytes")
                }

                fn visit_bytes<E: de::Error>(
                    self,
                    value: &[u8],
                ) -> Result<Uuid, E> {
                    Uuid::from_slice(value).map_err(E::custom)
                }
            }

            deserializer.deserialize_bytes(UuidBytesVisitor)
        }
    }
}

#[cfg(all(test, feature = "serde", not(feature = "dense_serde")))]
mod serde_tests {
    use serde_test;

    use prelude::*;

    #[test]
    fn test_serialize_readable() {
        use serde_test::Configure;

        let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
        let u = Uuid::parse_str(uuid_str).unwrap();
        serde_test::assert_tokens(
            &u.readable(),
            &[serde_test::Token::Str(uuid_str)],
        );
    }

    #[test]
    fn test_serialize_compact() {
        use serde_test::Configure;

        let uuid_bytes = b"F9168C5E-CEB2-4F";
        let u = Uuid::from_slice(uuid_bytes).unwrap();
        serde_test::assert_tokens(
            &u.compact(),
            &[serde_test::Token::Bytes(uuid_bytes)],
        );
    }
}

#[cfg(all(test, feature = "dense_serde"))]
mod dense_serde_tests {
    use serde_test;

    use prelude::*;

    #[test]
    fn test_serialize_readable() {
        use serde_test::Configure;

        let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
        let u = Uuid::parse_str(uuid_str).unwrap();
        serde_test::assert_tokens(
            &u.readable(),
            &[serde_test::Token::Str(uuid_str)],
        );
    }

    #[test]
    fn test_serialize_compact() {
        use serde_test::Configure;

        let uuid_bytes = b"F9168C5E-CEB2-4F";
        let u = Uuid::from_slice(uuid_bytes).unwrap();
        serde_test::assert_tokens(
            &u.compact(),
            &[
                serde_test::Token::Tuple { len: 16 },
                serde_test::Token::U8(uuid_bytes[0]),
                serde_test::Token::U8(uuid_bytes[1]),
                serde_test::Token::U8(uuid_bytes[2]),
                serde_test::Token::U8(uuid_bytes[3]),
                serde_test::Token::U8(uuid_bytes[4]),
                serde_test::Token::U8(uuid_bytes[5]),
                serde_test::Token::U8(uuid_bytes[6]),
                serde_test::Token::U8(uuid_bytes[7]),
                serde_test::Token::U8(uuid_bytes[8]),
                serde_test::Token::U8(uuid_bytes[9]),
                serde_test::Token::U8(uuid_bytes[10]),
                serde_test::Token::U8(uuid_bytes[11]),
                serde_test::Token::U8(uuid_bytes[12]),
                serde_test::Token::U8(uuid_bytes[13]),
                serde_test::Token::U8(uuid_bytes[14]),
                serde_test::Token::U8(uuid_bytes[15]),
                serde_test::Token::TupleEnd
            ],
        )
    }
}
<|endoftext|>


<commit_before>use diesel;
use diesel::prelude::*;
use diesel::pg::PgConnection;

use data::models;

#[derive(Serialize)]
pub struct Page {
    pub slug: String,
    pub title: String,
    pub body: String,
}

impl Page {
    fn from_db(page: models::Page) -> Page {
        Page {
            slug: page.slug,
            title: page.title,
            body: page.body,
        }
    }
}

pub fn create<'a>(connection: &PgConnection, slug: &'a str, title: &'a str, body: &'a str) -> models::Page {
    use data::schema::pages;

    let new_page = models::NewPage {
        slug: slug,
        title: title,
        body: body,
    };

    diesel::insert(&new_page).into(pages::table)
        .get_result(connection)
        .expect("Error saving new post")
}

pub fn update<'a>(connection: &PgConnection, slug: &'a str, title: &String, body: &String) {
}

pub fn get(connection: &PgConnection, slug: &str) -> Option<Page> {
    use data::schema::pages::dsl;

    let mut selected = dsl::pages
        .filter(dsl::slug.eq(slug))
        .load::<models::Page>(connection)
        .expect("Error loading posts");

    match selected.pop() {
        Some(p) => Some(Page::from_db(p)),
        _ => None,
    }
}
<commit_msg>Make edit function<commit_after>use diesel;
use diesel::prelude::*;
use diesel::pg::PgConnection;

use data::models;

#[derive(Serialize)]
pub struct Page {
    pub slug: String,
    pub title: String,
    pub body: String,
}

impl Page {
    fn from_db(page: models::Page) -> Page {
        Page {
            slug: page.slug,
            title: page.title,
            body: page.body,
        }
    }
}

pub fn create<'a>(connection: &PgConnection, slug: &'a str, title: &'a str, body: &'a str) -> models::Page {
    use data::schema::pages;

    let new_page = models::NewPage {
        slug: slug,
        title: title,
        body: body,
    };

    diesel::insert(&new_page).into(pages::table)
        .get_result(connection)
        .expect("Error saving new post")
}

pub fn update<'a>(connection: &PgConnection, slug: &'a str, title: &String, body: &String) {
    use data::schema::pages::dsl;

    diesel::update(dsl::pages.filter(dsl::slug.eq(slug)))
        .set(dsl::title.eq(title))
        .get_result::<models::Page>(connection)
        .unwrap();
    diesel::update(dsl::pages.filter(dsl::slug.eq(slug)))
        .set(dsl::body.eq(body))
        .get_result::<models::Page>(connection)
        .unwrap();
}

pub fn get(connection: &PgConnection, slug: &str) -> Option<Page> {
    use data::schema::pages::dsl;

    let mut selected = dsl::pages
        .filter(dsl::slug.eq(slug))
        .load::<models::Page>(connection)
        .expect("Error loading posts");

    match selected.pop() {
        Some(p) => Some(Page::from_db(p)),
        _ => None,
    }
}
<|endoftext|>


<commit_before>//! An importer for aseprite's image+json sprite animations.
//!
//! In aseprite, go to file->export sprite sheet,
//! choose to export json data, and select "array" rather than "hash"
//! because that makes sense.
//!
//! Tested with aseprite 1.1.6, as on Debian Stretch.

use serde_derive;

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct Rect {
    x: u32,
    y: u32,
    w: u32,
    h: u32,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct Dimensions {
    w: u32,
    h: u32,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct Frame {
    filename: String,
    frame: Rect,
    rotated: bool,
    trimmed: bool,
    #[serde(rename = "spriteSourceSize")]
    sprite_source_size: Rect,
    #[serde(rename = "sourceSize")]
    source_size: Dimensions,
    duration: u32,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct Frametag {
    name: String,
    from: u32,
    to: u32,
    direction: String,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct Layer {
    name: String,
    opacity: u32,
    #[serde(rename = "blendMode")]
    blend_mode: String,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct Metadata {
    app: String,
    version: String,
    format: String,
    size: Dimensions,
    scale: String, // Surely this should be a number?
    #[serde(rename = "frameTags")]
    frame_tags: Vec<Frametag>,
    layers: Vec<Layer>,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct SpritesheetData {
    frames: Vec<Frame>,
    meta: Metadata,
}

#[cfg(test)]
mod tests {
    use serde_json;

    #[test]
    fn test_sprite_load_save() {
        let s = r##"{ "frames": [
   {
    "filename": "boonga 0.ase",
    "frame": { "x": 1, "y": 1, "w": 18, "h": 18 },
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": { "x": 0, "y": 0, "w": 16, "h": 16 },
    "sourceSize": { "w": 16, "h": 16 },
    "duration": 250
   },
   {
    "filename": "boonga 1.ase",
    "frame": { "x": 20, "y": 1, "w": 18, "h": 18 },
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": { "x": 0, "y": 0, "w": 16, "h": 16 },
    "sourceSize": { "w": 16, "h": 16 },
    "duration": 250
   }
 ],
 "meta": {
  "app": "http://www.aseprite.org/",
  "version": "1.1.6-dev",
  "image": "/home/icefox/models/boonga.png",
  "format": "RGBA8888",
  "size": { "w": 39, "h": 20 },
  "scale": "1",
  "frameTags": [
   { "name": "testtag", "from": 0, "to": 1, "direction": "forward" }
  ],
  "layers": [
   { "name": "Layer 1", "opacity": 255, "blendMode": "normal" }
  ]
 }
}
"##;

        let deserialized: super::SpritesheetData = serde_json::from_str(s).unwrap();

        let serialized = serde_json::to_string(&deserialized).unwrap();
        let deserialized_again: super::SpritesheetData = serde_json::from_str(&serialized).unwrap();

        assert_eq!(deserialized, deserialized_again);
    }
}
<commit_msg>Made the spritesheet types derive Copy/Clone as necessary.<commit_after>//! An importer for aseprite's image+json sprite animations.
//!
//! In aseprite, go to file->export sprite sheet,
//! choose to export json data, and select "array" rather than "hash"
//! because that makes sense.
//!
//! Tested with aseprite 1.1.6, as on Debian Stretch.

use serde_derive;

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
pub struct Rect {
    x: u32,
    y: u32,
    w: u32,
    h: u32,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
pub struct Dimensions {
    w: u32,
    h: u32,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Frame {
    filename: String,
    frame: Rect,
    rotated: bool,
    trimmed: bool,
    #[serde(rename = "spriteSourceSize")]
    sprite_source_size: Rect,
    #[serde(rename = "sourceSize")]
    source_size: Dimensions,
    duration: u32,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Frametag {
    name: String,
    from: u32,
    to: u32,
    direction: String,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Layer {
    name: String,
    opacity: u32,
    #[serde(rename = "blendMode")]
    blend_mode: String,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Metadata {
    app: String,
    version: String,
    format: String,
    size: Dimensions,
    scale: String, // Surely this should be a number?
    #[serde(rename = "frameTags")]
    frame_tags: Vec<Frametag>,
    layers: Vec<Layer>,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct SpritesheetData {
    frames: Vec<Frame>,
    meta: Metadata,
}

#[cfg(test)]
mod tests {
    use serde_json;

    #[test]
    fn test_sprite_load_save() {
        let s = r##"{ "frames": [
   {
    "filename": "boonga 0.ase",
    "frame": { "x": 1, "y": 1, "w": 18, "h": 18 },
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": { "x": 0, "y": 0, "w": 16, "h": 16 },
    "sourceSize": { "w": 16, "h": 16 },
    "duration": 250
   },
   {
    "filename": "boonga 1.ase",
    "frame": { "x": 20, "y": 1, "w": 18, "h": 18 },
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": { "x": 0, "y": 0, "w": 16, "h": 16 },
    "sourceSize": { "w": 16, "h": 16 },
    "duration": 250
   }
 ],
 "meta": {
  "app": "http://www.aseprite.org/",
  "version": "1.1.6-dev",
  "image": "/home/icefox/models/boonga.png",
  "format": "RGBA8888",
  "size": { "w": 39, "h": 20 },
  "scale": "1",
  "frameTags": [
   { "name": "testtag", "from": 0, "to": 1, "direction": "forward" }
  ],
  "layers": [
   { "name": "Layer 1", "opacity": 255, "blendMode": "normal" }
  ]
 }
}
"##;

        let deserialized: super::SpritesheetData = serde_json::from_str(s).unwrap();

        let serialized = serde_json::to_string(&deserialized).unwrap();
        let deserialized_again: super::SpritesheetData = serde_json::from_str(&serialized).unwrap();

        assert_eq!(deserialized, deserialized_again);
    }
}
<|endoftext|>


<commit_before>use std::ops::{Index, IndexMut};

#[derive(Debug)]
pub struct SquareMatrix<T> {
    n: usize,
    data: Vec<T>
}

impl<T> Index<(usize, usize)> for SquareMatrix<T> {
    type Output = T;

    /// (row, col)
    #[inline(always)]
    fn index<'a>(&'a self, pos: (usize, usize)) -> &'a T {
        match pos {
            (row, col) => {
                let idx = row * self.n + col;
                &self.data[idx]
            }
        }
    }
}

impl<T> IndexMut<(usize, usize)> for SquareMatrix<T> {
    /// (row, col)
    #[inline(always)]
    fn index_mut<'a>(&'a mut self, pos: (usize, usize)) -> &'a mut T {
        match pos {
            (row, col) => {
                let idx = row * self.n + col;
                &mut self.data[idx]
            }
        }
    }
}

impl<T: Copy> SquareMatrix<T> {
    pub fn from_row_vec(n: usize, data: Vec<T>) -> SquareMatrix<T> {
        assert!(n > 0);
        assert!(data.len() == n*n);
        SquareMatrix {n: n, data: data}
    }
    #[inline(always)]
    pub fn n(&self) -> usize { self.n }
    pub fn into_vec(self) -> Vec<T> { self.data }

    #[inline(always)]
    pub fn map_row<F: Fn(T) -> T>(&mut self, row: usize, f: F) {
        for col in 0..self.n {
            let n = f(self[(row, col)]);
            self[(row, col)] = n;
        }
    }

    #[inline(always)]
    pub fn map_col<F: Fn(T) -> T>(&mut self, col: usize, f: F) {
        for row in 0..self.n {
            let n = f(self[(row, col)]);
            self[(row, col)] = n;
        }
    }

}
<commit_msg>Add from_fn()<commit_after>use std::ops::{Index, IndexMut};

#[derive(Debug)]
pub struct SquareMatrix<T> {
    n: usize,
    data: Vec<T>
}

impl<T> Index<(usize, usize)> for SquareMatrix<T> {
    type Output = T;

    /// (row, col)
    #[inline(always)]
    fn index<'a>(&'a self, pos: (usize, usize)) -> &'a T {
        match pos {
            (row, col) => {
                let idx = row * self.n + col;
                &self.data[idx]
            }
        }
    }
}

impl<T> IndexMut<(usize, usize)> for SquareMatrix<T> {
    /// (row, col)
    #[inline(always)]
    fn index_mut<'a>(&'a mut self, pos: (usize, usize)) -> &'a mut T {
        match pos {
            (row, col) => {
                let idx = row * self.n + col;
                &mut self.data[idx]
            }
        }
    }
}

impl<T: Copy> SquareMatrix<T> {
    pub fn from_fn<F: Fn((usize,usize)) -> T>(n: usize, f: F) -> SquareMatrix<T> {
        let data = (0..n*n).map(|i| f((i/n, i%n))).collect();
        SquareMatrix::from_row_vec(n, data)
    }

    pub fn from_row_vec(n: usize, data: Vec<T>) -> SquareMatrix<T> {
        assert!(n > 0);
        assert!(data.len() == n*n);
        SquareMatrix {n: n, data: data}
    }
    #[inline(always)]
    pub fn n(&self) -> usize { self.n }
    pub fn into_vec(self) -> Vec<T> { self.data }

    #[inline(always)]
    pub fn map_row<F: Fn(T) -> T>(&mut self, row: usize, f: F) {
        for col in 0..self.n {
            let n = f(self[(row, col)]);
            self[(row, col)] = n;
        }
    }

    #[inline(always)]
    pub fn map_col<F: Fn(T) -> T>(&mut self, col: usize, f: F) {
        for row in 0..self.n {
            let n = f(self[(row, col)]);
            self[(row, col)] = n;
        }
    }

}
<|endoftext|>


<commit_before>use std::thread;
use std::process;
use std::time::Instant;
use std::sync::{mpsc, Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};

use fps_clock::FpsClock;
use piston_window::{
    PistonWindow,
    WindowSettings,
    math,
};

use renderer::Renderer;
use animation::{Animation, MoveAnimation, RotateAnimation, AnimationStatus};
use state::{TurtleState, DrawingState, Path, Pen};
use radians::{self, Radians};
use {Speed, color, Distance};

/// Types that will be shared with another thread
pub type Shared<T> = Arc<RwLock<T>>;
/// Alias to help make the types more understandable without exposing as many implementation details
pub type ReadOnlyRef<'a, T> = RwLockReadGuard<'a, T>;
pub type MutableRef<'a, T> = RwLockWriteGuard<'a, T>;

/// A structure that provides read-only access to shared state
pub struct ReadOnly {
    turtle: Shared<TurtleState>,
    drawing: Shared<DrawingState>,
    /// A temporary path for use during animations
    temporary_path: Shared<Option<Path>>,
}

impl ReadOnly {
    pub fn turtle(&self) -> ReadOnlyRef<TurtleState> {
        self.turtle.read().expect("bug: Lock was poisoned")
    }

    pub fn drawing(&self) -> ReadOnlyRef<DrawingState> {
        self.drawing.read().expect("bug: Lock was poisoned")
    }

    pub fn temporary_path(&self) -> ReadOnlyRef<Option<Path>> {
        self.temporary_path.read().expect("bug: Lock was poisoned")
    }
}

pub struct TurtleWindow {
    thread_handle: Option<thread::JoinHandle<()>>,
    /// Channel for sending completed paths so they can be stored and re-rendered
    /// in the rendering thread
    paths_channel: mpsc::Sender<Path>,

    turtle: Shared<TurtleState>,
    drawing: Shared<DrawingState>,
    /// A temporary path for use during animations
    temporary_path: Shared<Option<Path>>,
}

impl TurtleWindow {
    pub fn new() -> TurtleWindow {
        let (paths_tx, paths_rx) = mpsc::channel();

        let mut turtle_window = Self {
            thread_handle: None,
            paths_channel: paths_tx,
            turtle: Arc::new(RwLock::new(TurtleState {
                position: [0., 0.],
                heading: Radians::from_degrees_value(90.),
                speed: Speed::Five,
                visible: true,
            })),
            drawing: Arc::new(RwLock::new(DrawingState {
                pen: Pen {
                    enabled: true,
                    thickness: 1.,
                    color: color::BLACK,
                },
                background: color::WHITE,
            })),
            temporary_path: Arc::new(RwLock::new(None)),
        };

        let read_only = turtle_window.read_only();
        let handle = thread::spawn(move || {
            let mut window: PistonWindow = WindowSettings::new(
                "Turtle", [800, 600]
            ).exit_on_esc(true).build().unwrap();

            Renderer::new().run(&mut window, paths_rx, read_only);
        });

        turtle_window.thread_handle = Some(handle);
        turtle_window
    }

    /// Provide a read-only version of the state
    pub fn read_only(&self) -> ReadOnly {
        ReadOnly {
            turtle: self.turtle.clone(),
            drawing: self.drawing.clone(),
            temporary_path: self.temporary_path.clone(),
        }
    }

    /// Provides read-only access to the turtle state
    pub fn turtle(&self) -> ReadOnlyRef<TurtleState> {
        self.turtle.read().expect("bug: Lock was poisoned")
    }

    /// Provides mutable access to the turtle state
    pub fn turtle_mut(&mut self) -> MutableRef<TurtleState> {
        self.turtle.write().expect("bug: Lock was poisoned")
    }

    /// Provides read-only access to the drawing
    pub fn drawing(&self) -> ReadOnlyRef<DrawingState> {
        self.drawing.read().expect("bug: Lock was poisoned")
    }

    /// Provides mutable access to the drawing
    pub fn drawing_mut(&mut self) -> MutableRef<DrawingState> {
        self.drawing.write().expect("bug: Lock was poisoned")
    }

    fn set_temporary_path(&mut self, path: Option<Path>) {
        let mut temp = self.temporary_path.write().expect("bug: Lock was poisoned");
        *temp = path;
    }

    /// Move the turtle forward by the given distance. To move backwards, use a negative distance.
    ///
    /// The turtle's motion will be animated based on the speed
    pub fn forward(&mut self, distance: Distance) {
        if distance == 0. {
            return;
        }

        let TurtleState {position: start, heading, speed, ..} = *self.turtle();
        let x = distance * heading.cos();
        let y = distance * heading.sin();
        let end = math::add(start, [x, y]);

        let speed = speed.to_absolute(); // px per second
        let total_millis = distance / speed * 1000.;

        let animation = MoveAnimation {
            path: Path {
                start,
                end,
                pen: self.drawing().pen.clone(),
            },
            timer: Instant::now(),
            total_millis,
        };

        self.play_animation(animation);
    }

    /// Rotate the turtle in place by the given angle in the given direction of rotation
    pub fn rotate(&mut self, angle: Radians, clockwise: bool) {
        if angle == radians::ZERO {
            return;
        }

        let TurtleState {heading, speed, ..} = *self.turtle();
        let speed = speed.to_rotation(); // radians per second
        let total_millis = angle / speed * 1000.;
        let total_millis = total_millis.value();

        let animation = RotateAnimation {
            start: heading,
            delta_angle: angle,
            clockwise,
            timer: Instant::now(),
            total_millis,
        };

        self.play_animation(animation);
    }

    fn play_animation<A: Animation>(&mut self, animation: A) {
        let mut fps = FpsClock::new(60);
        loop {
            // We want to keep the lock for as little time as possible
            let status = {
                let mut turtle = self.turtle_mut();
                animation.advance(&mut *turtle)
            };
            match status {
                AnimationStatus::Running(path) => self.set_temporary_path(path),
                AnimationStatus::Complete(path) => {
                    if let Some(path) = path {
                        self.set_temporary_path(None);
                        match self.paths_channel.send(path) {
                            Ok(_) => {},
                            // The channel is closed which means the window was closed
                            Err(_) => {
                                // quit immediately
                                process::exit(0);
                            },
                        };
                    }

                    break;
                },
            }

            fps.tick();
        }
    }
}

impl Drop for TurtleWindow {
    fn drop(&mut self) {
        if let Some(handle) = self.thread_handle.take() {
            handle.join().unwrap();
        }
    }
}
<commit_msg>Fixed bug that was causing small movements to be rate limited<commit_after>use std::thread;
use std::process;
use std::time::Instant;
use std::sync::{mpsc, Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};

use fps_clock::FpsClock;
use piston_window::{
    PistonWindow,
    WindowSettings,
    math,
};

use renderer::Renderer;
use animation::{Animation, MoveAnimation, RotateAnimation, AnimationStatus};
use state::{TurtleState, DrawingState, Path, Pen};
use radians::{self, Radians};
use {Speed, color, Distance};

/// Types that will be shared with another thread
pub type Shared<T> = Arc<RwLock<T>>;
/// Alias to help make the types more understandable without exposing as many implementation details
pub type ReadOnlyRef<'a, T> = RwLockReadGuard<'a, T>;
pub type MutableRef<'a, T> = RwLockWriteGuard<'a, T>;

/// A structure that provides read-only access to shared state
pub struct ReadOnly {
    turtle: Shared<TurtleState>,
    drawing: Shared<DrawingState>,
    /// A temporary path for use during animations
    temporary_path: Shared<Option<Path>>,
}

impl ReadOnly {
    pub fn turtle(&self) -> ReadOnlyRef<TurtleState> {
        self.turtle.read().expect("bug: Lock was poisoned")
    }

    pub fn drawing(&self) -> ReadOnlyRef<DrawingState> {
        self.drawing.read().expect("bug: Lock was poisoned")
    }

    pub fn temporary_path(&self) -> ReadOnlyRef<Option<Path>> {
        self.temporary_path.read().expect("bug: Lock was poisoned")
    }
}

pub struct TurtleWindow {
    thread_handle: Option<thread::JoinHandle<()>>,
    /// Channel for sending completed paths so they can be stored and re-rendered
    /// in the rendering thread
    paths_channel: mpsc::Sender<Path>,

    turtle: Shared<TurtleState>,
    drawing: Shared<DrawingState>,
    /// A temporary path for use during animations
    temporary_path: Shared<Option<Path>>,
}

impl TurtleWindow {
    pub fn new() -> TurtleWindow {
        let (paths_tx, paths_rx) = mpsc::channel();

        let mut turtle_window = Self {
            thread_handle: None,
            paths_channel: paths_tx,
            turtle: Arc::new(RwLock::new(TurtleState {
                position: [0., 0.],
                heading: Radians::from_degrees_value(90.),
                speed: Speed::Five,
                visible: true,
            })),
            drawing: Arc::new(RwLock::new(DrawingState {
                pen: Pen {
                    enabled: true,
                    thickness: 1.,
                    color: color::BLACK,
                },
                background: color::WHITE,
            })),
            temporary_path: Arc::new(RwLock::new(None)),
        };

        let read_only = turtle_window.read_only();
        let handle = thread::spawn(move || {
            let mut window: PistonWindow = WindowSettings::new(
                "Turtle", [800, 600]
            ).exit_on_esc(true).build().unwrap();

            Renderer::new().run(&mut window, paths_rx, read_only);
        });

        turtle_window.thread_handle = Some(handle);
        turtle_window
    }

    /// Provide a read-only version of the state
    pub fn read_only(&self) -> ReadOnly {
        ReadOnly {
            turtle: self.turtle.clone(),
            drawing: self.drawing.clone(),
            temporary_path: self.temporary_path.clone(),
        }
    }

    /// Provides read-only access to the turtle state
    pub fn turtle(&self) -> ReadOnlyRef<TurtleState> {
        self.turtle.read().expect("bug: Lock was poisoned")
    }

    /// Provides mutable access to the turtle state
    pub fn turtle_mut(&mut self) -> MutableRef<TurtleState> {
        self.turtle.write().expect("bug: Lock was poisoned")
    }

    /// Provides read-only access to the drawing
    pub fn drawing(&self) -> ReadOnlyRef<DrawingState> {
        self.drawing.read().expect("bug: Lock was poisoned")
    }

    /// Provides mutable access to the drawing
    pub fn drawing_mut(&mut self) -> MutableRef<DrawingState> {
        self.drawing.write().expect("bug: Lock was poisoned")
    }

    fn set_temporary_path(&mut self, path: Option<Path>) {
        let mut temp = self.temporary_path.write().expect("bug: Lock was poisoned");
        *temp = path;
    }

    /// Move the turtle forward by the given distance. To move backwards, use a negative distance.
    ///
    /// The turtle's motion will be animated based on the speed
    pub fn forward(&mut self, distance: Distance) {
        if distance == 0. {
            return;
        }

        let TurtleState {position: start, heading, speed, ..} = *self.turtle();
        let x = distance * heading.cos();
        let y = distance * heading.sin();
        let end = math::add(start, [x, y]);

        let speed = speed.to_absolute(); // px per second
        let total_millis = distance / speed * 1000.;

        let animation = MoveAnimation {
            path: Path {
                start,
                end,
                pen: self.drawing().pen.clone(),
            },
            timer: Instant::now(),
            total_millis,
        };

        self.play_animation(animation);
    }

    /// Rotate the turtle in place by the given angle in the given direction of rotation
    pub fn rotate(&mut self, angle: Radians, clockwise: bool) {
        if angle == radians::ZERO {
            return;
        }

        let TurtleState {heading, speed, ..} = *self.turtle();
        let speed = speed.to_rotation(); // radians per second
        let total_millis = angle / speed * 1000.;
        let total_millis = total_millis.value();

        let animation = RotateAnimation {
            start: heading,
            delta_angle: angle,
            clockwise,
            timer: Instant::now(),
            total_millis,
        };

        self.play_animation(animation);
    }

    fn play_animation<A: Animation>(&mut self, animation: A) {
        // We only limit the framerate at all to be respectful of the user's CPU. If the framerate
        // is too small, every small movement (say forward(1) or right(1)) will take too long.
        // We use a huge framerate so we can sleep occasionally for longer animations but still
        // finish smaller ones in a reasonable amount of time.
        let mut fps = FpsClock::new(600);
        loop {
            // We want to keep the lock for as little time as possible
            let status = {
                let mut turtle = self.turtle_mut();
                animation.advance(&mut *turtle)
            };
            match status {
                AnimationStatus::Running(path) => self.set_temporary_path(path),
                AnimationStatus::Complete(path) => {
                    if let Some(path) = path {
                        self.set_temporary_path(None);
                        match self.paths_channel.send(path) {
                            Ok(_) => {},
                            // The channel is closed which means the window was closed
                            Err(_) => {
                                // quit immediately
                                process::exit(0);
                            },
                        };
                    }

                    break;
                },
            }

            fps.tick();
        }
    }
}

impl Drop for TurtleWindow {
    fn drop(&mut self) {
        if let Some(handle) = self.thread_handle.take() {
            handle.join().unwrap();
        }
    }
}
<|endoftext|>