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

use std::fmt;

/// CrateIds identify crates and include the crate name and optionally a path
/// and version. In the full form, they look like relative URLs. Example:
/// `github.com/mozilla/rust#std:1.0` would be a package ID with a path of
/// `gitub.com/mozilla/rust` and a crate name of `std` with a version of
/// `1.0`. If no crate name is given after the hash, the name is inferred to
/// be the last component of the path. If no version is given, it is inferred
/// to be `0.0`.

use std::from_str::FromStr;

#[deriving(Clone, PartialEq)]
pub struct CrateId {
    /// A path which represents the codes origin. By convention this is the
    /// URL, without `http://` or `https://` prefix, to the crate's repository
    pub path: String,
    /// The name of the crate.
    pub name: String,
    /// The version of the crate.
    pub version: Option<String>,
}

impl fmt::Show for CrateId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "{}", self.path));
        let version = match self.version {
            None => "0.0",
            Some(ref version) => version.as_slice(),
        };
        if self.path == self.name ||
                self.path
                    .as_slice()
                    .ends_with(format!("/{}", self.name).as_slice()) {
            write!(f, "\\#{}", version)
        } else {
            write!(f, "\\#{}:{}", self.name, version)
        }
    }
}

impl FromStr for CrateId {
    fn from_str(s: &str) -> Option<CrateId> {
        let pieces: Vec<&str> = s.splitn('#', 1).collect();
        let path = pieces.get(0).to_string();

        if path.as_slice().starts_with("/") || path.as_slice().ends_with("/") ||
            path.as_slice().starts_with(".") || path.is_empty() {
            return None;
        }

        let path_pieces: Vec<&str> = path.as_slice()
                                         .rsplitn('/', 1)
                                         .collect();
        let inferred_name = *path_pieces.get(0);

        let (name, version) = if pieces.len() == 1 {
            (inferred_name.to_string(), None)
        } else {
            let hash_pieces: Vec<&str> = pieces.get(1)
                                               .splitn(':', 1)
                                               .collect();
            let (hash_name, hash_version) = if hash_pieces.len() == 1 {
                ("", *hash_pieces.get(0))
            } else {
                (*hash_pieces.get(0), *hash_pieces.get(1))
            };

            let name = if !hash_name.is_empty() {
                hash_name.to_string()
            } else {
                inferred_name.to_string()
            };

            let version = if !hash_version.is_empty() {
                if hash_version == "0.0" {
                    None
                } else {
                    Some(hash_version.to_string())
                }
            } else {
                None
            };

            (name, version)
        };

        Some(CrateId {
            path: path.to_string(),
            name: name,
            version: version,
        })
    }
}

impl CrateId {
    pub fn version_or_default<'a>(&'a self) -> &'a str {
        match self.version {
            None => "0.0",
            Some(ref version) => version.as_slice(),
        }
    }

    pub fn short_name_with_version(&self) -> String {
        (format!("{}-{}", self.name, self.version_or_default())).to_string()
    }

    pub fn matches(&self, other: &CrateId) -> bool {
        // FIXME: why does this not match on `path`?
        if self.name != other.name { return false }
        match (&self.version, &other.version) {
            (&Some(ref v1), &Some(ref v2)) => v1 == v2,
            _ => true,
        }
    }
}

#[test]
fn bare_name() {
    let crateid: CrateId = from_str("foo").expect("valid crateid");
    assert_eq!(crateid.name, "foo".to_string());
    assert_eq!(crateid.version, None);
    assert_eq!(crateid.path, "foo".to_string());
}

#[test]
fn bare_name_single_char() {
    let crateid: CrateId = from_str("f").expect("valid crateid");
    assert_eq!(crateid.name, "f".to_string());
    assert_eq!(crateid.version, None);
    assert_eq!(crateid.path, "f".to_string());
}

#[test]
fn empty_crateid() {
    let crateid: Option<CrateId> = from_str("");
    assert!(crateid.is_none());
}

#[test]
fn simple_path() {
    let crateid: CrateId = from_str("example.com/foo/bar").expect("valid crateid");
    assert_eq!(crateid.name, "bar".to_string());
    assert_eq!(crateid.version, None);
    assert_eq!(crateid.path, "example.com/foo/bar".to_string());
}

#[test]
fn simple_version() {
    let crateid: CrateId = from_str("foo#1.0").expect("valid crateid");
    assert_eq!(crateid.name, "foo".to_string());
    assert_eq!(crateid.version, Some("1.0".to_string()));
    assert_eq!(crateid.path, "foo".to_string());
}

#[test]
fn absolute_path() {
    let crateid: Option<CrateId> = from_str("/foo/bar");
    assert!(crateid.is_none());
}

#[test]
fn path_ends_with_slash() {
    let crateid: Option<CrateId> = from_str("foo/bar/");
    assert!(crateid.is_none());
}

#[test]
fn path_and_version() {
    let crateid: CrateId = from_str("example.com/foo/bar#1.0").expect("valid crateid");
    assert_eq!(crateid.name, "bar".to_string());
    assert_eq!(crateid.version, Some("1.0".to_string()));
    assert_eq!(crateid.path, "example.com/foo/bar".to_string());
}

#[test]
fn single_chars() {
    let crateid: CrateId = from_str("a/b#1").expect("valid crateid");
    assert_eq!(crateid.name, "b".to_string());
    assert_eq!(crateid.version, Some("1".to_string()));
    assert_eq!(crateid.path, "a/b".to_string());
}

#[test]
fn missing_version() {
    let crateid: CrateId = from_str("foo#").expect("valid crateid");
    assert_eq!(crateid.name, "foo".to_string());
    assert_eq!(crateid.version, None);
    assert_eq!(crateid.path, "foo".to_string());
}

#[test]
fn path_and_name() {
    let crateid: CrateId = from_str("foo/rust-bar#bar:1.0").expect("valid crateid");
    assert_eq!(crateid.name, "bar".to_string());
    assert_eq!(crateid.version, Some("1.0".to_string()));
    assert_eq!(crateid.path, "foo/rust-bar".to_string());
}

#[test]
fn empty_name() {
    let crateid: CrateId = from_str("foo/bar#:1.0").expect("valid crateid");
    assert_eq!(crateid.name, "bar".to_string());
    assert_eq!(crateid.version, Some("1.0".to_string()));
    assert_eq!(crateid.path, "foo/bar".to_string());
}
<commit_msg>auto merge of #14627 : Indiv0/rust/fix-crateid-doc-typo, r=alexcrichton<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;

/// CrateIds identify crates and include the crate name and optionally a path
/// and version. In the full form, they look like relative URLs. Example:
/// `github.com/mozilla/rust#std:1.0` would be a package ID with a path of
/// `github.com/mozilla/rust` and a crate name of `std` with a version of
/// `1.0`. If no crate name is given after the hash, the name is inferred to
/// be the last component of the path. If no version is given, it is inferred
/// to be `0.0`.

use std::from_str::FromStr;

#[deriving(Clone, PartialEq)]
pub struct CrateId {
    /// A path which represents the codes origin. By convention this is the
    /// URL, without `http://` or `https://` prefix, to the crate's repository
    pub path: String,
    /// The name of the crate.
    pub name: String,
    /// The version of the crate.
    pub version: Option<String>,
}

impl fmt::Show for CrateId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "{}", self.path));
        let version = match self.version {
            None => "0.0",
            Some(ref version) => version.as_slice(),
        };
        if self.path == self.name ||
                self.path
                    .as_slice()
                    .ends_with(format!("/{}", self.name).as_slice()) {
            write!(f, "\\#{}", version)
        } else {
            write!(f, "\\#{}:{}", self.name, version)
        }
    }
}

impl FromStr for CrateId {
    fn from_str(s: &str) -> Option<CrateId> {
        let pieces: Vec<&str> = s.splitn('#', 1).collect();
        let path = pieces.get(0).to_string();

        if path.as_slice().starts_with("/") || path.as_slice().ends_with("/") ||
            path.as_slice().starts_with(".") || path.is_empty() {
            return None;
        }

        let path_pieces: Vec<&str> = path.as_slice()
                                         .rsplitn('/', 1)
                                         .collect();
        let inferred_name = *path_pieces.get(0);

        let (name, version) = if pieces.len() == 1 {
            (inferred_name.to_string(), None)
        } else {
            let hash_pieces: Vec<&str> = pieces.get(1)
                                               .splitn(':', 1)
                                               .collect();
            let (hash_name, hash_version) = if hash_pieces.len() == 1 {
                ("", *hash_pieces.get(0))
            } else {
                (*hash_pieces.get(0), *hash_pieces.get(1))
            };

            let name = if !hash_name.is_empty() {
                hash_name.to_string()
            } else {
                inferred_name.to_string()
            };

            let version = if !hash_version.is_empty() {
                if hash_version == "0.0" {
                    None
                } else {
                    Some(hash_version.to_string())
                }
            } else {
                None
            };

            (name, version)
        };

        Some(CrateId {
            path: path.to_string(),
            name: name,
            version: version,
        })
    }
}

impl CrateId {
    pub fn version_or_default<'a>(&'a self) -> &'a str {
        match self.version {
            None => "0.0",
            Some(ref version) => version.as_slice(),
        }
    }

    pub fn short_name_with_version(&self) -> String {
        (format!("{}-{}", self.name, self.version_or_default())).to_string()
    }

    pub fn matches(&self, other: &CrateId) -> bool {
        // FIXME: why does this not match on `path`?
        if self.name != other.name { return false }
        match (&self.version, &other.version) {
            (&Some(ref v1), &Some(ref v2)) => v1 == v2,
            _ => true,
        }
    }
}

#[test]
fn bare_name() {
    let crateid: CrateId = from_str("foo").expect("valid crateid");
    assert_eq!(crateid.name, "foo".to_string());
    assert_eq!(crateid.version, None);
    assert_eq!(crateid.path, "foo".to_string());
}

#[test]
fn bare_name_single_char() {
    let crateid: CrateId = from_str("f").expect("valid crateid");
    assert_eq!(crateid.name, "f".to_string());
    assert_eq!(crateid.version, None);
    assert_eq!(crateid.path, "f".to_string());
}

#[test]
fn empty_crateid() {
    let crateid: Option<CrateId> = from_str("");
    assert!(crateid.is_none());
}

#[test]
fn simple_path() {
    let crateid: CrateId = from_str("example.com/foo/bar").expect("valid crateid");
    assert_eq!(crateid.name, "bar".to_string());
    assert_eq!(crateid.version, None);
    assert_eq!(crateid.path, "example.com/foo/bar".to_string());
}

#[test]
fn simple_version() {
    let crateid: CrateId = from_str("foo#1.0").expect("valid crateid");
    assert_eq!(crateid.name, "foo".to_string());
    assert_eq!(crateid.version, Some("1.0".to_string()));
    assert_eq!(crateid.path, "foo".to_string());
}

#[test]
fn absolute_path() {
    let crateid: Option<CrateId> = from_str("/foo/bar");
    assert!(crateid.is_none());
}

#[test]
fn path_ends_with_slash() {
    let crateid: Option<CrateId> = from_str("foo/bar/");
    assert!(crateid.is_none());
}

#[test]
fn path_and_version() {
    let crateid: CrateId = from_str("example.com/foo/bar#1.0").expect("valid crateid");
    assert_eq!(crateid.name, "bar".to_string());
    assert_eq!(crateid.version, Some("1.0".to_string()));
    assert_eq!(crateid.path, "example.com/foo/bar".to_string());
}

#[test]
fn single_chars() {
    let crateid: CrateId = from_str("a/b#1").expect("valid crateid");
    assert_eq!(crateid.name, "b".to_string());
    assert_eq!(crateid.version, Some("1".to_string()));
    assert_eq!(crateid.path, "a/b".to_string());
}

#[test]
fn missing_version() {
    let crateid: CrateId = from_str("foo#").expect("valid crateid");
    assert_eq!(crateid.name, "foo".to_string());
    assert_eq!(crateid.version, None);
    assert_eq!(crateid.path, "foo".to_string());
}

#[test]
fn path_and_name() {
    let crateid: CrateId = from_str("foo/rust-bar#bar:1.0").expect("valid crateid");
    assert_eq!(crateid.name, "bar".to_string());
    assert_eq!(crateid.version, Some("1.0".to_string()));
    assert_eq!(crateid.path, "foo/rust-bar".to_string());
}

#[test]
fn empty_name() {
    let crateid: CrateId = from_str("foo/bar#:1.0").expect("valid crateid");
    assert_eq!(crateid.name, "bar".to_string());
    assert_eq!(crateid.version, Some("1.0".to_string()));
    assert_eq!(crateid.path, "foo/bar".to_string());
}
<|endoftext|>


<commit_before>use runtime::Error;
use values::Value;
use memory::Memory;

use std::rc::Rc;

pub static PRIMITIVES: [&'static str, ..18] = [
    "*",
    "+",
    "-",
    "/",
    "<",
    "<=",
    "=",
    ">",
    ">=",
    "car",
    "cdr",
    "cons",
    "length",
    "list",
    "list?",
    "not",
    "null?",
    "pair?",
];

pub fn apply(name: &String, args_: Vec<Rc<Value>>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    let args = args_.iter().map(|a| a.deref()).collect();

    match name.as_slice() {
        "*"      => product(args, mem),
        "+"      => plus(args, mem),
        "-"      => minus(args, mem),
        "/"      => division(args, mem),
        "<"      => less_than(args, mem),
        "<="     => less_than_or_equal(args, mem),
        "="      => equals(args, mem),
        ">"      => greater_than(args, mem),
        ">="     => greater_than_or_equal(args, mem),
        "car"    => car(args, mem),
        "cdr"    => cdr(args, mem),
        "cons"   => cons(args, mem),
        "length" => length(args, mem),
        "list"   => list(args, mem),
        "list?"  => list_question_mark(args, mem),
        "not"    => not(args, mem),
        "null?"  => null(args, mem),
        "pair?"  => pair(args, mem),
        _        => Err(Error::PrimitiveFailed(name.to_string()))
    }
}

fn plus(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    let args_ = try!(list_of_integers(args));
    let sum = args_.iter().fold(0, |sum, n| sum + *n);

    Ok(mem.integer(sum))
}

fn minus(args_: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    let args = try!(list_of_integers(args_));

    if args.len() == 0 {
        return Err(Error::BadArity(Some("-".to_string())))
    }

    let head = args.head().unwrap();
    let tail = args.tail();

    if tail.is_empty() {
        return Ok(mem.integer(- *head))
    }

    let tail_sum = tail.iter().fold(0, |sum, n| sum + *n);
    Ok(mem.integer(*head - tail_sum))
}

fn division(args_: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    let args = try!(list_of_integers(args_));

    if args.len() == 0 {
        return Err(Error::BadArity(Some("/".to_string())))
    }

    let head = args.head().unwrap();
    let tail = args.tail();

    if tail.is_empty() {
        return Ok(mem.integer(1 / *head))
    }

    let div = tail.iter().fold(*head, |div, n| div / *n);
    Ok(mem.integer(div))
}

fn product(args_: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    let args = try!(list_of_integers(args_));
    let product = args.iter().fold(1, |product, n| product * *n);

    Ok(mem.integer(product))
}

fn equals(args_: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args_.len() < 2 {
        return Ok(mem.b_true());
    }

    let args = try!(list_of_integers(args_));
    let head = args.head().unwrap();
    let outcome = args.iter().skip(1).all(|n| *n == *head);

    Ok(mem.boolean(outcome))
}

fn less_than(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    ord(args, mem, |a, b| a < b)
}

fn less_than_or_equal(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    ord(args, mem, |a, b| a <= b)
}

fn greater_than(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    ord(args, mem, |a, b| a > b)
}

fn greater_than_or_equal(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    ord(args, mem, |a, b| a >= b)
}

fn not(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("not".to_string())))
    }

    let outcome = match *args.head().unwrap() {
        &Value::Bool(false) => true,
        _                   => false,
    };

    Ok(mem.boolean(outcome))
}

fn list(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    let list = args.iter().map(|a| a.deref().clone()).collect();

    Ok(mem.list(list))
}

fn length(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("length".to_string())));
    }

    match args[0] {
        &Value::List(ref list) =>
            Ok(mem.integer(list.len() as i64)),
        value =>
            Err(Error::WrongArgumentType(value.clone())),
    }
}

fn pair(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("pair?".to_string())));
    }

    let outcome = if let &Value::List(ref list) = args[0] {
        !list.is_empty()
    } else if let &Value::DottedList(ref _list, ref _el) = args[0] {
        true
    } else {
        false
    };

    Ok(mem.boolean(outcome))
}

fn cons(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 2 {
        return Err(Error::BadArity(Some("cons".to_string())));
    }

    let mut list: Vec<Value> = Vec::new();

    if let &Value::List(ref l) = args[1] {
        list.push(args[0].clone());
        list.push_all(l.clone().as_slice());

        Ok(mem.list(list))
    } else {
        list.push(args[0].clone());
        Ok(mem.dotted_list(list, args[1].clone()))
    }
}

fn car(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("car".to_string())));
    }

    match args[0] {
        &Value::List(ref l) if !l.is_empty() =>
            Ok(mem.store(l.head().unwrap().clone())),
        &Value::DottedList(ref l, ref _t) =>
            Ok(mem.store(l.head().unwrap().clone())),
        value =>
            Err(Error::WrongArgumentType(value.clone())),
    }
}

fn cdr(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("cdr".to_string())));
    }

    match args[0] {
        &Value::List(ref l) if !l.is_empty() =>
            match l.tail() {
                tail if tail.is_empty() =>
                    Ok(mem.empty_list()),
                tail =>
                    Ok(mem.list(tail.to_vec())),
            },
        &Value::DottedList(ref _l, ref t) =>
            Ok(mem.store(*t.clone())),
        value =>
            Err(Error::WrongArgumentType(value.clone())),
    }
}

fn null(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("null?".to_string())));
    }

    let out = match args[0] {
        &Value::List(ref l) if l.is_empty() => true,
        _ => false
    };

    Ok(mem.boolean(out))
}

fn list_question_mark(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("list?".to_string())));
    }

    let out = if let &Value::List(ref _l) = args[0] {
        true
    } else {
        false
    };

    Ok(mem.boolean(out))
}

fn list_of_integers(list: Vec<&Value>) -> Result<Vec<i64>, Error> {
    let mut integers = Vec::with_capacity(list.len());

    for val in list.iter() {
        match *val {
            &Value::Integer(n) =>
                integers.push(n),
            value =>
                return Err(Error::WrongArgumentType(value.clone())),
        }
    }

    Ok(integers)
}

fn ord(args_: Vec<&Value>, mem: &mut Memory, cmp: |i64, i64| -> bool) -> Result<Rc<Value>, Error> {
    if args_.len() < 2 {
        return Ok(mem.b_true())
    }

    let args = try!(list_of_integers(args_));
    let outcome = range(0, args.len() - 1).all(|i|
        cmp(args[i], args[i + 1u])
    );

    return Ok(mem.boolean(outcome))
}
<commit_msg>Improved `null?`.<commit_after>use runtime::Error;
use values::Value;
use memory::Memory;

use std::rc::Rc;

pub static PRIMITIVES: [&'static str, ..18] = [
    "*",
    "+",
    "-",
    "/",
    "<",
    "<=",
    "=",
    ">",
    ">=",
    "car",
    "cdr",
    "cons",
    "length",
    "list",
    "list?",
    "not",
    "null?",
    "pair?",
];

pub fn apply(name: &String, args_: Vec<Rc<Value>>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    let args = args_.iter().map(|a| a.deref()).collect();

    match name.as_slice() {
        "*"      => product(args, mem),
        "+"      => plus(args, mem),
        "-"      => minus(args, mem),
        "/"      => division(args, mem),
        "<"      => less_than(args, mem),
        "<="     => less_than_or_equal(args, mem),
        "="      => equals(args, mem),
        ">"      => greater_than(args, mem),
        ">="     => greater_than_or_equal(args, mem),
        "car"    => car(args, mem),
        "cdr"    => cdr(args, mem),
        "cons"   => cons(args, mem),
        "length" => length(args, mem),
        "list"   => list(args, mem),
        "list?"  => list_question_mark(args, mem),
        "not"    => not(args, mem),
        "null?"  => null(args, mem),
        "pair?"  => pair(args, mem),
        _        => Err(Error::PrimitiveFailed(name.to_string()))
    }
}

fn plus(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    let args_ = try!(list_of_integers(args));
    let sum = args_.iter().fold(0, |sum, n| sum + *n);

    Ok(mem.integer(sum))
}

fn minus(args_: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    let args = try!(list_of_integers(args_));

    if args.len() == 0 {
        return Err(Error::BadArity(Some("-".to_string())))
    }

    let head = args.head().unwrap();
    let tail = args.tail();

    if tail.is_empty() {
        return Ok(mem.integer(- *head))
    }

    let tail_sum = tail.iter().fold(0, |sum, n| sum + *n);
    Ok(mem.integer(*head - tail_sum))
}

fn division(args_: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    let args = try!(list_of_integers(args_));

    if args.len() == 0 {
        return Err(Error::BadArity(Some("/".to_string())))
    }

    let head = args.head().unwrap();
    let tail = args.tail();

    if tail.is_empty() {
        return Ok(mem.integer(1 / *head))
    }

    let div = tail.iter().fold(*head, |div, n| div / *n);
    Ok(mem.integer(div))
}

fn product(args_: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    let args = try!(list_of_integers(args_));
    let product = args.iter().fold(1, |product, n| product * *n);

    Ok(mem.integer(product))
}

fn equals(args_: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args_.len() < 2 {
        return Ok(mem.b_true());
    }

    let args = try!(list_of_integers(args_));
    let head = args.head().unwrap();
    let outcome = args.iter().skip(1).all(|n| *n == *head);

    Ok(mem.boolean(outcome))
}

fn less_than(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    ord(args, mem, |a, b| a < b)
}

fn less_than_or_equal(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    ord(args, mem, |a, b| a <= b)
}

fn greater_than(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    ord(args, mem, |a, b| a > b)
}

fn greater_than_or_equal(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    ord(args, mem, |a, b| a >= b)
}

fn not(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("not".to_string())))
    }

    let outcome = match *args.head().unwrap() {
        &Value::Bool(false) => true,
        _                   => false,
    };

    Ok(mem.boolean(outcome))
}

fn list(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    let list = args.iter().map(|a| a.deref().clone()).collect();

    Ok(mem.list(list))
}

fn length(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("length".to_string())));
    }

    match args[0] {
        &Value::List(ref list) =>
            Ok(mem.integer(list.len() as i64)),
        value =>
            Err(Error::WrongArgumentType(value.clone())),
    }
}

fn pair(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("pair?".to_string())));
    }

    let outcome = if let &Value::List(ref list) = args[0] {
        !list.is_empty()
    } else if let &Value::DottedList(ref _list, ref _el) = args[0] {
        true
    } else {
        false
    };

    Ok(mem.boolean(outcome))
}

fn cons(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 2 {
        return Err(Error::BadArity(Some("cons".to_string())));
    }

    let mut list: Vec<Value> = Vec::new();

    if let &Value::List(ref l) = args[1] {
        list.push(args[0].clone());
        list.push_all(l.clone().as_slice());

        Ok(mem.list(list))
    } else {
        list.push(args[0].clone());
        Ok(mem.dotted_list(list, args[1].clone()))
    }
}

fn car(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("car".to_string())));
    }

    match args[0] {
        &Value::List(ref l) if !l.is_empty() =>
            Ok(mem.store(l.head().unwrap().clone())),
        &Value::DottedList(ref l, ref _t) =>
            Ok(mem.store(l.head().unwrap().clone())),
        value =>
            Err(Error::WrongArgumentType(value.clone())),
    }
}

fn cdr(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("cdr".to_string())));
    }

    match args[0] {
        &Value::List(ref l) if !l.is_empty() =>
            match l.tail() {
                tail if tail.is_empty() =>
                    Ok(mem.empty_list()),
                tail =>
                    Ok(mem.list(tail.to_vec())),
            },
        &Value::DottedList(ref _l, ref t) =>
            Ok(mem.store(*t.clone())),
        value =>
            Err(Error::WrongArgumentType(value.clone())),
    }
}

fn null(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("null?".to_string())));
    }

    let outcome = args[0] == mem.empty_list().deref();
    Ok(mem.boolean(outcome))
}

fn list_question_mark(args: Vec<&Value>, mem: &mut Memory) -> Result<Rc<Value>, Error> {
    if args.len() != 1 {
        return Err(Error::BadArity(Some("list?".to_string())));
    }

    let out = if let &Value::List(ref _l) = args[0] {
        true
    } else {
        false
    };

    Ok(mem.boolean(out))
}

fn list_of_integers(list: Vec<&Value>) -> Result<Vec<i64>, Error> {
    let mut integers = Vec::with_capacity(list.len());

    for val in list.iter() {
        match *val {
            &Value::Integer(n) =>
                integers.push(n),
            value =>
                return Err(Error::WrongArgumentType(value.clone())),
        }
    }

    Ok(integers)
}

fn ord(args_: Vec<&Value>, mem: &mut Memory, cmp: |i64, i64| -> bool) -> Result<Rc<Value>, Error> {
    if args_.len() < 2 {
        return Ok(mem.b_true())
    }

    let args = try!(list_of_integers(args_));
    let outcome = range(0, args.len() - 1).all(|i|
        cmp(args[i], args[i + 1u])
    );

    return Ok(mem.boolean(outcome))
}
<|endoftext|>


<commit_before>extern crate byteorder;

use std::io::Read;
use error::{Result, Error, ErrorKind};
use reader::FbxEvent;

mod macros;

#[derive(Clone, Copy, PartialEq, Eq)]
enum ParserMode {
    /// Reading magic binary (i.e. the first line)
    Magic,
    /// Reading binary FBX
    Binary,
    /// Reading ASCII FBX
    Ascii,
}

pub struct Parser {
    pos: u64,
    mode: ParserMode,
}

impl Parser {
    pub fn new() -> Self {
        Parser {
            pos: 0,
            mode: ParserMode::Magic,
        }
    }

    pub fn next<R: Read>(&mut self, reader: &mut R) -> Result<FbxEvent> {
        match self.mode {
            ParserMode::Magic => self.magic_next(reader),
            ParserMode::Binary => self.binary_next(reader),
            ParserMode::Ascii => self.ascii_next(reader),
        }
    }
    pub fn magic_next<R: Read>(&mut self, _reader: &mut R) -> Result<FbxEvent> {
        Err(Error::new(self.pos, ErrorKind::Unimplemented("Parser for magic binary is not implemented yet".to_string())))
    }

    pub fn binary_next<R: Read>(&mut self, _reader: &mut R) -> Result<FbxEvent> {
        Err(Error::new(self.pos, ErrorKind::Unimplemented("Parser for Binary FBX format is not implemented yet".to_string())))
    }

    pub fn ascii_next<R: Read>(&mut self, _reader: &mut R) -> Result<FbxEvent> {
        Err(Error::new(self.pos, ErrorKind::Unimplemented("Parser for ASCII FBX format is not implemented yet".to_string())))
    }
}
<commit_msg>Add code to parse FBX magic binary<commit_after>extern crate byteorder;

use std::io::Read;
use error::{Result, Error, ErrorKind};
use reader::{FbxEvent, FbxFormatType};

mod macros;

#[derive(Clone, Copy, PartialEq, Eq)]
enum ParserMode {
    /// Reading magic binary (i.e. the first line)
    Magic,
    /// Reading binary FBX
    Binary,
    /// Reading ASCII FBX
    Ascii,
}

pub struct Parser {
    pos: u64,
    mode: ParserMode,
    ascii_buffer: String,
}

impl Parser {
    pub fn new() -> Self {
        Parser {
            pos: 0,
            mode: ParserMode::Magic,
            ascii_buffer: String::new(),
        }
    }

    pub fn next<R: Read>(&mut self, reader: &mut R) -> Result<FbxEvent> {
        match self.mode {
            ParserMode::Magic => self.magic_next(reader),
            ParserMode::Binary => self.binary_next(reader),
            ParserMode::Ascii => self.ascii_next(reader),
        }
    }

    pub fn magic_next<R: Read>(&mut self, reader: &mut R) -> Result<FbxEvent> {
        // 20 is the length of `b"Kaydara FBX Binary  "`.
        let mut first_line_bytes = Vec::with_capacity(20);
        // First, read the first line.
        // Read the first line manually.
        let magic_end_byte;
        loop {
            let c = try_read_le_u8!(self.pos, reader);
            if (c == 0) || (c == ('\n' as u8)) {
                magic_end_byte = c;
                break;
            }
            first_line_bytes.push(c);
        }
        // In Binary FBX, magic binary is `"Kaydara FBX Binary  "`,
        // and in ASCII FBX, there is no magic and it should be treated as normal line.
        if magic_end_byte == 0 {
            // Binary FBX?
            if first_line_bytes == b"Kaydara FBX Binary  " {
                // Binary FBX!
                self.mode = ParserMode::Binary;
                // "unknown but all observed files show these bytes",
                // see https://code.blender.org/2013/08/fbx-binary-file-format-specification/ .
                {
                    let bytes = try_read_exact!(self.pos, reader, 2);
                    if bytes != vec![0x1A, 0x00] {
                        warn!("expected [0x1A, 0x00] right after magic, but got {:?}", bytes);
                    }
                }
                // Read FBX version.
                let version = try_read_le_u32!(self.pos, reader);
                debug!("magic binary read, Binary FBX (version={})", version);
                Ok(FbxEvent::StartFbx(FbxFormatType::Binary(version)))
            } else {
                Err(Error::new(self.pos, ErrorKind::InvalidMagic))
            }
        } else {
            assert_eq!(magic_end_byte, ('\n' as u8));
            // Maybe ASCII FBX
            self.mode = ParserMode::Ascii;
            if first_line_bytes[0] != (';' as u8) {
                // The line is not comment, so the parser should remember it to use next time.
                self.ascii_buffer = try_with_pos!(self.pos, String::from_utf8(first_line_bytes));
                self.ascii_buffer.push('\n');
            }
            Ok(FbxEvent::StartFbx(FbxFormatType::Text))
        }
    }

    pub fn binary_next<R: Read>(&mut self, _reader: &mut R) -> Result<FbxEvent> {
        Err(Error::new(self.pos, ErrorKind::Unimplemented("Parser for Binary FBX format is not implemented yet".to_string())))
    }

    pub fn ascii_next<R: Read>(&mut self, _reader: &mut R) -> Result<FbxEvent> {
        Err(Error::new(self.pos, ErrorKind::Unimplemented("Parser for ASCII FBX format is not implemented yet".to_string())))
    }
}
<|endoftext|>


<commit_before>use std::io::Read;
use error::{Result, Error, ErrorKind};
use reader::{FbxEvent, FbxFormatType};
use self::binary::BinaryParser;
use self::ascii::AsciiParser;

mod macros;
mod ascii;
mod binary;

#[derive(Debug, Clone)]
enum ParserState {
    /// Reading magic binary (i.e. the first line)
    Magic,
    /// Reading binary FBX
    Binary(BinaryParser),
    /// Reading ASCII FBX
    Ascii(AsciiParser),
}

#[derive(Debug, Clone)]
struct CommonState {
    pos: u64,
}

pub struct Parser {
    common: CommonState,
    state: ParserState,
}

impl Parser {
    pub fn new() -> Self {
        Parser {
            common: CommonState {
                pos: 0,
            },
            state: ParserState::Magic,
        }
    }

    pub fn next<R: Read>(&mut self, reader: &mut R) -> Result<FbxEvent> {
        match self.state {
            ParserState::Magic => self.magic_next(reader),
            ParserState::Binary(ref mut parser) => parser.next(reader, &mut self.common),
            ParserState::Ascii(ref mut parser) => parser.next(reader, &mut self.common),
        }
    }

    fn magic_next<R: Read>(&mut self, reader: &mut R) -> Result<FbxEvent> {
        // 20 is the length of `b"Kaydara FBX Binary  "`.
        let mut first_line_bytes = Vec::with_capacity(20);
        // First, read the first line.
        // Read the first line manually.
        let magic_end_byte;
        loop {
            let c = try_read_le_u8!(self.common.pos, reader);
            if (c == 0) || (c == ('\n' as u8)) {
                magic_end_byte = c;
                break;
            }
            first_line_bytes.push(c);
        }
        // In Binary FBX, magic binary is `"Kaydara FBX Binary  "`,
        // and in ASCII FBX, there is no magic and it should be treated as normal line.
        if magic_end_byte == 0 {
            // Binary FBX?
            if first_line_bytes == b"Kaydara FBX Binary  " {
                // Binary FBX!
                // "unknown but all observed files show these bytes",
                // see https://code.blender.org/2013/08/fbx-binary-file-format-specification/ .
                {
                    let bytes = try_read_exact!(self.common.pos, reader, 2);
                    if bytes != vec![0x1A, 0x00] {
                        warn!("expected [0x1A, 0x00] right after magic, but got {:?}", bytes);
                    }
                }
                // Read FBX version.
                let version = try_read_le_u32!(self.common.pos, reader);
                debug!("magic binary read, Binary FBX (version={})", version);
                self.state = ParserState::Binary(BinaryParser::new(version));
                Ok(FbxEvent::StartFbx(FbxFormatType::Binary(version)))
            } else {
                Err(Error::new(self.common.pos, ErrorKind::InvalidMagic))
            }
        } else {
            assert_eq!(magic_end_byte, ('\n' as u8));
            // Maybe ASCII FBX
            let mut buffer;
            if first_line_bytes[0] != (';' as u8) {
                // The line is not comment, so the parser should remember it to use next time.
                buffer = try_with_pos!(self.common.pos, String::from_utf8(first_line_bytes));
                buffer.push('\n');
            } else {
                buffer = String::new();
            }
            self.state = ParserState::Ascii(AsciiParser::new(buffer));
            Ok(FbxEvent::StartFbx(FbxFormatType::Text))
        }
    }
}
<commit_msg>Add a type for a property of FBX node<commit_after>use std::io::Read;
use error::{Result, Error, ErrorKind};
use reader::{FbxEvent, FbxFormatType};
use self::binary::BinaryParser;
use self::ascii::AsciiParser;

mod macros;
mod ascii;
mod binary;

#[derive(Debug, Clone)]
enum ParserState {
    /// Reading magic binary (i.e. the first line)
    Magic,
    /// Reading binary FBX
    Binary(BinaryParser),
    /// Reading ASCII FBX
    Ascii(AsciiParser),
}

#[derive(Debug, Clone)]
struct CommonState {
    pos: u64,
}

pub struct Parser {
    common: CommonState,
    state: ParserState,
}

impl Parser {
    pub fn new() -> Self {
        Parser {
            common: CommonState {
                pos: 0,
            },
            state: ParserState::Magic,
        }
    }

    pub fn next<R: Read>(&mut self, reader: &mut R) -> Result<FbxEvent> {
        match self.state {
            ParserState::Magic => self.magic_next(reader),
            ParserState::Binary(ref mut parser) => parser.next(reader, &mut self.common),
            ParserState::Ascii(ref mut parser) => parser.next(reader, &mut self.common),
        }
    }

    fn magic_next<R: Read>(&mut self, reader: &mut R) -> Result<FbxEvent> {
        // 20 is the length of `b"Kaydara FBX Binary  "`.
        let mut first_line_bytes = Vec::with_capacity(20);
        // First, read the first line.
        // Read the first line manually.
        let magic_end_byte;
        loop {
            let c = try_read_le_u8!(self.common.pos, reader);
            if (c == 0) || (c == ('\n' as u8)) {
                magic_end_byte = c;
                break;
            }
            first_line_bytes.push(c);
        }
        // In Binary FBX, magic binary is `"Kaydara FBX Binary  "`,
        // and in ASCII FBX, there is no magic and it should be treated as normal line.
        if magic_end_byte == 0 {
            // Binary FBX?
            if first_line_bytes == b"Kaydara FBX Binary  " {
                // Binary FBX!
                // "unknown but all observed files show these bytes",
                // see https://code.blender.org/2013/08/fbx-binary-file-format-specification/ .
                {
                    let bytes = try_read_exact!(self.common.pos, reader, 2);
                    if bytes != vec![0x1A, 0x00] {
                        warn!("expected [0x1A, 0x00] right after magic, but got {:?}", bytes);
                    }
                }
                // Read FBX version.
                let version = try_read_le_u32!(self.common.pos, reader);
                debug!("magic binary read, Binary FBX (version={})", version);
                self.state = ParserState::Binary(BinaryParser::new(version));
                Ok(FbxEvent::StartFbx(FbxFormatType::Binary(version)))
            } else {
                Err(Error::new(self.common.pos, ErrorKind::InvalidMagic))
            }
        } else {
            assert_eq!(magic_end_byte, ('\n' as u8));
            // Maybe ASCII FBX
            let mut buffer;
            if first_line_bytes[0] != (';' as u8) {
                // The line is not comment, so the parser should remember it to use next time.
                buffer = try_with_pos!(self.common.pos, String::from_utf8(first_line_bytes));
                buffer.push('\n');
            } else {
                buffer = String::new();
            }
            self.state = ParserState::Ascii(AsciiParser::new(buffer));
            Ok(FbxEvent::StartFbx(FbxFormatType::Text))
        }
    }
}

/// A property type of the FBX node.
#[derive(Debug, Clone, PartialEq)]
pub enum PropertyValue {
    /// Boolean.
    Bool(bool),
    /// 2 byte signed integer.
    I16(i16),
    /// 4 byte signed integer.
    I32(i32),
    /// 8 byte signed integer.
    I64(i64),
    /// 4 byte single-precision IEEE 754 number.
    F32(f32),
    /// 8 byte double-precision IEEE 754 number.
    F64(f64),
    /// Array of boolean.
    VecBool(Vec<bool>),
    /// Array of 4 byte signed integer.
    VecI32(Vec<i32>),
    /// Array of 8 byte signed integer.
    VecI64(Vec<i64>),
    /// Array of 4 byte single-precision IEEE 754 number.
    VecF32(Vec<f32>),
    /// Array of 8 byte double-precision IEEE 754 number.
    VecF64(Vec<f64>),
    /// String.
    String(String),
    /// Raw binary data.
    Binary(Vec<u8>),
}
<|endoftext|>


<commit_before>
use {Field, Borrowed, Value};
use vecmath::{relative_rectangle, margin_rectangle,
rotate_radians, multiply, translate, scale, shear, identity};
use {Transform2d, Matrix2d, Rectangle};
use {RectangleColorContext};
use {AddColor, AddRound, View};
use {RelativeRectangle};
use {RoundRectangleContext};

/// A rectangle context.
pub struct RectangleContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
}

impl<'a> Transform2d<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn trans_local(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(self.transform.get(), &trans))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad_local(&'a self, angle: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(self.transform.get(), &rot))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale_local(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(self.transform.get(), &scale))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear_local(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(self.transform.get(), &shear))
            },
            rect: Borrowed(self.rect.get()),
        }
    }
}

impl<'a> AddColor<'a, RectangleColorContext<'a>> for RectangleContext<'a> {
    /// Creates a RectangleColorContext.
    #[inline(always)]
    fn rgba(&'a self, r: f32, g: f32, b: f32, a: f32) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value([r, g, b, a]),
            rect: Borrowed(self.rect.get()),
        }
    }
}

#[test]
fn test_rgba() {
    use {Context, AddRectangle};

    let c = Context::new();
    let d = c.rect(0.0, 0.0, 100.0, 100.0);
    let e = d.rgba(1.0, 0.0, 0.0, 1.0);
    assert_eq!(e.color.get()[0], 1.0);
}

impl<'a> RelativeRectangle<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn margin(&'a self, m: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value(margin_rectangle(self.rect.get(), m)),
        }
    }

    #[inline(always)]
    fn rel(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value(relative_rectangle(self.rect.get(), x, y)),
        }
    }
}

impl<'a> AddRound<'a, RoundRectangleContext<'a>> for RectangleContext<'a> {
    #[inline(always)]
    fn round(&'a self, radius: f64) -> RoundRectangleContext<'a> {
        RoundRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            round_rect: {
                let rect = self.rect.get();
                Value([rect[0], rect[1], rect[2], rect[3], radius])
            },
        }
    }
}

impl<'a> View<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
        }
    }
}

<commit_msg>Implemented `AddImage` for `RectangleContext`<commit_after>
use {Field, Borrowed, Value};
use vecmath::{relative_rectangle, margin_rectangle,
rotate_radians, multiply, translate, scale, shear, identity};
use {Transform2d, Matrix2d, Rectangle, Image};
use {RectangleColorContext};
use {AddColor, AddRound, View, AddImage};
use {RelativeRectangle};
use {RoundRectangleContext, ImageRectangleContext};

/// A rectangle context.
pub struct RectangleContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
}

impl<'a> Transform2d<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn trans_local(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(self.transform.get(), &trans))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad_local(&'a self, angle: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(self.transform.get(), &rot))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale_local(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(self.transform.get(), &scale))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear_local(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(self.transform.get(), &shear))
            },
            rect: Borrowed(self.rect.get()),
        }
    }
}

impl<'a> AddColor<'a, RectangleColorContext<'a>> for RectangleContext<'a> {
    /// Creates a RectangleColorContext.
    #[inline(always)]
    fn rgba(&'a self, r: f32, g: f32, b: f32, a: f32) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value([r, g, b, a]),
            rect: Borrowed(self.rect.get()),
        }
    }
}

#[test]
fn test_rgba() {
    use {Context, AddRectangle};

    let c = Context::new();
    let d = c.rect(0.0, 0.0, 100.0, 100.0);
    let e = d.rgba(1.0, 0.0, 0.0, 1.0);
    assert_eq!(e.color.get()[0], 1.0);
}

impl<'a> RelativeRectangle<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn margin(&'a self, m: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value(margin_rectangle(self.rect.get(), m)),
        }
    }

    #[inline(always)]
    fn rel(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value(relative_rectangle(self.rect.get(), x, y)),
        }
    }
}

impl<'a> AddRound<'a, RoundRectangleContext<'a>> for RectangleContext<'a> {
    #[inline(always)]
    fn round(&'a self, radius: f64) -> RoundRectangleContext<'a> {
        RoundRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            round_rect: {
                let rect = self.rect.get();
                Value([rect[0], rect[1], rect[2], rect[3], radius])
            },
        }
    }
}

impl<'a> View<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
        }
    }
}

impl<'a> AddImage<'a, ImageRectangleContext<'a>> for RectangleContext<'a> {
    fn image(&'a self, image: Image) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
            image: Value(image),
        }
    }
}

<|endoftext|>


<commit_before>extern crate "rust-crypto" as rust_crypto;
extern crate serialize;

use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::{File, BufferedStream};
use std::string::String;
use std::os;

use rust_crypto::sha1::Sha1;
use rust_crypto::digest::Digest;
use serialize::base64::{ToBase64, STANDARD};

use std::io::Timer;
use std::io::timer;
use std::time::duration::Duration;

pub const CR: u8 = b'\r';
pub const LF: u8 = b'\n';
pub const SP: u8 = b' ';
pub const COLON: u8 = b':';
pub const CRLF: &'static [u8] = &[CR,LF];

struct RequestedRoute {
    method: String,
    pathname: String
}

struct ClientHeader {
    key: String,
    value: String
}

enum Payload {
    Text(String),
    Binary(Vec<u8>),
    Empty
}

enum Opcode {
    EmptyOp = 0x0,
    TextOp = 0x1,
    BinaryOp = 0x2,
    CloseOp = 0x8,
}

struct Message {
    payload: Payload,
    opcode: Opcode,
    fin: u8
 }

impl Message {

    fn from_payload (payload: Payload, fin: u8) -> Message {
        let opcode: Opcode = match payload {
            Payload::Text(_) => Opcode::TextOp,
            Payload::Binary(_) => Opcode::BinaryOp,
            Payload::Empty => Opcode::EmptyOp
        };
        return Message {payload: payload, opcode: opcode, fin: fin};
    }

    fn continue_from_payload (payload: Payload) -> Message {
        let opcode = Opcode::EmptyOp;
        let fin = 0x0;
        return Message {payload: payload, opcode: opcode, fin: fin};
    }

    fn send (&self,
            mut stream: &mut BufferedStream<TcpStream>) {
        let msg = match self.payload {
            Payload::Text(ref s) => s.as_bytes(),
            Payload::Binary(ref s) => s.as_slice(),
            Payload::Empty => "".as_bytes(),
        };

        let length = msg.len() as u8;

        println!("fin: {}, msg: {}, opcode: {}", self.fin, msg, self.opcode as u8);

        stream.write_u8(self.fin | self.opcode as u8).unwrap();
        stream.write_u8(length).unwrap();
        stream.write(msg).unwrap();
        stream.flush();
    }
}

fn get_header_by_name (header: &[u8], headers: &Vec<ClientHeader>) -> String {
    let mut result = String::new();

    for h in headers.iter() {
        if h.key.as_bytes() == header {
            result = h.value.clone();
            break;
        }
    }

    return result;
}

fn parse_request_line (header: &str) -> RequestedRoute {
    let mut pathname = String::new();
    let mut method = String::new();
    let mut starting = true;
    let mut found_method = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];

        if starting && cbyte != SP {
            method.push_str(ch);
        }
        if starting && cbyte == SP {
            starting = false;
            found_method = true;
            continue;
        }
        if found_method && cbyte != SP {
            pathname.push_str(ch);
        }
        if found_method && cbyte == SP {
            break;
        }

    }

    return RequestedRoute {method: method, pathname: pathname};
}

fn parse_normal_header (header: &str) -> ClientHeader {
    let mut lhs = String::new(); // lhs of ':' in header
    let mut rhs = String::new(); // rhs of ':' in header
    let mut found_colon = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];
        if !found_colon && cbyte == COLON {
            found_colon = true;
            continue;
        }

        if cbyte == CR || cbyte == LF {
            continue;
        }

        if !found_colon {
            lhs.push_str(ch);
        } else {
            rhs.push_str(ch);
        }
    }

    return ClientHeader {
        key:lhs.trim().to_string(),
        value:rhs.trim().to_string()
    };
}

fn get_normal_body (path_on_disk: &str) -> String {
    let path = Path::new(path_on_disk);
    let display = path.display();
    let mut file = match File::open(&path) {
        Ok(f) => f,
        Err(err) => panic!("file error: {}", err)
    };

    let content = match file.read_to_end() {
        Ok(c) => c,
        Err(err) => panic!("{}", err)
    };

    let s = String::from_utf8(content).unwrap();
    return s;
}

fn sec_handshake (from_server: &[u8]) -> String {

    // from rfc6455 [page 6]
    let guid = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

    let mut sha = Sha1::new();

    sha.input(from_server);
    sha.input(guid);
    let mut out = [0u8, ..20];
    sha.result(out.as_mut_slice());

    return out.to_base64(STANDARD);
}

fn ws_handshake (mut stream: BufferedStream<TcpStream>,
                 headers: Vec<ClientHeader>) {

    let header_sec_key = b"Sec-WebSocket-Key";

    let from_server = get_header_by_name(header_sec_key, &headers);
    let accept = sec_handshake(from_server.as_bytes());

    let sec_header = format!("Sec-WebSocket-Accept: {}\r\n", accept);

    stream.write(b"HTTP/1.1 101 Switching Protocols\r\n").unwrap();
    stream.write(b"Upgrade: websocket\r\n").unwrap();
    stream.write(b"Connection: Upgrade\r\n").unwrap();
    stream.write(b"Sec-WebSocket-Version: 13\r\n").unwrap();
    stream.write(b"Sec-WebSocket-Protocol: protocolOne\r\n").unwrap();
    stream.write(sec_header.as_bytes()).unwrap();
    stream.write(b"\r\n");

    ws_listen(stream, headers);
}

fn ws_listen(mut stream: BufferedStream<TcpStream>,
             mut headers: Vec<ClientHeader>) {

    let payload = Payload::Text("text ".to_string());
    let msg = Message::from_payload(payload, 0b0000_0000);
    msg.send(&mut stream);

    let payload = Payload::Text("here".to_string());
    let msg = Message::continue_from_payload(payload);
    let mut stream2 = stream;
    msg.send(&mut stream2);

    let payload = Payload::Empty;
    let msg = Message::from_payload(payload, 0b1000_0000);
    let mut stream3 = stream2;
    msg.send(&mut stream3);

    let mut timer = Timer::new().unwrap();
    let interval = Duration::milliseconds(5000);
    timer::sleep(interval);

    let mut stream4 = stream3;
    let mut buf = [0, ..100];
    match stream4.read(&mut buf) {
        Ok(nread) => println!("Read {} bytes", nread),
        Err(e) => println!("error reading: {}", e)
    }

    println!("buf {}", buf.as_slice());

}

fn main () {

    for argument in os::args().iter() {
        println!("arg: {}", argument);
    }

    let addr = "127.0.0.1:8099";

    let listener = TcpListener::bind(addr).unwrap();
    let mut acceptor = listener.listen().unwrap();
    println!("Listening on {}", addr);

    fn handle_client(mut stream: BufferedStream<TcpStream>) {
        let mut body: String = "
You sent it!
".to_string();

        let mut cur_line: String;
        let mut ii = 0u;
        let mut req: RequestedRoute = RequestedRoute {
            pathname: String::new(),
            method: String::new()
        };

        let mut headers: Vec<ClientHeader> = Vec::new();
        loop {
            match stream.read_line() { // XXX: strange unwrap like thing
                Ok(line) => cur_line = line,
                Err(_) => break
            }

            body = body + cur_line + "
";
            if cur_line.as_bytes() == CRLF {
                break;
            }

            if ii == 0u { // the Request-Line is always the first line
                req = parse_request_line(cur_line.as_slice());
                println!("{}", req.pathname);
                ii += 1;
            } else { // this should be  "normal" key-value type header
                headers.push(parse_normal_header(cur_line.as_slice()));
            }

        }

        println!("pathname {} method {}", req.pathname, req.method);

        if req.pathname.as_bytes() == b"/" {
            body = get_normal_body("./html/ws1.html");
        } else if req.pathname.as_bytes() == b"/ws1.js" {
            body = get_normal_body("./html/ws1.js");
        } else if req.pathname.as_bytes() == b"/ws" {
            ws_handshake(stream, headers);
            return;
        }

        let body_length = format!("Content-length: {}", body.len());

        stream.write(b"HTTP/1.1 200 OK\r\n").unwrap();
        stream.write(b"Content-type: text/html\r\n").unwrap();
        stream.write(b"X-header: from bytes\r\n").unwrap();
        stream.write(body_length.as_bytes()).unwrap();
        stream.write(b"\r\n\r\n").unwrap();
        stream.write(body.as_bytes()).unwrap();
        stream.flush().unwrap();

        println!("Done handling acceptor");
    }

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("connection failed: {}", e) }
            Ok(stream) => spawn(proc() {
                let bs = BufferedStream::new(stream);
                handle_client(bs)
            })
        }
    }

    drop(acceptor);
}
<commit_msg>start with from_buffer<commit_after>extern crate "rust-crypto" as rust_crypto;
extern crate serialize;

use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::{File, BufferedStream};
use std::string::String;
use std::os;
use std::vec::Vec;

use rust_crypto::sha1::Sha1;
use rust_crypto::digest::Digest;
use serialize::base64::{ToBase64, STANDARD};

use std::io::Timer;
use std::io::timer;
use std::time::duration::Duration;

pub const CR: u8 = b'\r';
pub const LF: u8 = b'\n';
pub const SP: u8 = b' ';
pub const COLON: u8 = b':';
pub const CRLF: &'static [u8] = &[CR,LF];

struct RequestedRoute {
    method: String,
    pathname: String
}

struct ClientHeader {
    key: String,
    value: String
}

enum Payload {
    Text(String),
    Binary(Vec<u8>),
    Empty
}

enum Opcode {
    EmptyOp = 0x0,
    TextOp = 0x1,
    BinaryOp = 0x2,
    CloseOp = 0x8,
}

struct Message {
    payload: Payload,
    opcode: Opcode,
    fin: u8
 }

impl Message {

    fn from_payload (payload: Payload, fin: u8) -> Message {
        let opcode: Opcode = match payload {
            Payload::Text(_) => Opcode::TextOp,
            Payload::Binary(_) => Opcode::BinaryOp,
            Payload::Empty => Opcode::EmptyOp
        };
        return Message {payload: payload, opcode: opcode, fin: fin};
    }

    fn continue_from_payload (payload: Payload) -> Message {
        let opcode = Opcode::EmptyOp;
        let fin = 0x0;
        return Message {payload: payload, opcode: opcode, fin: fin};
    }

    fn send (&self,
            mut stream: &mut BufferedStream<TcpStream>) {
        let msg = match self.payload {
            Payload::Text(ref s) => s.as_bytes(),
            Payload::Binary(ref s) => s.as_slice(),
            Payload::Empty => "".as_bytes(),
        };

        let length = msg.len() as u8;

        println!("fin: {}, msg: {}, opcode: {}", self.fin, msg, self.opcode as u8);

        stream.write_u8(self.fin | self.opcode as u8).unwrap();
        stream.write_u8(length).unwrap();
        stream.write(msg).unwrap();
        stream.flush();
    }

    fn from_buffer (buf: &[u8]) {
        let fin = buf[0] & 0b1000_0000;
        let rsv = buf.slice(1, 4);

        println!("fin {}, rsv {}, buf {}", fin, rsv, buf.as_slice());
    }

    fn continue_from_buffer(buf: &[u8]) {

    }
}

fn get_header_by_name (header: &[u8], headers: &Vec<ClientHeader>) -> String {
    let mut result = String::new();

    for h in headers.iter() {
        if h.key.as_bytes() == header {
            result = h.value.clone();
            break;
        }
    }

    return result;
}

fn parse_request_line (header: &str) -> RequestedRoute {
    let mut pathname = String::new();
    let mut method = String::new();
    let mut starting = true;
    let mut found_method = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];

        if starting && cbyte != SP {
            method.push_str(ch);
        }
        if starting && cbyte == SP {
            starting = false;
            found_method = true;
            continue;
        }
        if found_method && cbyte != SP {
            pathname.push_str(ch);
        }
        if found_method && cbyte == SP {
            break;
        }

    }

    return RequestedRoute {method: method, pathname: pathname};
}

fn parse_normal_header (header: &str) -> ClientHeader {
    let mut lhs = String::new(); // lhs of ':' in header
    let mut rhs = String::new(); // rhs of ':' in header
    let mut found_colon = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];
        if !found_colon && cbyte == COLON {
            found_colon = true;
            continue;
        }

        if cbyte == CR || cbyte == LF {
            continue;
        }

        if !found_colon {
            lhs.push_str(ch);
        } else {
            rhs.push_str(ch);
        }
    }

    return ClientHeader {
        key:lhs.trim().to_string(),
        value:rhs.trim().to_string()
    };
}

fn get_normal_body (path_on_disk: &str) -> String {
    let path = Path::new(path_on_disk);
    let display = path.display();
    let mut file = match File::open(&path) {
        Ok(f) => f,
        Err(err) => panic!("file error: {}", err)
    };

    let content = match file.read_to_end() {
        Ok(c) => c,
        Err(err) => panic!("{}", err)
    };

    let s = String::from_utf8(content).unwrap();
    return s;
}

fn sec_handshake (from_server: &[u8]) -> String {

    // from rfc6455 [page 6]
    let guid = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

    let mut sha = Sha1::new();

    sha.input(from_server);
    sha.input(guid);
    let mut out = [0u8, ..20];
    sha.result(out.as_mut_slice());

    return out.to_base64(STANDARD);
}

fn ws_handshake (mut stream: BufferedStream<TcpStream>,
                 headers: Vec<ClientHeader>) {

    let header_sec_key = b"Sec-WebSocket-Key";

    let from_server = get_header_by_name(header_sec_key, &headers);
    let accept = sec_handshake(from_server.as_bytes());

    let sec_header = format!("Sec-WebSocket-Accept: {}\r\n", accept);

    stream.write(b"HTTP/1.1 101 Switching Protocols\r\n").unwrap();
    stream.write(b"Upgrade: websocket\r\n").unwrap();
    stream.write(b"Connection: Upgrade\r\n").unwrap();
    stream.write(b"Sec-WebSocket-Version: 13\r\n").unwrap();
    stream.write(b"Sec-WebSocket-Protocol: protocolOne\r\n").unwrap();
    stream.write(sec_header.as_bytes()).unwrap();
    stream.write(b"\r\n");

    ws_listen(stream, headers);
}

fn ws_listen(mut stream: BufferedStream<TcpStream>,
             mut headers: Vec<ClientHeader>) {

    let payload = Payload::Text("text ".to_string());
    let msg = Message::from_payload(payload, 0b0000_0000);
    msg.send(&mut stream);

    let payload = Payload::Text("here".to_string());
    let msg = Message::continue_from_payload(payload);
    let mut stream2 = stream;
    msg.send(&mut stream2);

    let payload = Payload::Empty;
    let msg = Message::from_payload(payload, 0b1000_0000);
    let mut stream3 = stream2;
    msg.send(&mut stream3);

    let mut timer = Timer::new().unwrap();
    let interval = Duration::milliseconds(5000);
    timer::sleep(interval);

    let mut stream4 = stream3;
    let mut buf = [0, ..100];
    match stream4.read(&mut buf) {
        Ok(nread) => println!("Read {} bytes", nread),
        Err(e) => println!("error reading: {}", e)
    }

    Message::from_buffer(&buf);

}

fn main () {

    for argument in os::args().iter() {
        println!("arg: {}", argument);
    }

    let addr = "127.0.0.1:8099";

    let listener = TcpListener::bind(addr).unwrap();
    let mut acceptor = listener.listen().unwrap();
    println!("Listening on {}", addr);

    fn handle_client(mut stream: BufferedStream<TcpStream>) {
        let mut body: String = "
You sent it!
".to_string();

        let mut cur_line: String;
        let mut ii = 0u;
        let mut req: RequestedRoute = RequestedRoute {
            pathname: String::new(),
            method: String::new()
        };

        let mut headers: Vec<ClientHeader> = Vec::new();
        loop {
            match stream.read_line() { // XXX: strange unwrap like thing
                Ok(line) => cur_line = line,
                Err(_) => break
            }

            body = body + cur_line + "
";
            if cur_line.as_bytes() == CRLF {
                break;
            }

            if ii == 0u { // the Request-Line is always the first line
                req = parse_request_line(cur_line.as_slice());
                println!("{}", req.pathname);
                ii += 1;
            } else { // this should be  "normal" key-value type header
                headers.push(parse_normal_header(cur_line.as_slice()));
            }

        }

        println!("pathname {} method {}", req.pathname, req.method);

        if req.pathname.as_bytes() == b"/" {
            body = get_normal_body("./html/ws1.html");
        } else if req.pathname.as_bytes() == b"/ws1.js" {
            body = get_normal_body("./html/ws1.js");
        } else if req.pathname.as_bytes() == b"/ws" {
            ws_handshake(stream, headers);
            return;
        }

        let body_length = format!("Content-length: {}", body.len());

        stream.write(b"HTTP/1.1 200 OK\r\n").unwrap();
        stream.write(b"Content-type: text/html\r\n").unwrap();
        stream.write(b"X-header: from bytes\r\n").unwrap();
        stream.write(body_length.as_bytes()).unwrap();
        stream.write(b"\r\n\r\n").unwrap();
        stream.write(body.as_bytes()).unwrap();
        stream.flush().unwrap();

        println!("Done handling acceptor");
    }

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("connection failed: {}", e) }
            Ok(stream) => spawn(proc() {
                let bs = BufferedStream::new(stream);
                handle_client(bs)
            })
        }
    }

    drop(acceptor);
}
<|endoftext|>


<commit_before>use na::{DefaultAllocator, Dim, VectorN, U1, U2, U3};
use na::allocator::Allocator;
use domain::NPoint;

/// A kd tree
pub struct KdTree<N : Dim>(Box<kd_tree::KdTreeImpl<N>>) where DefaultAllocator: Allocator<f64, N>;

impl<N : Dim> KdTree<N> where DefaultAllocator: Allocator<f64, N> {
    /// Get all the points from the kd-tree
    fn get_points(self) -> Vec<Box<NPoint<N>>>  {
        let mut pts = Vec::new();
        let KdTree(tree) = self;
        kd_tree::add_points_to_vector(tree, &mut pts);
        pts
    }

    fn build<TItem : NPoint<N> + Copy + 'static>(pts : &Vec<TItem>) -> Self where DefaultAllocator: Allocator<f64, N> {
        KdTree(Box::new(kd_tree::build(pts, 0)))
    }
}

mod kd_tree {
    use na::{DefaultAllocator, Dim, Vector3, VectorN, U1, U2, U3};
    use na::allocator::Allocator;
    use std::cmp::Ordering;
    use domain::NPoint;
    use super::{KdTree};

    /// kd-Tree implementation structure
    pub(super) enum KdTreeImpl<N : Dim> where DefaultAllocator: Allocator<f64, N> {
        Node(usize, Box<KdTreeImpl<N>>, Box<NPoint<N>>, Box<KdTreeImpl<N>>),
        Empty()
    }

    /// mutably enunerate points from a kd tree into a vector
    pub(super) fn add_points_to_vector<N : Dim>(tree : Box<KdTreeImpl<N>>, pts : &mut Vec<Box<NPoint<N>>>) where DefaultAllocator: Allocator<f64, N> {
        let unboxed_tree = *tree;
        match unboxed_tree {
            KdTreeImpl::Node(_, l, pt, r) => {
                add_points_to_vector(l, pts);
                pts.push(pt);
                add_points_to_vector(r, pts);
            },
            KdTreeImpl::Empty() => {}
        }
    }

    fn split_vec_with_median<N : Dim, TItem : NPoint<N> + Copy + 'static>(pts : &Vec<TItem>, dim_count :usize) -> (Option<Vec<TItem>>, Option<TItem>, Option<Vec<TItem>>) where DefaultAllocator: Allocator<f64, N> {
        unsafe {
            let mut pts = pts.to_vec();
            pts.sort_by( |a,b| a.from_origin().get_unchecked(0, dim_count).partial_cmp(b.from_origin().get_unchecked(0, dim_count)).unwrap() );
            if pts.len() >= 3 {
                let length = pts.len();
                let mut middle = pts.split_off(length / 2);
                let right = middle.split_off(1);
                (Some(pts), Some(middle[0]), Some(right))
            } else if pts.len() == 2 {
                let length = pts.len();
                let mut middle = pts.split_off(1);
                (Some(pts), Some(middle[0]), None)
            } else if pts.len() == 1 {
                (None, Some(pts[0]), None)
            } else{
                (None, None, None)
            }
        }
    }

    pub(super) fn build<N : Dim, TItem : NPoint<N> + Copy + 'static>(pts : &Vec<TItem>, dimIdx :usize) -> KdTreeImpl<N> where DefaultAllocator: Allocator<f64, N> {
        match pts.first() {
            Some(firstPt) => {
                let nextDimIdx = if dimIdx + 1 >= firstPt.from_origin().ncols() {0} else {dimIdx + 1};
                match split_vec_with_median(pts, dimIdx) {
                    (Some(vec1), Some(pt), Some(vec2))  => KdTreeImpl::Node(nextDimIdx,     Box::new(build(&vec1, nextDimIdx)),   Box::new(pt),     Box::new(build(&vec2, nextDimIdx))),
                    (Some(vec1), Some(pt), None      )  => KdTreeImpl::Node(nextDimIdx,     Box::new(build(&vec1, nextDimIdx)),   Box::new(pt),     Box::new(KdTreeImpl::Empty())),
                    (None,       Some(pt), Some(vec2))  => KdTreeImpl::Node(nextDimIdx,     Box::new(KdTreeImpl::Empty()),        Box::new(pt),     Box::new(build(&vec2, nextDimIdx))),
                    (None,       Some(pt), None      )  => KdTreeImpl::Node(nextDimIdx,     Box::new(KdTreeImpl::Empty()),        Box::new(pt),     Box::new(KdTreeImpl::Empty())),
                    (None,       None,     None      )  => panic!("Should be impossible to have a first point but still split into (None, None, None)."),
                    (_      ,    None,     _         )  => panic!("Meaningless result: point must be contained in a kd-tree node.")
                }
            }
            None => {
                KdTreeImpl::Empty()
            }
        }
    }
}
<commit_msg>fixed naming conventions<commit_after>use na::{DefaultAllocator, Dim, VectorN, U1, U2, U3};
use na::allocator::Allocator;
use domain::NPoint;

/// A kd tree
pub struct KdTree<N : Dim>(Box<kd_tree::KdTreeImpl<N>>) where DefaultAllocator: Allocator<f64, N>;

impl<N : Dim> KdTree<N> where DefaultAllocator: Allocator<f64, N> {
    /// Get all the points from the kd-tree
    fn get_points(self) -> Vec<Box<NPoint<N>>>  {
        let mut pts = Vec::new();
        let KdTree(tree) = self;
        kd_tree::add_points_to_vector(tree, &mut pts);
        pts
    }

    fn build<TItem : NPoint<N> + Copy + 'static>(pts : &Vec<TItem>) -> Self where DefaultAllocator: Allocator<f64, N> {
        KdTree(Box::new(kd_tree::build(pts, 0)))
    }
}

mod kd_tree {
    use na::{DefaultAllocator, Dim, Vector3, VectorN, U1, U2, U3};
    use na::allocator::Allocator;
    use std::cmp::Ordering;
    use domain::NPoint;
    use super::{KdTree};

    /// kd-Tree implementation structure
    pub(super) enum KdTreeImpl<N : Dim> where DefaultAllocator: Allocator<f64, N> {
        Node(usize, Box<KdTreeImpl<N>>, Box<NPoint<N>>, Box<KdTreeImpl<N>>),
        Empty()
    }

    /// mutably enunerate points from a kd tree into a vector
    pub(super) fn add_points_to_vector<N : Dim>(tree : Box<KdTreeImpl<N>>, pts : &mut Vec<Box<NPoint<N>>>) where DefaultAllocator: Allocator<f64, N> {
        let unboxed_tree = *tree;
        match unboxed_tree {
            KdTreeImpl::Node(_, l, pt, r) => {
                add_points_to_vector(l, pts);
                pts.push(pt);
                add_points_to_vector(r, pts);
            },
            KdTreeImpl::Empty() => {}
        }
    }

    fn split_vec_with_median<N : Dim, TItem : NPoint<N> + Copy + 'static>(pts : &Vec<TItem>, dim_idx :usize) -> (Option<Vec<TItem>>, Option<TItem>, Option<Vec<TItem>>) where DefaultAllocator: Allocator<f64, N> {
        unsafe {
            let mut pts = pts.to_vec();
            pts.sort_by( |a,b| a.from_origin().get_unchecked(0, dim_idx).partial_cmp(b.from_origin().get_unchecked(0, dim_idx)).unwrap() );
            if pts.len() >= 3 {
                let length = pts.len();
                let mut middle = pts.split_off(length / 2);
                let right = middle.split_off(1);
                (Some(pts), Some(middle[0]), Some(right))
            } else if pts.len() == 2 {
                let length = pts.len();
                let mut middle = pts.split_off(1);
                (Some(pts), Some(middle[0]), None)
            } else if pts.len() == 1 {
                (None, Some(pts[0]), None)
            } else{
                (None, None, None)
            }
        }
    }

    pub(super) fn build<N : Dim, TItem : NPoint<N> + Copy + 'static>(pts : &Vec<TItem>, dimIdx :usize) -> KdTreeImpl<N> where DefaultAllocator: Allocator<f64, N> {
        match pts.first() {
            Some(first_pt) => {
                let next_dim_idx = if dimIdx + 1 >= first_pt.from_origin().ncols() {0} else {dimIdx + 1};
                match split_vec_with_median(pts, dimIdx) {
                    (Some(vec1), Some(pt), Some(vec2))  => KdTreeImpl::Node(next_dim_idx,     Box::new(build(&vec1, next_dim_idx)),   Box::new(pt),     Box::new(build(&vec2, next_dim_idx))),
                    (Some(vec1), Some(pt), None      )  => KdTreeImpl::Node(next_dim_idx,     Box::new(build(&vec1, next_dim_idx)),   Box::new(pt),     Box::new(KdTreeImpl::Empty())),
                    (None,       Some(pt), Some(vec2))  => KdTreeImpl::Node(next_dim_idx,     Box::new(KdTreeImpl::Empty()),        Box::new(pt),     Box::new(build(&vec2, next_dim_idx))),
                    (None,       Some(pt), None      )  => KdTreeImpl::Node(next_dim_idx,     Box::new(KdTreeImpl::Empty()),        Box::new(pt),     Box::new(KdTreeImpl::Empty())),
                    (None,       None,     None      )  => panic!("Should be impossible to have a first point but still split into (None, None, None)."),
                    (_      ,    None,     _         )  => panic!("Meaningless result: point must be contained in a kd-tree node.")
                }
            }
            None => {
                KdTreeImpl::Empty()
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Asynchronous notifications.

use fallible_iterator::{FallibleIterator, IntoFallibleIterator};
use std::fmt;
use std::time::Duration;
use postgres_protocol::message::backend;

#[doc(inline)]
pub use postgres_shared::Notification;

use {desynchronized, Result, Connection};
use error::Error;

/// Notifications from the Postgres backend.
pub struct Notifications<'conn> {
    conn: &'conn Connection,
}

impl<'a> fmt::Debug for Notifications<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Notifications")
            .field("pending", &self.len())
            .finish()
    }
}

impl<'conn> Notifications<'conn> {
    pub(crate) fn new(conn: &'conn Connection) -> Notifications<'conn> {
        Notifications { conn: conn }
    }

    /// Returns the number of pending notifications.
    pub fn len(&self) -> usize {
        self.conn.0.borrow().notifications.len()
    }

    /// Determines if there are any pending notifications.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns a fallible iterator over pending notifications.
    ///
    /// # Note
    ///
    /// This iterator may start returning `Some` after previously returning
    /// `None` if more notifications are received.
    pub fn iter<'a>(&'a self) -> Iter<'a> {
        Iter { conn: self.conn }
    }

    /// Returns a fallible iterator over notifications that blocks until one is
    /// received if none are pending.
    ///
    /// The iterator will never return `None`.
    pub fn blocking_iter<'a>(&'a self) -> BlockingIter<'a> {
        BlockingIter { conn: self.conn }
    }

    /// Returns a fallible iterator over notifications that blocks for a limited
    /// time waiting to receive one if none are pending.
    ///
    /// # Note
    ///
    /// This iterator may start returning `Some` after previously returning
    /// `None` if more notifications are received.
    pub fn timeout_iter<'a>(&'a self, timeout: Duration) -> TimeoutIter<'a> {
        TimeoutIter {
            conn: self.conn,
            timeout: timeout,
        }
    }
}

impl<'a, 'conn> IntoFallibleIterator for &'a Notifications<'conn> {
    type Item = Notification;
    type Error = Error;
    type IntoIter = Iter<'a>;

    fn into_fallible_iterator(self) -> Iter<'a> {
        self.iter()
    }
}

/// A fallible iterator over pending notifications.
pub struct Iter<'a> {
    conn: &'a Connection,
}

impl<'a> FallibleIterator for Iter<'a> {
    type Item = Notification;
    type Error = Error;

    fn next(&mut self) -> Result<Option<Notification>> {
        let mut conn = self.conn.0.borrow_mut();

        if let Some(notification) = conn.notifications.pop_front() {
            return Ok(Some(notification));
        }

        if conn.is_desynchronized() {
            return Err(desynchronized().into());
        }

        match conn.read_message_with_notification_nonblocking() {
            Ok(Some(backend::Message::NotificationResponse(body))) => {
                Ok(Some(Notification {
                    process_id: body.process_id(),
                    channel: body.channel()?.to_owned(),
                    payload: body.message()?.to_owned(),
                }))
            }
            Ok(None) => Ok(None),
            Err(err) => Err(err.into()),
            _ => unreachable!(),
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.conn.0.borrow().notifications.len(), None)
    }
}

/// An iterator over notifications which will block if none are pending.
pub struct BlockingIter<'a> {
    conn: &'a Connection,
}

impl<'a> FallibleIterator for BlockingIter<'a> {
    type Item = Notification;
    type Error = Error;

    fn next(&mut self) -> Result<Option<Notification>> {
        let mut conn = self.conn.0.borrow_mut();

        if let Some(notification) = conn.notifications.pop_front() {
            return Ok(Some(notification));
        }

        if conn.is_desynchronized() {
            return Err(desynchronized().into());
        }

        match conn.read_message_with_notification() {
            Ok(backend::Message::NotificationResponse(body)) => {
                Ok(Some(Notification {
                    process_id: body.process_id(),
                    channel: body.channel()?.to_owned(),
                    payload: body.message()?.to_owned(),
                }))
            }
            Err(err) => Err(err.into()),
            _ => unreachable!(),
        }
    }
}

/// An iterator over notifications which will block for a period of time if
/// none are pending.
pub struct TimeoutIter<'a> {
    conn: &'a Connection,
    timeout: Duration,
}

impl<'a> FallibleIterator for TimeoutIter<'a> {
    type Item = Notification;
    type Error = Error;

    fn next(&mut self) -> Result<Option<Notification>> {
        let mut conn = self.conn.0.borrow_mut();

        if let Some(notification) = conn.notifications.pop_front() {
            return Ok(Some(notification));
        }

        if conn.is_desynchronized() {
            return Err(desynchronized().into());
        }

        match conn.read_message_with_notification_timeout(self.timeout) {
            Ok(Some(backend::Message::NotificationResponse(body))) => {
                Ok(Some(Notification {
                    process_id: body.process_id(),
                    channel: body.channel()?.to_owned(),
                    payload: body.message()?.to_owned(),
                }))
            }
            Ok(None) => Ok(None),
            Err(err) => Err(err.into()),
            _ => unreachable!(),
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.conn.0.borrow().notifications.len(), None)
    }
}
<commit_msg>Add handling of DB-Errors in Notification processing<commit_after>//! Asynchronous notifications.

use fallible_iterator::{FallibleIterator, IntoFallibleIterator};
use std::fmt;
use std::time::Duration;
use postgres_protocol::message::backend::{self, ErrorFields};
use error::DbError;

#[doc(inline)]
use postgres_shared;
pub use postgres_shared::Notification;

use {desynchronized, Result, Connection};
use error::Error;

/// Notifications from the Postgres backend.
pub struct Notifications<'conn> {
    conn: &'conn Connection,
}

impl<'a> fmt::Debug for Notifications<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Notifications")
            .field("pending", &self.len())
            .finish()
    }
}

impl<'conn> Notifications<'conn> {
    pub(crate) fn new(conn: &'conn Connection) -> Notifications<'conn> {
        Notifications { conn: conn }
    }

    /// Returns the number of pending notifications.
    pub fn len(&self) -> usize {
        self.conn.0.borrow().notifications.len()
    }

    /// Determines if there are any pending notifications.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns a fallible iterator over pending notifications.
    ///
    /// # Note
    ///
    /// This iterator may start returning `Some` after previously returning
    /// `None` if more notifications are received.
    pub fn iter<'a>(&'a self) -> Iter<'a> {
        Iter { conn: self.conn }
    }

    /// Returns a fallible iterator over notifications that blocks until one is
    /// received if none are pending.
    ///
    /// The iterator will never return `None`.
    pub fn blocking_iter<'a>(&'a self) -> BlockingIter<'a> {
        BlockingIter { conn: self.conn }
    }

    /// Returns a fallible iterator over notifications that blocks for a limited
    /// time waiting to receive one if none are pending.
    ///
    /// # Note
    ///
    /// This iterator may start returning `Some` after previously returning
    /// `None` if more notifications are received.
    pub fn timeout_iter<'a>(&'a self, timeout: Duration) -> TimeoutIter<'a> {
        TimeoutIter {
            conn: self.conn,
            timeout: timeout,
        }
    }
}

impl<'a, 'conn> IntoFallibleIterator for &'a Notifications<'conn> {
    type Item = Notification;
    type Error = Error;
    type IntoIter = Iter<'a>;

    fn into_fallible_iterator(self) -> Iter<'a> {
        self.iter()
    }
}

/// A fallible iterator over pending notifications.
pub struct Iter<'a> {
    conn: &'a Connection,
}

impl<'a> FallibleIterator for Iter<'a> {
    type Item = Notification;
    type Error = Error;

    fn next(&mut self) -> Result<Option<Notification>> {
        let mut conn = self.conn.0.borrow_mut();

        if let Some(notification) = conn.notifications.pop_front() {
            return Ok(Some(notification));
        }

        if conn.is_desynchronized() {
            return Err(desynchronized().into());
        }

        match conn.read_message_with_notification_nonblocking() {
            Ok(Some(backend::Message::NotificationResponse(body))) => {
                Ok(Some(Notification {
                    process_id: body.process_id(),
                    channel: body.channel()?.to_owned(),
                    payload: body.message()?.to_owned(),
                }))
            }
            Ok(Some(backend::Message::ErrorResponse(body))) => Err(err(&mut body.fields())),
            Ok(None) => Ok(None),
            Err(err) => Err(err.into()),
            _ => unreachable!(),
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.conn.0.borrow().notifications.len(), None)
    }
}

/// An iterator over notifications which will block if none are pending.
pub struct BlockingIter<'a> {
    conn: &'a Connection,
}

impl<'a> FallibleIterator for BlockingIter<'a> {
    type Item = Notification;
    type Error = Error;

    fn next(&mut self) -> Result<Option<Notification>> {
        let mut conn = self.conn.0.borrow_mut();

        if let Some(notification) = conn.notifications.pop_front() {
            return Ok(Some(notification));
        }

        if conn.is_desynchronized() {
            return Err(desynchronized().into());
        }

        match conn.read_message_with_notification() {
            Ok(backend::Message::NotificationResponse(body)) => {
                Ok(Some(Notification {
                    process_id: body.process_id(),
                    channel: body.channel()?.to_owned(),
                    payload: body.message()?.to_owned(),
                }))
            }
            Ok(backend::Message::ErrorResponse(body)) => Err(err(&mut body.fields())),
            Err(err) => Err(err.into()),
            _ => unreachable!(),
        }
    }
}

/// An iterator over notifications which will block for a period of time if
/// none are pending.
pub struct TimeoutIter<'a> {
    conn: &'a Connection,
    timeout: Duration,
}

impl<'a> FallibleIterator for TimeoutIter<'a> {
    type Item = Notification;
    type Error = Error;

    fn next(&mut self) -> Result<Option<Notification>> {
        let mut conn = self.conn.0.borrow_mut();

        if let Some(notification) = conn.notifications.pop_front() {
            return Ok(Some(notification));
        }

        if conn.is_desynchronized() {
            return Err(desynchronized().into());
        }

        match conn.read_message_with_notification_timeout(self.timeout) {
            Ok(Some(backend::Message::NotificationResponse(body))) => {
                Ok(Some(Notification {
                    process_id: body.process_id(),
                    channel: body.channel()?.to_owned(),
                    payload: body.message()?.to_owned(),
                }))
            }
            Ok(Some(backend::Message::ErrorResponse(body))) => Err(err(&mut body.fields())),
            Ok(None) => Ok(None),
            Err(err) => Err(err.into()),
            _ => unreachable!(),
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.conn.0.borrow().notifications.len(), None)
    }
}

fn err(fields: &mut ErrorFields) -> Error {
    match DbError::new(fields) {
        Ok(err) => postgres_shared::error::db(err),
        Err(err) => err.into(),
    }
}
<|endoftext|>


<commit_before>extern crate r6;

use std::io::BufReader;
use r6::runtime::Runtime;
use r6::compiler::Compiler;
use r6::base::libbase;
use r6::parser::Parser;

macro_rules! assert_evaluates_to {
    ($src:expr, $expected:expr) => (
        {
            let mut src_reader = BufReader::new($src.as_bytes());
            let mut src_parser = Parser::new(&mut src_reader);
            let sourcecode = match src_parser.parse_datum() {
                Ok(code) => code,
                Err(e) => panic!("failed to parse source: {:?}", e)
            };

            let mut res_reader = BufReader::new($expected.as_bytes());
            let mut res_parser = Parser::new(&mut res_reader);
            let expected = match res_parser.parse_datum() {
                Ok(val) => val,
                Err(e) => panic!("failed to parse result: {:?}", e)
            };

            let base = libbase();
            let mut compiler = Compiler::new(&base);
            let bytecode = match compiler.compile(&sourcecode) {
                Ok(code) => code,
                Err(e) => panic!("compile failure: {:?}", e)
            };
            let mut runtime = Runtime::new(bytecode);
            let result = runtime.run();
            if !((result == expected) && (expected == result)) {
                panic!("test failed: expected `{:?}` but got `{:?}`", expected, result);
            }
        }
    )
}

#[test]
fn lexical_scoping() {
    // (\y f -> f 2) #f ((\y -> (\x -> y)) #t)
    // If it's dynamic scope, it should return 0
    // If it's static scope, it should return 1
    assert_evaluates_to!("((lambda (y f) (f 2)) #f ((lambda (y) (lambda (x) y)) #t))", "#t")
}

#[test]
fn if_expression() {
    assert_evaluates_to!("(if #t 1 0)", "1");
    assert_evaluates_to!("(if #f 1 0)", "0");
}
<commit_msg>Some constant tests<commit_after>extern crate r6;

use std::io::BufReader;
use r6::runtime::Runtime;
use r6::compiler::Compiler;
use r6::base::libbase;
use r6::parser::Parser;

macro_rules! assert_evaluates_to {
    ($src:expr, $expected:expr) => (
        {
            let mut src_reader = BufReader::new($src.as_bytes());
            let mut src_parser = Parser::new(&mut src_reader);
            let sourcecode = match src_parser.parse_datum() {
                Ok(code) => code,
                Err(e) => panic!("failed to parse source: {:?}", e)
            };

            let mut res_reader = BufReader::new($expected.as_bytes());
            let mut res_parser = Parser::new(&mut res_reader);
            let expected = match res_parser.parse_datum() {
                Ok(val) => val,
                Err(e) => panic!("failed to parse result: {:?}", e)
            };

            let base = libbase();
            let mut compiler = Compiler::new(&base);
            let bytecode = match compiler.compile(&sourcecode) {
                Ok(code) => code,
                Err(e) => panic!("compile failure: {:?}", e)
            };
            let mut runtime = Runtime::new(bytecode);
            let result = runtime.run();
            if !((result == expected) && (expected == result)) {
                panic!("test failed: expected `{:?}` but got `{:?}`", expected, result);
            }
        }
    )
}

#[test]
fn lexical_scoping() {
    // (\y f -> f 2) #f ((\y -> (\x -> y)) #t)
    // If it's dynamic scope, it should return 0
    // If it's static scope, it should return 1
    assert_evaluates_to!("((lambda (y f) (f 2)) #f ((lambda (y) (lambda (x) y)) #t))", "#t")
}

#[test]
fn if_expression() {
    assert_evaluates_to!("(if #t 1 0)", "1");
    assert_evaluates_to!("(if #f 1 0)", "0");
}

#[test]
fn eval_to_self() {
    assert_evaluates_to!("#t", "#t");
    assert_evaluates_to!("23", "23");
}
<|endoftext|>