<commit_before>//! Lexer
//!
//! This module contains elements than can be used for writing plugins
//! but can be ignored for simple usage.

use token::Token;
use token::Token::*;
use token::ComparisonOperator::*;
use self::Element::*;
use regex::{Regex};
use error::{Error, Result};

#[derive(Clone, Debug, PartialEq)]
pub enum Element {
    Expression(Vec<Token>, String),
    Tag(Vec<Token>, String),
    Raw(String),
}

lazy_static! {
    static ref MARKUP: Regex = Regex::new("\\{%.*?%\\}|\\{\\{.*?\\}\\}").unwrap();
}

fn split_blocks(text: &str) -> Vec<&str> {
    let mut tokens = vec![];
    let mut current = 0;
    for mat in MARKUP.find_iter(text) {
        let start = mat.start();
        let end = mat.end();
        match &text[current..start] {
            "" => {}
            t => tokens.push(t),
        }
        tokens.push(&text[start..end]);
        current = end;
    }
    match &text[current..text.len()] {
        "" => {}
        t => tokens.push(t),
    }
    tokens
}

lazy_static! {
    static ref EXPRESSION: Regex = Regex::new("\\{\\{(.*?)\\}\\}").unwrap();
    static ref TAG: Regex = Regex::new("\\{%(.*?)%\\}").unwrap();
}

pub fn tokenize(text: &str) -> Result<Vec<Element>> {
    let mut blocks = vec![];

    for block in split_blocks(text) {
        if let Some(caps) = TAG.captures(block) {
            blocks.push(Tag(try!(granularize(caps.get(1).map(|x| x.as_str()).unwrap_or(""))),
                            block.to_owned()));
        } else if let Some(caps) = EXPRESSION.captures(block) {
            blocks.push(Expression(try!(granularize(caps.get(1).map(|x| x.as_str()).unwrap_or(""))),
                                   block.to_owned()));
        } else {
            blocks.push(Raw(block.to_owned()));
        }
    }

    Ok(blocks)
}

lazy_static! {
    static ref SPLIT: Regex = Regex::new(
        r#"'.*?'|".*?"|\s+|[\|:,\[\]\(\)\?]|\.\.|={1,2}|!=|<=|>=|[<>]"#).unwrap();
}

fn split_atom(block: &str) -> Vec<&str> {
    let mut tokens = vec![];
    let mut current = 0;
    for mat in SPLIT.find_iter(block) {
        let start = mat.start();
        let end = mat.end();
        // insert the stuff between identifiers
        tokens.push(&block[current..start]);
        // insert the identifier
        tokens.push(&block[start..end]);
        current = end;
    }
    // insert remaining things
    tokens.push(&block[current..block.len()]);
    tokens
}

lazy_static! {
    static ref IDENTIFIER: Regex = Regex::new(r"[a-zA-Z_][\w-]*\??").unwrap();
    static ref SINGLE_STRING_LITERAL: Regex = Regex::new(r"'[^']*'").unwrap();
    static ref DOUBLE_STRING_LITERAL: Regex = Regex::new("\"[^\"]*\"").unwrap();
    static ref NUMBER_LITERAL: Regex = Regex::new(r"^-?\d+(\.\d+)?$").unwrap();
    static ref BOOLEAN_LITERAL: Regex = Regex::new(r"^true|false$").unwrap();
}

pub fn granularize(block: &str) -> Result<Vec<Token>> {
    let mut result = vec![];

    for el in split_atom(block) {
        result.push(match &*el.trim() {
            "" => continue,

            "|" => Pipe,
            "." => Dot,
            ":" => Colon,
            "," => Comma,
            "[" => OpenSquare,
            "]" => CloseSquare,
            "(" => OpenRound,
            ")" => CloseRound,
            "?" => Question,
            "-" => Dash,
            "=" => Assignment,
            "or" => Or,

            "==" => Comparison(Equals),
            "!=" => Comparison(NotEquals),
            "<=" => Comparison(LessThanEquals),
            ">=" => Comparison(GreaterThanEquals),
            "<" => Comparison(LessThan),
            ">" => Comparison(GreaterThan),
            "contains" => Comparison(Contains),
            ".." => DotDot,

            x if SINGLE_STRING_LITERAL.is_match(x) || DOUBLE_STRING_LITERAL.is_match(x) => {
                StringLiteral(x[1..x.len() - 1].to_owned())
            }
            x if NUMBER_LITERAL.is_match(x) => {
                NumberLiteral(x.parse::<f32>().expect(&format!("Could not parse {:?} as float", x)))
            }
            x if BOOLEAN_LITERAL.is_match(x) => {
                BooleanLiteral(x.parse::<bool>()
                    .expect(&format!("Could not parse {:?} as bool", x)))
            }
            x if IDENTIFIER.is_match(x) => Identifier(x.to_owned()),
            x => return Err(Error::Lexer(format!("{} is not a valid identifier", x))),
        });
    }

    Ok(result)
}

#[test]
fn test_split_blocks() {
    assert_eq!(split_blocks("asdlkjfn\n{{askdljfbalkjsdbf}} asdjlfb"),
               vec!["asdlkjfn\n", "{{askdljfbalkjsdbf}}", " asdjlfb"]);
    assert_eq!(split_blocks("asdlkjfn\n{%askdljfbalkjsdbf%} asdjlfb"),
               vec!["asdlkjfn\n", "{%askdljfbalkjsdbf%}", " asdjlfb"]);
}

#[test]
fn test_split_atom() {
    assert_eq!(split_atom("truc | arg:val"),
               vec!["truc", " ", "", "|", "", " ", "arg", ":", "val"]);
    assert_eq!(split_atom("truc | filter:arg1,arg2"),
               vec!["truc", " ", "", "|", "", " ", "filter", ":", "arg1", ",", "arg2"]);
}

#[test]
fn test_tokenize() {
    assert_eq!(tokenize("{{hello 'world'}}").unwrap(),
               vec![Expression(vec![Identifier("hello".to_owned()),
                                    StringLiteral("world".to_owned())],
                               "{{hello 'world'}}".to_owned())]);
    assert_eq!(tokenize("{{hello.world}}").unwrap(),
               vec![Expression(vec![Identifier("hello.world".to_owned())],
                               "{{hello.world}}".to_owned())]);
    assert_eq!(tokenize("{{ hello 'world' }}").unwrap(),
               vec![Expression(vec![Identifier("hello".to_owned()),
                                    StringLiteral("world".to_owned())],
                               "{{ hello 'world' }}".to_owned())]);
    assert_eq!(tokenize("{{   hello   'world'    }}").unwrap(),
               vec![Expression(vec![Identifier("hello".to_owned()),
                                    StringLiteral("world".to_owned())],
                               "{{   hello   'world'    }}".to_owned())]);
    assert_eq!(tokenize("wat\n{{hello 'world'}} test").unwrap(),
               vec![Raw("wat\n".to_owned()),
                    Expression(vec![Identifier("hello".to_owned()),
                                    StringLiteral("world".to_owned())],
                               "{{hello 'world'}}".to_owned()),
                    Raw(" test".to_owned())]);
}

#[test]
fn test_granularize() {
    assert_eq!(granularize("include my-file.html").unwrap(),
               vec![Identifier("include".to_owned()), Identifier("my-file.html".to_owned())]);
    assert_eq!(granularize("test | me").unwrap(),
               vec![Identifier("test".to_owned()), Pipe, Identifier("me".to_owned())]);
    assert_eq!(granularize("test .. me").unwrap(),
               vec![Identifier("test".to_owned()), DotDot, Identifier("me".to_owned())]);
    assert_eq!(granularize("test : me").unwrap(),
               vec![Identifier("test".to_owned()), Colon, Identifier("me".to_owned())]);
    assert_eq!(granularize("test , me").unwrap(),
               vec![Identifier("test".to_owned()), Comma, Identifier("me".to_owned())]);
    assert_eq!(granularize("test [ me").unwrap(),
               vec![Identifier("test".to_owned()), OpenSquare, Identifier("me".to_owned())]);
    assert_eq!(granularize("test ] me").unwrap(),
               vec![Identifier("test".to_owned()), CloseSquare, Identifier("me".to_owned())]);
    assert_eq!(granularize("test ( me").unwrap(),
               vec![Identifier("test".to_owned()), OpenRound, Identifier("me".to_owned())]);
    assert_eq!(granularize("test ) me").unwrap(),
               vec![Identifier("test".to_owned()), CloseRound, Identifier("me".to_owned())]);
    assert_eq!(granularize("test ? me").unwrap(),
               vec![Identifier("test".to_owned()), Question, Identifier("me".to_owned())]);
    assert_eq!(granularize("test - me").unwrap(),
               vec![Identifier("test".to_owned()), Dash, Identifier("me".to_owned())]);
    assert_eq!(granularize("test me").unwrap(),
               vec![Identifier("test".to_owned()), Identifier("me".to_owned())]);
    assert_eq!(granularize("test = me").unwrap(),
               vec![Identifier("test".to_owned()), Assignment, Identifier("me".to_owned())]);
    assert_eq!(granularize("test == me").unwrap(),
               vec![Identifier("test".to_owned()),
                    Comparison(Equals),
                    Identifier("me".to_owned())]);
    assert_eq!(granularize("test >= me").unwrap(),
               vec![Identifier("test".to_owned()),
                    Comparison(GreaterThanEquals),
                    Identifier("me".to_owned())]);
    assert_eq!(granularize("test > me").unwrap(),
               vec![Identifier("test".to_owned()),
                    Comparison(GreaterThan),
                    Identifier("me".to_owned())]);
    assert_eq!(granularize("test < me").unwrap(),
               vec![Identifier("test".to_owned()),
                    Comparison(LessThan),
                    Identifier("me".to_owned())]);
    assert_eq!(granularize("test != me").unwrap(),
               vec![Identifier("test".to_owned()),
                    Comparison(NotEquals),
                    Identifier("me".to_owned())]);
    assert_eq!(granularize("test <= me").unwrap(),
               vec![Identifier("test".to_owned()),
                    Comparison(LessThanEquals),
                    Identifier("me".to_owned())]);
    assert_eq!(granularize("test.me").unwrap(),
               vec![Identifier("test.me".to_owned())]);
    assert_eq!(granularize("'test' == \"me\"").unwrap(),
               vec![StringLiteral("test".to_owned()),
                    Comparison(Equals),
                    StringLiteral("me".to_owned())]);
    assert_eq!(granularize("test | me:arg").unwrap(),
               vec![Identifier("test".to_owned()),
                    Pipe,
                    Identifier("me".to_owned()),
                    Colon,
                    Identifier("arg".to_owned())]);
    assert_eq!(granularize("test | me:arg1,arg2").unwrap(),
               vec![Identifier("test".to_owned()),
                    Pipe,
                    Identifier("me".to_owned()),
                    Colon,
                    Identifier("arg1".to_owned()),
                    Comma,
                    Identifier("arg2".to_owned())]);
    assert_eq!(granularize("test | me : arg1, arg2").unwrap(),
               vec![Identifier("test".to_owned()),
                    Pipe,
                    Identifier("me".to_owned()),
                    Colon,
                    Identifier("arg1".to_owned()),
                    Comma,
                    Identifier("arg2".to_owned())]);
    assert_eq!(granularize("multiply 5 3").unwrap(),
               vec![Identifier("multiply".to_owned()), NumberLiteral(5f32), NumberLiteral(3f32)]);
    assert_eq!(granularize("for i in (1..5)").unwrap(),
               vec![Identifier("for".to_owned()),
                    Identifier("i".to_owned()),
                    Identifier("in".to_owned()),
                    OpenRound,
                    NumberLiteral(1f32),
                    DotDot,
                    NumberLiteral(5f32),
                    CloseRound]);
    assert_eq!(granularize("\"1, '2', 3, 4\"").unwrap(),
               vec![StringLiteral("1, '2', 3, 4".to_owned())]);
    assert_eq!(granularize("'1, \"2\", 3, 4'").unwrap(),
               vec![StringLiteral("1, \"2\", 3, 4".to_owned())]);
    assert_eq!(granularize("\"1, '2', 3, 4\"\"1, '2', 3, 4\"").unwrap(),
               vec![StringLiteral("1, '2', 3, 4".to_owned()),
                    StringLiteral("1, '2', 3, 4".to_owned())]);
    assert_eq!(granularize("abc : \"1, '2', 3, 4\"").unwrap(),
               vec![Identifier("abc".to_owned()), Colon, StringLiteral("1, '2', 3, 4".to_owned())]);
}
<commit_msg>Rustfmt<commit_after>//! Lexer
//!
//! This module contains elements than can be used for writing plugins
//! but can be ignored for simple usage.

use token::Token;
use token::Token::*;
use token::ComparisonOperator::*;
use self::Element::*;
use regex::Regex;
use error::{Error, Result};

#[derive(Clone, Debug, PartialEq)]
pub enum Element {
    Expression(Vec<Token>, String),
    Tag(Vec<Token>, String),
    Raw(String),
}

lazy_static! {
    static ref MARKUP: Regex = Regex::new("\\{%.*?%\\}|\\{\\{.*?\\}\\}").unwrap();
}

fn split_blocks(text: &str) -> Vec<&str> {
    let mut tokens = vec![];
    let mut current = 0;
    for mat in MARKUP.find_iter(text) {
        let start = mat.start();
        let end = mat.end();
        match &text[current..start] {
            "" => {}
            t => tokens.push(t),
        }
        tokens.push(&text[start..end]);
        current = end;
    }
    match &text[current..text.len()] {
        "" => {}
        t => tokens.push(t),
    }
    tokens
}

lazy_static! {
    static ref EXPRESSION: Regex = Regex::new("\\{\\{(.*?)\\}\\}").unwrap();
    static ref TAG: Regex = Regex::new("\\{%(.*?)%\\}").unwrap();
}

pub fn tokenize(text: &str) -> Result<Vec<Element>> {
    let mut blocks = vec![];

    for block in split_blocks(text) {
        if let Some(caps) = TAG.captures(block) {
            blocks.push(Tag(try!(granularize(caps.get(1).map(|x| x.as_str()).unwrap_or(""))),
                            block.to_owned()));
        } else if let Some(caps) = EXPRESSION.captures(block) {
            blocks.push(Expression(try!(granularize(caps.get(1)
                                       .map(|x| x.as_str())
                                       .unwrap_or(""))),
                                   block.to_owned()));
        } else {
            blocks.push(Raw(block.to_owned()));
        }
    }

    Ok(blocks)
}

lazy_static! {
    static ref SPLIT: Regex = Regex::new(
        r#"'.*?'|".*?"|\s+|[\|:,\[\]\(\)\?]|\.\.|={1,2}|!=|<=|>=|[<>]"#).unwrap();
}

fn split_atom(block: &str) -> Vec<&str> {
    let mut tokens = vec![];
    let mut current = 0;
    for mat in SPLIT.find_iter(block) {
        let start = mat.start();
        let end = mat.end();
        // insert the stuff between identifiers
        tokens.push(&block[current..start]);
        // insert the identifier
        tokens.push(&block[start..end]);
        current = end;
    }
    // insert remaining things
    tokens.push(&block[current..block.len()]);
    tokens
}

lazy_static! {
    static ref IDENTIFIER: Regex = Regex::new(r"[a-zA-Z_][\w-]*\??").unwrap();
    static ref SINGLE_STRING_LITERAL: Regex = Regex::new(r"'[^']*'").unwrap();
    static ref DOUBLE_STRING_LITERAL: Regex = Regex::new("\"[^\"]*\"").unwrap();
    static ref NUMBER_LITERAL: Regex = Regex::new(r"^-?\d+(\.\d+)?$").unwrap();
    static ref BOOLEAN_LITERAL: Regex = Regex::new(r"^true|false$").unwrap();
}

pub fn granularize(block: &str) -> Result<Vec<Token>> {
    let mut result = vec![];

    for el in split_atom(block) {
        result.push(match &*el.trim() {
            "" => continue,

            "|" => Pipe,
            "." => Dot,
            ":" => Colon,
            "," => Comma,
            "[" => OpenSquare,
            "]" => CloseSquare,
            "(" => OpenRound,
            ")" => CloseRound,
            "?" => Question,
            "-" => Dash,
            "=" => Assignment,
            "or" => Or,

            "==" => Comparison(Equals),
            "!=" => Comparison(NotEquals),
            "<=" => Comparison(LessThanEquals),
            ">=" => Comparison(GreaterThanEquals),
            "<" => Comparison(LessThan),
            ">" => Comparison(GreaterThan),
            "contains" => Comparison(Contains),
            ".." => DotDot,

            x if SINGLE_STRING_LITERAL.is_match(x) || DOUBLE_STRING_LITERAL.is_match(x) => {
                StringLiteral(x[1..x.len() - 1].to_owned())
            }
            x if NUMBER_LITERAL.is_match(x) => {
                NumberLiteral(x.parse::<f32>().expect(&format!("Could not parse {:?} as float", x)))
            }
            x if BOOLEAN_LITERAL.is_match(x) => {
                BooleanLiteral(x.parse::<bool>()
                    .expect(&format!("Could not parse {:?} as bool", x)))
            }
            x if IDENTIFIER.is_match(x) => Identifier(x.to_owned()),
            x => return Err(Error::Lexer(format!("{} is not a valid identifier", x))),
        });
    }

    Ok(result)
}

#[test]
fn test_split_blocks() {
    assert_eq!(split_blocks("asdlkjfn\n{{askdljfbalkjsdbf}} asdjlfb"),
               vec!["asdlkjfn\n", "{{askdljfbalkjsdbf}}", " asdjlfb"]);
    assert_eq!(split_blocks("asdlkjfn\n{%askdljfbalkjsdbf%} asdjlfb"),
               vec!["asdlkjfn\n", "{%askdljfbalkjsdbf%}", " asdjlfb"]);
}

#[test]
fn test_split_atom() {
    assert_eq!(split_atom("truc | arg:val"),
               vec!["truc", " ", "", "|", "", " ", "arg", ":", "val"]);
    assert_eq!(split_atom("truc | filter:arg1,arg2"),
               vec!["truc", " ", "", "|", "", " ", "filter", ":", "arg1", ",", "arg2"]);
}

#[test]
fn test_tokenize() {
    assert_eq!(tokenize("{{hello 'world'}}").unwrap(),
               vec![Expression(vec![Identifier("hello".to_owned()),
                                    StringLiteral("world".to_owned())],
                               "{{hello 'world'}}".to_owned())]);
    assert_eq!(tokenize("{{hello.world}}").unwrap(),
               vec![Expression(vec![Identifier("hello.world".to_owned())],
                               "{{hello.world}}".to_owned())]);
    assert_eq!(tokenize("{{ hello 'world' }}").unwrap(),
               vec![Expression(vec![Identifier("hello".to_owned()),
                                    StringLiteral("world".to_owned())],
                               "{{ hello 'world' }}".to_owned())]);
    assert_eq!(tokenize("{{   hello   'world'    }}").unwrap(),
               vec![Expression(vec![Identifier("hello".to_owned()),
                                    StringLiteral("world".to_owned())],
                               "{{   hello   'world'    }}".to_owned())]);
    assert_eq!(tokenize("wat\n{{hello 'world'}} test").unwrap(),
               vec![Raw("wat\n".to_owned()),
                    Expression(vec![Identifier("hello".to_owned()),
                                    StringLiteral("world".to_owned())],
                               "{{hello 'world'}}".to_owned()),
                    Raw(" test".to_owned())]);
}

#[test]
fn test_granularize() {
    assert_eq!(granularize("include my-file.html").unwrap(),
               vec![Identifier("include".to_owned()), Identifier("my-file.html".to_owned())]);
    assert_eq!(granularize("test | me").unwrap(),
               vec![Identifier("test".to_owned()), Pipe, Identifier("me".to_owned())]);
    assert_eq!(granularize("test .. me").unwrap(),
               vec![Identifier("test".to_owned()), DotDot, Identifier("me".to_owned())]);
    assert_eq!(granularize("test : me").unwrap(),
               vec![Identifier("test".to_owned()), Colon, Identifier("me".to_owned())]);
    assert_eq!(granularize("test , me").unwrap(),
               vec![Identifier("test".to_owned()), Comma, Identifier("me".to_owned())]);
    assert_eq!(granularize("test [ me").unwrap(),
               vec![Identifier("test".to_owned()), OpenSquare, Identifier("me".to_owned())]);
    assert_eq!(granularize("test ] me").unwrap(),
               vec![Identifier("test".to_owned()), CloseSquare, Identifier("me".to_owned())]);
    assert_eq!(granularize("test ( me").unwrap(),
               vec![Identifier("test".to_owned()), OpenRound, Identifier("me".to_owned())]);
    assert_eq!(granularize("test ) me").unwrap(),
               vec![Identifier("test".to_owned()), CloseRound, Identifier("me".to_owned())]);
    assert_eq!(granularize("test ? me").unwrap(),
               vec![Identifier("test".to_owned()), Question, Identifier("me".to_owned())]);
    assert_eq!(granularize("test - me").unwrap(),
               vec![Identifier("test".to_owned()), Dash, Identifier("me".to_owned())]);
    assert_eq!(granularize("test me").unwrap(),
               vec![Identifier("test".to_owned()), Identifier("me".to_owned())]);
    assert_eq!(granularize("test = me").unwrap(),
               vec![Identifier("test".to_owned()), Assignment, Identifier("me".to_owned())]);
    assert_eq!(granularize("test == me").unwrap(),
               vec![Identifier("test".to_owned()),
                    Comparison(Equals),
                    Identifier("me".to_owned())]);
    assert_eq!(granularize("test >= me").unwrap(),
               vec![Identifier("test".to_owned()),
                    Comparison(GreaterThanEquals),
                    Identifier("me".to_owned())]);
    assert_eq!(granularize("test > me").unwrap(),
               vec![Identifier("test".to_owned()),
                    Comparison(GreaterThan),
                    Identifier("me".to_owned())]);
    assert_eq!(granularize("test < me").unwrap(),
               vec![Identifier("test".to_owned()),
                    Comparison(LessThan),
                    Identifier("me".to_owned())]);
    assert_eq!(granularize("test != me").unwrap(),
               vec![Identifier("test".to_owned()),
                    Comparison(NotEquals),
                    Identifier("me".to_owned())]);
    assert_eq!(granularize("test <= me").unwrap(),
               vec![Identifier("test".to_owned()),
                    Comparison(LessThanEquals),
                    Identifier("me".to_owned())]);
    assert_eq!(granularize("test.me").unwrap(),
               vec![Identifier("test.me".to_owned())]);
    assert_eq!(granularize("'test' == \"me\"").unwrap(),
               vec![StringLiteral("test".to_owned()),
                    Comparison(Equals),
                    StringLiteral("me".to_owned())]);
    assert_eq!(granularize("test | me:arg").unwrap(),
               vec![Identifier("test".to_owned()),
                    Pipe,
                    Identifier("me".to_owned()),
                    Colon,
                    Identifier("arg".to_owned())]);
    assert_eq!(granularize("test | me:arg1,arg2").unwrap(),
               vec![Identifier("test".to_owned()),
                    Pipe,
                    Identifier("me".to_owned()),
                    Colon,
                    Identifier("arg1".to_owned()),
                    Comma,
                    Identifier("arg2".to_owned())]);
    assert_eq!(granularize("test | me : arg1, arg2").unwrap(),
               vec![Identifier("test".to_owned()),
                    Pipe,
                    Identifier("me".to_owned()),
                    Colon,
                    Identifier("arg1".to_owned()),
                    Comma,
                    Identifier("arg2".to_owned())]);
    assert_eq!(granularize("multiply 5 3").unwrap(),
               vec![Identifier("multiply".to_owned()), NumberLiteral(5f32), NumberLiteral(3f32)]);
    assert_eq!(granularize("for i in (1..5)").unwrap(),
               vec![Identifier("for".to_owned()),
                    Identifier("i".to_owned()),
                    Identifier("in".to_owned()),
                    OpenRound,
                    NumberLiteral(1f32),
                    DotDot,
                    NumberLiteral(5f32),
                    CloseRound]);
    assert_eq!(granularize("\"1, '2', 3, 4\"").unwrap(),
               vec![StringLiteral("1, '2', 3, 4".to_owned())]);
    assert_eq!(granularize("'1, \"2\", 3, 4'").unwrap(),
               vec![StringLiteral("1, \"2\", 3, 4".to_owned())]);
    assert_eq!(granularize("\"1, '2', 3, 4\"\"1, '2', 3, 4\"").unwrap(),
               vec![StringLiteral("1, '2', 3, 4".to_owned()),
                    StringLiteral("1, '2', 3, 4".to_owned())]);
    assert_eq!(granularize("abc : \"1, '2', 3, 4\"").unwrap(),
               vec![Identifier("abc".to_owned()), Colon, StringLiteral("1, '2', 3, 4".to_owned())]);
}
<|endoftext|>


<commit_before>//!
//! Values manipulated by services
//!
use std::cmp::{PartialOrd, Ordering};
use std::time::Duration;
use std::str::FromStr;

use serde_json;
use chrono;
use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Error};

///
/// The type of values manipulated by endpoints.
///
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
pub enum Type {
    ///
    /// # Trivial values
    ///

    /// An empty value. Used for instance to inform that a countdown
    /// has reached 0 or that a device is ready.
    Unit,

    /// A boolean. Used for instance for on-off switches, presence
    /// detectors, etc.
    Bool,

    ///
    /// # Time
    ///

    /// A duration. Used for instance in countdowns.
    Duration,

    /// A precise timestamp. Used for instance to determine when an
    /// event has taken place.
    TimeStamp,

    Temperature,
    String,
    ///
    /// ...
    ///
    Color,
    Json,
    Binary,
    ExtNumeric,
}

/// A temperature. Internal representation may be either Fahrenheit or
/// Celcius. The FoxBox adapters are expected to perform conversions
/// to the format requested by their devices.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Temperature {
    /// Fahrenheit
    F(f64),
    /// Celcius
    C(f64),
}

impl Temperature {
    /// Get a temperature in Fahrenheit.
    pub fn as_f(&self) -> f64 {
        unimplemented!();
    }

    /// Get a temperature in Celcius.
    pub fn as_c(&self) -> f64 {
        unimplemented!();
    }
}

impl PartialOrd for Temperature {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.as_c().partial_cmp(&other.as_c())
    }
}

/// A color. Internal representation may vary. The FoxBox adapters are
/// expected to perform conversions to the format requested by their
/// device.
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
pub enum Color {
    RGBA(f64, f64, f64, f64, f64)
}

/// Representation of an object in JSON. It is often (albeit not
/// always) possible to choose a more precise data structure for
/// representing values send/accepted by a service. If possible,
/// adapters should rather pick such more precise data structure.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Json(pub serde_json::value::Value);

impl PartialOrd for Json {
    /// Two Json objects are never comparable to each other.
    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
        None
    }
}

/// A data structure holding a numeric value of a type that has not
/// been standardized yet.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtNumeric {
    pub value: f64,

    /// The vendor. Used for namespacing purposes, to avoid
    /// confusing two incompatible extensions with similar
    /// names. For instance, "foxlink@mozilla.com".
    pub vendor: String,

    /// Identification of the adapter introducing this value.
    /// Designed to aid with tracing and debugging.
    pub adapter: String,

    /// A string describing the nature of the value, designed to
    /// aid with type-checking.
    ///
    /// Examples: `"GroundHumidity"`.
    pub kind: String,
}

impl PartialOrd for ExtNumeric {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.vendor != other.vendor {
            return None;
        } else if self.kind != other.kind {
            return None;
        } else {
            self.value.partial_cmp(&other.value)
        }
    }
}

/// Representation of an actual value that can be sent to/received
/// from a service.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Value {
    Unit,
    Bool(bool),
    Duration(ValDuration),
    TimeStamp(TimeStamp),
    Temperature(Temperature),
    Color(Color),
    String(String),

    // FIXME: Add more as we identify needs

    /// A numeric value representing a unit that has not been
    /// standardized yet into the API.
    ExtNumeric(ExtNumeric),
    Json(Json),
    Binary {data: Vec<u8>, mimetype: String}
}

impl Value {
    pub fn get_type(&self) -> Type {
        match *self {
            Value::Unit => Type::Unit,
            Value::Bool(_) => Type::Bool,
            Value::String(_) => Type::String,
            Value::Duration(_) => Type::Duration,
            Value::TimeStamp(_) => Type::TimeStamp,
            Value::Temperature(_) => Type::Temperature,
            Value::Color(_) => Type::Color,
            Value::Json(_) => Type::Json,
            Value::Binary{..} => Type::Binary,
            Value::ExtNumeric(_) => Type::ExtNumeric,
        }
    }
}

impl PartialOrd for Value {
    /// Two values of the same type can be compared using the usual
    /// comparison for values of this type. Two values of distinct
    /// types cannot be compared.
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        use self::Value::*;
        use std::cmp::Ordering::*;
        match (self, other) {
            (&Unit, &Unit) => Some(Equal),
            (&Unit, _) => None,

            (&Bool(a), &Bool(b)) => a.partial_cmp(&b),
            (&Bool(_), _) => None,

            (&Duration(ref a), &Duration(ref b)) => a.partial_cmp(b),
            (&Duration(_), _) => None,

            (&TimeStamp(ref a), &TimeStamp(ref b)) => a.partial_cmp(b),
            (&TimeStamp(_), _) => None,

            (&Temperature(ref a), &Temperature(ref b)) => a.partial_cmp(b),
            (&Temperature(_), _) => None,

            (&Color(ref a), &Color(ref b)) => a.partial_cmp(b),
            (&Color(_), _) => None,

            (&ExtNumeric(ref a), &ExtNumeric(ref b)) => a.partial_cmp(b),
            (&ExtNumeric(_), _) => None,

            (&String(ref a), &String(ref b)) => a.partial_cmp(b),
            (&String(_), _) => None,

            (&Json(ref a), &Json(ref b)) => a.partial_cmp(b),
            (&Json(_), _) => None,

            (&Binary{mimetype: ref a_mimetype, data: ref a_data},
             &Binary{mimetype: ref b_mimetype, data: ref b_data}) if a_mimetype == b_mimetype => a_data.partial_cmp(b_data),
            (&Binary{..}, _) => None,
        }
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct ValDuration(pub Duration);
impl Serialize for ValDuration {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let as_ms : u64 = self.0.as_secs() * 1000
            + (self.0.subsec_nanos() as u64) / 1_000_000;
        as_ms.serialize(serializer)
    }
}
impl Deserialize for ValDuration {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let as_ms : u64 = try!(u64::deserialize(deserializer));
        let as_sec = as_ms / 1000;
        let as_ns = (as_ms / 1_000_000) as u32;
        Ok(ValDuration(Duration::new(as_sec, as_ns)))
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct TimeStamp(chrono::DateTime<chrono::Local>);
impl Serialize for TimeStamp {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let str = self.0.to_rfc3339();
        str.serialize(serializer)
    }
}
impl Deserialize for TimeStamp {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let str = try!(String::deserialize(deserializer));
        match chrono::DateTime::<chrono::Local>::from_str(&str) {
            Ok(dt) => Ok(TimeStamp(dt)),
            Err(_) => Err(D::Error::syntax("Invalid date"))
        }
    }
}
<commit_msg>[fxbox/taxonomy] Actually, implemented ValDuration::new()<commit_after>//!
//! Values manipulated by services
//!
use std::cmp::{PartialOrd, Ordering};
use std::time::Duration;
use std::str::FromStr;

use serde_json;
use chrono;
use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Error};

///
/// The type of values manipulated by endpoints.
///
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
pub enum Type {
    ///
    /// # Trivial values
    ///

    /// An empty value. Used for instance to inform that a countdown
    /// has reached 0 or that a device is ready.
    Unit,

    /// A boolean. Used for instance for on-off switches, presence
    /// detectors, etc.
    Bool,

    ///
    /// # Time
    ///

    /// A duration. Used for instance in countdowns.
    Duration,

    /// A precise timestamp. Used for instance to determine when an
    /// event has taken place.
    TimeStamp,

    Temperature,
    String,
    ///
    /// ...
    ///
    Color,
    Json,
    Binary,
    ExtNumeric,
}

/// A temperature. Internal representation may be either Fahrenheit or
/// Celcius. The FoxBox adapters are expected to perform conversions
/// to the format requested by their devices.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Temperature {
    /// Fahrenheit
    F(f64),
    /// Celcius
    C(f64),
}

impl Temperature {
    /// Get a temperature in Fahrenheit.
    pub fn as_f(&self) -> f64 {
        unimplemented!();
    }

    /// Get a temperature in Celcius.
    pub fn as_c(&self) -> f64 {
        unimplemented!();
    }
}

impl PartialOrd for Temperature {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.as_c().partial_cmp(&other.as_c())
    }
}

/// A color. Internal representation may vary. The FoxBox adapters are
/// expected to perform conversions to the format requested by their
/// device.
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
pub enum Color {
    RGBA(f64, f64, f64, f64, f64)
}

/// Representation of an object in JSON. It is often (albeit not
/// always) possible to choose a more precise data structure for
/// representing values send/accepted by a service. If possible,
/// adapters should rather pick such more precise data structure.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Json(pub serde_json::value::Value);

impl PartialOrd for Json {
    /// Two Json objects are never comparable to each other.
    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
        None
    }
}

/// A data structure holding a numeric value of a type that has not
/// been standardized yet.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtNumeric {
    pub value: f64,

    /// The vendor. Used for namespacing purposes, to avoid
    /// confusing two incompatible extensions with similar
    /// names. For instance, "foxlink@mozilla.com".
    pub vendor: String,

    /// Identification of the adapter introducing this value.
    /// Designed to aid with tracing and debugging.
    pub adapter: String,

    /// A string describing the nature of the value, designed to
    /// aid with type-checking.
    ///
    /// Examples: `"GroundHumidity"`.
    pub kind: String,
}

impl PartialOrd for ExtNumeric {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.vendor != other.vendor {
            return None;
        } else if self.kind != other.kind {
            return None;
        } else {
            self.value.partial_cmp(&other.value)
        }
    }
}

/// Representation of an actual value that can be sent to/received
/// from a service.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Value {
    Unit,
    Bool(bool),
    Duration(ValDuration),
    TimeStamp(TimeStamp),
    Temperature(Temperature),
    Color(Color),
    String(String),

    // FIXME: Add more as we identify needs

    /// A numeric value representing a unit that has not been
    /// standardized yet into the API.
    ExtNumeric(ExtNumeric),
    Json(Json),
    Binary {data: Vec<u8>, mimetype: String}
}

impl Value {
    pub fn get_type(&self) -> Type {
        match *self {
            Value::Unit => Type::Unit,
            Value::Bool(_) => Type::Bool,
            Value::String(_) => Type::String,
            Value::Duration(_) => Type::Duration,
            Value::TimeStamp(_) => Type::TimeStamp,
            Value::Temperature(_) => Type::Temperature,
            Value::Color(_) => Type::Color,
            Value::Json(_) => Type::Json,
            Value::Binary{..} => Type::Binary,
            Value::ExtNumeric(_) => Type::ExtNumeric,
        }
    }
}

impl PartialOrd for Value {
    /// Two values of the same type can be compared using the usual
    /// comparison for values of this type. Two values of distinct
    /// types cannot be compared.
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        use self::Value::*;
        use std::cmp::Ordering::*;
        match (self, other) {
            (&Unit, &Unit) => Some(Equal),
            (&Unit, _) => None,

            (&Bool(a), &Bool(b)) => a.partial_cmp(&b),
            (&Bool(_), _) => None,

            (&Duration(ref a), &Duration(ref b)) => a.partial_cmp(b),
            (&Duration(_), _) => None,

            (&TimeStamp(ref a), &TimeStamp(ref b)) => a.partial_cmp(b),
            (&TimeStamp(_), _) => None,

            (&Temperature(ref a), &Temperature(ref b)) => a.partial_cmp(b),
            (&Temperature(_), _) => None,

            (&Color(ref a), &Color(ref b)) => a.partial_cmp(b),
            (&Color(_), _) => None,

            (&ExtNumeric(ref a), &ExtNumeric(ref b)) => a.partial_cmp(b),
            (&ExtNumeric(_), _) => None,

            (&String(ref a), &String(ref b)) => a.partial_cmp(b),
            (&String(_), _) => None,

            (&Json(ref a), &Json(ref b)) => a.partial_cmp(b),
            (&Json(_), _) => None,

            (&Binary{mimetype: ref a_mimetype, data: ref a_data},
             &Binary{mimetype: ref b_mimetype, data: ref b_data}) if a_mimetype == b_mimetype => a_data.partial_cmp(b_data),
            (&Binary{..}, _) => None,
        }
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct ValDuration(Duration);
impl ValDuration {
    pub fn new(duration: Duration) -> Self {
        ValDuration(duration)
    }
}
impl Serialize for ValDuration {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let as_ms : u64 = self.0.as_secs() * 1000
            + (self.0.subsec_nanos() as u64) / 1_000_000;
        as_ms.serialize(serializer)
    }
}
impl Deserialize for ValDuration {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let as_ms : u64 = try!(u64::deserialize(deserializer));
        let as_sec = as_ms / 1000;
        let as_ns = (as_ms / 1_000_000) as u32;
        Ok(ValDuration(Duration::new(as_sec, as_ns)))
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct TimeStamp(chrono::DateTime<chrono::Local>);
impl Serialize for TimeStamp {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let str = self.0.to_rfc3339();
        str.serialize(serializer)
    }
}
impl Deserialize for TimeStamp {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let str = try!(String::deserialize(deserializer));
        match chrono::DateTime::<chrono::Local>::from_str(&str) {
            Ok(dt) => Ok(TimeStamp(dt)),
            Err(_) => Err(D::Error::syntax("Invalid date"))
        }
    }
}
<|endoftext|>


<commit_before>use opengles::gl2;
use cgmath::vector::{Vec2, Vec4};
use glfw;
use texture::Texture;
use shader::Shader;
use fonter::Fonter;
use stb;

static VERTEX_SHADER: &'static str =
    "#version 130
    in vec3 in_pos;
    in vec2 in_texcoord;

    uniform sampler2D texture;
    out vec2 texcoord;

    void main(void) {
        texcoord = in_texcoord;
        gl_Position = vec4(in_pos, 1.0);
    }
    ";

static FRAGMENT_SHADER: &'static str =
    "#version 130
    uniform sampler2D texture;
    in vec2 texcoord;

    void main(void) {
        vec4 col = texture2D(texture, texcoord);
        gl_FragColor = vec4(1, 1, 1, col.w);
    }
    ";

static FONT_DATA: &'static [u8] = include!("../../gen/font_data.rs");
static FONT_SIZE: f32 = 13.0;
static FONT_START_CHAR: uint = 32;
static FONT_NUM_CHARS: uint = 95;

// TODO: Make a proper type.
type Color = Vec4<u8>;

pub struct App {
    resolution: Vec2<f32>,
    draw_color: Color,
    window: ~glfw::Window,
    alive: bool,
    fonter: ~Fonter,
    texture: Option<~Texture>,
    shader: ~Shader,
}

impl App {
    pub fn new(width: uint, height: uint, title: &str) -> App {
        if !glfw::init().is_ok() {
            fail!("Failed to initialize GLFW");
        }

        let window = glfw::Window::create(width as u32, height as u32, title, glfw::Windowed)
            .expect("Failed to create GLFW window.");
        window.make_context_current();

        gl2::enable(gl2::BLEND);
        gl2::blend_func(gl2::SRC_ALPHA, gl2::ONE_MINUS_SRC_ALPHA);

        gl2::viewport(0, 0, width as i32, height as i32);
        gl2::clear(gl2::COLOR_BUFFER_BIT | gl2::DEPTH_BUFFER_BIT);

        let truetype = stb::truetype::Font::new(FONT_DATA.to_owned()).expect("Bad FONT_DATA.");

        let ret = App {
            resolution: Vec2::new(width as f32, height as f32),
            draw_color: Vec4::new(0u8, 0u8, 0u8, 255u8),
            window: ~window,
            alive: true,
            fonter: ~Fonter::new(&truetype, FONT_SIZE, FONT_START_CHAR, FONT_NUM_CHARS),
            texture: None,
            shader: ~Shader::new(VERTEX_SHADER, FRAGMENT_SHADER),
        };

        ret.shader.bind();

        ret
    }

    pub fn set_color(&mut self, color: &Color) {
        self.draw_color = *color;
    }

    pub fn draw_string(&mut self, _pos: Vec2<f32>, _text: &str) {
        self.fonter.test(self.shader);
        // TODO: This is where we'd add rectangles of the characters to the
        // rect renderer.
    }

    // TODO: Init texture
    // TODO: Draw texture rect
    // TODO: Draw filled rect

    pub fn flush(&mut self) {
        // TODO: Recter gets rendered here.
        self.window.swap_buffers();
        if self.window.should_close() {
            self.alive = false
        }
    }
}

impl Drop for App {
   fn drop(&mut self) {
        glfw::terminate();
   }
}
<commit_msg>Texture recter in app<commit_after>use std::mem;
use opengles::gl2;
use cgmath::vector::{Vec2, Vec4};
use cgmath::point::{Point2, Point3};
use cgmath::aabb::{Aabb, Aabb2};
use glfw;
use texture::Texture;
use shader::Shader;
use fonter::Fonter;
use stb;

use gl_check;

static VERTEX_SHADER: &'static str =
    "#version 130
    in vec3 in_pos;
    in vec2 in_texcoord;

    uniform sampler2D texture;
    out vec2 texcoord;

    void main(void) {
        texcoord = in_texcoord;
        gl_Position = vec4(in_pos, 1.0);
    }
    ";

static FRAGMENT_SHADER: &'static str =
    "#version 130
    uniform sampler2D texture;
    in vec2 texcoord;

    void main(void) {
        vec4 col = texture2D(texture, texcoord);
        gl_FragColor = vec4(1, 1, 1, col.w);
    }
    ";

static FONT_DATA: &'static [u8] = include!("../../gen/font_data.rs");
static FONT_SIZE: f32 = 13.0;
static FONT_START_CHAR: uint = 32;
static FONT_NUM_CHARS: uint = 95;

// TODO: Make a proper type.
type Color = Vec4<u8>;

struct Recter {
    vertices: ~[Point3<f32>],
    texcoords: ~[Point2<f32>],
    colors: ~[Color],
}

impl Recter {
    fn new() -> Recter {
        Recter {
            vertices: ~[],
            texcoords: ~[],
            colors: ~[],
        }
    }

    fn add(&mut self, area: &Aabb2<f32>, texcoords: &Aabb2<f32>, color: &Color) {
        self.vertices.push(Point3::new(area.min().x, area.min().y, 0.0));
        self.texcoords.push(Point2::new(texcoords.min().x, texcoords.max().y));
        self.colors.push(*color);

        self.vertices.push(Point3::new(area.min().x, area.max().y, 0.0));
        self.texcoords.push(Point2::new(texcoords.min().x, texcoords.min().y));
        self.colors.push(*color);

        self.vertices.push(Point3::new(area.max().x, area.max().y, 0.0));
        self.texcoords.push(Point2::new(texcoords.max().x, texcoords.min().y));
        self.colors.push(*color);

        self.vertices.push(Point3::new(area.min().x, area.min().y, 0.0));
        self.texcoords.push(Point2::new(texcoords.min().x, texcoords.max().y));
        self.colors.push(*color);

        self.vertices.push(Point3::new(area.max().x, area.max().y, 0.0));
        self.texcoords.push(Point2::new(texcoords.max().x, texcoords.min().y));
        self.colors.push(*color);

        self.vertices.push(Point3::new(area.max().x, area.min().y, 0.0));
        self.texcoords.push(Point2::new(texcoords.max().x, texcoords.max().y));
        self.colors.push(*color);
    }

    fn clear(&mut self) {
        self.vertices = ~[];
        self.texcoords = ~[];
        self.colors = ~[];
    }

    fn render(&mut self, shader: &Shader) {
        // Generate buffers.
        // TODO: Wrap STREAM_DRAW buffers into RAII handles.
	let gen = gl_check!(gl2::gen_buffers(3));
	let vert = gen[0];
	let tex = gen[1];
	let col = gen[2];

	gl_check!(gl2::bind_buffer(gl2::ARRAY_BUFFER, vert));
	gl_check!(gl2::buffer_data(gl2::ARRAY_BUFFER, self.vertices, gl2::STREAM_DRAW));

	gl_check!(gl2::bind_buffer(gl2::ARRAY_BUFFER, tex));
	gl_check!(gl2::buffer_data(gl2::ARRAY_BUFFER, self.texcoords, gl2::STREAM_DRAW));

	gl_check!(gl2::bind_buffer(gl2::ARRAY_BUFFER, col));
	gl_check!(gl2::buffer_data(gl2::ARRAY_BUFFER, self.colors, gl2::STREAM_DRAW));

        // Bind shader vars.
        let in_pos = shader.attrib("in_pos").unwrap();
	gl_check!(gl2::enable_vertex_attrib_array(in_pos));
	gl_check!(gl2::bind_buffer(gl2::ARRAY_BUFFER, vert));
	gl_check!(gl2::vertex_attrib_pointer_f32(in_pos, 3, false, mem::size_of::<Point3<f32>>() as i32, 0));
        let in_texcoord = shader.attrib("in_texcoord").unwrap();
	gl_check!(gl2::enable_vertex_attrib_array(in_texcoord));
	gl_check!(gl2::bind_buffer(gl2::ARRAY_BUFFER, tex));
	gl_check!(gl2::vertex_attrib_pointer_f32(in_texcoord, 2, false, mem::size_of::<Point2<f32>>() as i32, 0));
        // TODO: Color in shader

	gl_check!(gl2::draw_arrays(gl2::TRIANGLES, 0, self.vertices.len() as i32));
	gl_check!(gl2::bind_buffer(gl2::ARRAY_BUFFER, 0));

	gl_check!(gl2::disable_vertex_attrib_array(in_texcoord));
	gl_check!(gl2::disable_vertex_attrib_array(in_pos));

        self.clear();
        gl2::delete_buffers(gen);
    }
}

pub struct App {
    resolution: Vec2<f32>,
    draw_color: Color,
    window: ~glfw::Window,
    alive: bool,
    fonter: ~Fonter,
    texture: Option<~Texture>,
    shader: ~Shader,
    recter: Recter,
}

impl App {
    pub fn new(width: uint, height: uint, title: &str) -> App {
        if !glfw::init().is_ok() {
            fail!("Failed to initialize GLFW");
        }

        let window = glfw::Window::create(width as u32, height as u32, title, glfw::Windowed)
            .expect("Failed to create GLFW window.");
        window.make_context_current();

        gl2::enable(gl2::BLEND);
        gl2::blend_func(gl2::SRC_ALPHA, gl2::ONE_MINUS_SRC_ALPHA);

        gl2::viewport(0, 0, width as i32, height as i32);
        gl2::clear(gl2::COLOR_BUFFER_BIT | gl2::DEPTH_BUFFER_BIT);

        let truetype = stb::truetype::Font::new(FONT_DATA.to_owned()).expect("Bad FONT_DATA.");

        let ret = App {
            resolution: Vec2::new(width as f32, height as f32),
            draw_color: Vec4::new(0u8, 0u8, 0u8, 255u8),
            window: ~window,
            alive: true,
            fonter: ~Fonter::new(&truetype, FONT_SIZE, FONT_START_CHAR, FONT_NUM_CHARS),
            texture: None,
            shader: ~Shader::new(VERTEX_SHADER, FRAGMENT_SHADER),
            recter: Recter::new(),
        };

        ret.shader.bind();

        ret
    }

    pub fn set_color(&mut self, color: &Color) {
        self.draw_color = *color;
    }

    pub fn draw_string(&mut self, _pos: Vec2<f32>, _text: &str) {
        //self.fonter.test(self.shader);
        self.recter.add(
            &Aabb2::new(&Point2::new(0.0f32, 0.0f32), &Point2::new(1.0f32, 1.0f32)),
            &Aabb2::new(&Point2::new(0.0f32, 0.0f32), &Point2::new(1.0f32, 1.0f32)),
            &Vec4::new(255u8, 0u8, 0u8, 255u8));
        self.fonter.bind();
        self.recter.render(self.shader);
        // TODO: This is where we'd add rectangles of the characters to the
        // rect renderer.
    }

    // TODO: Init texture
    // TODO: Draw texture rect
    // TODO: Draw filled rect

    pub fn flush(&mut self) {
        // TODO: Recter gets rendered here.
        self.window.swap_buffers();
        if self.window.should_close() {
            self.alive = false
        }
    }
}

impl Drop for App {
   fn drop(&mut self) {
        glfw::terminate();
   }
}
<|endoftext|>


<commit_before>#[derive(Debug,PartialEq)]
pub struct SrcBlock {
    pub name: String,
    pub src: Vec<SrcKind>
}

#[derive(Debug,PartialEq)]
pub struct DefBlock {
    pub name: String,
    pub defs: Vec<(String,VarKind)>
}

#[derive(Debug,PartialEq)]
pub enum BlockKind {
    Src(SrcBlock),
    Def(DefBlock),
}

/// delimited by new line
#[derive(Debug,PartialEq)]
pub enum SrcKind {
    Logic(String, LogicKind), // ex: item_logic has_item

    // references logic in env and either--
    // node destination or return varkind;
    // logic must resolve to true
    // ex: if item_logic give_quest
    If(String, String),

    Next(String),
    Return(VarKind),
}

impl SrcKind {
    pub fn parse(mut exp: Vec<String>) -> SrcKind {
        if exp[0] == "if" {
            if exp.len() == 3 {
                let last = exp.pop().unwrap();
                SrcKind::If(exp.pop().unwrap(), last)
            }
            else { panic!("ERROR: Uneven IF Logic {:?}",exp) }
        }
        else if exp[0] == "next" {
            if exp.len() == 2 {
                SrcKind::Next(exp.pop().unwrap())
            }
            else { panic!("ERROR: Uneven NEXT Logic {:?}",exp) }
        }
        else if exp[0] == "return" {
            if exp.len() == 2 {
                SrcKind::Return(VarKind::parse(&exp.pop().unwrap()))
            }
            else { panic!("ERROR: Uneven RETURN Logic {:?}",exp) }

        }
        else {
            SrcKind::Logic(exp.remove(0),
                           LogicKind::parse(exp))
        }
    }
}

/// delimited by new line
/// should resolve to boolean
#[derive(Debug,PartialEq)]
pub enum LogicKind {
    GT(String,f32), // weight > 1
    LT(String,f32),

    //boolean checks
    Is(String),
    IsNot(String),
}

impl LogicKind {
    // TODO: conv to pop/removals
    pub fn parse(exp: Vec<String>) -> LogicKind {
        let start = 0;
        let len = exp.len() - start;

        if len == 1 {
            if exp[start].split_at(1).0 == "!" {
                LogicKind::IsNot(exp[start][1..].to_owned())
            }
            else {
                LogicKind::Is(exp[start][1..].to_owned())
            }
        }
        else if len == 3 {
            let var = VarKind::parse(&exp[start+2]);

            match var {
                VarKind::Num(num) => {
                    let key = exp[start].to_owned();
                    let sym = exp[start + 1].to_owned();

                    if sym == ">" {
                        LogicKind::GT(key,num)
                    }
                    else if sym == "<" {
                        LogicKind::LT(key,num)
                    }
                    else { panic!("ERROR: Invalid LogicKind Syntax") }
                },
                _ => { panic!("ERROR: Invalid LogicKind Value {:?}",exp) }
            }
        }
        else { panic!("ERROR: Unbalanced LogicKind Syntax ({:?})",exp) }
    }
}

#[derive(Debug,PartialEq)]
pub enum VarKind {
    String(String),
    Num(f32),
    Bool(bool),
}

impl VarKind {
    pub fn parse(t: &str) -> VarKind {
        let val;

        if let Ok(v) = t.parse::<f32>() {
            val = VarKind::Num(v);
        }
        else if let Ok(v) = t.parse::<bool>() {
            val = VarKind::Bool(v);
        }
        else { val = VarKind::String(t.to_owned()) }

        val
    }
}

pub struct Parser;
impl Parser {
    pub fn parse_blocks (src: &str) -> Vec<BlockKind> {
        let mut v = vec!();
        let mut exp = String::new();
        let mut exps: Vec<String> = vec!();
        let mut block: Option<BlockKind> = None;

        let mut in_string = false;

        for c in src.chars() {
            if c == '\n' && !in_string {
                for n in exp.split_whitespace() {
                    exps.push(n.trim().to_owned());
                }
                exp = String::new();

                if exps.len() < 1 { continue }

                // determine block type
                if block.is_none() {
                    let name = exps.pop().unwrap();

                    if name == "with" {
                        let b = DefBlock {
                            name: exps.pop().unwrap(),
                            defs: vec!()
                        };

                        block = Some(BlockKind::Def(b));
                    }
                    else {
                        let b = SrcBlock {
                            name: name,
                            src: vec!()
                        };

                        block = Some(BlockKind::Src(b));
                    }
                }
                else { // build block type
                    match block {
                        Some(BlockKind::Def(ref mut b)) => {
                            b.defs.push((exps[0].to_owned(),
                                         VarKind::parse(&exps[1])));
                        },
                        Some(BlockKind::Src(ref mut b)) => {
                            println!("EXPS{:?}",exps);
                            b.src.push(SrcKind::parse(exps));
                        },
                        _ => {}
                    }

                    exps = vec!();
                }
            }
            else if c == '"' {
                in_string = !in_string;
                if in_string {
                    for n in exp.split_whitespace() {
                        exps.push(n.trim().to_owned());
                    }
                    exp = String::new();
                }
                else if !in_string {
                    exps.push(exp);
                    exp = String::new();
                }
            }
            else if c == ';' && !in_string {
                //fail otherwise, block should be built!
                v.push(block.unwrap());
                block = None;
            }
            else {
                exp.push(c);
            }
        }

        v
    }
}
<commit_msg>remove if<commit_after>#[derive(Debug,PartialEq)]
pub struct SrcBlock {
    pub name: String,
    pub src: Vec<SrcKind>
}

#[derive(Debug,PartialEq)]
pub struct DefBlock {
    pub name: String,
    pub defs: Vec<(String,VarKind)>
}

#[derive(Debug,PartialEq)]
pub enum BlockKind {
    Src(SrcBlock),
    Def(DefBlock),
}

/// delimited by new line
#[derive(Debug,PartialEq)]
pub enum SrcKind {
    Logic(String, LogicKind), // ex: item_logic has_item

    Next(String),
    Return(VarKind),
}

impl SrcKind {
    pub fn parse(mut exp: Vec<String>) -> SrcKind {
        if exp[0] == "next" {
            if exp.len() == 2 {
                SrcKind::Next(exp.pop().unwrap())
            }
            else { panic!("ERROR: Uneven NEXT Logic {:?}",exp) }
        }
        else if exp[0] == "return" {
            if exp.len() == 2 {
                SrcKind::Return(VarKind::parse(&exp.pop().unwrap()))
            }
            else { panic!("ERROR: Uneven RETURN Logic {:?}",exp) }

        }
        else {
            SrcKind::Logic(exp.remove(0),
                           LogicKind::parse(exp))
        }
    }
}

/// delimited by new line
/// should resolve to boolean
#[derive(Debug,PartialEq)]
pub enum LogicKind {
    GT(String,f32), // weight > 1
    LT(String,f32),

    //boolean checks
    Is(String),
    IsNot(String),
}

impl LogicKind {
    // TODO: conv to pop/removals
    pub fn parse(exp: Vec<String>) -> LogicKind {
        let start = 0;
        let len = exp.len() - start;

        if len == 1 {
            if exp[start].split_at(1).0 == "!" {
                LogicKind::IsNot(exp[start][1..].to_owned())
            }
            else {
                LogicKind::Is(exp[start][1..].to_owned())
            }
        }
        else if len == 3 {
            let var = VarKind::parse(&exp[start+2]);

            match var {
                VarKind::Num(num) => {
                    let key = exp[start].to_owned();
                    let sym = exp[start + 1].to_owned();

                    if sym == ">" {
                        LogicKind::GT(key,num)
                    }
                    else if sym == "<" {
                        LogicKind::LT(key,num)
                    }
                    else { panic!("ERROR: Invalid LogicKind Syntax") }
                },
                _ => { panic!("ERROR: Invalid LogicKind Value {:?}",exp) }
            }
        }
        else { panic!("ERROR: Unbalanced LogicKind Syntax ({:?})",exp) }
    }
}

#[derive(Debug,PartialEq)]
pub enum VarKind {
    String(String),
    Num(f32),
    Bool(bool),
}

impl VarKind {
    pub fn parse(t: &str) -> VarKind {
        let val;

        if let Ok(v) = t.parse::<f32>() {
            val = VarKind::Num(v);
        }
        else if let Ok(v) = t.parse::<bool>() {
            val = VarKind::Bool(v);
        }
        else { val = VarKind::String(t.to_owned()) }

        val
    }
}

pub struct Parser;
impl Parser {
    pub fn parse_blocks (src: &str) -> Vec<BlockKind> {
        let mut v = vec!();
        let mut exp = String::new();
        let mut exps: Vec<String> = vec!();
        let mut block: Option<BlockKind> = None;

        let mut in_string = false;

        for c in src.chars() {
            if c == '\n' && !in_string {
                for n in exp.split_whitespace() {
                    exps.push(n.trim().to_owned());
                }
                exp = String::new();

                if exps.len() < 1 { continue }

                // determine block type
                if block.is_none() {
                    let name = exps.pop().unwrap();

                    if name == "with" {
                        let b = DefBlock {
                            name: exps.pop().unwrap(),
                            defs: vec!()
                        };

                        block = Some(BlockKind::Def(b));
                    }
                    else {
                        let b = SrcBlock {
                            name: name,
                            src: vec!()
                        };

                        block = Some(BlockKind::Src(b));
                    }
                }
                else { // build block type
                    match block {
                        Some(BlockKind::Def(ref mut b)) => {
                            b.defs.push((exps[0].to_owned(),
                                         VarKind::parse(&exps[1])));
                        },
                        Some(BlockKind::Src(ref mut b)) => {
                            println!("EXPS{:?}",exps);
                            b.src.push(SrcKind::parse(exps));
                        },
                        _ => {}
                    }

                    exps = vec!();
                }
            }
            else if c == '"' {
                in_string = !in_string;
                if in_string {
                    for n in exp.split_whitespace() {
                        exps.push(n.trim().to_owned());
                    }
                    exp = String::new();
                }
                else if !in_string {
                    exps.push(exp);
                    exp = String::new();
                }
            }
            else if c == ';' && !in_string {
                //fail otherwise, block should be built!
                v.push(block.unwrap());
                block = None;
            }
            else {
                exp.push(c);
            }
        }

        v
    }
}
<|endoftext|>


<commit_before>extern crate nickel;
extern crate mysql;
extern crate time;

use database::Database;

mod database;
mod note;
mod settings;
mod result;

fn main() {
    let database = Database::new(settings::DATABASE_USERNAME.to_string());
}
<commit_msg>Begin nickel integration<commit_after>extern crate nickel;
extern crate mysql;
extern crate time;

use std::io::net::ip::Ipv4Addr;
use nickel::{
    Nickel,
    Request,
    Response,
};

use database::Database;

mod database;
mod note;
mod settings;
mod result;

fn main() {
    // Initialize database connection.
    let database = Database::new(settings::DATABASE_USERNAME.to_string());

    // Initialize webserver.
    let mut server = Nickel::new();

    fn a_handler(_request: &Request, response: &mut Response) {
        response.send("hello world");
    }

    fn get_note(request: &Request, response: &mut Response) {
        let noteid = request.params.get(&"noteid".to_string());

        let note = database.get_note(noteid);

        response.send(noteid.as_slice());
        response.send("test");
    }

    server.get("/", a_handler);
    server.get("/note/:noteid", get_note);
    server.listen(Ipv4Addr(127, 0, 0, 1), 3000);
    println!("Server listening on 3000.");
}
<|endoftext|>


<commit_before>use bytes::{BufMut, BytesMut};

use std::io;
use std::mem;
use std::str;

use tokio_core::net::TcpStream;
use tokio_io::codec::{Decoder, Encoder, Framed};
use tokio_tls::TlsStream;

use parser;

pub type ImapTransport = Framed<TlsStream<TcpStream>, ImapCodec>;

pub struct ImapCodec;

impl<'a> Decoder for ImapCodec {
    type Item = ResponseData;
    type Error = io::Error;
    fn decode(&mut self, buf: &mut BytesMut)
             -> Result<Option<Self::Item>, io::Error> {
        if let Some(n) = buf.iter().position(|b| *b == b'\n') {
            let msg = buf.split_to(n - 1);
            buf.split_to(2);
            let owned = str::from_utf8(&msg).unwrap().to_string();
            Ok(Some(ResponseData::new(owned)))
        } else {
            Ok(None)
        }
    }
}

impl Encoder for ImapCodec {
    type Item = Request;
    type Error = io::Error;
    fn encode(&mut self, msg: Self::Item, dst: &mut BytesMut)
             -> Result<(), io::Error> {
        dst.put(msg.0.as_bytes());
        dst.put(b' ');
        dst.put(msg.1.to_string().as_bytes());
        dst.put("\r\n");
        Ok(())
    }
}

#[derive(Debug)]
pub struct Request(pub RequestId, pub Command);

#[derive(Debug)]
pub enum Command {
    Check,
    Fetch(SequenceSet, MessageData),
    Login(String, String),
    Select(String),
}

impl ToString for Command {
    fn to_string(&self) -> String {
        match *self {
            Command::Check => {
                format!("CHECK")
            },
            Command::Fetch(ref set, ref items) => {
                format!("FETCH {} {}", &set.to_string(), &items.to_string())
            },
            Command::Login(ref user_name, ref password) => {
                format!("LOGIN {} {}", user_name, password)
            },
            Command::Select(ref mailbox) => {
                format!("SELECT {}", mailbox)
            },
        }
    }
}

#[derive(Debug)]
pub enum MessageData {
    All,
    Fast,
    Full,
}

impl ToString for MessageData {
    fn to_string(&self) -> String {
        use self::MessageData::*;
        match *self {
            All => "ALL".to_string(),
            Fast => "FAST".to_string(),
            Full => "FULL".to_string(),
        }
    }
}

#[derive(Debug)]
pub enum SequenceSet {
    Range(usize, usize),
}

impl ToString for SequenceSet {
    fn to_string(&self) -> String {
        use self::SequenceSet::*;
        match *self {
            Range(start, stop) => format!("{}:{}", start, stop),
        }
    }
}

#[derive(Debug)]
pub struct ResponseData {
    raw: String,
    pub response: Response<'static>,
}

impl ResponseData {
    fn new<'a>(raw: String) -> ResponseData {
        let rsp = unsafe { mem::transmute(parser::parse(&raw)) };
        ResponseData {
            raw: raw,
            response: rsp,
        }
    }
    pub fn request_id(&self) -> Option<&RequestId> {
        match self.response {
            Response::Done(ref req_id, ..) => Some(req_id),
            _ => None,
        }
    }
}

#[derive(Debug)]
pub enum Response<'a> {
    Capabilities(Vec<&'a str>),
    Done(RequestId, Status, Option<ResponseCode<'a>>, &'a str),
    Data(Status, Option<ResponseCode<'a>>, &'a str),
    Expunge(usize),
    Fetch(usize, Vec<Attribute<'a>>),
    MailboxData(MailboxDatum<'a>),
}

#[allow(dead_code)]
#[derive(Debug)]
pub enum Status {
    Ok,
    No,
    Bad,
    PreAuth,
    Bye,
}

#[derive(Debug)]
pub enum ResponseCode<'a> {
    PermanentFlags(Vec<&'a str>),
    ReadOnly,
    ReadWrite,
    TryCreate,
    UidNext(usize),
    UidValidity(usize),
}

#[derive(Debug)]
pub enum MailboxDatum<'a> {
    Exists(usize),
    Flags(Vec<&'a str>),
    Recent(usize),
}

#[derive(Debug)]
pub enum Attribute<'a> {
    Envelope(Envelope<'a>),
    Flags(Vec<&'a str>),
    InternalDate(&'a str),
    Rfc822Size(usize),
}

#[derive(Debug)]
pub struct Envelope<'a> {
    pub date: Option<&'a str>,
    pub subject: Option<&'a str>,
    pub from: Option<Vec<Address<'a>>>,
    pub sender: Option<Vec<Address<'a>>>,
    pub reply_to: Option<Vec<Address<'a>>>,
    pub to: Option<Vec<Address<'a>>>,
    pub cc: Option<Vec<Address<'a>>>,
    pub bcc: Option<Vec<Address<'a>>>,
    pub in_reply_to: Option<&'a str>,
    pub message_id: Option<&'a str>,
}

#[derive(Debug)]
pub struct Address<'a> {
    pub name: Option<&'a str>,
    pub adl: Option<&'a str>,
    pub mailbox: Option<&'a str>,
    pub host: Option<&'a str>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RequestId(pub String);

impl RequestId {
    fn as_bytes(&self) -> &[u8] {
        self.0.as_bytes()
    }
}

pub struct IdGenerator {
    next: u64,
}

impl IdGenerator {
    pub fn new() -> IdGenerator {
        IdGenerator { next: 0 }
    }
}

impl Iterator for IdGenerator {
    type Item = RequestId;
    fn next(&mut self) -> Option<Self::Item> {
        self.next += 1;
        Some(RequestId(format!("A{:04}", self.next % 10000)))
    }
}

#[allow(dead_code)]
pub enum State {
    NotAuthenticated,
    Authenticated,
    Selected,
    Logout,
}
<commit_msg>Add a comment about the use of unsafe<commit_after>use bytes::{BufMut, BytesMut};

use std::io;
use std::mem;
use std::str;

use tokio_core::net::TcpStream;
use tokio_io::codec::{Decoder, Encoder, Framed};
use tokio_tls::TlsStream;

use parser;

pub type ImapTransport = Framed<TlsStream<TcpStream>, ImapCodec>;

pub struct ImapCodec;

impl<'a> Decoder for ImapCodec {
    type Item = ResponseData;
    type Error = io::Error;
    fn decode(&mut self, buf: &mut BytesMut)
             -> Result<Option<Self::Item>, io::Error> {
        if let Some(n) = buf.iter().position(|b| *b == b'\n') {
            let msg = buf.split_to(n - 1);
            buf.split_to(2);
            let owned = str::from_utf8(&msg).unwrap().to_string();
            Ok(Some(ResponseData::new(owned)))
        } else {
            Ok(None)
        }
    }
}

impl Encoder for ImapCodec {
    type Item = Request;
    type Error = io::Error;
    fn encode(&mut self, msg: Self::Item, dst: &mut BytesMut)
             -> Result<(), io::Error> {
        dst.put(msg.0.as_bytes());
        dst.put(b' ');
        dst.put(msg.1.to_string().as_bytes());
        dst.put("\r\n");
        Ok(())
    }
}

#[derive(Debug)]
pub struct Request(pub RequestId, pub Command);

#[derive(Debug)]
pub enum Command {
    Check,
    Fetch(SequenceSet, MessageData),
    Login(String, String),
    Select(String),
}

impl ToString for Command {
    fn to_string(&self) -> String {
        match *self {
            Command::Check => {
                format!("CHECK")
            },
            Command::Fetch(ref set, ref items) => {
                format!("FETCH {} {}", &set.to_string(), &items.to_string())
            },
            Command::Login(ref user_name, ref password) => {
                format!("LOGIN {} {}", user_name, password)
            },
            Command::Select(ref mailbox) => {
                format!("SELECT {}", mailbox)
            },
        }
    }
}

#[derive(Debug)]
pub enum MessageData {
    All,
    Fast,
    Full,
}

impl ToString for MessageData {
    fn to_string(&self) -> String {
        use self::MessageData::*;
        match *self {
            All => "ALL".to_string(),
            Fast => "FAST".to_string(),
            Full => "FULL".to_string(),
        }
    }
}

#[derive(Debug)]
pub enum SequenceSet {
    Range(usize, usize),
}

impl ToString for SequenceSet {
    fn to_string(&self) -> String {
        use self::SequenceSet::*;
        match *self {
            Range(start, stop) => format!("{}:{}", start, stop),
        }
    }
}

#[derive(Debug)]
pub struct ResponseData {
    raw: String,
    pub response: Response<'static>,
}

impl ResponseData {
    fn new<'a>(raw: String) -> ResponseData {
        // This SHOULD be acceptable/safe: the String memory is allocated on
        // the heap, so that moving the String itself does not invalidate
        // references to the string data contained in the parsed Response.
        let rsp = unsafe { mem::transmute(parser::parse(&raw)) };
        ResponseData {
            raw: raw,
            response: rsp,
        }
    }
    pub fn request_id(&self) -> Option<&RequestId> {
        match self.response {
            Response::Done(ref req_id, ..) => Some(req_id),
            _ => None,
        }
    }
}

#[derive(Debug)]
pub enum Response<'a> {
    Capabilities(Vec<&'a str>),
    Done(RequestId, Status, Option<ResponseCode<'a>>, &'a str),
    Data(Status, Option<ResponseCode<'a>>, &'a str),
    Expunge(usize),
    Fetch(usize, Vec<Attribute<'a>>),
    MailboxData(MailboxDatum<'a>),
}

#[allow(dead_code)]
#[derive(Debug)]
pub enum Status {
    Ok,
    No,
    Bad,
    PreAuth,
    Bye,
}

#[derive(Debug)]
pub enum ResponseCode<'a> {
    PermanentFlags(Vec<&'a str>),
    ReadOnly,
    ReadWrite,
    TryCreate,
    UidNext(usize),
    UidValidity(usize),
}

#[derive(Debug)]
pub enum MailboxDatum<'a> {
    Exists(usize),
    Flags(Vec<&'a str>),
    Recent(usize),
}

#[derive(Debug)]
pub enum Attribute<'a> {
    Envelope(Envelope<'a>),
    Flags(Vec<&'a str>),
    InternalDate(&'a str),
    Rfc822Size(usize),
}

#[derive(Debug)]
pub struct Envelope<'a> {
    pub date: Option<&'a str>,
    pub subject: Option<&'a str>,
    pub from: Option<Vec<Address<'a>>>,
    pub sender: Option<Vec<Address<'a>>>,
    pub reply_to: Option<Vec<Address<'a>>>,
    pub to: Option<Vec<Address<'a>>>,
    pub cc: Option<Vec<Address<'a>>>,
    pub bcc: Option<Vec<Address<'a>>>,
    pub in_reply_to: Option<&'a str>,
    pub message_id: Option<&'a str>,
}

#[derive(Debug)]
pub struct Address<'a> {
    pub name: Option<&'a str>,
    pub adl: Option<&'a str>,
    pub mailbox: Option<&'a str>,
    pub host: Option<&'a str>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RequestId(pub String);

impl RequestId {
    fn as_bytes(&self) -> &[u8] {
        self.0.as_bytes()
    }
}

pub struct IdGenerator {
    next: u64,
}

impl IdGenerator {
    pub fn new() -> IdGenerator {
        IdGenerator { next: 0 }
    }
}

impl Iterator for IdGenerator {
    type Item = RequestId;
    fn next(&mut self) -> Option<Self::Item> {
        self.next += 1;
        Some(RequestId(format!("A{:04}", self.next % 10000)))
    }
}

#[allow(dead_code)]
pub enum State {
    NotAuthenticated,
    Authenticated,
    Selected,
    Logout,
}
<|endoftext|>


<commit_before>// lock-free radix tree
// this is purpose-built for mapping PageID's to T's
// it supports optimistic mutation, without automatic retry
// goal: high pointer density with a dense address space
// it never deallocates space, eventually this will be addressed

use std::ptr;
use std::sync::Arc;
use std::sync::atomic::{AtomicPtr, Ordering};

use super::*;

const FANFACTOR: u64 = 6;
const FANOUT: u64 = 1 << FANFACTOR;
const FAN_MASK: u64 = FANOUT - 1;

#[inline(always)]
pub fn split_fanout(i: u64) -> (u64, u64) {
    let rem = i >> FANFACTOR;
    let first_6 = i & FAN_MASK;
    (first_6, rem)
}

#[derive(Clone)]
struct Node<T> {
    inner: Arc<AtomicPtr<T>>,
    children: Arc<Vec<AtomicPtr<Node<T>>>>,
}

impl<T> Default for Node<T> {
    fn default() -> Node<T> {
        let children = rep_no_copy!(AtomicPtr::new(ptr::null_mut()); FANOUT as usize);
        Node {
            inner: Arc::new(AtomicPtr::new(ptr::null_mut())),
            children: Arc::new(children),
        }
    }
}

impl<T> Drop for Node<T> {
    fn drop(&mut self) {
        for c in self.children.iter() {
            let ptr = c.load(Ordering::SeqCst);
            if !ptr.is_null() {
                unsafe { Box::from_raw(ptr) };
            }
        }
    }
}

impl<T> Node<T> {
    fn cas(&self, pid: PageID, old: *mut T, new: *mut T) -> Result<(), ()> {
        if pid == 0 {
            // we've reached the CAS node
            if old == self.inner.compare_and_swap(old, new, Ordering::SeqCst) {
                return Ok(());
            } else {
                return Err(());
            }
        }
        let (first_six, remainder) = split_fanout(pid);
        let child_index = first_six as usize;
        let ref slot = self.children[child_index];
        let mut next_ptr = slot.load(Ordering::SeqCst);
        if next_ptr.is_null() {
            let child = Node::default();
            let child_ptr = Box::into_raw(Box::new(child));
            let ret = slot.compare_and_swap(next_ptr, child_ptr, Ordering::SeqCst);
            if ret == next_ptr {
                // CAS worked
                next_ptr = child_ptr;
            } else {
                // another thread beat us, drop child and use what they set
                unsafe { Box::from_raw(child_ptr) };
                next_ptr = ret;
            }
        }

        let ret = unsafe { (*next_ptr).cas(remainder, old, new) };
        ret
    }

    fn get(&self, pid: PageID) -> Option<*mut T> {
        if pid == 0 {
            // we've reached our Node
            let v = self.inner.load(Ordering::SeqCst);
            if v.is_null() {
                return None;
            } else {
                return Some(v);
            }
        }
        // we need to continue
        let (first_six, remainder) = split_fanout(pid);
        let next_ptr = self.children[first_six as usize].load(Ordering::SeqCst);
        if next_ptr.is_null() {
            return None;
        }
        let ret = unsafe { (*next_ptr).get(remainder) };
        ret
    }
}

#[derive(Clone)]
pub struct Radix<T> {
    head: Arc<Node<T>>,
}

impl<T> Default for Radix<T> {
    fn default() -> Radix<T> {
        let head = Node::default();
        Radix { head: Arc::new(head) }
    }
}

impl<T> Radix<T> {
    pub fn insert(&self, pid: PageID, inner: *mut T) -> Result<(), ()> {
        self.head.cas(pid, ptr::null_mut(), inner)
    }

    pub fn cas(&self, pid: PageID, old: *mut T, new: *mut T) -> Result<(), ()> {
        self.head.cas(pid, old, new)
    }

    pub fn get(&self, pid: PageID) -> Option<*mut T> {
        self.head.get(pid)

    }

    pub fn del(&self, pid: PageID) -> Result<(), ()> {
        if let Some(cur) = self.get(pid) {
            self.cas(pid, cur, ptr::null_mut())
        } else {
            Err(())
        }
    }
}

#[test]
fn test_split_fanout() {
    let i = 0 + 0b111111;
    assert_eq!(split_fanout(i), (0b111111, 0));
}

#[test]
fn basic_functionality() {
    let rt = Radix::default();
    let one = Box::into_raw(Box::new(1));
    let two = Box::into_raw(Box::new(2));
    let three = Box::into_raw(Box::new(3));
    let four = Box::into_raw(Box::new(4));
    let five = Box::into_raw(Box::new(5));
    let six = Box::into_raw(Box::new(6));
    rt.insert(0, five).unwrap();
    assert_eq!(rt.get(0), Some(five));
    rt.cas(0, five, six).unwrap();
    assert_eq!(rt.get(0), Some(six));
    rt.del(0).unwrap();
    assert_eq!(rt.get(0), None);

    rt.insert(321, two).unwrap();
    assert_eq!(rt.get(321), Some(two));
    assert_eq!(rt.get(322), None);
    rt.insert(322, three).unwrap();
    assert_eq!(rt.get(322), Some(three));
    assert_eq!(rt.get(321), Some(two));
}
<commit_msg>refactor radix a bit<commit_after>// lock-free radix tree
// this is purpose-built for mapping PageID's to T's
// it supports optimistic mutation, without automatic retry
// goal: high pointer density with a dense address space
// it never deallocates space, eventually this will be addressed

use std::ptr;
use std::sync::Arc;
use std::sync::atomic::{AtomicPtr, Ordering};

use super::*;

const FANFACTOR: u64 = 6;
const FANOUT: u64 = 1 << FANFACTOR;
const FAN_MASK: u64 = FANOUT - 1;

#[inline(always)]
fn split_fanout(i: u64) -> (u64, u64) {
    let rem = i >> FANFACTOR;
    let first_6 = i & FAN_MASK;
    (first_6, rem)
}

#[derive(Clone)]
struct Node<T> {
    inner: Arc<AtomicPtr<T>>,
    children: Arc<Vec<AtomicPtr<Node<T>>>>,
}

impl<T> Default for Node<T> {
    fn default() -> Node<T> {
        let children = rep_no_copy!(AtomicPtr::new(ptr::null_mut()); FANOUT as usize);
        Node {
            inner: Arc::new(AtomicPtr::new(ptr::null_mut())),
            children: Arc::new(children),
        }
    }
}

impl<T> Drop for Node<T> {
    fn drop(&mut self) {
        for c in self.children.iter() {
            let ptr = c.load(Ordering::SeqCst);
            if !ptr.is_null() {
                unsafe { Box::from_raw(ptr) };
            }
        }
    }
}

#[derive(Clone)]
pub struct Radix<T> {
    head: Arc<Node<T>>,
}

impl<T> Default for Radix<T> {
    fn default() -> Radix<T> {
        let head = Node::default();
        Radix { head: Arc::new(head) }
    }
}

impl<T> Radix<T> {
    pub fn insert(&self, pid: PageID, inner: *mut T) -> Result<*mut T, *mut T> {
        self.cas(pid, ptr::null_mut(), inner)
    }

    pub fn swap(&self, pid: PageID, new: *mut T) -> *mut T {
        let tip = traverse(&*self.head as *const Node<T>, pid, true);
        if tip.is_null() {
            return ptr::null_mut();
        }

        unsafe { (*tip).inner.swap(new, Ordering::SeqCst) }
    }

    pub fn cas(&self, pid: PageID, old: *mut T, new: *mut T) -> Result<*mut T, *mut T> {
        let tip = traverse(&*self.head as *const Node<T>, pid, true);
        if tip.is_null() {
            return Err(ptr::null_mut());
        }

        let res = unsafe { (*tip).inner.compare_and_swap(old, new, Ordering::SeqCst) };
        if old == res {
            return Ok(res);
        } else {
            return Err(res);
        }
    }

    pub fn get(&self, pid: PageID) -> Option<*mut T> {
        let tip = traverse(&*self.head as *const Node<T>, pid, false);
        if tip.is_null() {
            return None;
        }
        let v = unsafe { (*tip).inner.load(Ordering::SeqCst) };
        if v.is_null() {
            None
        } else {
            Some(v)
        }
    }

    pub fn del(&self, pid: PageID) -> *mut T {
        self.swap(pid, ptr::null_mut())
    }
}

#[inline(always)]
fn traverse<T>(ptr: *const Node<T>, pid: PageID, create_intermediate: bool) -> *const Node<T> {
    if pid == 0 {
        return ptr;
    }

    let (first_six, remainder) = split_fanout(pid);
    let child_index = first_six as usize;
    let children = unsafe { (*ptr).children.clone() };
    let mut next_ptr = children[child_index].load(Ordering::SeqCst);

    if next_ptr.is_null() {
        if !create_intermediate {
            return ptr::null_mut();
        }

        let child = Node::default();
        let child_ptr = Box::into_raw(Box::new(child));
        let ret = children[child_index].compare_and_swap(next_ptr, child_ptr, Ordering::SeqCst);
        if ret == next_ptr {
            // CAS worked
            next_ptr = child_ptr;
        } else {
            // another thread beat us, drop unused created
            // child and use what is already set
            unsafe { Box::from_raw(child_ptr) };
            next_ptr = ret;
        }
    }

    traverse(next_ptr, remainder, create_intermediate)
}

#[test]
fn test_split_fanout() {
    let i = 0 + 0b111111;
    assert_eq!(split_fanout(i), (0b111111, 0));
}

#[test]
fn basic_functionality() {
    let rt = Radix::default();
    let one = Box::into_raw(Box::new(1));
    let two = Box::into_raw(Box::new(2));
    let three = Box::into_raw(Box::new(3));
    let four = Box::into_raw(Box::new(4));
    let five = Box::into_raw(Box::new(5));
    let six = Box::into_raw(Box::new(6));
    rt.insert(0, five).unwrap();
    assert_eq!(rt.get(0), Some(five));
    rt.cas(0, five, six).unwrap();
    assert_eq!(rt.get(0), Some(six));
    assert_ne!(rt.del(0), ptr::null_mut());
    assert_eq!(rt.get(0), None);

    rt.insert(321, two).unwrap();
    assert_eq!(rt.get(321), Some(two));
    assert_eq!(rt.get(322), None);
    rt.insert(322, three).unwrap();
    assert_eq!(rt.get(322), Some(three));
    assert_eq!(rt.get(321), Some(two));
}
<|endoftext|>


<commit_before>//! The Scene system is basically for transitioning between
//! *completely* different states that have entirely different game
//! loops and but which all share a state.  It operates as a stack, with new
//! scenes getting pushed to the stack (while the old ones stay in
//! memory unchanged).  Apparently this is basically a push-down automata.
//!
//! Also there's no reason you can't have a Scene contain its own
//! Scene subsystem to do its own indirection.  With a different state
//! type, as well!  What fun!  Though whether you want to go that deep
//! down the rabbit-hole is up to you.  I haven't found it necessary
//! yet.
//!
//! This is basically identical in concept to the Amethyst engine's scene
//! system, the only difference is the details of how the pieces are put
//! together.

use ggez;

use input;

pub enum SceneSwitch<C, Ev> {
    None,
    Push(Box<Scene<C, Ev>>),
    Replace(Box<Scene<C, Ev>>),
    Pop,
}

pub trait Scene<C, Ev> {
    fn update(&mut self, gameworld: &mut C) -> SceneSwitch<C, Ev>;
    fn draw(&mut self, gameworld: &mut C, ctx: &mut ggez::Context) -> ggez::GameResult<()>;
    fn input(&mut self, gameworld: &mut C, event: Ev, started: bool);
    /// Only used for human-readable convenience (or not at all, tbh)
    fn name(&self) -> &str;
    /// Whether or not to draw the next lowest scene on the stack as well;
    /// this is useful for GUI stuff that only partially covers the screen.
    fn draw_previous(&self) -> bool {
        false
    }
}

impl<C, Ev> SceneSwitch<C, Ev> {
    /// Convenient shortcut function for boxing scenes.
    ///
    /// Slightly nicer than writing
    /// `SceneSwitch::Replace(Box::new(x))` all the damn time.
    fn replace<S>(scene: S) -> Self
        where S: Scene<C, Ev> + 'static {
        SceneSwitch::Replace(Box::new(scene))
    }

    /// Same as `replace()` but returns SceneSwitch::Push
    fn push<S>(scene: S) -> Self
        where S: Scene<C, Ev> + 'static {
        SceneSwitch::Push(Box::new(scene))
    }

}

pub struct SceneStack<C, Ev> {
    pub world: C,
    scenes: Vec<Box<Scene<C, Ev>>>,
}

impl<C, Ev> SceneStack<C, Ev> {
    pub fn new<F>(ctx: &mut ggez::Context, creator: F) -> Self
        where F: Fn(&mut ggez::Context) -> C
    {
        let c = creator(ctx);
        Self {
            world: c,
            scenes: Vec::new(),
        }
    }

    pub fn push(&mut self, scene: Box<Scene<C, Ev>>) {
        self.scenes.push(scene)
    }

    pub fn pop(&mut self) -> Box<Scene<C, Ev>> {
        self.scenes
            .pop()
            .expect("ERROR: Popped an empty scene stack.")
    }

    pub fn current(&self) -> &Scene<C, Ev> {
        &**self.scenes
            .last()
            .expect("ERROR: Tried to get current scene of an empty scene stack.")
    }

    pub fn switch(&mut self, next_scene: SceneSwitch<C, Ev>) -> Option<Box<Scene<C, Ev>>> {
        // let operation = self.current_mut().next();
        match next_scene {
            SceneSwitch::None => None,
            SceneSwitch::Pop => {
                let s = self.pop();
                let current_name = self.current().name();
                Some(s)
            }
            SceneSwitch::Push(s) => {
                self.push(s);
                None
            }
            SceneSwitch::Replace(s) => {
                let old_scene = self.pop();
                self.push(s);
                Some(old_scene)

            }
        }
    }

    // These functions must be on the SceneStack because otherwise
    // if you try to get the current scene and the world to call
    // update() on the current scene it causes a double-borrow.  :/
    pub fn update(&mut self) {
        let next_scene = {
            let current_scene = &mut **self.scenes
                .last_mut()
                .expect("Tried to update empty scene stack");
            current_scene.update(&mut self.world)
        };
        self.switch(next_scene);
    }

    // We walk down the scene stack until we find a scene where we aren't
    // supposed to draw the previous one, then draw them from the bottom up.
    //
    // This allows for layering GUI's and such.
    fn draw_scenes(scenes: &mut [Box<Scene<C, Ev>>], world: &mut C, ctx: &mut ggez::Context) {
        if scenes.len() > 0 {
            if let Some((current, rest)) = scenes.split_last_mut() {
                if current.draw_previous() {
                    SceneStack::draw_scenes(rest, world, ctx);
                }
                current.draw(world, ctx)
                    .expect("I would hope drawing a scene never fails!");

            }
        }
    }

    pub fn draw(&mut self, ctx: &mut ggez::Context) {
        SceneStack::draw_scenes(&mut self.scenes, &mut self.world, ctx)
    }

    pub fn input(&mut self, event: Ev, started: bool) {
        let current_scene = &mut **self.scenes
            .last_mut()
            .expect("Tried to do input for empty scene stack");
        current_scene.input(&mut self.world, event, started);
    }
}

<commit_msg>Argh made SceneSwitch sized again<commit_after>//! The Scene system is basically for transitioning between
//! *completely* different states that have entirely different game
//! loops and but which all share a state.  It operates as a stack, with new
//! scenes getting pushed to the stack (while the old ones stay in
//! memory unchanged).  Apparently this is basically a push-down automata.
//!
//! Also there's no reason you can't have a Scene contain its own
//! Scene subsystem to do its own indirection.  With a different state
//! type, as well!  What fun!  Though whether you want to go that deep
//! down the rabbit-hole is up to you.  I haven't found it necessary
//! yet.
//!
//! This is basically identical in concept to the Amethyst engine's scene
//! system, the only difference is the details of how the pieces are put
//! together.

use ggez;

use input;

pub enum SceneSwitch<C, Ev> {
    None,
    Push(Box<Scene<C, Ev>>),
    Replace(Box<Scene<C, Ev>>),
    Pop,
}

pub trait Scene<C, Ev> {
    fn update(&mut self, gameworld: &mut C) -> SceneSwitch<C, Ev>;
    fn draw(&mut self, gameworld: &mut C, ctx: &mut ggez::Context) -> ggez::GameResult<()>;
    fn input(&mut self, gameworld: &mut C, event: Ev, started: bool);
    /// Only used for human-readable convenience (or not at all, tbh)
    fn name(&self) -> &str;
    /// Whether or not to draw the next lowest scene on the stack as well;
    /// this is useful for GUI stuff that only partially covers the screen.
    fn draw_previous(&self) -> bool {
        false
    }
}

impl<C, Ev> SceneSwitch<C, Ev> {
    /// Convenient shortcut function for boxing scenes.
    ///
    /// Slightly nicer than writing
    /// `SceneSwitch::Replace(Box::new(x))` all the damn time.
    fn replace(scene: Box<Scene<C, Ev>>) -> Self {
        SceneSwitch::Replace(scene)
    }

    /// Same as `replace()` but returns SceneSwitch::Push
    fn push(scene: Box<Scene<C, Ev>>) -> Self {
        SceneSwitch::Push(scene)
    }
}

pub struct SceneStack<C, Ev> {
    pub world: C,
    scenes: Vec<Box<Scene<C, Ev>>>,
}

impl<C, Ev> SceneStack<C, Ev> {
    pub fn new<F>(ctx: &mut ggez::Context, creator: F) -> Self
        where F: Fn(&mut ggez::Context) -> C
    {
        let c = creator(ctx);
        Self {
            world: c,
            scenes: Vec::new(),
        }
    }

    pub fn push(&mut self, scene: Box<Scene<C, Ev>>) {
        self.scenes.push(scene)
    }

    pub fn pop(&mut self) -> Box<Scene<C, Ev>> {
        self.scenes
            .pop()
            .expect("ERROR: Popped an empty scene stack.")
    }

    pub fn current(&self) -> &Scene<C, Ev> {
        &**self.scenes
            .last()
            .expect("ERROR: Tried to get current scene of an empty scene stack.")
    }

    pub fn switch(&mut self, next_scene: SceneSwitch<C, Ev>) -> Option<Box<Scene<C, Ev>>> {
        // let operation = self.current_mut().next();
        match next_scene {
            SceneSwitch::None => None,
            SceneSwitch::Pop => {
                let s = self.pop();
                let current_name = self.current().name();
                Some(s)
            }
            SceneSwitch::Push(s) => {
                self.push(s);
                None
            }
            SceneSwitch::Replace(s) => {
                let old_scene = self.pop();
                self.push(s);
                Some(old_scene)

            }
        }
    }

    // These functions must be on the SceneStack because otherwise
    // if you try to get the current scene and the world to call
    // update() on the current scene it causes a double-borrow.  :/
    pub fn update(&mut self) {
        let next_scene = {
            let current_scene = &mut **self.scenes
                .last_mut()
                .expect("Tried to update empty scene stack");
            current_scene.update(&mut self.world)
        };
        self.switch(next_scene);
    }

    // We walk down the scene stack until we find a scene where we aren't
    // supposed to draw the previous one, then draw them from the bottom up.
    //
    // This allows for layering GUI's and such.
    fn draw_scenes(scenes: &mut [Box<Scene<C, Ev>>], world: &mut C, ctx: &mut ggez::Context) {
        if scenes.len() > 0 {
            if let Some((current, rest)) = scenes.split_last_mut() {
                if current.draw_previous() {
                    SceneStack::draw_scenes(rest, world, ctx);
                }
                current.draw(world, ctx)
                    .expect("I would hope drawing a scene never fails!");

            }
        }
    }

    pub fn draw(&mut self, ctx: &mut ggez::Context) {
        SceneStack::draw_scenes(&mut self.scenes, &mut self.world, ctx)
    }

    pub fn input(&mut self, event: Ev, started: bool) {
        let current_scene = &mut **self.scenes
            .last_mut()
            .expect("Tried to do input for empty scene stack");
        current_scene.input(&mut self.world, event, started);
    }
}

<|endoftext|>


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

use model::Model;
use resource::ResourceManager;

pub struct Scene<'a> {
  /// Resource manager.
  res_manager: ResourceManager,
  /// List of all models used in the scene.
  models: Vec<Model<'a>>,
  /// Model cache used to resolve Id based on instance name.
  model_cache: HashMap<String, Id>,
  /// Scene model instances.
  model_instances: Vec<Id>
}

impl<'a> Scene<'a> {
  pub fn get_id<T>(&mut self, inst_name: String) -> Option<Id> where T: GetId {
    T::get_id(self, inst_name)
  }
}

pub type Id = u32;

pub trait GetId {
  fn get_id<'a>(scene: &mut Scene<'a>, inst_name: String) -> Option<Id>;
}

impl<'b> GetId for Model<'b> {
  fn get_id<'a>(scene: &mut Scene<'a>, inst_name: String) -> Option<Id> {
    match scene.model_cache.get(&inst_name).cloned() {
      id@Some(..) => id,
      None => {
        // cache miss; load then
        let path_str = format!("data/models/{}.obj", inst_name);
        let path = Path::new(&path_str);

        if path.exists() {
          match Model::load(&mut scene.res_manager, path) {
            Ok(model) => {
              let model_id = scene.models.len() as u32;

              // add the model to the list of loaded models
              scene.models.push(model);
              // add the model to the cache
              scene.model_cache.insert(inst_name, model_id);

              Some(model_id)
            },
            Err(e) => {
              err!("unable to load model '{}': '{:?}'", inst_name, e);
              None
            }
          }
        } else { // TODO: add a manifest override to look in somewhere else
          err!("model '{}' cannot be found", inst_name);
          None
        }
      }
    }
  }
}
<commit_msg>Added Scene::new().<commit_after>use std::collections::HashMap;
use std::path::Path;

use model::Model;
use resource::ResourceManager;

pub struct Scene<'a> {
  /// Resource manager.
  res_manager: ResourceManager,
  /// List of all models used in the scene.
  models: Vec<Model<'a>>,
  /// Model cache used to resolve Id based on instance name.
  model_cache: HashMap<String, Id>,
  /// Scene model instances.
  model_instances: Vec<Id>
}

impl<'a> Scene<'a> {
  pub fn new<P>(root: P) -> Self where P: AsRef<Path>{
    Scene {
      res_manager: ResourceManager::new(root),
      models: Vec::new(),
      model_cache: HashMap::new(),
      model_instances: Vec::new()
    }
  }

  pub fn get_id<T>(&mut self, inst_name: String) -> Option<Id> where T: GetId {
    T::get_id(self, inst_name)
  }
}

pub type Id = u32;

pub trait GetId {
  fn get_id<'a>(scene: &mut Scene<'a>, inst_name: String) -> Option<Id>;
}

impl<'b> GetId for Model<'b> {
  fn get_id<'a>(scene: &mut Scene<'a>, inst_name: String) -> Option<Id> {
    match scene.model_cache.get(&inst_name).cloned() {
      id@Some(..) => id,
      None => {
        // cache miss; load then
        let path_str = format!("data/models/{}.obj", inst_name);
        let path = Path::new(&path_str);

        if path.exists() {
          match Model::load(&mut scene.res_manager, path) {
            Ok(model) => {
              let model_id = scene.models.len() as u32;

              // add the model to the list of loaded models
              scene.models.push(model);
              // add the model to the cache
              scene.model_cache.insert(inst_name, model_id);

              Some(model_id)
            },
            Err(e) => {
              err!("unable to load model '{}': '{:?}'", inst_name, e);
              None
            }
          }
        } else { // TODO: add a manifest override to look in somewhere else
          err!("model '{}' cannot be found", inst_name);
          None
        }
      }
    }
  }
}
<|endoftext|>