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

/*!
Divides the document tree into pages.

Each page corresponds is a logical section. There may be pages for
individual modules, pages for the crate, indexes, etc.
*/

use core::prelude::*;

use astsrv;
use config;
use doc::{ItemUtils, PageUtils};
use doc;
use fold::Fold;
use fold;
use pass::Pass;
use sort_pass;
use util::NominalOp;
use util;

use core::oldcomm;
use core::option;
use core::vec;
use syntax::ast;

pub fn mk_pass(output_style: config::OutputStyle) -> Pass {
    Pass {
        name: ~"page",
        f: fn~(srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc {
            run(srv, doc, output_style)
        }
    }
}

pub fn run(
    _srv: astsrv::Srv,
    doc: doc::Doc,
    output_style: config::OutputStyle
) -> doc::Doc {

    if output_style == config::DocPerCrate {
        return doc;
    }

    let (result_port, page_chan) = do util::spawn_conversation
        |page_port, result_chan| {
        oldcomm::send(result_chan, make_doc_from_pages(page_port));
    };

    find_pages(doc, page_chan);
    oldcomm::recv(result_port)
}

type PagePort = oldcomm::Port<Option<doc::Page>>;
type PageChan = oldcomm::Chan<Option<doc::Page>>;

type NominalPageChan = NominalOp<PageChan>;

fn make_doc_from_pages(page_port: PagePort) -> doc::Doc {
    let mut pages = ~[];
    loop {
        let val = oldcomm::recv(page_port);
        if val.is_some() {
            pages += ~[option::unwrap(move val)];
        } else {
            break;
        }
    }
    doc::Doc {
        pages: pages
    }
}

fn find_pages(doc: doc::Doc, page_chan: PageChan) {
    let fold = Fold {
        fold_crate: fold_crate,
        fold_mod: fold_mod,
        fold_nmod: fold_nmod,
        .. fold::default_any_fold(NominalOp { op: page_chan })
    };
    (fold.fold_doc)(&fold, copy doc);

    oldcomm::send(page_chan, None);
}

fn fold_crate(
    fold: &fold::Fold<NominalPageChan>,
    doc: doc::CrateDoc
) -> doc::CrateDoc {

    let doc = fold::default_seq_fold_crate(fold, doc);

    let page = doc::CratePage(doc::CrateDoc {
        topmod: strip_mod(copy doc.topmod),
        .. copy doc
    });

    oldcomm::send(fold.ctxt.op, Some(page));

    doc
}

fn fold_mod(
    fold: &fold::Fold<NominalPageChan>,
    doc: doc::ModDoc
) -> doc::ModDoc {

    let doc = fold::default_any_fold_mod(fold, doc);

    if doc.id() != ast::crate_node_id {

        let doc = strip_mod(copy doc);
        let page = doc::ItemPage(doc::ModTag(doc));
        oldcomm::send(fold.ctxt.op, Some(page));
    }

    doc
}

fn strip_mod(doc: doc::ModDoc) -> doc::ModDoc {
    doc::ModDoc {
        items: do doc.items.filtered |item| {
            match *item {
              doc::ModTag(_) => false,
              doc::NmodTag(_) => false,
              _ => true
            }
        },
        .. copy doc
    }
}

fn fold_nmod(
    fold: &fold::Fold<NominalPageChan>,
    doc: doc::NmodDoc
) -> doc::NmodDoc {
    let doc = fold::default_seq_fold_nmod(fold, doc);
    let page = doc::ItemPage(doc::NmodTag(copy doc));
    oldcomm::send(fold.ctxt.op, Some(page));
    return doc;
}

#[test]
fn should_not_split_the_doc_into_pages_for_doc_per_crate() {
    let doc = test::mk_doc_(
        config::DocPerCrate,
        ~"mod a { } mod b { mod c { } }"
    );
    assert doc.pages.len() == 1u;
}

#[test]
fn should_make_a_page_for_every_mod() {
    let doc = test::mk_doc(~"mod a { }");
    assert doc.pages.mods()[0].name() == ~"a";
}

#[test]
fn should_remove_mods_from_containing_mods() {
    let doc = test::mk_doc(~"mod a { }");
    assert vec::is_empty(doc.cratemod().mods());
}

#[test]
fn should_make_a_page_for_every_foreign_mod() {
    let doc = test::mk_doc(~"extern mod a { }");
    assert doc.pages.nmods()[0].name() == ~"a";
}

#[test]
fn should_remove_foreign_mods_from_containing_mods() {
    let doc = test::mk_doc(~"extern mod a { }");
    assert vec::is_empty(doc.cratemod().nmods());
}

#[cfg(test)]
mod test {
    use astsrv;
    use config;
    use doc;
    use extract;
    use page_pass::run;

    pub fn mk_doc_(
        output_style: config::OutputStyle,
        source: ~str
    ) -> doc::Doc {
        do astsrv::from_str(copy source) |srv| {
            let doc = extract::from_srv(srv.clone(), ~"");
            run(srv.clone(), doc, output_style)
        }
    }

    pub fn mk_doc(source: ~str) -> doc::Doc {
        mk_doc_(config::DocPerMod, copy source)
    }
}
<commit_msg>rustdoc: Convert page_pass to pipes<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
Divides the document tree into pages.

Each page corresponds is a logical section. There may be pages for
individual modules, pages for the crate, indexes, etc.
*/

use core::prelude::*;

use astsrv;
use config;
use doc::{ItemUtils, PageUtils};
use doc;
use fold::Fold;
use fold;
use pass::Pass;
use sort_pass;
use util::NominalOp;
use util;

use core::option;
use core::vec;
use core::pipes::*;
use syntax::ast;

pub fn mk_pass(output_style: config::OutputStyle) -> Pass {
    Pass {
        name: ~"page",
        f: fn~(srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc {
            run(srv, doc, output_style)
        }
    }
}

pub fn run(
    _srv: astsrv::Srv,
    doc: doc::Doc,
    output_style: config::OutputStyle
) -> doc::Doc {

    if output_style == config::DocPerCrate {
        return doc;
    }

    let (result_port, result_chan) = stream();
    let (page_port, page_chan) = stream();
    let page_chan = SharedChan(page_chan);
    do task::spawn {
        result_chan.send(make_doc_from_pages(&page_port));
    };

    find_pages(doc, page_chan);
    result_port.recv()
}

type PagePort = Port<Option<doc::Page>>;
type PageChan = SharedChan<Option<doc::Page>>;

type NominalPageChan = NominalOp<PageChan>;

fn make_doc_from_pages(page_port: &PagePort) -> doc::Doc {
    let mut pages = ~[];
    loop {
        let val = page_port.recv();
        if val.is_some() {
            pages += ~[option::unwrap(move val)];
        } else {
            break;
        }
    }
    doc::Doc {
        pages: pages
    }
}

fn find_pages(doc: doc::Doc, page_chan: PageChan) {
    let fold = Fold {
        ctxt: NominalOp { op: page_chan.clone() },
        fold_crate: fold_crate,
        fold_mod: fold_mod,
        fold_nmod: fold_nmod,
        .. fold::default_any_fold(NominalOp { op: page_chan.clone() })
    };
    (fold.fold_doc)(&fold, copy doc);

    page_chan.send(None);
}

fn fold_crate(
    fold: &fold::Fold<NominalPageChan>,
    doc: doc::CrateDoc
) -> doc::CrateDoc {

    let doc = fold::default_seq_fold_crate(fold, doc);

    let page = doc::CratePage(doc::CrateDoc {
        topmod: strip_mod(copy doc.topmod),
        .. copy doc
    });

    fold.ctxt.op.send(Some(page));

    doc
}

fn fold_mod(
    fold: &fold::Fold<NominalPageChan>,
    doc: doc::ModDoc
) -> doc::ModDoc {

    let doc = fold::default_any_fold_mod(fold, doc);

    if doc.id() != ast::crate_node_id {

        let doc = strip_mod(copy doc);
        let page = doc::ItemPage(doc::ModTag(doc));
        fold.ctxt.op.send(Some(page));
    }

    doc
}

fn strip_mod(doc: doc::ModDoc) -> doc::ModDoc {
    doc::ModDoc {
        items: do doc.items.filtered |item| {
            match *item {
              doc::ModTag(_) => false,
              doc::NmodTag(_) => false,
              _ => true
            }
        },
        .. copy doc
    }
}

fn fold_nmod(
    fold: &fold::Fold<NominalPageChan>,
    doc: doc::NmodDoc
) -> doc::NmodDoc {
    let doc = fold::default_seq_fold_nmod(fold, doc);
    let page = doc::ItemPage(doc::NmodTag(copy doc));
    fold.ctxt.op.send(Some(page));
    return doc;
}

#[test]
fn should_not_split_the_doc_into_pages_for_doc_per_crate() {
    let doc = test::mk_doc_(
        config::DocPerCrate,
        ~"mod a { } mod b { mod c { } }"
    );
    assert doc.pages.len() == 1u;
}

#[test]
fn should_make_a_page_for_every_mod() {
    let doc = test::mk_doc(~"mod a { }");
    assert doc.pages.mods()[0].name() == ~"a";
}

#[test]
fn should_remove_mods_from_containing_mods() {
    let doc = test::mk_doc(~"mod a { }");
    assert vec::is_empty(doc.cratemod().mods());
}

#[test]
fn should_make_a_page_for_every_foreign_mod() {
    let doc = test::mk_doc(~"extern mod a { }");
    assert doc.pages.nmods()[0].name() == ~"a";
}

#[test]
fn should_remove_foreign_mods_from_containing_mods() {
    let doc = test::mk_doc(~"extern mod a { }");
    assert vec::is_empty(doc.cratemod().nmods());
}

#[cfg(test)]
mod test {
    use astsrv;
    use config;
    use doc;
    use extract;
    use page_pass::run;

    pub fn mk_doc_(
        output_style: config::OutputStyle,
        source: ~str
    ) -> doc::Doc {
        do astsrv::from_str(copy source) |srv| {
            let doc = extract::from_srv(srv.clone(), ~"");
            run(srv.clone(), doc, output_style)
        }
    }

    pub fn mk_doc(source: ~str) -> doc::Doc {
        mk_doc_(config::DocPerMod, copy source)
    }
}
<|endoftext|>


<commit_before><commit_msg>Cleanup and fix ServerInfo.from_string<commit_after><|endoftext|>


<commit_before><commit_msg>(feat) Added a Body modifier, for efficiently setting a response body.<commit_after><|endoftext|>


<commit_before><commit_msg>add src/bin/rblas_ndarray_generic_compilation_test.rs<commit_after>extern crate num;
use num::{One, Zero};

extern crate rblas;
use rblas::attribute::Transpose;
use rblas::{Gemm};
// the matrix trait is in scope
use rblas::matrix::Matrix;

extern crate ndarray;
// this implements Matrix for BlasArrayViewMut
use ndarray::blas::{AsBlas, BlasArrayViewMut};
use ndarray::blas;
use ndarray::{ArrayBase, DataOwned, DataMut};

fn multiply_f64(
    a: &mut ArrayBase<Vec<f64>, (usize, usize)>,
    b: &mut ArrayBase<Vec<f64>, (usize, usize)>,
    c: &mut ArrayBase<Vec<f64>, (usize, usize)>,
)
{
    Gemm::gemm(
        &1.,
        Transpose::NoTrans, &a.blas(),
        Transpose::NoTrans, &b.blas(),
        &0.,
        &mut c.blas())
}

// fn multiply<FloatT, ContainerT, StorageT, Ix>(
//     a: &mut ContainerT,
//     b: &mut ContainerT,
//     c: &mut ContainerT
// )
//     where FloatT: One + Zero + Clone + Gemm,
//           ContainerT: AsBlas<FloatT, StorageT, (Ix, Ix)>,
//           StorageT: DataOwned<Elem=FloatT> + DataMut<Elem=FloatT>,
// {
//     let ablas: BlasArrayViewMut<FloatT, (Ix, Ix)> = a.blas();
//     let bblas: BlasArrayViewMut<FloatT, (Ix, Ix)> = b.blas();
//     let mut cblas: BlasArrayViewMut<FloatT, (Ix, Ix)> = c.blas();
//     Gemm::gemm(
//         &FloatT::one(),
//         Transpose::NoTrans, &ablas,
//         Transpose::NoTrans, &bblas,
//         &FloatT::zero(),
//         &mut cblas())
// }

fn main() {
    let mut a: ArrayBase<Vec<f64>, (usize, usize)> =
        ArrayBase::from_elem((10, 10), 2.);
    let mut b: ArrayBase<Vec<f64>, (usize, usize)> =
        ArrayBase::from_elem((10, 10), 2.);
    let mut c: ArrayBase<Vec<f64>, (usize, usize)> =
        ArrayBase::from_elem((10, 10), 2.);
    multiply_f64(&mut a, &mut b, &mut c);
    println!("{:?}", c);
}
<|endoftext|>


<commit_before><commit_msg>Use writeln!() instead of write!()<commit_after><|endoftext|>


<commit_before><commit_msg>Simplify implementation of Wiki::all_ids()<commit_after><|endoftext|>


<commit_before><commit_msg>Missed committing repository_metadata_slurp.rs<commit_after>extern mod extra;
extern mod http_client;
extern mod sqlite;

extern mod link_header;

use std::hashmap::HashMap;
use std::str;
use std::result::{Ok, Err};

use extra::json;
use extra::json::{Object, List, String, Number};
use extra::net::url::Url;
use extra::net::url;

use http_client::uv_http_request;
use http_client::StatusCode;
use sqlite::open;

use link_header::*;
pub struct RepoResponse {
    rawJson: ~[~str],
    inLinkField: bool
}

impl RepoResponse {
    fn add(&mut self, data: ~str) {
        self.rawJson.push(data)
    }
}

fn s(key:~str, j:~HashMap<~str, json::Json>) -> ~str {
    match copy *j.get(&key) {
        String(value) =>  value,
        _ => fail!("foo was wrong type " + key)
    }
}

fn n(key:~str, j:~HashMap<~str, json::Json>) -> float {
    match copy *j.get(&key) {
        Number(value) =>  value,
        _ => fail!("foo was wrong type")
    }
}

fn handleRepo(repo: json::Json) {
    match repo {
        Object(o) => {
            println(fmt!("repository_id = %?", n(~"id", copy o)));

            if (o.contains_key(& ~"name")) {
                let name = match copy *o.get(&~"full_name") {
                    String(value) =>  value,
                    _ => fail!("foo was wrong type")
                };
                println(fmt!("repository_name %?", name));
            }

            println(fmt!("html_url = %?", s(~"html_url", o)));
        },
        _ => fail!("Why you no Repo?")
    }
}

fn readJson(json: json::Json) {
    match json {
        json::List(l) => {
            println(fmt!("Got %? items", l.len()));
            //for l.consume_iter().advance |repo| {
            for l.iter().advance |repo| {
                //println(fmt!("repo=%?\n\n", repo));
                handleRepo(copy *repo);
            }
            println("A list of Objects, perhaps")
        }
        _ => {
            println("ERROR: Unrecognized JSON format")
        }
    }
}

// Task
// Given a starting https://api.github.com/repositories URL
// This task downloads the metadata, figures out the next
// api_url and stores these in the database. it then starts
// over with the new api_url
fn slurp_repos(api_url:&str) {
    // https://api.github.com/repositories
    // http://ozten.com/random/sample.json
    let u: Url = url::from_str(api_url).get();
    let mut options:HashMap<~str, ~str> = HashMap::new();

    options.insert(~"User-Agent",
                   ~"curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8x zlib/1.2.5");
    options.insert(~"Accept", ~"*/*");
    // ~"curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8x zlib/1.2.5"

    let mut request = uv_http_request(u, options);

    let res = @mut RepoResponse{rawJson: ~[], inLinkField: false};

    do request.begin |event| {
        match event {
            http_client::Error(e) => {
                println(fmt!("Ouch... error %?", e));
            },
            http_client::Status(s) => match s {
                // TODO wait... how did I break how match works here
                // I should need the pattern guard.
                StatusOK if s == StatusOK => {
                    println(fmt!("Status %?", s));
                    match json::from_str(res.rawJson.concat()) {
                        Ok(json) => {
                            readJson(json);
                        }
                        Err(e) => {
                            println(fmt!("Error parsing JSON %?", e));
                            fail!("Can't read JSON");
                        }
                    }
                }
                StatusFound if s == StatusFound => {
                    println(fmt!("Redirected? %?", s));
                }
                StatusUnknown => {
                    println(fmt!("hmmm status is unknown %?", s));
                    fail!("No JSON of Repositiories");
                }
            },
            http_client::HeaderField(field) => {
                let hField = str::from_bytes(field.take());
                match hField {
                    ~"link" | ~"Link" => {
                        res.inLinkField = true;
                        println("We found link");
                    },
                    _ => ()
                }
            },
            http_client::HeaderValue(field) => {
                if (res.inLinkField) {
                    res.inLinkField = false;
                    let hValue = str::from_bytes(field.take());
                    println("Queing up next page from ");
                    let link:@~str = link_header::parse(hValue);
                    //println(*link.replace("api.github.com", "localhost:8002"));
                    println(link.replace("api.github.com", "localhost:8002"));

                }

            },
            http_client::Payload(p) => {
                let data = p.take();
                res.rawJson.push(str::from_bytes(data));
            }
        }
    }
}<|endoftext|>


<commit_before><commit_msg>Rewrite: Diary::get_youngest_entry_id()<commit_after><|endoftext|>


<commit_before>use redox::*;

use super::Mode;
use super::Mode::*;
use super::Editor;

pub fn exec(editor: &mut Editor, mode: &mut Mode, multiplier: &mut Option<u32>, last_change: &mut String, key_event: KeyEvent, window: &mut Window) {
    match (*mode, key_event.scancode) {
        (Insert, K_ESC) => {
            *mode = Normal;
        },
        (Insert, K_BKSP) => editor.backspace(window),
        (Insert, K_DEL) => editor.delete(window),
        (_, K_F5) => editor.reload(window),
        (_, K_F6) => editor.save(window),
        (_, K_HOME) => editor.offset = 0,
        (_, K_UP) => editor.up(),
        (_, K_LEFT) => editor.left(),
        (_, K_RIGHT) => editor.right(),
        (_, K_END) => editor.offset = editor.string.len(),
        (_, K_DOWN) => editor.down(),
        (m, _) => {
            let (no_mult, mut times) = match *multiplier {
                Some(n) => (false, n),
                None => (true, 1),
            };
            let mut is_none = false;

            match key_event.character {
                '0' if !no_mult => times *= 10,

                '1' if no_mult => times = 1,
                '1' => times = times * 10 + 1,

                '2' if no_mult => times = 2,
                '2' => times = times * 10 + 2,

                '3' if no_mult => times = 3,
                '3' => times = times * 10 + 3,

                '4' if no_mult => times = 4,
                '4' => times = times * 10 + 4,

                '5' if no_mult => times = 5,
                '5' => times = times * 10 + 5,

                '6' if no_mult => times = 6,
                '6' => times = times * 10 + 6,

                '7' if no_mult => times = 7,
                '7' => times = times * 10 + 7,

                '8' if no_mult => times = 8,
                '8' => times = times * 10 + 8,

                '9' if no_mult => times = 9,
                '9' => times = times * 10 + 9,
                _ => {
                    for _ in 0 .. times {
                        match (m, key_event.character) {
                            (Normal, 'i') => {
                                *mode = Insert;
                                *last_change = editor.string.clone();
                            },
                            (Normal, 'h') => editor.left(),
                            (Normal, 'l') => editor.right(),
                            (Normal, 'k') => editor.up(),
                            (Normal, 'j') => editor.down(),
                            (Normal, 'g') => editor.offset = 0,
                            (Normal, 'G') => editor.offset = editor.string.len(),
                            (Normal, 'a') => {
                                editor.right();
                                *mode = Insert;
                                *last_change = editor.string.clone();
                            },
                            (Normal, 'x') => editor.delete(window),
                            (Normal, 'X') => editor.backspace(window),
                            (Normal, 'u') => {
                                editor.offset = 0;
                                ::core::mem::swap(last_change, &mut editor.string);
                            },
                            (Normal, 'o') => {
                                exec(editor, mode, multiplier, last_change, KeyEvent {
                                    character: '$',
                                    scancode: 0,
                                    pressed: true,
                                }, window);
                                exec(editor, mode, multiplier, last_change, KeyEvent {
                                    character: 'i',
                                    scancode: 0,
                                    pressed: true,
                                }, window);
                                exec(editor, mode, multiplier, last_change, KeyEvent {
                                    character: '\n',
                                    scancode: 0,
                                    pressed: true,
                                }, window);
                            },
                            (Normal, '$') => {
                                let mut new_offset = editor.string.len();
                                for i in editor.offset..editor.string.len() {
                                    match editor.string.as_bytes()[i] {
                                        0 => break,
                                        10 => {
                                            new_offset = i;
                                            break;
                                        }
                                        _ => (),
                                    }
                                }
                                editor.offset = new_offset;
                            },
                            (Normal, '0') => {

                                let mut new_offset = 0;
                                for i in 2..editor.offset {
                                    match editor.string.as_bytes()[editor.offset - i] {
                                        0 => break,
                                        10 => {
                                            new_offset = editor.offset - i + 1;
                                            break;
                                        }
                                        _ => (),
                                    }
                                }
                                editor.offset = new_offset;
                            },
                            (Insert, '\0') => (),
                            (Insert, _) => {
                                window.set_title(&format!("{}{}{}","Editor (", &editor.url, ") Changed"));
                                editor.string = editor.string[0 .. editor.offset].to_string() +
                                    &key_event.character.to_string() +
                                    &editor.string[editor.offset .. editor.string.len()];
                                editor.offset += 1;
                            },
                            _ => {},
                        }
                    }
                    is_none = true;
                }
            }

            if !is_none {
                *multiplier = Some(times);
            } else {
                *multiplier = None;
            }
        }
    }
}
<commit_msg>Add `O` command<commit_after>use redox::*;

use super::Mode;
use super::Mode::*;
use super::Editor;

pub fn exec(editor: &mut Editor, mode: &mut Mode, multiplier: &mut Option<u32>, last_change: &mut String, key_event: KeyEvent, window: &mut Window) {
    match (*mode, key_event.scancode) {
        (Insert, K_ESC) => {
            *mode = Normal;
        },
        (Insert, K_BKSP) => editor.backspace(window),
        (Insert, K_DEL) => editor.delete(window),
        (_, K_F5) => editor.reload(window),
        (_, K_F6) => editor.save(window),
        (_, K_HOME) => editor.offset = 0,
        (_, K_UP) => editor.up(),
        (_, K_LEFT) => editor.left(),
        (_, K_RIGHT) => editor.right(),
        (_, K_END) => editor.offset = editor.string.len(),
        (_, K_DOWN) => editor.down(),
        (m, _) => {
            let (no_mult, mut times) = match *multiplier {
                Some(n) => (false, n),
                None => (true, 1),
            };
            let mut is_none = false;

            match key_event.character {
                '0' if !no_mult => times *= 10,

                '1' if no_mult => times = 1,
                '1' => times = times * 10 + 1,

                '2' if no_mult => times = 2,
                '2' => times = times * 10 + 2,

                '3' if no_mult => times = 3,
                '3' => times = times * 10 + 3,

                '4' if no_mult => times = 4,
                '4' => times = times * 10 + 4,

                '5' if no_mult => times = 5,
                '5' => times = times * 10 + 5,

                '6' if no_mult => times = 6,
                '6' => times = times * 10 + 6,

                '7' if no_mult => times = 7,
                '7' => times = times * 10 + 7,

                '8' if no_mult => times = 8,
                '8' => times = times * 10 + 8,

                '9' if no_mult => times = 9,
                '9' => times = times * 10 + 9,
                _ => {
                    for _ in 0 .. times {
                        match (m, key_event.character) {
                            (Normal, 'i') => {
                                *mode = Insert;
                                *last_change = editor.string.clone();
                            },
                            (Normal, 'h') => editor.left(),
                            (Normal, 'l') => editor.right(),
                            (Normal, 'k') => editor.up(),
                            (Normal, 'j') => editor.down(),
                            (Normal, 'g') => editor.offset = 0,
                            (Normal, 'G') => editor.offset = editor.string.len(),
                            (Normal, 'a') => {
                                editor.right();
                                *mode = Insert;
                                *last_change = editor.string.clone();
                            },
                            (Normal, 'x') => editor.delete(window),
                            (Normal, 'X') => editor.backspace(window),
                            (Normal, 'u') => {
                                editor.offset = 0;
                                ::core::mem::swap(last_change, &mut editor.string);
                            },
                            (Normal, 'o') => {
                                exec(editor, mode, multiplier, last_change, KeyEvent {
                                    character: '$',
                                    scancode: 0,
                                    pressed: true,
                                }, window);
                                exec(editor, mode, multiplier, last_change, KeyEvent {
                                    character: 'i',
                                    scancode: 0,
                                    pressed: true,
                                }, window);
                                exec(editor, mode, multiplier, last_change, KeyEvent {
                                    character: '\n',
                                    scancode: 0,
                                    pressed: true,
                                }, window);
                            },
                            (Normal, 'O') => {
                                exec(editor, mode, multiplier, last_change, KeyEvent {
                                    character: 'k',
                                    scancode: 0,
                                    pressed: true,
                                }, window);
                                exec(editor, mode, multiplier, last_change, KeyEvent {
                                    character: '$',
                                    scancode: 0,
                                    pressed: true,
                                }, window);
                                exec(editor, mode, multiplier, last_change, KeyEvent {
                                    character: 'i',
                                    scancode: 0,
                                    pressed: true,
                                }, window);
                                exec(editor, mode, multiplier, last_change, KeyEvent {
                                    character: '\n',
                                    scancode: 0,
                                    pressed: true,
                                }, window);
                            },
                            (Normal, '$') => {
                                let mut new_offset = editor.string.len();
                                for i in editor.offset..editor.string.len() {
                                    match editor.string.as_bytes()[i] {
                                        0 => break,
                                        10 => {
                                            new_offset = i;
                                            break;
                                        }
                                        _ => (),
                                    }
                                }
                                editor.offset = new_offset;
                            },
                            (Normal, '0') => {

                                let mut new_offset = 0;
                                for i in 2..editor.offset {
                                    match editor.string.as_bytes()[editor.offset - i] {
                                        0 => break,
                                        10 => {
                                            new_offset = editor.offset - i + 1;
                                            break;
                                        }
                                        _ => (),
                                    }
                                }
                                editor.offset = new_offset;
                            },
                            (Insert, '\0') => (),
                            (Insert, _) => {
                                window.set_title(&format!("{}{}{}","Editor (", &editor.url, ") Changed"));
                                editor.string = editor.string[0 .. editor.offset].to_string() +
                                    &key_event.character.to_string() +
                                    &editor.string[editor.offset .. editor.string.len()];
                                editor.offset += 1;
                            },
                            _ => {},
                        }
                    }
                    is_none = true;
                }
            }

            if !is_none {
                *multiplier = Some(times);
            } else {
                *multiplier = None;
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add benchmark to compare GCD implementations.<commit_after>//! Benchmark comparing the current GCD implemtation against an older one.

#![feature(test)]

extern crate num_integer;
extern crate num_traits;
extern crate test;

use num_integer::Integer;
use num_traits::{AsPrimitive, Bounded, Signed};
use test::{black_box, Bencher};

trait GcdOld: Integer {
    fn gcd_old(&self, other: &Self) -> Self;
}

macro_rules! impl_gcd_old_for_isize {
    ($T:ty) => {
        impl GcdOld for $T {
            /// Calculates the Greatest Common Divisor (GCD) of the number and
            /// `other`. The result is always positive.
            #[inline]
            fn gcd_old(&self, other: &Self) -> Self {
                // Use Stein's algorithm
                let mut m = *self;
                let mut n = *other;
                if m == 0 || n == 0 {
                    return (m | n).abs();
                }

                // find common factors of 2
                let shift = (m | n).trailing_zeros();

                // The algorithm needs positive numbers, but the minimum value
                // can't be represented as a positive one.
                // It's also a power of two, so the gcd can be
                // calculated by bitshifting in that case

                // Assuming two's complement, the number created by the shift
                // is positive for all numbers except gcd = abs(min value)
                // The call to .abs() causes a panic in debug mode
                if m == Self::min_value() || n == Self::min_value() {
                    return (1 << shift).abs();
                }

                // guaranteed to be positive now, rest like unsigned algorithm
                m = m.abs();
                n = n.abs();

                // divide n and m by 2 until odd
                // m inside loop
                n >>= n.trailing_zeros();

                while m != 0 {
                    m >>= m.trailing_zeros();
                    if n > m {
                        std::mem::swap(&mut n, &mut m)
                    }
                    m -= n;
                }

                n << shift
            }
        }
    };
}

impl_gcd_old_for_isize!(i8);
impl_gcd_old_for_isize!(i16);
impl_gcd_old_for_isize!(i32);
impl_gcd_old_for_isize!(i64);
impl_gcd_old_for_isize!(isize);
impl_gcd_old_for_isize!(i128);

macro_rules! impl_gcd_old_for_usize {
    ($T:ty) => {
        impl GcdOld for $T {
            /// Calculates the Greatest Common Divisor (GCD) of the number and
            /// `other`. The result is always positive.
            #[inline]
            fn gcd_old(&self, other: &Self) -> Self {
                // Use Stein's algorithm
                let mut m = *self;
                let mut n = *other;
                if m == 0 || n == 0 {
                    return m | n;
                }

                // find common factors of 2
                let shift = (m | n).trailing_zeros();

                // divide n and m by 2 until odd
                // m inside loop
                n >>= n.trailing_zeros();

                while m != 0 {
                    m >>= m.trailing_zeros();
                    if n > m {
                        std::mem::swap(&mut n, &mut m)
                    }
                    m -= n;
                }

                n << shift
            }
        }
    };
}

impl_gcd_old_for_usize!(u8);
impl_gcd_old_for_usize!(u16);
impl_gcd_old_for_usize!(u32);
impl_gcd_old_for_usize!(u64);
impl_gcd_old_for_usize!(usize);
impl_gcd_old_for_usize!(u128);

/// Return an iterator that yields all Fibonacci numbers fitting into a u128.
fn fibonacci() -> impl Iterator<Item=u128> {
    (0..185).scan((0, 1), |&mut (ref mut a, ref mut b), _| {
        let tmp = *a;
        *a = *b;
        *b += tmp;
        Some(*b)
    })
}

fn run_bench<T: Integer + Bounded + Copy + 'static>(b: &mut Bencher, gcd: fn(&T, &T) -> T)
where
    T: AsPrimitive<u128>,
    u128: AsPrimitive<T>,
{
    let max_value: u128 = T::max_value().as_();
    let pairs: Vec<(T, T)> = fibonacci()
        .collect::<Vec<_>>()
        .windows(2)
        .filter(|&pair| pair[0] <= max_value && pair[1] <= max_value)
        .map(|pair| (pair[0].as_(), pair[1].as_()))
        .collect();
    b.iter(|| {
        for &(ref m, ref n) in &pairs {
            black_box(gcd(m, n));
        }
    });
}

macro_rules! bench_gcd {
    ($T:ident) => {
        mod $T {
            use crate::{run_bench, GcdOld};
            use num_integer::Integer;
            use test::Bencher;

            #[bench]
            fn bench_gcd(b: &mut Bencher) {
                run_bench(b, $T::gcd);
            }

            #[bench]
            fn bench_gcd_old(b: &mut Bencher) {
                run_bench(b, $T::gcd_old);
            }
        }
    };
}

bench_gcd!(u8);
bench_gcd!(u16);
bench_gcd!(u32);
bench_gcd!(u64);
bench_gcd!(u128);

bench_gcd!(i8);
bench_gcd!(i16);
bench_gcd!(i32);
bench_gcd!(i64);
bench_gcd!(i128);
<|endoftext|>


<commit_before><commit_msg>Factor out listener thread into function.<commit_after><|endoftext|>


<commit_before><commit_msg>Move acks into acker.<commit_after><|endoftext|>


<commit_before><commit_msg>Unit tests for key formatter<commit_after><|endoftext|>


<commit_before><commit_msg>Tests for key formatter and skeleton tests for metric parser<commit_after><|endoftext|>


<commit_before><commit_msg>Add tests for get_slice()<commit_after>#[test]
fn get_slice_array_test() {
    let array = [1, 2, 3, 4, 5];
    assert_eq!(array.get_slice(2, None), array[2..]);
    assert_eq!(array.get_slice(2, array.len()), array[2..array.len()]);
    assert_eq!(array.get_slice(None, 2), array[..2]);
    assert_eq!(array.get_slice(0, 2), array[0..2]);
    assert_eq!(array.get_slice(1, array.len()), array[1..array.len()]);
    assert_eq!(array.get_slice(1, array.len() + 1), array[1..array.len()]);
    assert_eq!(array.get_slice(array.len(), array.len()), array[array.len()..array.len()]);
    assert_eq!(array.get_slice(array.len() + 2, array.len() + 2), array[array.len()..array.len()]);
}
<|endoftext|>


<commit_before>//! Server Requests
//!
//! These are requests that a `hyper::Server` receives, and include its method,
//! target URI, headers, and message body.
use std::io::IoResult;
use std::io::net::ip::SocketAddr;

use {HttpResult};
use version::{HttpVersion};
use method::Method::{self, Get, Head};
use header::Headers;
use header::common::{ContentLength, TransferEncoding};
use http::{read_request_line};
use http::HttpReader;
use http::HttpReader::{SizedReader, ChunkedReader, EmptyReader};
use uri::RequestUri;

/// A request bundles several parts of an incoming `NetworkStream`, given to a `Handler`.
pub struct Request<'a> {
    /// The IP address of the remote connection.
    pub remote_addr: SocketAddr,
    /// The `Method`, such as `Get`, `Post`, etc.
    pub method: Method,
    /// The headers of the incoming request.
    pub headers: Headers,
    /// The target request-uri for this request.
    pub uri: RequestUri,
    /// The version of HTTP for this request.
    pub version: HttpVersion,
    body: HttpReader<&'a mut (Reader + 'a)>
}

impl<'a> Request<'a> {

    /// Create a new Request, reading the StartLine and Headers so they are
    /// immediately useful.
    pub fn new(mut stream: &'a mut (Reader + 'a), addr: SocketAddr) -> HttpResult<Request<'a>> {
        let (method, uri, version) = try!(read_request_line(&mut stream));
        debug!("Request Line: {:?} {:?} {:?}", method, uri, version);
        let headers = try!(Headers::from_raw(&mut stream));
        debug!("{:?}", headers);

        let body = if method == Get || method == Head {
            EmptyReader(stream)
        } else if headers.has::<ContentLength>() {
            match headers.get::<ContentLength>() {
                Some(&ContentLength(len)) => SizedReader(stream, len),
                None => unreachable!()
            }
        } else if headers.has::<TransferEncoding>() {
            todo!("check for Transfer-Encoding: chunked");
            ChunkedReader(stream, None)
        } else {
            EmptyReader(stream)
        };

        Ok(Request {
            remote_addr: addr,
            method: method,
            uri: uri,
            headers: headers,
            version: version,
            body: body
        })
    }
}

impl<'a> Reader for Request<'a> {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        self.body.read(buf)
    }
}

#[cfg(test)]
mod tests {
    use header::common::{Host, TransferEncoding};
    use header::common::transfer_encoding::Encoding;
    use mock::MockStream;
    use super::Request;

    use std::io::net::ip::SocketAddr;

    fn sock(s: &str) -> SocketAddr {
        s.parse().unwrap()
    }

    #[test]
    fn test_get_empty_body() {
        let mut stream = MockStream::with_input(b"\
            GET / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(req.read_to_string(), Ok("".to_string()));
    }

    #[test]
    fn test_head_empty_body() {
        let mut stream = MockStream::with_input(b"\
            HEAD / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(req.read_to_string(), Ok("".to_string()));
    }

    #[test]
    fn test_post_empty_body() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(req.read_to_string(), Ok("".to_string()));
    }

    #[test]
    fn test_parse_chunked_request() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            1\r\n\
            q\r\n\
            2\r\n\
            we\r\n\
            2\r\n\
            rt\r\n\
            0\r\n\
            \r\n"
        );

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        // The headers are correct?
        match req.headers.get::<Host>() {
            Some(host) => {
                assert_eq!("example.domain", host.hostname);
            },
            None => panic!("Host header expected!"),
        };
        match req.headers.get::<TransferEncoding>() {
            Some(encodings) => {
                assert_eq!(1, encodings.len());
                assert_eq!(Encoding::Chunked, encodings[0]);
            }
            None => panic!("Transfer-Encoding: chunked expected!"),
        };
        // The content is correctly read?
        let body = req.read_to_string().unwrap();
        assert_eq!("qwert", body);
    }

    /// Tests that when a chunk size is not a valid radix-16 number, an error
    /// is returned.
    #[test]
    fn test_invalid_chunk_size_not_hex_digit() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            X\r\n\
            1\r\n\
            0\r\n\
            \r\n"
        );

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        assert!(req.read_to_string().is_err());
    }

    /// Tests that when a chunk size contains an invalid extension, an error is
    /// returned.
    #[test]
    fn test_invalid_chunk_size_extension() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            1 this is an invalid extension\r\n\
            1\r\n\
            0\r\n\
            \r\n"
        );

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        assert!(req.read_to_string().is_err());
    }

    /// Tests that when a valid extension that contains a digit is appended to
    /// the chunk size, the chunk is correctly read.
    #[test]
    fn test_chunk_size_with_extension() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            1;this is an extension with a digit 1\r\n\
            1\r\n\
            0\r\n\
            \r\n"
        );

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        assert_eq!("1", req.read_to_string().unwrap())
    }

}
<commit_msg>feat(server): add a deconstruct method to Request.<commit_after>//! Server Requests
//!
//! These are requests that a `hyper::Server` receives, and include its method,
//! target URI, headers, and message body.
use std::io::IoResult;
use std::io::net::ip::SocketAddr;

use {HttpResult};
use version::{HttpVersion};
use method::Method::{self, Get, Head};
use header::Headers;
use header::common::{ContentLength, TransferEncoding};
use http::{read_request_line};
use http::HttpReader;
use http::HttpReader::{SizedReader, ChunkedReader, EmptyReader};
use uri::RequestUri;

/// A request bundles several parts of an incoming `NetworkStream`, given to a `Handler`.
pub struct Request<'a> {
    /// The IP address of the remote connection.
    pub remote_addr: SocketAddr,
    /// The `Method`, such as `Get`, `Post`, etc.
    pub method: Method,
    /// The headers of the incoming request.
    pub headers: Headers,
    /// The target request-uri for this request.
    pub uri: RequestUri,
    /// The version of HTTP for this request.
    pub version: HttpVersion,
    body: HttpReader<&'a mut (Reader + 'a)>
}

impl<'a> Request<'a> {
    /// Create a new Request, reading the StartLine and Headers so they are
    /// immediately useful.
    pub fn new(mut stream: &'a mut (Reader + 'a), addr: SocketAddr) -> HttpResult<Request<'a>> {
        let (method, uri, version) = try!(read_request_line(&mut stream));
        debug!("Request Line: {:?} {:?} {:?}", method, uri, version);
        let headers = try!(Headers::from_raw(&mut stream));
        debug!("{:?}", headers);

        let body = if method == Get || method == Head {
            EmptyReader(stream)
        } else if headers.has::<ContentLength>() {
            match headers.get::<ContentLength>() {
                Some(&ContentLength(len)) => SizedReader(stream, len),
                None => unreachable!()
            }
        } else if headers.has::<TransferEncoding>() {
            todo!("check for Transfer-Encoding: chunked");
            ChunkedReader(stream, None)
        } else {
            EmptyReader(stream)
        };

        Ok(Request {
            remote_addr: addr,
            method: method,
            uri: uri,
            headers: headers,
            version: version,
            body: body
        })
    }

    /// Deconstruct a Request into its constituent parts.
    pub fn deconstruct(self) -> (SocketAddr, Method, Headers,
                                 RequestUri, HttpVersion,
                                 HttpReader<&'a mut (Reader + 'a)>,) {
        (self.remote_addr, self.method, self.headers,
         self.uri, self.version, self.body)
    }
}

impl<'a> Reader for Request<'a> {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        self.body.read(buf)
    }
}

#[cfg(test)]
mod tests {
    use header::common::{Host, TransferEncoding};
    use header::common::transfer_encoding::Encoding;
    use mock::MockStream;
    use super::Request;

    use std::io::net::ip::SocketAddr;

    fn sock(s: &str) -> SocketAddr {
        s.parse().unwrap()
    }

    #[test]
    fn test_get_empty_body() {
        let mut stream = MockStream::with_input(b"\
            GET / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(req.read_to_string(), Ok("".to_string()));
    }

    #[test]
    fn test_head_empty_body() {
        let mut stream = MockStream::with_input(b"\
            HEAD / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(req.read_to_string(), Ok("".to_string()));
    }

    #[test]
    fn test_post_empty_body() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(req.read_to_string(), Ok("".to_string()));
    }

    #[test]
    fn test_parse_chunked_request() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            1\r\n\
            q\r\n\
            2\r\n\
            we\r\n\
            2\r\n\
            rt\r\n\
            0\r\n\
            \r\n"
        );

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        // The headers are correct?
        match req.headers.get::<Host>() {
            Some(host) => {
                assert_eq!("example.domain", host.hostname);
            },
            None => panic!("Host header expected!"),
        };
        match req.headers.get::<TransferEncoding>() {
            Some(encodings) => {
                assert_eq!(1, encodings.len());
                assert_eq!(Encoding::Chunked, encodings[0]);
            }
            None => panic!("Transfer-Encoding: chunked expected!"),
        };
        // The content is correctly read?
        let body = req.read_to_string().unwrap();
        assert_eq!("qwert", body);
    }

    /// Tests that when a chunk size is not a valid radix-16 number, an error
    /// is returned.
    #[test]
    fn test_invalid_chunk_size_not_hex_digit() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            X\r\n\
            1\r\n\
            0\r\n\
            \r\n"
        );

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        assert!(req.read_to_string().is_err());
    }

    /// Tests that when a chunk size contains an invalid extension, an error is
    /// returned.
    #[test]
    fn test_invalid_chunk_size_extension() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            1 this is an invalid extension\r\n\
            1\r\n\
            0\r\n\
            \r\n"
        );

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        assert!(req.read_to_string().is_err());
    }

    /// Tests that when a valid extension that contains a digit is appended to
    /// the chunk size, the chunk is correctly read.
    #[test]
    fn test_chunk_size_with_extension() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            1;this is an extension with a digit 1\r\n\
            1\r\n\
            0\r\n\
            \r\n"
        );

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        assert_eq!("1", req.read_to_string().unwrap())
    }

}
<|endoftext|>


<commit_before><commit_msg>Auto merge of #3669 - avborhanian:extra_results_files, r=oli-obk<commit_after>use std::fs::{self, DirEntry};
use std::path::Path;

#[test]
fn test_missing_tests() {
    let missing_files = explore_directory(Path::new("./tests"));
    if !missing_files.is_empty() {
        assert!(
            false,
            format!(
                "Didn't see a test file for the following files:\n\n{}\n",
                missing_files
                    .iter()
                    .map(|s| format!("\t{}", s))
                    .collect::<Vec<_>>()
                    .join("\n")
            )
        );
    }
}

/*
Test for missing files.

Since rs files are alphabetically before stderr/stdout, we can sort by the full name
and iter in that order. If we've seen the file stem for the first time and it's not
a rust file, it means the rust file has to be missing.
*/
fn explore_directory(dir: &Path) -> Vec<String> {
    let mut missing_files: Vec<String> = Vec::new();
    let mut current_file = String::new();
    let mut files: Vec<DirEntry> = fs::read_dir(dir).unwrap().filter_map(Result::ok).collect();
    files.sort_by_key(|e| e.path());
    for entry in &files {
        let path = entry.path();
        if path.is_dir() {
            missing_files.extend(explore_directory(&path));
        } else {
            let file_stem = path.file_stem().unwrap().to_str().unwrap().to_string();
            if let Some(ext) = path.extension() {
                match ext.to_str().unwrap() {
                    "rs" => current_file = file_stem.clone(),
                    "stderr" | "stdout" => {
                        if file_stem != current_file {
                            missing_files.push(path.to_str().unwrap().to_string());
                        }
                    },
                    _ => continue,
                };
            }
        }
    }
    missing_files
}
<|endoftext|>


<commit_before><commit_msg>commons: raw global list fetching example<commit_after>extern crate wayland_commons as wc;

use std::env;
use std::os::unix::io::{FromRawFd, IntoRawFd};
use std::os::unix::net::UnixStream;
use std::path::PathBuf;

use wc::socket::{BufferedSocket, Socket};
use wc::wire::{Argument, ArgumentType, Message, MessageDesc};

fn main() {
    let xdg_dir = env::var_os("XDG_RUNTIME_DIR").unwrap();
    let mut path: PathBuf = xdg_dir.into();
    path.push("wayland-0");

    let socket = UnixStream::connect(path).unwrap();
    let mut socket = BufferedSocket::new(unsafe { Socket::from_raw_fd(socket.into_raw_fd()) });

    socket
        .write_message(&Message {
            sender_id: 1, // wl_display
            opcode: 1,    // get registry
            args: vec![
                Argument::NewId(2), // id of the created registry
            ],
        })
        .unwrap();

    socket.flush().unwrap();

    ::std::thread::sleep(::std::time::Duration::from_millis(500)); // sleep 0.5 seconds

    let ret = socket.read_messages(
        |id, opcode| match (id, opcode) {
            (2, 0) => Some(&GLOBAL_EVENT.signature),
            _ => None,
        },
        |msg| {
            println!("{:?}", msg);
            true
        },
    );
    println!("{:?}", ret);
}

/*
 * The registry interface
 */

const GLOBAL_EVENT: MessageDesc = MessageDesc {
    name: "global",
    signature: &[ArgumentType::Uint, ArgumentType::Str, ArgumentType::Uint],
    since: 1,
};
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A language syntax coloring and indentation plugin for xi-editor.

#[macro_use]
extern crate xi_plugin_lib;

use xi_plugin_lib::caching_plugin::{self, PluginCtx, SpansBuilder};

use std::env;

mod rust;
mod colorize;
mod statestack;
mod peg;

use rust::RustColorize;
use statestack::State;
use colorize::{Style, StyleNewState, Colorize};

fn add_style_span(builder: &mut SpansBuilder, style: &Style, start: usize, end: usize) {
    builder.add_style_span(start, end,
        style.fg_color, style.font);
}

struct PluginState {
    colorize: RustColorize<StyleNewState<fn(&mut Style, &rust::StateEl)>>,
    line_num: usize,
    offset: usize,
    state: State,
    spans_start: usize,
    builder: Option<SpansBuilder>,
}

impl PluginState {
    fn new() -> PluginState {
        PluginState {
            colorize: RustColorize::new(StyleNewState::new(rust::to_style)),
            line_num: 0,
            offset: 0,
            state: State::default(),
            spans_start: 0,
            builder: None,
        }
    }

    // Return true if there's more to do.
    fn highlight_one_line(&mut self, ctx: &mut PluginCtx) -> bool {
        let line = ctx.get_line(self.line_num);
        if let Err(err) = line {
            print_err!("Error: {:?}", err);
            return false;
        }
        let line = line.unwrap();
        if line.is_none() {
            return false;
        }

        let line = line.unwrap();
        if self.builder.is_none() {
            self.spans_start = self.offset;
            self.builder = Some(SpansBuilder::new());
        }

        let mut i = 0;
        while i < line.len() {
            let (prevlen, s0, len, s1) = self.colorize.colorize(&line[i..], self.state);
            if prevlen > 0 {
                // TODO: maybe make an iterator to avoid this duplication
                let style = self.colorize.get_new_state().get_style(self.state);
                let start = self.offset - self.spans_start + i;
                let end = start + prevlen;
                add_style_span(self.builder.as_mut().unwrap(), style, start, end);
                i += prevlen;
            }
            let style = self.colorize.get_new_state().get_style(s0);
            let start = self.offset - self.spans_start + i;
            let end = start + len;
            add_style_span(self.builder.as_mut().unwrap(), style, start, end);
            i += len;
            self.state = s1;
        }
        self.line_num += 1;
        self.offset += line.len();
        true
    }

    fn flush_spans(&mut self, ctx: &mut PluginCtx) {
        if let Some(builder) = self.builder.take() {
            ctx.set_fg_spans(self.spans_start, self.offset - self.spans_start, builder.build());
        }
    }

    fn do_highlighting(&mut self, mut ctx: PluginCtx) {
        self.line_num = 0;
        self.offset = 0;
        self.state = State::default();
        ctx.schedule_idle(0);
    }
}

const LINES_PER_RPC: usize = 50;

impl caching_plugin::Handler for PluginState {
    fn init_buf(&mut self, ctx: PluginCtx, _buf_size: usize) {
        self.do_highlighting(ctx);
    }

    fn update(&mut self, ctx: PluginCtx) {
        self.do_highlighting(ctx);
    }

    fn idle(&mut self, mut ctx: PluginCtx, _token: usize) {
        print_err!("idle task at line {}", self.line_num);
        for _ in 0..LINES_PER_RPC {
            if !self.highlight_one_line(&mut ctx) {
                self.flush_spans(&mut ctx);
                return;
            }
            if ctx.request_is_pending() {
                print_err!("request pending at line {}", self.line_num);
                break;
            }
        }
        self.flush_spans(&mut ctx);
        ctx.schedule_idle(0);
    }
}

fn xi_plugin_main() {
    let mut state = PluginState::new();
    caching_plugin::mainloop(&mut state);
}

fn main() {
    if let Some(ref s) = env::args().skip(1).next() {
        if s == "test" {
            rust::test();
            return;
        }
    }
    xi_plugin_main();
}
<commit_msg>Rename init_buf in xi-lang<commit_after>// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A language syntax coloring and indentation plugin for xi-editor.

#[macro_use]
extern crate xi_plugin_lib;

use xi_plugin_lib::caching_plugin::{self, PluginCtx, SpansBuilder};

use std::env;

mod rust;
mod colorize;
mod statestack;
mod peg;

use rust::RustColorize;
use statestack::State;
use colorize::{Style, StyleNewState, Colorize};

fn add_style_span(builder: &mut SpansBuilder, style: &Style, start: usize, end: usize) {
    builder.add_style_span(start, end,
        style.fg_color, style.font);
}

struct PluginState {
    colorize: RustColorize<StyleNewState<fn(&mut Style, &rust::StateEl)>>,
    line_num: usize,
    offset: usize,
    state: State,
    spans_start: usize,
    builder: Option<SpansBuilder>,
}

impl PluginState {
    fn new() -> PluginState {
        PluginState {
            colorize: RustColorize::new(StyleNewState::new(rust::to_style)),
            line_num: 0,
            offset: 0,
            state: State::default(),
            spans_start: 0,
            builder: None,
        }
    }

    // Return true if there's more to do.
    fn highlight_one_line(&mut self, ctx: &mut PluginCtx) -> bool {
        let line = ctx.get_line(self.line_num);
        if let Err(err) = line {
            print_err!("Error: {:?}", err);
            return false;
        }
        let line = line.unwrap();
        if line.is_none() {
            return false;
        }

        let line = line.unwrap();
        if self.builder.is_none() {
            self.spans_start = self.offset;
            self.builder = Some(SpansBuilder::new());
        }

        let mut i = 0;
        while i < line.len() {
            let (prevlen, s0, len, s1) = self.colorize.colorize(&line[i..], self.state);
            if prevlen > 0 {
                // TODO: maybe make an iterator to avoid this duplication
                let style = self.colorize.get_new_state().get_style(self.state);
                let start = self.offset - self.spans_start + i;
                let end = start + prevlen;
                add_style_span(self.builder.as_mut().unwrap(), style, start, end);
                i += prevlen;
            }
            let style = self.colorize.get_new_state().get_style(s0);
            let start = self.offset - self.spans_start + i;
            let end = start + len;
            add_style_span(self.builder.as_mut().unwrap(), style, start, end);
            i += len;
            self.state = s1;
        }
        self.line_num += 1;
        self.offset += line.len();
        true
    }

    fn flush_spans(&mut self, ctx: &mut PluginCtx) {
        if let Some(builder) = self.builder.take() {
            ctx.set_fg_spans(self.spans_start, self.offset - self.spans_start, builder.build());
        }
    }

    fn do_highlighting(&mut self, mut ctx: PluginCtx) {
        self.line_num = 0;
        self.offset = 0;
        self.state = State::default();
        ctx.schedule_idle(0);
    }
}

const LINES_PER_RPC: usize = 50;

impl caching_plugin::Handler for PluginState {
    fn initialize(&mut self, ctx: PluginCtx, _buf_size: usize) {
        self.do_highlighting(ctx);
    }

    fn update(&mut self, ctx: PluginCtx) {
        self.do_highlighting(ctx);
    }

    fn idle(&mut self, mut ctx: PluginCtx, _token: usize) {
        print_err!("idle task at line {}", self.line_num);
        for _ in 0..LINES_PER_RPC {
            if !self.highlight_one_line(&mut ctx) {
                self.flush_spans(&mut ctx);
                return;
            }
            if ctx.request_is_pending() {
                print_err!("request pending at line {}", self.line_num);
                break;
            }
        }
        self.flush_spans(&mut ctx);
        ctx.schedule_idle(0);
    }
}

fn xi_plugin_main() {
    let mut state = PluginState::new();
    caching_plugin::mainloop(&mut state);
}

fn main() {
    if let Some(ref s) = env::args().skip(1).next() {
        if s == "test" {
            rust::test();
            return;
        }
    }
    xi_plugin_main();
}
<|endoftext|>


<commit_before>use std::fmt::{Debug, Formatter, Error};

extern crate clap;
use clap::{App, ArgMatches};

pub struct ModuleConfig {
    pub load : bool,
}

impl ModuleConfig {
    pub fn new() -> ModuleConfig {
        ModuleConfig {
            load: false,
        }
    }
}

pub struct CliConfig<'a> {
    pub module_configs  : Vec<ModuleConfig>,
    pub cli_matches     : ArgMatches<'a, 'a>,
}

impl<'a> CliConfig<'a> {
    pub fn new(app : clap::App<'a, 'a, 'a, 'a, 'a, 'a>) -> CliConfig<'a> {
        CliConfig {
            module_configs: vec![],
            cli_matches: app.get_matches(),
        }
    }

    pub fn is_verbose(&self) -> bool {
        self.cli_matches.is_present("verbose") || self.is_debugging()
    }

    pub fn is_debugging(&self) -> bool {
        self.cli_matches.is_present("debug")
    }

    pub fn get_rtp(&self) -> Option<String> {
        self.cli_matches.value_of("rtp").and_then(|s| Some(String::from(s)))
    }

    pub fn store_path(&self) -> Option<String> {
        self.get_rtp().and_then(|rtp| {
            self.cli_matches
                .value_of("storepath")
                .and_then(|s| Some(rtp + s))
        })
    }
}

impl<'a> Debug for CliConfig<'a> {

    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "CliConfig (verbose: {}, debugging: {}, rtp: {})",
            self.is_verbose(),
            self.is_debugging(),
            self.get_rtp().or(Some(String::from("NONE"))).unwrap())
    }

}
<commit_msg>cli.rs: Add documentation to functions<commit_after>use std::fmt::{Debug, Formatter, Error};

extern crate clap;
use clap::{App, ArgMatches};

pub struct ModuleConfig {
    pub load : bool,
}

impl ModuleConfig {
    pub fn new() -> ModuleConfig {
        ModuleConfig {
            load: false,
        }
    }
}

pub struct CliConfig<'a> {
    pub module_configs  : Vec<ModuleConfig>,
    pub cli_matches     : ArgMatches<'a, 'a>,
}

impl<'a> CliConfig<'a> {
    pub fn new(app : clap::App<'a, 'a, 'a, 'a, 'a, 'a>) -> CliConfig<'a> {
        CliConfig {
            module_configs: vec![],
            cli_matches: app.get_matches(),
        }
    }

    /**
     * Check whether the CLI says we should run verbose
     */
    pub fn is_verbose(&self) -> bool {
        self.cli_matches.is_present("verbose") || self.is_debugging()
    }

    /**
     * Check whether the CLI says we should run in debugging
     */
    pub fn is_debugging(&self) -> bool {
        self.cli_matches.is_present("debug")
    }

    /**
     * Get the runtime path the CLI configured
     */
    pub fn get_rtp(&self) -> Option<String> {
        self.cli_matches.value_of("rtp").and_then(|s| Some(String::from(s)))
    }

    /**
     * Get the store path the CLI configured
     *
     * TODO: Implement properly. Not working by now.
     */
    pub fn store_path(&self) -> Option<String> {
        self.get_rtp().and_then(|rtp| {
            self.cli_matches
                .value_of("storepath")
                .and_then(|s| Some(rtp + s))
        })
    }
}

impl<'a> Debug for CliConfig<'a> {

    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "CliConfig (verbose: {}, debugging: {}, rtp: {})",
            self.is_verbose(),
            self.is_debugging(),
            self.get_rtp().or(Some(String::from("NONE"))).unwrap())
    }

}
<|endoftext|>


<commit_before><commit_msg>implemented crude form of interrupt handling.<commit_after><|endoftext|>


<commit_before><commit_msg>"(6 kyu) Salesman's Travel" solved in Rust<commit_after><|endoftext|>


<commit_before><commit_msg>Use unwrap() since it'll panic anyway if it fails<commit_after><|endoftext|>


<commit_before><commit_msg>Add test for sample config.<commit_after><|endoftext|>


<commit_before><commit_msg>#1 Added 1_hello.rs<commit_after>/*
 * Rust hello world application
 */
fn main() {
    // prints `Hello, World`
    println!("Hello, World!");
}<|endoftext|>


<commit_before><commit_msg>Fix a `BorrowMut` error when stdout is closed<commit_after><|endoftext|>


<commit_before><commit_msg>Writes basic tests.<commit_after>extern crate gwent_api;
use self::gwent_api::client::gw_client::Client;

#[test]
fn it_retrieves_a_card_by_its_name() {
    match Client::get_card_by_name("Alchemist") {
        Err(e) => panic!("Could not retrieve the card: {}", e),
        Ok(card) => assert_eq!(card.name.as_str(), "Alchemist")
    };
}

#[test]
#[should_panic]
fn it_fails_to_retrieve_a_non_existing_card() {
    match Client::get_card_by_name("Pere Fourras") {
        Err(e) => panic!("Could not retrieve the card: {}", e),
        Ok(card) => assert_eq!(card.name.as_str(), "Pere Fourras")
    };
}

#[test]
fn it_retrieves_default_card_art() {
    let card = Client::get_card_by_name("Cantarella");
    match Client::get_card_default_art(&card.unwrap()) {
        Err(e) => panic!("Card art was not retrieved: {}", e),
        Ok(variation) => assert_eq!(variation.art.thumbnail_image.as_str(), "https://api.gwentapi.com/media/cantarella-thumbnail.png")
    };
}<|endoftext|>


<commit_before>//! The `game` module contains traits and structs to actually run your game mainloop
//! and handle top-level state.

use context::Context;
use GameResult;
use conf;
use timer;

use std::time::Duration;

use super::event as gevent;

use sdl2::event::Event::*;
use sdl2::event;
use sdl2::mouse;
use sdl2::keyboard;

/// A trait for defining a game state.
/// Implement `load()`, `update()` and `draw()` callbacks on this trait
/// and create a `Game` object using your gamestate type.
/// You may also implement the `*_event` callbacks if you wish to handle
/// those events.
///
/// The default event handlers do nothing, apart from `key_down_event()`,
/// which *should* by default exit the game if escape is pressed.
/// (Once we work around some event bugs in rust-sdl2.)
pub trait GameState: EventHandler {
    // Tricksy trait and lifetime magic happens in load()'s
    // signature.
    // It doesn't look complicated but is easy to get wrong.
    // Much thanks to aatch on #rust-beginners for helping make this work.

    /// Called to initially create your `GameState` object
    /// after all hardware initialization has been done.
    /// It is handed a `Context` to load resources from,
    /// and the `Conf` object that has either been loaded
    /// from your `resources/conf.toml` file or the default
    /// that has been provided to `Game::new()` if no conf
    /// file exists.
    fn load(ctx: &mut Context) -> GameResult<Self> where Self: Sized;
}

pub trait EventHandler {
    /// Called upon each physics update to the game.
    /// This should be where the game's logic takes place.
    fn update(&mut self, ctx: &mut Context, dt: Duration) -> GameResult<()>;

    /// Called to do the drawing of your game.
    /// You probably want to start this with
    /// `graphics::clear()` and end it with
    /// `graphics::present()` and `timer::sleep_until_next_frame()`
    fn draw(&mut self, ctx: &mut Context) -> GameResult<()>;

    // You don't have to override these if you don't want to; the defaults
    // do nothing.
    // It might be nice to be able to have custom event types and a map or
    // such of handlers?  Hmm, maybe later.
    fn mouse_button_down_event(&mut self, _button: mouse::MouseButton, _x: i32, _y: i32) {}

    fn mouse_button_up_event(&mut self, _button: mouse::MouseButton, _x: i32, _y: i32) {}

    fn mouse_motion_event(&mut self,
                          _state: mouse::MouseState,
                          _x: i32,
                          _y: i32,
                          _xrel: i32,
                          _yrel: i32) {
    }

    fn mouse_wheel_event(&mut self, _x: i32, _y: i32) {}

    fn key_down_event(&mut self, _keycode: gevent::Keycode, _keymod: gevent::Mod, _repeat: bool) {}

    fn key_up_event(&mut self, _keycode: gevent::Keycode, _keymod: gevent::Mod, _repeat: bool) {}

    fn controller_button_down_event(&mut self, _btn: gevent::Button) {}
    fn controller_button_up_event(&mut self, _btn: gevent::Button) {}
    fn controller_axis_event(&mut self, _axis: gevent::Axis, _value: i16) {}

    fn focus_event(&mut self, _gained: bool) {}

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self) -> bool {
        println!("Quitting game");
        false
    }
}

/// The `Game` struct takes an object you define that
/// implements the `GameState` trait
/// and does the actual work of running a gameloop,
/// passing events to your handlers, and all that stuff.
#[derive(Debug)]
pub struct Game<'a, S> {
    state: S,
    context: Context<'a>,
}

impl<'a, S> Game<'a, S> {
    pub fn from_state(ctx: Context<'a>, state: S) -> Game<S> {
        Game {
            state: state,
            context: ctx,
        }
    }

    /// Replaces the gamestate with the given one without
    /// having to re-initialize the hardware context.
    pub fn replace_state(&mut self, state: S) {
        self.state = state;
    }

    /// Calls the given function to create a new gamestate, and replaces
    /// the current one with it.
    pub fn replace_state_with<F>(&mut self, f: &F) -> GameResult<()>
        where F: Fn(&mut Context) -> GameResult<S>
    {
        let newstate = f(&mut self.context)?;
        self.state = newstate;
        Ok(())
    }
}

impl<'a, S: GameState + 'static> Game<'a, S> {
    /// Creates a new `Game` with the given  default config
    /// (which will be used if there is no config file).
    /// It will initialize a hardware context and call the `load()` method of
    /// the given `GameState` type to create a new `GameState`.
    ///
    /// The `id` field is a unique identifier for your game that will
    /// be used to create a save directory to write files to.
    pub fn new(id: &str, default_config: conf::Conf) -> GameResult<Game<'a, S>> {
        let mut context = Context::load_from_conf(id, default_config)?;

        let init_state = S::load(&mut context)?;

        Ok(Game {
            state: init_state,
            context: context,
        })
    }

    /// Re-creates a fresh `GameState` using the existing one's `::load()` method.
    pub fn reload_state(&mut self) -> GameResult<()> {
        let newstate = S::load(&mut self.context)?;
        self.state = newstate;
        Ok(())
    }
}

impl<'a, S: EventHandler + 'static> Game<'a, S> {
    /// Runs the game's mainloop.
    /// Continues until a `Quit` event is created, for instance
    /// via `Context::quit()`
    pub fn run(&mut self) -> GameResult<()> {
        let ctx = &mut self.context;
        let mut event_pump = ctx.sdl_context.event_pump()?;

        let mut continuing = true;
        let mut residual_update_dt = Duration::new(0, 0);
        let mut residual_draw_dt = Duration::new(0, 0);
        while continuing {
            ctx.timer_context.tick();

            for event in event_pump.poll_iter() {
                match event {
                    Quit { .. } => {
                        continuing = self.state.quit_event();
                        // println!("Quit event: {:?}", t);
                    }
                    // TODO: We need a good way to have
                    // a default like this, while still allowing
                    // it to be overridden.
                    // Bah, just put it in the GameState trait
                    // as the default function.
                    // But it doesn't have access to the context
                    // to call quit!  Bah.
                    KeyDown { keycode, keymod, repeat, .. } => {
                        if let Some(key) = keycode {
                            if key == keyboard::Keycode::Escape {
                                ctx.quit()?;
                            } else {
                                self.state.key_down_event(key, keymod, repeat)
                            }
                        }
                    }
                    KeyUp { keycode, keymod, repeat, .. } => {
                        if let Some(key) = keycode {
                            self.state.key_up_event(key, keymod, repeat)
                        }
                    }
                    MouseButtonDown { mouse_btn, x, y, .. } => {
                        self.state.mouse_button_down_event(mouse_btn, x, y)
                    }
                    MouseButtonUp { mouse_btn, x, y, .. } => {
                        self.state.mouse_button_up_event(mouse_btn, x, y)
                    }
                    MouseMotion { mousestate, x, y, xrel, yrel, .. } => {
                        self.state.mouse_motion_event(mousestate, x, y, xrel, yrel)
                    }
                    MouseWheel { x, y, .. } => self.state.mouse_wheel_event(x, y),
                    ControllerButtonDown { button, .. } => {
                        self.state.controller_button_down_event(button)
                    }
                    ControllerButtonUp { button, .. } => {
                        self.state.controller_button_up_event(button)
                    }
                    ControllerAxisMotion { axis, value, .. } => {
                        self.state.controller_axis_event(axis, value)
                    }
                    Window { win_event: event::WindowEvent::FocusGained, .. } => {
                        self.state.focus_event(true)
                    }
                    Window { win_event: event::WindowEvent::FocusLost, .. } => {
                        self.state.focus_event(false)
                    }
                    _ => {}
                }
            }

            let update_dt = Duration::from_millis(10);
            let draw_dt = Duration::new(0, 16_666_666);
            let dt = timer::get_delta(ctx);
            {
                let mut current_dt = dt + residual_update_dt;
                while current_dt > update_dt {
                    self.state.update(ctx, update_dt)?;
                    current_dt -= update_dt;
                }
                residual_update_dt = current_dt;
            }

            {
                let mut current_dt = dt + residual_draw_dt;
                while current_dt > draw_dt {
                    self.state.draw(ctx)?;
                    current_dt -= draw_dt;
                }
                residual_draw_dt = draw_dt;
            }
            timer::sleep(Duration::new(0, 0));
        }

        Ok(())
    }
}
<commit_msg>Changed return type of Game.run() to return its Context<commit_after>//! The `game` module contains traits and structs to actually run your game mainloop
//! and handle top-level state.

use context::Context;
use GameResult;
use conf;
use timer;

use std::time::Duration;

use super::event as gevent;

use sdl2::event::Event::*;
use sdl2::event;
use sdl2::mouse;
use sdl2::keyboard;

/// A trait for defining a game state.
/// Implement `load()`, `update()` and `draw()` callbacks on this trait
/// and create a `Game` object using your gamestate type.
/// You may also implement the `*_event` callbacks if you wish to handle
/// those events.
///
/// The default event handlers do nothing, apart from `key_down_event()`,
/// which *should* by default exit the game if escape is pressed.
/// (Once we work around some event bugs in rust-sdl2.)
pub trait GameState: EventHandler {
    // Tricksy trait and lifetime magic happens in load()'s
    // signature.
    // It doesn't look complicated but is easy to get wrong.
    // Much thanks to aatch on #rust-beginners for helping make this work.

    /// Called to initially create your `GameState` object
    /// after all hardware initialization has been done.
    /// It is handed a `Context` to load resources from,
    /// and the `Conf` object that has either been loaded
    /// from your `resources/conf.toml` file or the default
    /// that has been provided to `Game::new()` if no conf
    /// file exists.
    fn load(ctx: &mut Context) -> GameResult<Self> where Self: Sized;
}

pub trait EventHandler {
    /// Called upon each physics update to the game.
    /// This should be where the game's logic takes place.
    fn update(&mut self, ctx: &mut Context, dt: Duration) -> GameResult<()>;

    /// Called to do the drawing of your game.
    /// You probably want to start this with
    /// `graphics::clear()` and end it with
    /// `graphics::present()` and `timer::sleep_until_next_frame()`
    fn draw(&mut self, ctx: &mut Context) -> GameResult<()>;

    // You don't have to override these if you don't want to; the defaults
    // do nothing.
    // It might be nice to be able to have custom event types and a map or
    // such of handlers?  Hmm, maybe later.
    fn mouse_button_down_event(&mut self, _button: mouse::MouseButton, _x: i32, _y: i32) {}

    fn mouse_button_up_event(&mut self, _button: mouse::MouseButton, _x: i32, _y: i32) {}

    fn mouse_motion_event(&mut self,
                          _state: mouse::MouseState,
                          _x: i32,
                          _y: i32,
                          _xrel: i32,
                          _yrel: i32) {
    }

    fn mouse_wheel_event(&mut self, _x: i32, _y: i32) {}

    fn key_down_event(&mut self, _keycode: gevent::Keycode, _keymod: gevent::Mod, _repeat: bool) {}

    fn key_up_event(&mut self, _keycode: gevent::Keycode, _keymod: gevent::Mod, _repeat: bool) {}

    fn controller_button_down_event(&mut self, _btn: gevent::Button) {}
    fn controller_button_up_event(&mut self, _btn: gevent::Button) {}
    fn controller_axis_event(&mut self, _axis: gevent::Axis, _value: i16) {}

    fn focus_event(&mut self, _gained: bool) {}

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self) -> bool {
        println!("Quitting game");
        false
    }
}

/// The `Game` struct takes an object you define that
/// implements the `GameState` trait
/// and does the actual work of running a gameloop,
/// passing events to your handlers, and all that stuff.
#[derive(Debug)]
pub struct Game<'a, S> {
    state: S,
    context: Context<'a>,
}

impl<'a, S> Game<'a, S> {
    pub fn from_state(ctx: Context<'a>, state: S) -> Game<S> {
        Game {
            state: state,
            context: ctx,
        }
    }

    /// Replaces the gamestate with the given one without
    /// having to re-initialize the hardware context.
    pub fn replace_state(&mut self, state: S) {
        self.state = state;
    }

    /// Calls the given function to create a new gamestate, and replaces
    /// the current one with it.
    pub fn replace_state_with<F>(&mut self, f: &F) -> GameResult<()>
        where F: Fn(&mut Context) -> GameResult<S>
    {
        let newstate = f(&mut self.context)?;
        self.state = newstate;
        Ok(())
    }
}

impl<'a, S: GameState + 'static> Game<'a, S> {
    /// Creates a new `Game` with the given  default config
    /// (which will be used if there is no config file).
    /// It will initialize a hardware context and call the `load()` method of
    /// the given `GameState` type to create a new `GameState`.
    ///
    /// The `id` field is a unique identifier for your game that will
    /// be used to create a save directory to write files to.
    pub fn new(id: &str, default_config: conf::Conf) -> GameResult<Game<'a, S>> {
        let mut context = Context::load_from_conf(id, default_config)?;

        let init_state = S::load(&mut context)?;

        Ok(Game {
            state: init_state,
            context: context,
        })
    }

    /// Re-creates a fresh `GameState` using the existing one's `::load()` method.
    pub fn reload_state(&mut self) -> GameResult<()> {
        let newstate = S::load(&mut self.context)?;
        self.state = newstate;
        Ok(())
    }
}

impl<'a, S: EventHandler + 'static> Game<'a, S> {
    /// Runs the game's mainloop.
    /// Continues until a `Quit` event is created, for instance
    /// via `Context::quit()`
    pub fn run(&mut self) -> GameResult<Context<'a>> {
        let ctx = &mut self.context;
        let mut event_pump = ctx.sdl_context.event_pump()?;

        let mut continuing = true;
        let mut residual_update_dt = Duration::new(0, 0);
        let mut residual_draw_dt = Duration::new(0, 0);
        while continuing {
            ctx.timer_context.tick();

            for event in event_pump.poll_iter() {
                println!("Event: {:?}", event);
                match event {
                    Quit { .. } => {
                        continuing = self.state.quit_event();
                        // println!("Quit event: {:?}", t);
                    }
                    // TODO: We need a good way to have
                    // a default like this, while still allowing
                    // it to be overridden.
                    // Bah, just put it in the GameState trait
                    // as the default function.
                    // But it doesn't have access to the context
                    // to call quit!  Bah.
                    KeyDown { keycode, keymod, repeat, .. } => {
                        if let Some(key) = keycode {
                            if key == keyboard::Keycode::Escape {
                                ctx.quit()?;
                            } else {
                                self.state.key_down_event(key, keymod, repeat)
                            }
                        }
                    }
                    KeyUp { keycode, keymod, repeat, .. } => {
                        if let Some(key) = keycode {
                            self.state.key_up_event(key, keymod, repeat)
                        }
                    }
                    MouseButtonDown { mouse_btn, x, y, .. } => {
                        self.state.mouse_button_down_event(mouse_btn, x, y)
                    }
                    MouseButtonUp { mouse_btn, x, y, .. } => {
                        self.state.mouse_button_up_event(mouse_btn, x, y)
                    }
                    MouseMotion { mousestate, x, y, xrel, yrel, .. } => {
                        self.state.mouse_motion_event(mousestate, x, y, xrel, yrel)
                    }
                    MouseWheel { x, y, .. } => self.state.mouse_wheel_event(x, y),
                    ControllerButtonDown { button, .. } => {
                        self.state.controller_button_down_event(button)
                    }
                    ControllerButtonUp { button, .. } => {
                        self.state.controller_button_up_event(button)
                    }
                    ControllerAxisMotion { axis, value, .. } => {
                        self.state.controller_axis_event(axis, value)
                    }
                    Window { win_event: event::WindowEvent::FocusGained, .. } => {
                        self.state.focus_event(true)
                    }
                    Window { win_event: event::WindowEvent::FocusLost, .. } => {
                        self.state.focus_event(false)
                    }
                    _ => {}
                }
            }

            let update_dt = Duration::from_millis(10);
            let draw_dt = Duration::new(0, 16_666_666);
            let dt = timer::get_delta(ctx);
            {
                let mut current_dt = dt + residual_update_dt;
                while current_dt > update_dt {
                    self.state.update(ctx, update_dt)?;
                    current_dt -= update_dt;
                }
                residual_update_dt = current_dt;
            }

            {
                let mut current_dt = dt + residual_draw_dt;
                while current_dt > draw_dt {
                    self.state.draw(ctx)?;
                    current_dt -= draw_dt;
                }
                residual_draw_dt = draw_dt;
            }
            timer::sleep(Duration::new(0, 0));
        }

        Ok(())
    }
}
<|endoftext|>