<commit_before>#![feature(box_syntax)]

extern crate two_three;

use two_three::{Node, TTTree, Two, Three, LeafTwo, LeafThree};

#[test]
fn it_works() {
    let mut tree: TTTree<u64> = TTTree::new();

    tree.insert(50);
    match tree {
        TTTree{root: Some(Node::LeafTwo(LeafTwo(50)))} => (),
        _ => panic!(),
    }

    tree.insert(50);
    match tree {
        TTTree{root: Some(Node::LeafTwo(LeafTwo(50)))} => (),
        _ => panic!(),
    }

    tree.insert(60);
    match tree {
        TTTree{root: Some(Node::LeafThree(LeafThree(50, 60)))} => (),
        _ => panic!(),
    }

    tree.insert(70);
    match tree {
        TTTree{root: Some(
            Node::Two(Two(60,
                box Node::LeafTwo(LeafTwo(50)),
                box Node::LeafTwo(LeafTwo(70))
            ))
        )} => (),
        _ => panic!(),
    }

    tree.insert(100);
    match tree {
        TTTree{root: Some(
            Node::Two(Two(60,
                box Node::LeafTwo(LeafTwo(50)),
                box Node::LeafThree(LeafThree(70, 100))
            ))
        )} => (),
        _ => panic!(),
    }

    tree.insert(55);
    match tree {
        TTTree{root: Some(
            Node::Two(Two(60,
                box Node::LeafThree(LeafThree(50, 55)),
                box Node::LeafThree(LeafThree(70, 100))
            ))
        )} => (),
        _ => panic!(),
    }

    tree.insert(68);
    match tree {
        TTTree{root: Some(
            Node::Three(Three(60, 70,
                box Node::LeafThree(LeafThree(50, 55)),
                box Node::LeafTwo(LeafTwo(68)),
                box Node::LeafTwo(LeafTwo(100))
            ))
        )} => (),
        _ => panic!(),
    }

    tree.insert(75);
    match tree {
        TTTree{root: Some(
            Node::Three(Three(60, 70,
                box Node::LeafThree(LeafThree(50, 55)),
                box Node::LeafTwo(LeafTwo(68)),
                box Node::LeafThree(LeafThree(75, 100))
            ))
        )} => (),
        _ => panic!(),
    }

    tree.insert(52);
    match tree {
        TTTree{root: Some(
            Node::Two(Two(60,
                box Node::Two(Two(52,
                    box Node::LeafTwo(LeafTwo(50)),
                    box Node::LeafTwo(LeafTwo(55)),
                )),
                box Node::Two(Two(70,
                    box Node::LeafTwo(LeafTwo(68)),
                    box Node::LeafThree(LeafThree(75, 100)),
                )),
            ))
        )} => (),
        _ => panic!(),
    }
}
<commit_msg>Allow box_patterns<commit_after>#![feature(box_patterns)]

extern crate two_three;

use two_three::{Node, TTTree, Two, Three, LeafTwo, LeafThree};

#[test]
fn it_works() {
    let mut tree: TTTree<u64> = TTTree::new();

    tree.insert(50);
    match tree {
        TTTree{root: Some(Node::LeafTwo(LeafTwo(50)))} => (),
        _ => panic!(),
    }

    tree.insert(50);
    match tree {
        TTTree{root: Some(Node::LeafTwo(LeafTwo(50)))} => (),
        _ => panic!(),
    }

    tree.insert(60);
    match tree {
        TTTree{root: Some(Node::LeafThree(LeafThree(50, 60)))} => (),
        _ => panic!(),
    }

    tree.insert(70);
    match tree {
        TTTree{root: Some(
            Node::Two(Two(60,
                box Node::LeafTwo(LeafTwo(50)),
                box Node::LeafTwo(LeafTwo(70))
            ))
        )} => (),
        _ => panic!(),
    }

    tree.insert(100);
    match tree {
        TTTree{root: Some(
            Node::Two(Two(60,
                box Node::LeafTwo(LeafTwo(50)),
                box Node::LeafThree(LeafThree(70, 100))
            ))
        )} => (),
        _ => panic!(),
    }

    tree.insert(55);
    match tree {
        TTTree{root: Some(
            Node::Two(Two(60,
                box Node::LeafThree(LeafThree(50, 55)),
                box Node::LeafThree(LeafThree(70, 100))
            ))
        )} => (),
        _ => panic!(),
    }

    tree.insert(68);
    match tree {
        TTTree{root: Some(
            Node::Three(Three(60, 70,
                box Node::LeafThree(LeafThree(50, 55)),
                box Node::LeafTwo(LeafTwo(68)),
                box Node::LeafTwo(LeafTwo(100))
            ))
        )} => (),
        _ => panic!(),
    }

    tree.insert(75);
    match tree {
        TTTree{root: Some(
            Node::Three(Three(60, 70,
                box Node::LeafThree(LeafThree(50, 55)),
                box Node::LeafTwo(LeafTwo(68)),
                box Node::LeafThree(LeafThree(75, 100))
            ))
        )} => (),
        _ => panic!(),
    }

    tree.insert(52);
    match tree {
        TTTree{root: Some(
            Node::Two(Two(60,
                box Node::Two(Two(52,
                    box Node::LeafTwo(LeafTwo(50)),
                    box Node::LeafTwo(LeafTwo(55)),
                )),
                box Node::Two(Two(70,
                    box Node::LeafTwo(LeafTwo(68)),
                    box Node::LeafThree(LeafThree(75, 100)),
                )),
            ))
        )} => (),
        _ => panic!(),
    }
}
<|endoftext|>


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

use util::foreach_html5lib_test;

use std::{num, char};
use std::mem::replace;
use std::default::Default;
use std::path::Path;
use test::{TestDesc, TestDescAndFn, DynTestName, DynTestFn};
use serialize::json;
use serialize::json::Json;
use std::collections::TreeMap;
use std::str::Slice;
use std::vec::MoveItems;

use html5ever::tokenizer::{Doctype, Attribute, StartTag, EndTag, Tag};
use html5ever::tokenizer::{Token, DoctypeToken, TagToken, CommentToken};
use html5ever::tokenizer::{CharacterTokens, NullCharacterToken, EOFToken, ParseError};
use html5ever::tokenizer::{TokenSink, Tokenizer, TokenizerOpts};
use html5ever::tokenizer::states::{Plaintext, RawData, Rcdata, Rawtext};

use string_cache::{Atom, QualName};

// Return all ways of splitting the string into at most n
// possibly-empty pieces.
fn splits(s: &str, n: uint) -> Vec<Vec<String>> {
    if n == 1 {
        return vec!(vec!(s.to_string()));
    }

    let mut points: Vec<uint> = s.char_indices().map(|(n,_)| n).collect();
    points.push(s.len());

    // do this with iterators?
    let mut out = vec!();
    for p in points.into_iter() {
        let y = s.slice_from(p);
        for mut x in splits(s.slice_to(p), n-1).into_iter() {
            x.push(y.to_string());
            out.push(x);
        }
    }

    out.extend(splits(s, n-1).into_iter());
    out
}

struct TokenLogger {
    tokens: Vec<Token>,
    current_str: String,
    exact_errors: bool,
}

impl TokenLogger {
    fn new(exact_errors: bool) -> TokenLogger {
        TokenLogger {
            tokens: vec!(),
            current_str: String::new(),
            exact_errors: exact_errors,
        }
    }

    // Push anything other than character tokens
    fn push(&mut self, token: Token) {
        self.finish_str();
        self.tokens.push(token);
    }

    fn finish_str(&mut self) {
        if self.current_str.len() > 0 {
            let s = replace(&mut self.current_str, String::new());
            self.tokens.push(CharacterTokens(s));
        }
    }

    fn get_tokens(mut self) -> Vec<Token> {
        self.finish_str();
        self.tokens
    }
}

impl TokenSink for TokenLogger {
    fn process_token(&mut self, token: Token) {
        match token {
            CharacterTokens(b) => {
                self.current_str.push_str(b.as_slice());
            }

            NullCharacterToken => {
                self.current_str.push('\0');
            }

            ParseError(_) => if self.exact_errors {
                self.push(ParseError(Slice("")));
            },

            TagToken(mut t) => {
                // The spec seems to indicate that one can emit
                // erroneous end tags with attrs, but the test
                // cases don't contain them.
                match t.kind {
                    EndTag => {
                        t.self_closing = false;
                        t.attrs = vec!();
                    }
                    _ => t.attrs.sort_by(|a1, a2| a1.name.cmp(&a2.name)),
                }
                self.push(TagToken(t));
            }

            EOFToken => (),

            _ => self.push(token),
        }
    }
}

fn tokenize(input: Vec<String>, opts: TokenizerOpts) -> Vec<Token> {
    let sink = TokenLogger::new(opts.exact_errors);
    let mut tok = Tokenizer::new(sink, opts);
    for chunk in input.into_iter() {
        tok.feed(chunk);
    }
    tok.end();
    tok.unwrap().get_tokens()
}

trait JsonExt {
    fn get_str(&self) -> String;
    fn get_nullable_str(&self) -> Option<String>;
    fn get_bool(&self) -> bool;
    fn get_obj<'t>(&'t self) -> &'t TreeMap<String, Self>;
    fn get_list<'t>(&'t self) -> &'t Vec<Self>;
    fn find<'t>(&'t self, key: &str) -> &'t Self;
}

impl JsonExt for Json {
    fn get_str(&self) -> String {
        match *self {
            json::String(ref s) => s.to_string(),
            _ => panic!("Json::get_str: not a String"),
        }
    }

    fn get_nullable_str(&self) -> Option<String> {
        match *self {
            json::Null => None,
            json::String(ref s) => Some(s.to_string()),
            _ => panic!("Json::get_nullable_str: not a String"),
        }
    }

    fn get_bool(&self) -> bool {
        match *self {
            json::Boolean(b) => b,
            _ => panic!("Json::get_bool: not a Boolean"),
        }
    }

    fn get_obj<'t>(&'t self) -> &'t TreeMap<String, Json> {
        match *self {
            json::Object(ref m) => &*m,
            _ => panic!("Json::get_obj: not an Object"),
        }
    }

    fn get_list<'t>(&'t self) -> &'t Vec<Json> {
        match *self {
            json::List(ref m) => m,
            _ => panic!("Json::get_list: not a List"),
        }
    }

    fn find<'t>(&'t self, key: &str) -> &'t Json {
        self.get_obj().find(&key.to_string()).unwrap()
    }
}

// Parse a JSON object (other than "ParseError") to a token.
fn json_to_token(js: &Json) -> Token {
    let parts = js.get_list();
    // Collect refs here so we don't have to use "ref" in all the patterns below.
    let args: Vec<&Json> = parts.slice_from(1).iter().collect();
    match (parts[0].get_str().as_slice(), args.as_slice()) {
        ("DOCTYPE", [name, public_id, system_id, correct]) => DoctypeToken(Doctype {
            name: name.get_nullable_str(),
            public_id: public_id.get_nullable_str(),
            system_id: system_id.get_nullable_str(),
            force_quirks: !correct.get_bool(),
        }),

        ("StartTag", [name, attrs, rest..]) => TagToken(Tag {
            kind: StartTag,
            name: Atom::from_slice(name.get_str().as_slice()),
            attrs: attrs.get_obj().iter().map(|(k,v)| {
                Attribute {
                    name: QualName::new(ns!(""), Atom::from_slice(k.as_slice())),
                    value: v.get_str()
                }
            }).collect(),
            self_closing: match rest {
                [ref b, ..] => b.get_bool(),
                _ => false,
            }
        }),

        ("EndTag", [name]) => TagToken(Tag {
            kind: EndTag,
            name: Atom::from_slice(name.get_str().as_slice()),
            attrs: vec!(),
            self_closing: false
        }),

        ("Comment", [txt]) => CommentToken(txt.get_str()),

        ("Character", [txt]) => CharacterTokens(txt.get_str()),

        // We don't need to produce NullCharacterToken because
        // the TokenLogger will convert them to CharacterTokens.

        _ => panic!("don't understand token {}", parts),
    }
}

// Parse the "output" field of the test case into a vector of tokens.
fn json_to_tokens(js: &Json, exact_errors: bool) -> Vec<Token> {
    // Use a TokenLogger so that we combine character tokens separated
    // by an ignored error.
    let mut sink = TokenLogger::new(exact_errors);
    for tok in js.get_list().iter() {
        match *tok {
            json::String(ref s)
                if s.as_slice() == "ParseError" => sink.process_token(ParseError(Slice(""))),
            _ => sink.process_token(json_to_token(tok)),
        }
    }
    sink.get_tokens()
}

// Undo the escaping in "doubleEscaped" tests.
fn unescape(s: &str) -> Option<String> {
    let mut out = String::with_capacity(s.len());
    let mut it = s.chars().peekable();
    loop {
        match it.next() {
            None => return Some(out),
            Some('\\') => {
                if it.peek() != Some(&'u') {
                    panic!("can't understand escape");
                }
                drop(it.next());
                let hex: String = it.by_ref().take(4).collect();
                match num::from_str_radix(hex.as_slice(), 16)
                          .and_then(char::from_u32) {
                    // Some of the tests use lone surrogates, but we have no
                    // way to represent them in the UTF-8 input to our parser.
                    // Since these can only come from script, we will catch
                    // them there.
                    None => return None,
                    Some(c) => out.push(c),
                }
            }
            Some(c) => out.push(c),
        }
    }
}

fn unescape_json(js: &Json) -> Json {
    match *js {
        // unwrap is OK here because the spec'd *output* of the tokenizer never
        // contains a lone surrogate.
        json::String(ref s) => json::String(unescape(s.as_slice()).unwrap()),
        json::List(ref xs) => json::List(xs.iter().map(unescape_json).collect()),
        json::Object(ref obj) => {
            let mut new_obj = TreeMap::new();
            for (k,v) in obj.iter() {
                new_obj.insert(k.clone(), unescape_json(v));
            }
            json::Object(new_obj)
        }
        _ => js.clone(),
    }
}

fn mk_test(desc: String, insplits: Vec<Vec<String>>, expect: Vec<Token>, opts: TokenizerOpts)
        -> TestDescAndFn {
    TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(desc),
            ignore: false,
            should_fail: false,
        },
        testfn: DynTestFn(proc() {
            for input in insplits.into_iter() {
                // Clone 'input' so we have it for the failure message.
                // Also clone opts.  If we don't, we get the wrong
                // result but the compiler doesn't catch it!
                // Possibly mozilla/rust#12223.
                let output = tokenize(input.clone(), opts.clone());
                if output != expect {
                    panic!("\ninput: {}\ngot: {}\nexpected: {}",
                        input, output, expect);
                }
            }
        }),
    }
}

fn mk_tests(tests: &mut Vec<TestDescAndFn>, path_str: &str, js: &Json) {
    let obj = js.get_obj();
    let mut input = js.find("input").unwrap().get_str();
    let mut expect = js.find("output").unwrap().clone();
    let desc = format!("tok: {:s}: {:s}",
        path_str, js.find("description").unwrap().get_str());

    // "Double-escaped" tests require additional processing of
    // the input and output.
    if obj.find(&"doubleEscaped".to_string()).map_or(false, |j| j.get_bool()) {
        match unescape(input.as_slice()) {
            None => return,
            Some(i) => input = i,
        }
        expect = unescape_json(&expect);
    }

    // Split up the input at different points to test incremental tokenization.
    let insplits = splits(input.as_slice(), 3);

    // Some tests have a last start tag name.
    let start_tag = obj.find(&"lastStartTag".to_string()).map(|s| s.get_str());

    // Some tests want to start in a state other than Data.
    let state_overrides = match obj.find(&"initialStates".to_string()) {
        Some(&json::List(ref xs)) => xs.iter().map(|s|
            Some(match s.get_str().as_slice() {
                "PLAINTEXT state" => Plaintext,
                "RAWTEXT state"   => RawData(Rawtext),
                "RCDATA state"    => RawData(Rcdata),
                s => panic!("don't know state {}", s),
            })).collect(),
        None => vec!(None),
        _ => panic!("don't understand initialStates value"),
    };

    // Build the tests.
    for state in state_overrides.into_iter() {
        for &exact_errors in [false, true].iter() {
            let mut newdesc = desc.clone();
            match state {
                Some(s) => newdesc = format!("{:s} (in state {})", newdesc, s),
                None  => (),
            };
            if exact_errors {
                newdesc = format!("{:s} (exact errors)", newdesc);
            }

            let expect_toks = json_to_tokens(&expect, exact_errors);
            tests.push(mk_test(newdesc, insplits.clone(), expect_toks, TokenizerOpts {
                exact_errors: exact_errors,
                initial_state: state,
                last_start_tag_name: start_tag.clone(),

                // Not discarding a BOM is what the test suite expects; see
                // https://github.com/html5lib/html5lib-tests/issues/2
                discard_bom: false,

                .. Default::default()
            }));
        }
    }
}

pub fn tests(src_dir: Path) -> MoveItems<TestDescAndFn> {
    let mut tests = vec!();

    foreach_html5lib_test(src_dir, "tokenizer", ".test", |path_str, mut file| {
        let js = json::from_reader(&mut file as &mut Reader)
            .ok().expect("json parse error");

        match js.get_obj().find(&"tests".to_string()) {
            Some(&json::List(ref lst)) => {
                for test in lst.iter() {
                    mk_tests(&mut tests, path_str.as_slice(), test);
                }
            }

            // xmlViolation.test doesn't follow this format.
            _ => (),
        }
    });

    tests.into_iter()
}
<commit_msg>rustup v2.<commit_after>// Copyright 2014 The html5ever Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use util::foreach_html5lib_test;

use std::{num, char};
use std::mem::replace;
use std::default::Default;
use std::path::Path;
use test::{TestDesc, TestDescAndFn, DynTestName, DynTestFn};
use serialize::json;
use serialize::json::Json;
use std::collections::TreeMap;
use std::str::Slice;
use std::vec::MoveItems;

use html5ever::tokenizer::{Doctype, Attribute, StartTag, EndTag, Tag};
use html5ever::tokenizer::{Token, DoctypeToken, TagToken, CommentToken};
use html5ever::tokenizer::{CharacterTokens, NullCharacterToken, EOFToken, ParseError};
use html5ever::tokenizer::{TokenSink, Tokenizer, TokenizerOpts};
use html5ever::tokenizer::states::{Plaintext, RawData, Rcdata, Rawtext};

use string_cache::{Atom, QualName};

// Return all ways of splitting the string into at most n
// possibly-empty pieces.
fn splits(s: &str, n: uint) -> Vec<Vec<String>> {
    if n == 1 {
        return vec!(vec!(s.to_string()));
    }

    let mut points: Vec<uint> = s.char_indices().map(|(n,_)| n).collect();
    points.push(s.len());

    // do this with iterators?
    let mut out = vec!();
    for p in points.into_iter() {
        let y = s.slice_from(p);
        for mut x in splits(s.slice_to(p), n-1).into_iter() {
            x.push(y.to_string());
            out.push(x);
        }
    }

    out.extend(splits(s, n-1).into_iter());
    out
}

struct TokenLogger {
    tokens: Vec<Token>,
    current_str: String,
    exact_errors: bool,
}

impl TokenLogger {
    fn new(exact_errors: bool) -> TokenLogger {
        TokenLogger {
            tokens: vec!(),
            current_str: String::new(),
            exact_errors: exact_errors,
        }
    }

    // Push anything other than character tokens
    fn push(&mut self, token: Token) {
        self.finish_str();
        self.tokens.push(token);
    }

    fn finish_str(&mut self) {
        if self.current_str.len() > 0 {
            let s = replace(&mut self.current_str, String::new());
            self.tokens.push(CharacterTokens(s));
        }
    }

    fn get_tokens(mut self) -> Vec<Token> {
        self.finish_str();
        self.tokens
    }
}

impl TokenSink for TokenLogger {
    fn process_token(&mut self, token: Token) {
        match token {
            CharacterTokens(b) => {
                self.current_str.push_str(b.as_slice());
            }

            NullCharacterToken => {
                self.current_str.push('\0');
            }

            ParseError(_) => if self.exact_errors {
                self.push(ParseError(Slice("")));
            },

            TagToken(mut t) => {
                // The spec seems to indicate that one can emit
                // erroneous end tags with attrs, but the test
                // cases don't contain them.
                match t.kind {
                    EndTag => {
                        t.self_closing = false;
                        t.attrs = vec!();
                    }
                    _ => t.attrs.sort_by(|a1, a2| a1.name.cmp(&a2.name)),
                }
                self.push(TagToken(t));
            }

            EOFToken => (),

            _ => self.push(token),
        }
    }
}

fn tokenize(input: Vec<String>, opts: TokenizerOpts) -> Vec<Token> {
    let sink = TokenLogger::new(opts.exact_errors);
    let mut tok = Tokenizer::new(sink, opts);
    for chunk in input.into_iter() {
        tok.feed(chunk);
    }
    tok.end();
    tok.unwrap().get_tokens()
}

trait JsonExt {
    fn get_str(&self) -> String;
    fn get_nullable_str(&self) -> Option<String>;
    fn get_bool(&self) -> bool;
    fn get_obj<'t>(&'t self) -> &'t TreeMap<String, Self>;
    fn get_list<'t>(&'t self) -> &'t Vec<Self>;
    fn find<'t>(&'t self, key: &str) -> &'t Self;
}

impl JsonExt for Json {
    fn get_str(&self) -> String {
        match *self {
            json::String(ref s) => s.to_string(),
            _ => panic!("Json::get_str: not a String"),
        }
    }

    fn get_nullable_str(&self) -> Option<String> {
        match *self {
            json::Null => None,
            json::String(ref s) => Some(s.to_string()),
            _ => panic!("Json::get_nullable_str: not a String"),
        }
    }

    fn get_bool(&self) -> bool {
        match *self {
            json::Boolean(b) => b,
            _ => panic!("Json::get_bool: not a Boolean"),
        }
    }

    fn get_obj<'t>(&'t self) -> &'t TreeMap<String, Json> {
        match *self {
            json::Object(ref m) => &*m,
            _ => panic!("Json::get_obj: not an Object"),
        }
    }

    fn get_list<'t>(&'t self) -> &'t Vec<Json> {
        match *self {
            json::List(ref m) => m,
            _ => panic!("Json::get_list: not a List"),
        }
    }

    fn find<'t>(&'t self, key: &str) -> &'t Json {
        self.get_obj().get(&key.to_string()).unwrap()
    }
}

// Parse a JSON object (other than "ParseError") to a token.
fn json_to_token(js: &Json) -> Token {
    let parts = js.get_list();
    // Collect refs here so we don't have to use "ref" in all the patterns below.
    let args: Vec<&Json> = parts.slice_from(1).iter().collect();
    match (parts[0].get_str().as_slice(), args.as_slice()) {
        ("DOCTYPE", [name, public_id, system_id, correct]) => DoctypeToken(Doctype {
            name: name.get_nullable_str(),
            public_id: public_id.get_nullable_str(),
            system_id: system_id.get_nullable_str(),
            force_quirks: !correct.get_bool(),
        }),

        ("StartTag", [name, attrs, rest..]) => TagToken(Tag {
            kind: StartTag,
            name: Atom::from_slice(name.get_str().as_slice()),
            attrs: attrs.get_obj().iter().map(|(k,v)| {
                Attribute {
                    name: QualName::new(ns!(""), Atom::from_slice(k.as_slice())),
                    value: v.get_str()
                }
            }).collect(),
            self_closing: match rest {
                [ref b, ..] => b.get_bool(),
                _ => false,
            }
        }),

        ("EndTag", [name]) => TagToken(Tag {
            kind: EndTag,
            name: Atom::from_slice(name.get_str().as_slice()),
            attrs: vec!(),
            self_closing: false
        }),

        ("Comment", [txt]) => CommentToken(txt.get_str()),

        ("Character", [txt]) => CharacterTokens(txt.get_str()),

        // We don't need to produce NullCharacterToken because
        // the TokenLogger will convert them to CharacterTokens.

        _ => panic!("don't understand token {}", parts),
    }
}

// Parse the "output" field of the test case into a vector of tokens.
fn json_to_tokens(js: &Json, exact_errors: bool) -> Vec<Token> {
    // Use a TokenLogger so that we combine character tokens separated
    // by an ignored error.
    let mut sink = TokenLogger::new(exact_errors);
    for tok in js.get_list().iter() {
        match *tok {
            json::String(ref s)
                if s.as_slice() == "ParseError" => sink.process_token(ParseError(Slice(""))),
            _ => sink.process_token(json_to_token(tok)),
        }
    }
    sink.get_tokens()
}

// Undo the escaping in "doubleEscaped" tests.
fn unescape(s: &str) -> Option<String> {
    let mut out = String::with_capacity(s.len());
    let mut it = s.chars().peekable();
    loop {
        match it.next() {
            None => return Some(out),
            Some('\\') => {
                if it.peek() != Some(&'u') {
                    panic!("can't understand escape");
                }
                drop(it.next());
                let hex: String = it.by_ref().take(4).collect();
                match num::from_str_radix(hex.as_slice(), 16)
                          .and_then(char::from_u32) {
                    // Some of the tests use lone surrogates, but we have no
                    // way to represent them in the UTF-8 input to our parser.
                    // Since these can only come from script, we will catch
                    // them there.
                    None => return None,
                    Some(c) => out.push(c),
                }
            }
            Some(c) => out.push(c),
        }
    }
}

fn unescape_json(js: &Json) -> Json {
    match *js {
        // unwrap is OK here because the spec'd *output* of the tokenizer never
        // contains a lone surrogate.
        json::String(ref s) => json::String(unescape(s.as_slice()).unwrap()),
        json::List(ref xs) => json::List(xs.iter().map(unescape_json).collect()),
        json::Object(ref obj) => {
            let mut new_obj = TreeMap::new();
            for (k,v) in obj.iter() {
                new_obj.insert(k.clone(), unescape_json(v));
            }
            json::Object(new_obj)
        }
        _ => js.clone(),
    }
}

fn mk_test(desc: String, insplits: Vec<Vec<String>>, expect: Vec<Token>, opts: TokenizerOpts)
        -> TestDescAndFn {
    TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(desc),
            ignore: false,
            should_fail: false,
        },
        testfn: DynTestFn(proc() {
            for input in insplits.into_iter() {
                // Clone 'input' so we have it for the failure message.
                // Also clone opts.  If we don't, we get the wrong
                // result but the compiler doesn't catch it!
                // Possibly mozilla/rust#12223.
                let output = tokenize(input.clone(), opts.clone());
                if output != expect {
                    panic!("\ninput: {}\ngot: {}\nexpected: {}",
                        input, output, expect);
                }
            }
        }),
    }
}

fn mk_tests(tests: &mut Vec<TestDescAndFn>, path_str: &str, js: &Json) {
    let obj = js.get_obj();
    let mut input = js.find("input").unwrap().get_str();
    let mut expect = js.find("output").unwrap().clone();
    let desc = format!("tok: {:s}: {:s}",
        path_str, js.find("description").unwrap().get_str());

    // "Double-escaped" tests require additional processing of
    // the input and output.
    if obj.get(&"doubleEscaped".to_string()).map_or(false, |j| j.get_bool()) {
        match unescape(input.as_slice()) {
            None => return,
            Some(i) => input = i,
        }
        expect = unescape_json(&expect);
    }

    // Split up the input at different points to test incremental tokenization.
    let insplits = splits(input.as_slice(), 3);

    // Some tests have a last start tag name.
    let start_tag = obj.get(&"lastStartTag".to_string()).map(|s| s.get_str());

    // Some tests want to start in a state other than Data.
    let state_overrides = match obj.get(&"initialStates".to_string()) {
        Some(&json::List(ref xs)) => xs.iter().map(|s|
            Some(match s.get_str().as_slice() {
                "PLAINTEXT state" => Plaintext,
                "RAWTEXT state"   => RawData(Rawtext),
                "RCDATA state"    => RawData(Rcdata),
                s => panic!("don't know state {}", s),
            })).collect(),
        None => vec!(None),
        _ => panic!("don't understand initialStates value"),
    };

    // Build the tests.
    for state in state_overrides.into_iter() {
        for &exact_errors in [false, true].iter() {
            let mut newdesc = desc.clone();
            match state {
                Some(s) => newdesc = format!("{:s} (in state {})", newdesc, s),
                None  => (),
            };
            if exact_errors {
                newdesc = format!("{:s} (exact errors)", newdesc);
            }

            let expect_toks = json_to_tokens(&expect, exact_errors);
            tests.push(mk_test(newdesc, insplits.clone(), expect_toks, TokenizerOpts {
                exact_errors: exact_errors,
                initial_state: state,
                last_start_tag_name: start_tag.clone(),

                // Not discarding a BOM is what the test suite expects; see
                // https://github.com/html5lib/html5lib-tests/issues/2
                discard_bom: false,

                .. Default::default()
            }));
        }
    }
}

pub fn tests(src_dir: Path) -> MoveItems<TestDescAndFn> {
    let mut tests = vec!();

    foreach_html5lib_test(src_dir, "tokenizer", ".test", |path_str, mut file| {
        let js = json::from_reader(&mut file as &mut Reader)
            .ok().expect("json parse error");

        match js.get_obj().get(&"tests".to_string()) {
            Some(&json::List(ref lst)) => {
                for test in lst.iter() {
                    mk_tests(&mut tests, path_str.as_slice(), test);
                }
            }

            // xmlViolation.test doesn't follow this format.
            _ => (),
        }
    });

    tests.into_iter()
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::{io, io::prelude::*};
use std::hash::Hash;
use std::fmt::Debug;
use std::collections::HashMap;

type Recipe<T> = Vec<(T, u32)>;
type RecipeBook<T> = HashMap<T, (Recipe<T>, u32)>;

fn get_input() -> io::Result<String> {
  let mut file = File::open("14.txt")?;
  let mut contents = String::new();
  file.read_to_string(&mut contents)?;

  Ok(contents)
}

fn parse_input(input: &str) -> RecipeBook<&str> {
  fn parse_ingredient(input: &str) -> Option<(&str, u32)> {
    let mut tokens = input.trim().split(" ");

    match (tokens.next(), tokens.next()) {
      (Some(amount), Some(id)) => {
        amount.parse::<u32>().ok()
        .map(|amount| (id, amount))
      },
      _ => None
    }
  }

  input.lines()
  .map(|line| line.split(" => "))
  .filter_map(|mut tokens| match (tokens.next(), tokens.next()) {
    (Some(ingredients), Some(outcome)) => {
      Some((ingredients.split(", "), outcome))
    },
    _ => None
  })
  .map(|(ingredients, outcome)| (ingredients.filter_map(parse_ingredient), parse_ingredient(outcome)))
  .filter_map(|(ingredients, outcome)| outcome.and_then(|outcome| {
    let ingredients = ingredients.collect::<Recipe<_>>();

    if ingredients.len() == 0 {
      return None;
    }

    Some((outcome.0, (ingredients, outcome.1)))
  }))
  .collect()
}

fn get_base_ingredient_amount<T>(recipes: &RecipeBook<T>, ingredient: T, amount: u32, residues: &mut HashMap<T, u32>) -> u32
where T: Eq + Clone + Copy + Debug + Hash {
  let mut amount = amount;

  if let Some(residue) = residues.get_mut(&ingredient) {
    if *residue >= amount {
      amount = 0;
      *residue -= amount;
    } else {
      amount -= *residue;
      *residue = 0;
    }
  }

  if amount == 0 {
    return 0;
  }

  let result = match recipes.get(&ingredient) {
    None => amount,
    Some((subrecipe, yield_amount)) => {
      let n = ((amount as f64) / (*yield_amount as f64)).ceil() as u32;
      let residue = yield_amount * n - amount;

      let result = subrecipe.iter()
        .map(|&(ingredient, amount)| {
          get_base_ingredient_amount(recipes, ingredient, amount * n, residues)
        })
        .sum();

      if residue > 0 {
        let new_residue = residues.get(&ingredient).cloned().unwrap_or(0) + residue;
        residues.insert(ingredient, new_residue);
      }

      result
    }
  };

  result
}

fn main() {
  let input = get_input().unwrap();
  let recipes = parse_input(&input);

  let x = get_base_ingredient_amount(&recipes, "FUEL", 1, &mut HashMap::new());

  println!("{:?}", x);
}
<commit_msg>Add day 14 part 1 solution<commit_after>use std::fs::File;
use std::{io, io::prelude::*};
use std::hash::Hash;
use std::fmt::Debug;
use std::collections::HashMap;

type Recipe<T> = HashMap<T, u64>;
type RecipeBook<T> = HashMap<T, (Recipe<T>, u64)>;

fn get_input() -> io::Result<String> {
  let mut file = File::open("14.txt")?;
  let mut contents = String::new();
  file.read_to_string(&mut contents)?;

  Ok(contents)
}

fn parse_input(input: &str) -> RecipeBook<&str> {
  fn parse_ingredient(input: &str) -> Option<(&str, u64)> {
    let mut tokens = input.trim().split(" ");

    match (tokens.next(), tokens.next()) {
      (Some(amount), Some(id)) => {
        amount.parse::<u64>().ok()
        .map(|amount| (id, amount))
      },
      _ => None
    }
  }

  input.lines()
  .map(|line| line.split(" => "))
  .filter_map(|mut tokens| match (tokens.next(), tokens.next()) {
    (Some(ingredients), Some(outcome)) => {
      Some((ingredients.split(", "), outcome))
    },
    _ => None
  })
  .map(|(ingredients, outcome)| (ingredients.filter_map(parse_ingredient), parse_ingredient(outcome)))
  .filter_map(|(ingredients, outcome)| outcome.and_then(|outcome| {
    let ingredients = ingredients.collect::<Recipe<_>>();

    if ingredients.len() == 0 {
      return None;
    }

    Some((outcome.0, (ingredients, outcome.1)))
  }))
  .collect()
}

fn get_base_ingredient_amount<T>(recipes: &RecipeBook<T>, ingredient: T, amount: u64, residues: &mut Recipe<T>) -> u64
where T: Eq + Clone + Copy + Debug + Hash {
  let mut amount = amount;

  if let Some(residue) = residues.get_mut(&ingredient) {
    if *residue >= amount {
      *residue -= amount;
      amount = 0;
    } else {
      amount -= *residue;
      *residue = 0;
    }
  }

  if amount == 0 {
    return 0;
  }

  match recipes.get(&ingredient) {
    None => amount,
    Some((subrecipe, yield_amount)) => {
      let times = (amount as f64 / *yield_amount as f64).ceil() as u64;
      let result = subrecipe.iter()
        .map(|(&ingredient, &amount)| {
          get_base_ingredient_amount(recipes, ingredient, amount * times, residues)
        })
        .sum();

      let new_residue = residues.get(&ingredient).cloned().unwrap_or(0) + *yield_amount * times - amount;
      residues.insert(ingredient, new_residue);

      result
    }
  }
}

fn main() {
  let input = get_input().unwrap();
  let recipes = parse_input(&input);

  let ore = get_base_ingredient_amount(&recipes, "FUEL", 1, &mut Recipe::new());
  println!("Part 1: {}", ore);
}
<|endoftext|>


<commit_before>//! Simple script to verify the coding style of this library
//!
//! ## How to run
//!
//! The first argument to this script is the directory to run on, so running
//! this script should be as simple as:
//!
//! ```notrust
//! rustc ci/style.rs
//! ./style src
//! ```
//!
//! ## Guidelines
//!
//! The current style is:
//!
//! * Specific module layout:
//!     1. use directives
//!     2. typedefs
//!     3. structs
//!     4. constants
//!     5. f! { ... } functions
//!     6. extern functions
//!     7. modules + pub use
//!
//! Things not verified:
//!
//! * alignment
//! * leading colons on paths

use std::env;
use std::fs;
use std::io::prelude::*;
use std::path::Path;

macro_rules! t {
    ($e:expr) => {
        match $e {
            Ok(e) => e,
            Err(e) => panic!("{} failed with {}", stringify!($e), e),
        }
    };
}

fn main() {
    let arg = env::args().skip(1).next().unwrap_or(".".to_string());

    let mut errors = Errors { errs: false };
    walk(Path::new(&arg), &mut errors);

    if errors.errs {
        panic!("found some lint errors");
    } else {
        println!("good style!");
    }
}

fn walk(path: &Path, err: &mut Errors) {
    for entry in t!(path.read_dir()).map(|e| t!(e)) {
        let path = entry.path();
        if t!(entry.file_type()).is_dir() {
            walk(&path, err);
            continue;
        }

        let name = entry.file_name().into_string().unwrap();
        match &name[..] {
            n if !n.ends_with(".rs") => continue,

            "lib.rs" | "macros.rs" => continue,

            _ => {}
        }

        let mut contents = String::new();
        t!(t!(fs::File::open(&path)).read_to_string(&mut contents));

        check_style(&contents, &path, err);
    }
}

struct Errors {
    errs: bool,
}

#[derive(Clone, Copy, PartialEq)]
enum State {
    Start,
    Imports,
    Typedefs,
    Structs,
    Constants,
    FunctionDefinitions,
    Functions,
    Modules,
}

fn check_style(file: &str, path: &Path, err: &mut Errors) {
    let mut state = State::Start;
    let mut s_macros = 0;
    let mut f_macros = 0;
    let mut in_impl = false;

    for (i, line) in file.lines().enumerate() {
        if line.contains("#[cfg(")
            && line.contains(']')
            && !line.contains(" if ")
            && !(line.contains("target_endian") || line.contains("target_arch"))
        {
            if state != State::Structs {
                err.error(path, i, "use cfg_if! and submodules instead of #[cfg]");
            }
        }
        if line.contains("#[derive(") && (line.contains("Copy") || line.contains("Clone")) {
            err.error(path, i, "impl ::Copy and ::Clone manually");
        }
        if line.contains("impl") {
            in_impl = true;
        }
        if in_impl && line.starts_with('}') {
            in_impl = false;
        }

        let orig_line = line;
        let line = line.trim_start();
        let is_pub = line.starts_with("pub ");
        let line = if is_pub { &line[4..] } else { line };

        let line_state = if line.starts_with("use ") {
            if line.contains("c_void") {
                continue;
            }
            if is_pub {
                State::Modules
            } else {
                State::Imports
            }
        } else if line.starts_with("const ") {
            State::Constants
        } else if line.starts_with("type ") && !in_impl {
            State::Typedefs
        } else if line.starts_with("s! {") {
            s_macros += 1;
            State::Structs
        } else if line.starts_with("f! {") {
            f_macros += 1;
            State::FunctionDefinitions
        } else if line.starts_with("extern ") && !orig_line.starts_with(" ") {
            State::Functions
        } else if line.starts_with("mod ") {
            State::Modules
        } else {
            continue;
        };

        if state as usize > line_state as usize {
            err.error(
                path,
                i,
                &format!(
                    "{} found after {} when it belongs before",
                    line_state.desc(),
                    state.desc()
                ),
            );
        }

        if f_macros == 2 {
            f_macros += 1;
            err.error(path, i, "multiple f! macros in one module");
        }
        if s_macros == 2 {
            s_macros += 1;
            err.error(path, i, "multiple s! macros in one module");
        }

        state = line_state;
    }
}

impl State {
    fn desc(&self) -> &str {
        match *self {
            State::Start => "start",
            State::Imports => "import",
            State::Typedefs => "typedef",
            State::Structs => "struct",
            State::Constants => "constant",
            State::FunctionDefinitions => "function definition",
            State::Functions => "extern function",
            State::Modules => "module",
        }
    }
}

impl Errors {
    fn error(&mut self, path: &Path, line: usize, msg: &str) {
        self.errs = true;
        println!("{}:{} - {}", path.display(), line + 1, msg);
    }
}
<commit_msg>Auto merge of #2846 - joshtriplett:style-quickfix, r=Amanieu<commit_after>//! Simple script to verify the coding style of this library
//!
//! ## How to run
//!
//! The first argument to this script is the directory to run on, so running
//! this script should be as simple as:
//!
//! ```notrust
//! rustc ci/style.rs
//! ./style src
//! ```
//!
//! ## Guidelines
//!
//! The current style is:
//!
//! * Specific module layout:
//!     1. use directives
//!     2. typedefs
//!     3. structs
//!     4. constants
//!     5. f! { ... } functions
//!     6. extern functions
//!     7. modules + pub use
//!
//! Things not verified:
//!
//! * alignment
//! * leading colons on paths

use std::env;
use std::fs;
use std::io::prelude::*;
use std::path::Path;

macro_rules! t {
    ($e:expr) => {
        match $e {
            Ok(e) => e,
            Err(e) => panic!("{} failed with {}", stringify!($e), e),
        }
    };
}

fn main() {
    let arg = env::args().skip(1).next().unwrap_or(".".to_string());

    let mut errors = Errors { errs: false };
    walk(Path::new(&arg), &mut errors);

    if errors.errs {
        panic!("found some lint errors");
    } else {
        println!("good style!");
    }
}

fn walk(path: &Path, err: &mut Errors) {
    for entry in t!(path.read_dir()).map(|e| t!(e)) {
        let path = entry.path();
        if t!(entry.file_type()).is_dir() {
            walk(&path, err);
            continue;
        }

        let name = entry.file_name().into_string().unwrap();
        match &name[..] {
            n if !n.ends_with(".rs") => continue,

            "lib.rs" | "macros.rs" => continue,

            _ => {}
        }

        let mut contents = String::new();
        t!(t!(fs::File::open(&path)).read_to_string(&mut contents));

        check_style(&contents, &path, err);
    }
}

struct Errors {
    errs: bool,
}

#[derive(Clone, Copy, PartialEq)]
enum State {
    Start,
    Imports,
    Typedefs,
    Structs,
    Constants,
    FunctionDefinitions,
    Functions,
    Modules,
}

fn check_style(file: &str, path: &Path, err: &mut Errors) {
    let mut state = State::Start;
    let mut s_macros = 0;
    let mut f_macros = 0;
    let mut in_impl = false;

    for (i, line) in file.lines().enumerate() {
        if line.contains("#[cfg(")
            && line.contains(']')
            && !line.contains(" if ")
            && !(line.contains("target_endian") || line.contains("target_arch"))
        {
            if state != State::Structs {
                err.error(path, i, "use cfg_if! and submodules instead of #[cfg]");
            }
        }
        if line.contains("#[derive(") && (line.contains("Copy") || line.contains("Clone")) {
            err.error(path, i, "impl ::Copy and ::Clone manually");
        }
        if line.contains("impl") {
            in_impl = true;
        }
        if in_impl && line.starts_with('}') {
            in_impl = false;
        }

        let orig_line = line;
        let line = line.trim_start();
        let is_pub = line.starts_with("pub ");
        let line = if is_pub { &line[4..] } else { line };

        let line_state = if line.starts_with("use ") {
            if line.contains("c_void") {
                continue;
            }
            if is_pub {
                State::Modules
            } else {
                State::Imports
            }
        } else if line.starts_with("const ") {
            State::Constants
        } else if line.starts_with("type ") && !in_impl {
            State::Typedefs
        } else if line.starts_with("s! {") {
            s_macros += 1;
            State::Structs
        } else if line.starts_with("f! {") {
            f_macros += 1;
            State::FunctionDefinitions
        } else if line.starts_with("extern ") && !orig_line.starts_with(" ") {
            State::Functions
        } else if line.starts_with("mod ") {
            State::Modules
        } else {
            continue;
        };

        if state as usize > line_state as usize {
            err.error(
                path,
                i,
                &format!(
                    "{} found after {} when it belongs before",
                    line_state.desc(),
                    state.desc()
                ),
            );
        }

        if f_macros == 2 {
            f_macros += 1;
            err.error(path, i, "multiple f! macros in one module");
        }
        if s_macros == 2 {
            s_macros += 1;
            err.error(path, i, "multiple s! macros in one module");
        }

        state = line_state;
    }
}

impl State {
    fn desc(&self) -> &str {
        match *self {
            State::Start => "start",
            State::Imports => "import",
            State::Typedefs => "typedef",
            State::Structs => "struct",
            State::Constants => "constant",
            State::FunctionDefinitions => "function definition",
            State::Functions => "extern function",
            State::Modules => "module",
        }
    }
}

impl Errors {
    fn error(&mut self, path: &Path, line: usize, msg: &str) {
        self.errs = true;
        println!("{}:{}: {}", path.display(), line + 1, msg);
    }
}
<|endoftext|>


<commit_before>#[cfg(target_arch="x86_64")]
#[path="ucontext_x86_64.rs"]
mod ucontext;

// This almost certainly needs to be made specific to just x86 (and
// add cases for the other processors).
#[cfg(not(target_arch="x86_64"))]
#[path="ucontext_generic.rs"]
mod ucontext;

// These almost certainly need to be replaced with something that is
// target/platform specific.
mod sigset;
mod sigstack;

#[cfg(target_arch="x86_64")]
const UNW_TDEP_CURSOR_LEN: usize = 127;

#[cfg(target_arch="x86_64")]
type unw_word_t = usize;

#[repr(C)]
pub struct unw_cursor_t {
    opaque: [unw_word_t; UNW_TDEP_CURSOR_LEN],
}

type unw_context_t = ucontext::ucontext_t;

extern {
    fn unw_getcontext(ucp: *mut unw_context_t);
    fn unw_init_local(c: *mut unw_cursor_t, ctxt: *mut unw_context_t);
    // fn unw_init_remote(c: *mut unw_cursor_t, as: unw_addr_space_t, arg: *mut c_void);
    // fn unw_step(cp: *mut unw_cursor_t);
    // fn unw_get_reg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_word_t);
    // fn unw_get_fpreg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_fpreg_t);
    // fn unw_resume(cp: *mut unw_cursor_t);

    // fn unw_create_addr_space(ap: *mut unw_accessors_t, byteorder: c_int);
    // fn unw_destroy_addr_space(as: unw_addr_space_t);
    // fn unw_get_accessors(as: unw_addr_space_t) -> *mut unw_accessors_t;
    // fn unw_flush_cache(as: unw_addr_space, lo: unw_word_t, hi: unw_word_t);
    // fn unw_set_caching_policy(as: unw_addr_space, policy: unw_caching_policy_t) -> c_int;

    // fn unw_regname(regnum: unw_regnum_t) -> *const c_char;
    // fn unw_get_proc_info(cp: *mut unw_cursor_t, pip: *mut unw_proc_info_t);
    // fn unw_get_save_loc(cp: *mut unw_cursor_t, _int: c_int, loc: *mut unw_save_loc_t);
    // fn unw_is_fpreg(r: unw_regnum_t) -> c_int;
    // fn unw_is_signal_frame(cp: *mut unw_cursor_t) -> c_int;
    // fn unw_get_proc_name(cp: *mut unw_cursor_t, bufp: *mut c_char, len: size_t, offp: *mut unw_word_t) -> c_int;

    // fn _U_dyn_register(di: *mut unw_dyn_info_t);
    // fn _U_dyn_cancel(di: *mut unw_dyn_info_t);
}
<commit_msg>uncommented a bunch of other `extern fn` declarations from `libunwind`.<commit_after>use libc::{c_char, c_double, c_int, size_t};

#[cfg(target_arch="x86_64")]
#[path="ucontext_x86_64.rs"]
mod ucontext;

// This almost certainly needs to be made specific to just x86 (and
// add cases for the other processors).
#[cfg(not(target_arch="x86_64"))]
#[path="ucontext_generic.rs"]
mod ucontext;

// These almost certainly need to be replaced with something that is
// target/platform specific.
mod sigset;
mod sigstack;

#[cfg(target_arch="x86_64")]
const UNW_TDEP_CURSOR_LEN: usize = 127;

#[cfg(target_arch="x86_64")]
type unw_word_t = usize;

#[repr(C)]
pub struct unw_cursor_t {
    opaque: [unw_word_t; UNW_TDEP_CURSOR_LEN],
}

type unw_context_t = ucontext::ucontext_t;
type unw_regnum_t = c_int;

#[cfg(target_arch="x86_64")]
type unw_fpreg_t = c_double;

extern {
    fn unw_getcontext(ucp: *mut unw_context_t);
    fn unw_init_local(c: *mut unw_cursor_t, ctxt: *mut unw_context_t);
    // fn unw_init_remote(c: *mut unw_cursor_t, as: unw_addr_space_t, arg: *mut c_void);
    fn unw_step(cp: *mut unw_cursor_t);
    fn unw_get_reg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_word_t);
    fn unw_get_fpreg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_fpreg_t);
    fn unw_resume(cp: *mut unw_cursor_t);

    // fn unw_create_addr_space(ap: *mut unw_accessors_t, byteorder: c_int);
    // fn unw_destroy_addr_space(as: unw_addr_space_t);
    // fn unw_get_accessors(as: unw_addr_space_t) -> *mut unw_accessors_t;
    // fn unw_flush_cache(as: unw_addr_space, lo: unw_word_t, hi: unw_word_t);
    // fn unw_set_caching_policy(as: unw_addr_space, policy: unw_caching_policy_t) -> c_int;

    fn unw_regname(regnum: unw_regnum_t) -> *const c_char;
    // fn unw_get_proc_info(cp: *mut unw_cursor_t, pip: *mut unw_proc_info_t);
    // fn unw_get_save_loc(cp: *mut unw_cursor_t, _int: c_int, loc: *mut unw_save_loc_t);
    fn unw_is_fpreg(r: unw_regnum_t) -> c_int;
    fn unw_is_signal_frame(cp: *mut unw_cursor_t) -> c_int;
    fn unw_get_proc_name(cp: *mut unw_cursor_t, bufp: *mut c_char, len: size_t, offp: *mut unw_word_t) -> c_int;

    // fn _U_dyn_register(di: *mut unw_dyn_info_t);
    // fn _U_dyn_cancel(di: *mut unw_dyn_info_t);
}
<|endoftext|>


<commit_before>// Copyright (C) 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use git_version::git_version;

fn main() {
    println!("cargo:rustc-env={}={}", "VERSION", git_version!());

    // Run in single thread due the active/inactive tests not
    // supporting to run in parallel for now.
    println!("cargo:rustc-env=RUST_TEST_THREADS=1");
}
<commit_msg>build: Fix a clippy warning of literal with an empty format string<commit_after>// Copyright (C) 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use git_version::git_version;

fn main() {
    println!("cargo:rustc-env=VERSION={}", git_version!());

    // Run in single thread due the active/inactive tests not
    // supporting to run in parallel for now.
    println!("cargo:rustc-env=RUST_TEST_THREADS=1");
}
<|endoftext|>


<commit_before>use state::State;
use context::BaseContext;

use self::message::Action as MessageAction;
use self::message::Command as MessageCommand;

#[derive(Debug)]
pub enum Action {
    Message(MessageAction)
}

impl Action {
    pub fn execute(&self, state: &State, context: &BaseContext) -> ActionCommand {
        match *self {
            Action::Message(ref action) => action.execute(state, context)
        }
    }
}

pub enum ActionCommand {
    Message(MessageCommand)
}

mod message {
    use context::BaseContext;
    use state::State;
    use Message;
    use super::ActionCommand;

    #[derive(Debug)]
    pub struct Action;

    impl Action {
        pub fn execute(&self, _: &State, _: &BaseContext) -> ActionCommand {
            ActionCommand::Message(Command(Message::new("".to_string())))
        }
    }

    pub struct Command(Message);
}
<commit_msg>action: add ActionHandlers struct<commit_after>use state::State;
use context::BaseContext;

use self::message::Action as MessageAction;
use self::message::Command as MessageCommand;
use self::message::MessageActionHandler;

#[derive(Debug)]
pub enum Action {
    Message(MessageAction)
}

impl Action {
    pub fn execute(&self, state: &State, context: &BaseContext) -> ActionCommand {
        match *self {
            Action::Message(ref action) => action.execute(state, context)
        }
    }
}

pub enum ActionCommand {
    Message(MessageCommand)
}

pub struct ActionHandlers {
    message_handler: Box<MessageActionHandler>
}

impl ActionHandlers {
    pub fn handle(&mut self, command: ActionCommand) {
        match command {
            ActionCommand::Message(message) => self.message_handler.handle(message)
        }
    }
}

mod message {
    use context::BaseContext;
    use state::State;
    use Message;
    use super::ActionCommand;

    #[derive(Debug)]
    pub struct Action;

    impl Action {
        pub fn execute(&self, _: &State, _: &BaseContext) -> ActionCommand {
            ActionCommand::Message(Command(Message::new("".to_string())))
        }
    }

    pub struct Command(Message);

    pub trait MessageActionHandler {
        fn handle(&mut self, command: Command);
    }
}
<|endoftext|>


<commit_before>use graphics::{DrawState, Transformed, rectangle};
use graphics::polygon::Polygon;
use graphics::line::Line;
use graphics::math::{transform_pos, rotate_radians};
use opengl_graphics::GlGraphics;
use piston::input::Key;
use rand::Rng;
use rand::distributions::{Range, IndependentSample, Normal};
use rand::distributions::range::SampleRange;
use std::f64::consts::PI;
use intersect::{lines_intersect, point_in};
use point::Point;

use config::Config;

pub fn to_cartesian(theta: f64, r: f64) -> (f64, f64) {
    return (theta.sin() * r, -theta.cos() * r);
}

fn random<T: SampleRange + PartialOrd>(low: T, high: T, mut rng: &mut Rng) -> T {
    return Range::new(low, high).ind_sample(&mut rng);
}

pub fn wrapped_add(a: f64, b: f64, bound: f64) -> f64 {
    (a + b + bound) % bound
}

#[derive(PartialEq, Debug)]
pub struct GameObject {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
}

impl GameObject {
    fn new(x: f64, y: f64, v: f64, theta: f64) -> GameObject {
        GameObject {
            x: x,
            y: y,
            v: v,
            theta: theta,
        }
    }
}

#[derive(Clone)]
pub struct Spaceship {
    x: f64,
    y: f64,
    v: f64,
    v_theta: f64,
    theta: f64,
    accel: f64,
    reverse: f64,
    left: f64,
    right: f64,
    firing: bool,
    cooldown: f64,
}

const SPACESHIP_POINTS: [[f64; 2]; 3] = [[5.0, 7.0], [-5.0, 7.0], [0.0, -13.0]];

impl Spaceship {
    pub fn new(config: &Config) -> Spaceship {
        return Spaceship {
            x: config.width() / 2.0,
            y: config.height() / 2.0,
            v: 0.0,
            v_theta: 0.0,
            theta: 0.0,
            accel: 0.0,
            reverse: 0.0,
            left: 0.0,
            right: 0.0,
            firing: false,
            cooldown: 0.0,
        };
    }

    pub fn handle_press(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 1.0,
            Key::Down => self.reverse = 1.0,
            Key::Left => self.left = 0.05,
            Key::Right => self.right = 0.05,
            Key::Space => self.firing = true,
            _ => (),
        }
    }

    pub fn handle_release(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 0.0,
            Key::Down => self.reverse = 0.0,
            Key::Left => self.left = 0.0,
            Key::Right => self.right = 0.0,
            Key::Space => self.firing = false,
            _ => (),
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        Polygon::new(color).draw(&SPACESHIP_POINTS,
                                 ds,
                                 t.trans(self.x, self.y)
                                  .rot_rad(self.theta),
                                 gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let (dx, dy) = to_cartesian(self.v_theta, self.v * dt);
        self.x = wrapped_add(self.x, dx, x_max);
        self.y = wrapped_add(self.y, dy, y_max);
    }

    pub fn accelerate(&mut self, dt: f64) {
        let net_accel = (self.accel - self.reverse) * dt * 100.0;
        let (dx, dy) = to_cartesian(self.v_theta, self.v);
        let (ddx, ddy) = to_cartesian(self.theta, net_accel);
        let new_dx = dx + ddx;
        let new_dy = dy + ddy;
        self.v = (new_dx * new_dx + new_dy * new_dy).sqrt().min(200.0).max(-200.0);
        self.v_theta = new_dx.atan2(-new_dy);
    }

    pub fn turn(&mut self, dt: f64) {
        self.theta += (self.right - self.left) * dt * 100.0;
    }

    pub fn cooldown(&mut self, dt: f64) {
        self.cooldown = (self.cooldown - dt).max(0.0);
    }

    pub fn ready_to_fire(&self) -> bool {
        return self.cooldown == 0.0;
    }

    pub fn is_firing(&self) -> bool {
        return self.firing;
    }

    pub fn fire(&mut self, bullets: &mut Vec<Bullet>) {
        self.cooldown = 0.5;
        bullets.push(Bullet::new(self.x, self.y, self.theta));
    }

    pub fn edges(&self) -> Vec<[f64; 4]> {
        let rotation_matrix = rotate_radians(self.theta);
        let points: Vec<[f64; 2]> = SPACESHIP_POINTS.iter()
                                                    .map(|p| transform_pos(rotation_matrix, *p))
                                                    .collect();
        return points.iter()
                     .zip(points.iter().cycle().skip(1))
                     .map(|(p1, p2)| {
                         [p1[0] + self.x, p1[1] + self.y, p2[0] + self.x, p2[1] + self.y]
                     })
                     .collect();
    }

    pub fn collides<I: Iterator<Item = [f64; 4]>>(&self, edges: I) -> bool {
        let edges_vec: Vec<[f64; 4]> = edges.collect();
        return self.edges().iter().any(|edge| {
            edges_vec.iter().any(|other_edge| lines_intersect(*edge, *other_edge))
        });
    }
}

#[derive(Clone, Debug)]
pub struct Bullet {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
    distance: f64,
}

impl Bullet {
    fn new(x: f64, y: f64, theta: f64) -> Bullet {
        return Bullet {
            x: x,
            y: y,
            v: 100.0,
            theta: theta,
            distance: 0.0,
        };
    }

    pub fn draw(&self, color: [f32; 4], t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        rectangle(color, rectangle::square(self.x, self.y, 2.0), t, gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.x = wrapped_add(self.x, self.theta.sin() * self.v * dt, x_max);
        self.y = wrapped_add(self.y, -self.theta.cos() * self.v * dt, y_max);
        self.distance += self.v * dt;
    }

    pub fn is_alive(&self) -> bool {
        return self.distance < 100.0;
    }

    pub fn coords(&self) -> Point {
        return Point::new(self.x, self.y);
    }

    pub fn collides(&self, astroid: &Astroid) -> bool {
        return point_in(self.coords(), astroid.edges().iter().cloned());
    }
}

#[derive(Clone)]
pub struct Astroid {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
    size: i64,
    border: Vec<[f64; 4]>,
}

const ASTROID_LARGE: i64 = 3;

impl Astroid {
    pub fn large_new(config: &Config, mut rng: &mut Rng) -> Astroid {
        return Self::new(ASTROID_LARGE, config, rng);
    }

    fn random_start(max: f64, gap: f64, mut rng: &mut Rng) -> f64 {
        if random(0, 2, rng) == 0 {
            return random(0.0, max / 2.0 - gap, rng);
        } else {
            return random(max / 2.0 + gap, max, rng);
        }
    }

    pub fn new(size: i64, config: &Config, mut rng: &mut Rng) -> Astroid {
        let radius = (size * 5) as f64;
        return Astroid {
            x: Astroid::random_start(config.width(), config.astroid_gap_distance(), &mut rng),
            y: Astroid::random_start(config.height(), config.astroid_gap_distance(), &mut rng),
            v: random(40.0, 60.0, &mut rng),
            theta: random(0.0, 2.0 * PI, &mut rng),
            size: size,
            border: Astroid::create_border(&mut rng, radius),
        };
    }

    fn exploded(&self, mut rng: &mut Rng) -> Astroid {
        let new_size = self.size - 1;
        let radius = (new_size * 5) as f64;
        let theta_range = Normal::new(0.0, PI / 2.0);
        let d_theta = theta_range.ind_sample(&mut rng);
        let theta = self.theta + d_theta;
        return Astroid {
            x: self.x + random(-5.0, 5.0, &mut rng),
            y: self.y + random(-5.0, 5.0, &mut rng),
            v: random(40.0, 60.0, &mut rng),
            theta: theta,
            size: new_size,
            border: Astroid::create_border(&mut rng, radius),
        };
    }

    pub fn explode(&self, mut rng: &mut Rng) -> Vec<Astroid> {
        if self.size <= 1 {
            vec![]
        } else {
            vec![self.exploded(rng), self.exploded(rng)]
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        let line_info = Line::new(color, 0.5);
        for line_points in self.border.iter() {
            line_info.draw(*line_points, ds, t.trans(self.x, self.y), gl);
        }
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.x = wrapped_add(self.x, self.theta.sin() * self.v * dt, x_max);
        self.y = wrapped_add(self.y, -self.theta.cos() * self.v * dt, y_max);
    }

    pub fn create_border(mut rng: &mut Rng, radius: f64) -> Vec<[f64; 4]> {
        let spread = radius / 5.0;
        let point_count = random(8, 12, &mut rng);
        let mut points = Vec::with_capacity(point_count);
        let theta_0 = random(0.0, 2.0 * PI, &mut rng);
        let corner_i_to_theta = |i| theta_0 + 2.0 * PI * i as f64 / point_count as f64;
        for theta in (1..point_count + 1).map(corner_i_to_theta) {
            let distance = radius + random(-spread, spread, &mut rng);
            points.push(to_cartesian(theta, distance));
        }
        let point = points[0];
        points.push(point);
        let mut lines = Vec::with_capacity(point_count);
        for point in points.iter().zip(points.iter().skip(1)) {
            let (&(x1, x2), &(y1, y2)) = point;
            lines.push([x1, x2, y1, y2]);
        }
        return lines;
    }

    pub fn edges(&self) -> Vec<[f64; 4]> {
        return self.border
                   .iter()
                   .map(|edge| {
                       [edge[0] + self.x, edge[1] + self.y, edge[2] + self.x, edge[3] + self.y]
                   })
                   .collect();
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::f64::consts::PI;
    use expectest::prelude::*;

    #[test]
    fn test_wrapped_add() {
        assert_eq!(wrapped_add(1.0, 1.0, 10.0), 2.0);
        assert_eq!(wrapped_add(1.0, 10.0, 10.0), 1.0);
        assert_eq!(wrapped_add(1.0, -5.0, 10.0), 6.0);
    }

    fn expect_both_close_to((r, theta): (f64, f64), (x_expected, y_expected): (f64, f64)) {
        match to_cartesian(r, theta) {
            (x, y) => {
                expect!(x_expected).to(be_close_to(x));
                expect!(y_expected).to(be_close_to(y));
            }
        }
    }

    #[test]
    fn test_to_cartesian() {
        expect_both_close_to((0.0, 1.0), (0.0, -1.0));
        expect_both_close_to((PI / 2.0, 1.0), (1.0, 0.0));
    }

    #[test]
    fn test_game_object_factories() {
        expect!(GameObject::new(2.0, 3.0, 5.0, 7.0)).to(be_equal_to(GameObject {
            x: 2.0,
            y: 3.0,
            v: 5.0,
            theta: 7.0,
        }));
    }
}
<commit_msg>Make game objects use GameObject<commit_after>use graphics::{DrawState, Transformed, rectangle};
use graphics::polygon::Polygon;
use graphics::line::Line;
use graphics::math::{transform_pos, rotate_radians};
use opengl_graphics::GlGraphics;
use piston::input::Key;
use rand::Rng;
use rand::distributions::{Range, IndependentSample, Normal};
use rand::distributions::range::SampleRange;
use std::f64::consts::PI;
use intersect::{lines_intersect, point_in};
use point::Point;

use config::Config;

pub fn to_cartesian(theta: f64, r: f64) -> (f64, f64) {
    return (theta.sin() * r, -theta.cos() * r);
}

fn random<T: SampleRange + PartialOrd>(low: T, high: T, mut rng: &mut Rng) -> T {
    return Range::new(low, high).ind_sample(&mut rng);
}

pub fn wrapped_add(a: f64, b: f64, bound: f64) -> f64 {
    (a + b + bound) % bound
}

#[derive(PartialEq, Debug, Clone)]
pub struct GameObject {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
}

impl GameObject {
    fn new(x: f64, y: f64, v: f64, theta: f64) -> GameObject {
        GameObject {
            x: x,
            y: y,
            v: v,
            theta: theta,
        }
    }
}

#[derive(Clone)]
pub struct Spaceship {
    obj: GameObject,
    v_theta: f64,
    accel: f64,
    reverse: f64,
    left: f64,
    right: f64,
    firing: bool,
    cooldown: f64,
}

const SPACESHIP_POINTS: [[f64; 2]; 3] = [[5.0, 7.0], [-5.0, 7.0], [0.0, -13.0]];

impl Spaceship {
    pub fn new(config: &Config) -> Spaceship {
        return Spaceship {
            obj: GameObject::new(
                config.width() / 2.0,
                config.height() / 2.0,
                0.0,
                0.0,
            ),
            v_theta: 0.0,
            accel: 0.0,
            reverse: 0.0,
            left: 0.0,
            right: 0.0,
            firing: false,
            cooldown: 0.0,
        };
    }

    pub fn handle_press(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 1.0,
            Key::Down => self.reverse = 1.0,
            Key::Left => self.left = 0.05,
            Key::Right => self.right = 0.05,
            Key::Space => self.firing = true,
            _ => (),
        }
    }

    pub fn handle_release(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 0.0,
            Key::Down => self.reverse = 0.0,
            Key::Left => self.left = 0.0,
            Key::Right => self.right = 0.0,
            Key::Space => self.firing = false,
            _ => (),
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        Polygon::new(color).draw(&SPACESHIP_POINTS,
                                 ds,
                                 t.trans(self.obj.x, self.obj.y)
                                  .rot_rad(self.obj.theta),
                                 gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let (dx, dy) = to_cartesian(self.v_theta, self.obj.v * dt);
        self.obj.x = wrapped_add(self.obj.x, dx, x_max);
        self.obj.y = wrapped_add(self.obj.y, dy, y_max);
    }

    pub fn accelerate(&mut self, dt: f64) {
        let net_accel = (self.accel - self.reverse) * dt * 100.0;
        let (dx, dy) = to_cartesian(self.v_theta, self.obj.v);
        let (ddx, ddy) = to_cartesian(self.obj.theta, net_accel);
        let new_dx = dx + ddx;
        let new_dy = dy + ddy;
        self.obj.v = (new_dx * new_dx + new_dy * new_dy).sqrt().min(200.0).max(-200.0);
        self.v_theta = new_dx.atan2(-new_dy);
    }

    pub fn turn(&mut self, dt: f64) {
        self.obj.theta += (self.right - self.left) * dt * 100.0;
    }

    pub fn cooldown(&mut self, dt: f64) {
        self.cooldown = (self.cooldown - dt).max(0.0);
    }

    pub fn ready_to_fire(&self) -> bool {
        return self.cooldown == 0.0;
    }

    pub fn is_firing(&self) -> bool {
        return self.firing;
    }

    pub fn fire(&mut self, bullets: &mut Vec<Bullet>) {
        self.cooldown = 0.5;
        bullets.push(Bullet::new(self.obj.x, self.obj.y, self.obj.theta));
    }

    pub fn edges(&self) -> Vec<[f64; 4]> {
        let rotation_matrix = rotate_radians(self.obj.theta);
        let points: Vec<[f64; 2]> = SPACESHIP_POINTS.iter()
                                                    .map(|p| transform_pos(rotation_matrix, *p))
                                                    .collect();
        return points.iter()
                     .zip(points.iter().cycle().skip(1))
                     .map(|(p1, p2)| {
                         [p1[0] + self.obj.x, p1[1] + self.obj.y, p2[0] + self.obj.x, p2[1] + self.obj.y]
                     })
                     .collect();
    }

    pub fn collides<I: Iterator<Item = [f64; 4]>>(&self, edges: I) -> bool {
        let edges_vec: Vec<[f64; 4]> = edges.collect();
        return self.edges().iter().any(|edge| {
            edges_vec.iter().any(|other_edge| lines_intersect(*edge, *other_edge))
        });
    }
}

#[derive(Clone, Debug)]
pub struct Bullet {
    obj: GameObject,
    distance: f64,
}

impl Bullet {
    fn new(x: f64, y: f64, theta: f64) -> Bullet {
        return Bullet {
            obj: GameObject::new(
                x,
                y,
                100.0,
                theta,
            ),
            distance: 0.0,
        };
    }

    pub fn draw(&self, color: [f32; 4], t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        rectangle(color, rectangle::square(self.obj.x, self.obj.y, 2.0), t, gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.obj.x = wrapped_add(self.obj.x, self.obj.theta.sin() * self.obj.v * dt, x_max);
        self.obj.y = wrapped_add(self.obj.y, -self.obj.theta.cos() * self.obj.v * dt, y_max);
        self.distance += self.obj.v * dt;
    }

    pub fn is_alive(&self) -> bool {
        return self.distance < 100.0;
    }

    pub fn coords(&self) -> Point {
        return Point::new(self.obj.x, self.obj.y);
    }

    pub fn collides(&self, astroid: &Astroid) -> bool {
        return point_in(self.coords(), astroid.edges().iter().cloned());
    }
}

#[derive(Clone)]
pub struct Astroid {
    obj: GameObject,
    size: i64,
    border: Vec<[f64; 4]>,
}

const ASTROID_LARGE: i64 = 3;

impl Astroid {
    pub fn large_new(config: &Config, mut rng: &mut Rng) -> Astroid {
        return Self::new(ASTROID_LARGE, config, rng);
    }

    fn random_start(max: f64, gap: f64, mut rng: &mut Rng) -> f64 {
        if random(0, 2, rng) == 0 {
            return random(0.0, max / 2.0 - gap, rng);
        } else {
            return random(max / 2.0 + gap, max, rng);
        }
    }

    pub fn new(size: i64, config: &Config, mut rng: &mut Rng) -> Astroid {
        let radius = (size * 5) as f64;
        return Astroid {
            obj: GameObject::new(
                Astroid::random_start(config.width(), config.astroid_gap_distance(), &mut rng),
                Astroid::random_start(config.height(), config.astroid_gap_distance(), &mut rng),
                random(40.0, 60.0, &mut rng),
                random(0.0, 2.0 * PI, &mut rng),
            ),
            size: size,
            border: Astroid::create_border(&mut rng, radius),
        };
    }

    fn exploded(&self, mut rng: &mut Rng) -> Astroid {
        let new_size = self.size - 1;
        let radius = (new_size * 5) as f64;
        let theta_range = Normal::new(0.0, PI / 2.0);
        let d_theta = theta_range.ind_sample(&mut rng);
        let theta = self.obj.theta + d_theta;
        return Astroid {
            obj: GameObject::new(
                self.obj.x + random(-5.0, 5.0, &mut rng),
                self.obj.y + random(-5.0, 5.0, &mut rng),
                random(40.0, 60.0, &mut rng),
                theta,
            ),
            size: new_size,
            border: Astroid::create_border(&mut rng, radius),
        };
    }

    pub fn explode(&self, mut rng: &mut Rng) -> Vec<Astroid> {
        if self.size <= 1 {
            vec![]
        } else {
            vec![self.exploded(rng), self.exploded(rng)]
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        let line_info = Line::new(color, 0.5);
        for line_points in self.border.iter() {
            line_info.draw(*line_points, ds, t.trans(self.obj.x, self.obj.y), gl);
        }
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.obj.x = wrapped_add(self.obj.x, self.obj.theta.sin() * self.obj.v * dt, x_max);
        self.obj.y = wrapped_add(self.obj.y, -self.obj.theta.cos() * self.obj.v * dt, y_max);
    }

    pub fn create_border(mut rng: &mut Rng, radius: f64) -> Vec<[f64; 4]> {
        let spread = radius / 5.0;
        let point_count = random(8, 12, &mut rng);
        let mut points = Vec::with_capacity(point_count);
        let theta_0 = random(0.0, 2.0 * PI, &mut rng);
        let corner_i_to_theta = |i| theta_0 + 2.0 * PI * i as f64 / point_count as f64;
        for theta in (1..point_count + 1).map(corner_i_to_theta) {
            let distance = radius + random(-spread, spread, &mut rng);
            points.push(to_cartesian(theta, distance));
        }
        let point = points[0];
        points.push(point);
        let mut lines = Vec::with_capacity(point_count);
        for point in points.iter().zip(points.iter().skip(1)) {
            let (&(x1, x2), &(y1, y2)) = point;
            lines.push([x1, x2, y1, y2]);
        }
        return lines;
    }

    pub fn edges(&self) -> Vec<[f64; 4]> {
        return self.border
                   .iter()
                   .map(|edge| {
                       [edge[0] + self.obj.x, edge[1] + self.obj.y, edge[2] + self.obj.x, edge[3] + self.obj.y]
                   })
                   .collect();
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::f64::consts::PI;
    use expectest::prelude::*;

    #[test]
    fn test_wrapped_add() {
        assert_eq!(wrapped_add(1.0, 1.0, 10.0), 2.0);
        assert_eq!(wrapped_add(1.0, 10.0, 10.0), 1.0);
        assert_eq!(wrapped_add(1.0, -5.0, 10.0), 6.0);
    }

    fn expect_both_close_to((r, theta): (f64, f64), (x_expected, y_expected): (f64, f64)) {
        match to_cartesian(r, theta) {
            (x, y) => {
                expect!(x_expected).to(be_close_to(x));
                expect!(y_expected).to(be_close_to(y));
            }
        }
    }

    #[test]
    fn test_to_cartesian() {
        expect_both_close_to((0.0, 1.0), (0.0, -1.0));
        expect_both_close_to((PI / 2.0, 1.0), (1.0, 0.0));
    }

    #[test]
    fn test_game_object_factories() {
        expect!(GameObject::new(2.0, 3.0, 5.0, 7.0)).to(be_equal_to(GameObject {
            x: 2.0,
            y: 3.0,
            v: 5.0,
            theta: 7.0,
        }));
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate extra;

use std::env;
use std::fs;
use std::io::{stdout, stderr, StdoutLock, Stderr, Write};
use extra::option::OptionalExt;
use std::process::exit;

const MAN_PAGE: &'static str = /* @MANSTART{du} */ r#"
NAME
    du - list directory content with sizes

SYNOPSIS
    du [ -h | --help][FILE]...

DESCRIPTION
    List the name and size of the FILE(s), or the current directory

OPTIONS
    -h
    --help
        display this help and exit
"#; /* @MANEND */

fn list_entry(path: &str, name: &str, stdout: &mut StdoutLock, stderr: &mut Stderr) {
    let metadata = fs::metadata(path).try(stderr);
    let size = metadata.len();

    stdout.write(((size + 1023) / 1024).to_string().as_bytes()).try(stderr);
    stdout.write(b"\t").try(stderr);
    stdout.write(name.as_bytes()).try(stderr);
    stdout.write(b"\n").try(stderr);
}

fn list_dir(path: &str, stdout: &mut StdoutLock, stderr: &mut Stderr) {
    if fs::metadata(path).try(stderr).is_dir() {
        let dir = fs::read_dir(path).try(stderr);

        let mut entries = Vec::new();
        for entry_result in dir {
            let entry = entry_result.try(stderr);
            let directory = entry.file_type().map(|x| x.is_dir()).unwrap_or(false);

            let file_name = entry.file_name();
            let path_str = file_name.to_str().try(stderr);
            entries.push(path_str.to_owned());

            if directory {
                entries.last_mut().unwrap().push('/');
            }
        }

        entries.sort();

        for entry in entries {
            let mut entry_path = path.to_owned();
            if !entry_path.ends_with('/') {
                entry_path.push('/');
            }
            entry_path.push_str(&entry);

            list_entry(&entry_path, &entry, stdout, stderr);
        }
    } else {
        list_entry(path, path, stdout, stderr);
    }
}
fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();

    for arg in env::args().skip(1){
        if arg.as_str() == "-h" || arg.as_str() == "--help" {
            stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
            stdout.flush().try(&mut stderr);
            exit(0);
        }
    }

    let mut args = env::args().skip(1);
    if let Some(ref x) = args.next() {
        list_dir(x, &mut stdout, &mut stderr);
        for y in args {
            list_dir(&y, &mut stdout, &mut stderr);
        }
    } else {
        list_dir(".", &mut stdout, &mut stderr);
    }
}
<commit_msg>Fix du<commit_after>#![deny(warnings)]

extern crate extra;

use std::env;
use std::fs;
use std::path::Path;
use std::io::{stdout, stderr, StdoutLock, Stderr, Write};
use extra::option::OptionalExt;
use std::process::exit;

const MAN_PAGE: &'static str = /* @MANSTART{du} */ r#"
NAME
    du - list directory content with sizes

SYNOPSIS
    du [ -h | --help][FILE]...

DESCRIPTION
    List the name and size of the FILE(s), or the current directory

OPTIONS
    -h
    --help
        display this help and exit
"#; /* @MANEND */

fn list_entry(path: &str, name: &str, stdout: &mut StdoutLock, stderr: &mut Stderr) {
    let metadata = fs::metadata(path).try(stderr);
    let size = metadata.len();

    stdout.write(((size + 1023) / 1024).to_string().as_bytes()).try(stderr);
    stdout.write(b"\t").try(stderr);
    stdout.write(name.as_bytes()).try(stderr);
    stdout.write(b"\n").try(stderr);
}

fn list_dir(path: &str, stdout: &mut StdoutLock, stderr: &mut Stderr) {
    if fs::metadata(path).try(stderr).is_dir() {
        let read_dir = Path::new(path).read_dir().try(stderr);

        let mut entries = vec![];
        for dir in read_dir {
            let dir = match dir {
                Ok(x) => x,
                Err(_) => continue,
            };
            let mut file_name = dir.file_name().to_string_lossy().into_owned();
            if dir.file_type().try(stderr).is_dir() {
                file_name.push('/');
            }
            entries.push(file_name);
        }

        entries.sort();

        for entry in entries.iter() {
            let mut entry_path = path.to_owned();
            if !entry_path.ends_with('/') {
                entry_path.push('/');
            }
            entry_path.push_str(&entry);

            list_entry(&entry_path, &entry, stdout, stderr);
        }
    } else {
        list_entry(path, path, stdout, stderr);
    }
}
fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();

    for arg in env::args().skip(1){
        if arg.as_str() == "-h" || arg.as_str() == "--help" {
            stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
            stdout.flush().try(&mut stderr);
            exit(0);
        }
    }

    let mut args = env::args().skip(1);
    if let Some(ref x) = args.next() {
        list_dir(x, &mut stdout, &mut stderr);
        for y in args {
            list_dir(&y, &mut stdout, &mut stderr);
        }
    } else {
        list_dir(".", &mut stdout, &mut stderr);
    }
}
<|endoftext|>


<commit_before>
extern crate sysfs_gpio;
extern crate sysfs_pwm;

use self::sysfs_gpio::{Direction, Pin};
use self::sysfs_pwm::{Pwm};
use ::std::error::Error;

use super::{PinProxyContract,PwmProxyContract,DirectionProxied,ProxyError,ProxyResult};

pub struct PinProxy {
	pin : Pin,
}

impl PinProxyContract for PinProxy
{
	fn new(pin_num: u64) -> PinProxy {
		PinProxy{ pin: Pin::new(pin_num) }
	}

	fn export(&self) ->  ProxyResult<()>{
		match self.pin.export()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn unexport(&self) ->  ProxyResult<()> {
		match self.pin.unexport()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_value(&self, value: u8) ->  ProxyResult<()> {
		match self.pin.set_value(value)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_direction(&self, dir: DirectionProxied) ->  ProxyResult<()>{
		let dirmapped =  match dir {
										DirectionProxied::In =>  Direction::In,
										DirectionProxied::Out => Direction::Out,
										DirectionProxied::High => Direction::High,
										DirectionProxied::Low => Direction::Low,
									};
		match self.pin.set_direction(dirmapped)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}
}

pub struct PwmProxy {
	pwm : Pwm,
}

impl PwmProxyContract for PwmProxy
{
	fn new(chip: u32, number: u32) -> ProxyResult<PwmProxy>{

		match Pwm::new(chip, number) {
			Ok(pwm) => Ok(PwmProxy{ pwm: pwm}),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn export(&self) ->  ProxyResult<()>{
		match self.pwm.export()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn unexport(&self) ->  ProxyResult<()> {
		match self.pwm.unexport()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn enable(&self, enable: bool) -> ProxyResult<()>
	{
		match self.pwm.enable(enable)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{} caused by {}",result.description(),result.cause().unwrap());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_duty_cycle_ns(&self, duty_cycle_ns: u32) -> ProxyResult<()>
	{
		match self.pwm.set_duty_cycle_ns(duty_cycle_ns)
		{
			Ok(()) => {println!("setting dutycycle {}",duty_cycle_ns); Ok(())},
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_period_ns(&self, period_ns: u32) -> ProxyResult<()>
	{
		match self.pwm.set_period_ns(period_ns)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn get_period_ns(&self) -> ProxyResult<u32>
	{
		match self.pwm.get_period_ns()
		{
			Ok(result) => Ok(result),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}

	}

	fn increase_to_max(&self, duration_ms: u32, update_period_ms: u32)
	{
			let step: f32 = duration_ms as f32 / update_period_ms as f32;
			println!("step {}",step);
			let mut duty_cycle = 0.0;
			match self.pwm.get_period_ns()
			{
				Ok(period_ns) => {
				println!("period {}",period_ns);
					while duty_cycle < 1.0 {
						println!("duty cycle {}",duty_cycle);
						println!("set duty cycle ns{}",(duty_cycle * period_ns as f32) as u32);
						self.pwm.set_duty_cycle_ns((duty_cycle * period_ns as f32) as u32).unwrap();
						duty_cycle += step;
					}
					self.pwm.set_duty_cycle_ns(period_ns).unwrap()
				}
				Err(result) => {println!("{}",result.description())}
			}
	}

	fn decrease_to_minimum(&self, duration_ms: u32, update_period_ms: u32)
	{
		let step: f32 = duration_ms as f32 / update_period_ms as f32;
		println!("step {}",step);
		let mut duty_cycle = 1.0;
		match self.pwm.get_period_ns()
		{
			Ok(period_ns) => {
			println!("period {}",period_ns);
				while duty_cycle > 0.0 {
					println!("duty cycle {}",duty_cycle);
					println!("set duty cycle ns{}",(duty_cycle * period_ns as f32) as u32);
						self.pwm.set_duty_cycle_ns((duty_cycle * period_ns as f32) as u32).unwrap();
						duty_cycle -= step;
				}
				self.pwm.set_duty_cycle_ns(0).unwrap()
			}
			Err(result) => {println!("{}",result.description())}
		}
	}
}<commit_msg>duty cycle calculation<commit_after>
extern crate sysfs_gpio;
extern crate sysfs_pwm;

use self::sysfs_gpio::{Direction, Pin};
use self::sysfs_pwm::{Pwm};
use ::std::error::Error;

use super::{PinProxyContract,PwmProxyContract,DirectionProxied,ProxyError,ProxyResult};

pub struct PinProxy {
	pin : Pin,
}

impl PinProxyContract for PinProxy
{
	fn new(pin_num: u64) -> PinProxy {
		PinProxy{ pin: Pin::new(pin_num) }
	}

	fn export(&self) ->  ProxyResult<()>{
		match self.pin.export()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn unexport(&self) ->  ProxyResult<()> {
		match self.pin.unexport()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_value(&self, value: u8) ->  ProxyResult<()> {
		match self.pin.set_value(value)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_direction(&self, dir: DirectionProxied) ->  ProxyResult<()>{
		let dirmapped =  match dir {
										DirectionProxied::In =>  Direction::In,
										DirectionProxied::Out => Direction::Out,
										DirectionProxied::High => Direction::High,
										DirectionProxied::Low => Direction::Low,
									};
		match self.pin.set_direction(dirmapped)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}
}

pub struct PwmProxy {
	pwm : Pwm,
}

impl PwmProxyContract for PwmProxy
{
	fn new(chip: u32, number: u32) -> ProxyResult<PwmProxy>{

		match Pwm::new(chip, number) {
			Ok(pwm) => Ok(PwmProxy{ pwm: pwm}),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn export(&self) ->  ProxyResult<()>{
		match self.pwm.export()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn unexport(&self) ->  ProxyResult<()> {
		match self.pwm.unexport()
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn enable(&self, enable: bool) -> ProxyResult<()>
	{
		match self.pwm.enable(enable)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{} caused by {}",result.description(),result.cause().unwrap());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_duty_cycle_ns(&self, duty_cycle_ns: u32) -> ProxyResult<()>
	{
		match self.pwm.set_duty_cycle_ns(duty_cycle_ns)
		{
			Ok(()) => {println!("setting dutycycle {}",duty_cycle_ns); Ok(())},
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn set_period_ns(&self, period_ns: u32) -> ProxyResult<()>
	{
		match self.pwm.set_period_ns(period_ns)
		{
			Ok(()) => Ok(()),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}
	}

	fn get_period_ns(&self) -> ProxyResult<u32>
	{
		match self.pwm.get_period_ns()
		{
			Ok(result) => Ok(result),
			Err(result) => {println!("{}",result.description());
				Err(ProxyError::MonErreur)},
		}

	}

	fn increase_to_max(&self, duration_ms: u32, update_period_ms: u32)
	{
			let step: f32 = (duration_ms as f32 / update_period_ms as f32) / 1000.0;
			println!("step {}",step);
			let mut duty_cycle = 0.0;
			match self.pwm.get_period_ns()
			{
				Ok(period_ns) => {
				println!("period {}",period_ns);
					while duty_cycle < 1.0 {
						println!("duty cycle {}",duty_cycle);
						println!("set duty cycle ns{}",(duty_cycle * period_ns as f32) as u32);
						self.pwm.set_duty_cycle_ns((duty_cycle * period_ns as f32) as u32).unwrap();
						duty_cycle += step;
					}
					self.pwm.set_duty_cycle_ns(period_ns).unwrap()
				}
				Err(result) => {println!("{}",result.description())}
			}
	}

	fn decrease_to_minimum(&self, duration_ms: u32, update_period_ms: u32)
	{
		let step: f32 = (duration_ms as f32 / update_period_ms as f32) / 1000.0;
		println!("step {}",step);
		let mut duty_cycle = 1.0;
		match self.pwm.get_period_ns()
		{
			Ok(period_ns) => {
			println!("period {}",period_ns);
				while duty_cycle > 0.0 {
					println!("duty cycle {}",duty_cycle);
					println!("set duty cycle ns{}",(duty_cycle * period_ns as f32) as u32);
						self.pwm.set_duty_cycle_ns((duty_cycle * period_ns as f32) as u32).unwrap();
						duty_cycle -= step;
				}
				self.pwm.set_duty_cycle_ns(0).unwrap()
			}
			Err(result) => {println!("{}",result.description())}
		}
	}
}<|endoftext|>