<commit_before>use std::rt::io::process::{Process, ProcessConfig, CreatePipe, Ignored};
use std::rt::io::{Reader, Writer};
use std::rt::io::pipe::PipeStream;
use std::str;

fn main() {
    test_output_multi_files_print_all_chars();
    test_stdin_squeeze();
    test_stdin_number_non_blank();
}

fn read_all(input: &mut Reader) -> ~str {
    let mut ret = ~"";
    let mut buf = [0, ..1024];
    loop {
        match input.read(buf) {
            None => { break }
            Some(n) => { ret = ret + str::from_utf8(buf.slice_to(n)); }
        }
    }
    return ret;
}

fn test_output_multi_files_print_all_chars() {
    let output = PipeStream::new().unwrap();
    let io = ~[Ignored,
               CreatePipe(output, false, true)];
    let args = ProcessConfig {
        program: "build/cat",
        args: [~"cat/fixtures/alpha.txt", ~"cat/fixtures/256.txt", ~"-A", ~"-n"],
        env: None,
        cwd: None,
        io: io,
    };
    let mut p = Process::new(args).expect("proc fail");
    let out = read_all(p.io[1].get_mut_ref() as &mut Reader);
    assert_eq!(p.wait(), 0);
    assert_eq!(out, ~"     1\tabcde$\n     2\tfghij$\n     3\tklmno$\n     4\tpqrst$\n     5\tuvwxyz$\n     6\t^@^A^B^C^D^E^F^G^H^I$\n     7\t^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\\^]^^^_ !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~^?M-^@M-^AM-^BM-^CM-^DM-^EM-^FM-^GM-^HM-^IM-^JM-^KM-^LM-^MM-^NM-^OM-^PM-^QM-^RM-^SM-^TM-^UM-^VM-^WM-^XM-^YM-^ZM-^[M-^\\M-^]M-^^M-^_M- M-!M-\"M-#M-$M-%M-&M-\'M-(M-)M-*M-+M-,M--M-.M-/M-0M-1M-2M-3M-4M-5M-6M-7M-8M-9M-:M-;M-<M-=M->M-?M-@M-AM-BM-CM-DM-EM-FM-GM-HM-IM-JM-KM-LM-MM-NM-OM-PM-QM-RM-SM-TM-UM-VM-WM-XM-YM-ZM-[M-\\M-]M-^M-_M-`M-aM-bM-cM-dM-eM-fM-gM-hM-iM-jM-kM-lM-mM-nM-oM-pM-qM-rM-sM-tM-uM-vM-wM-xM-yM-zM-{M-|M-}M-~M-^?");
}

fn test_stdin_squeeze() {
    let input = PipeStream::new().unwrap();
    let output = PipeStream::new().unwrap();
    let io = ~[CreatePipe(input, true, false),
               CreatePipe(output, false, true)];
    let args = ProcessConfig {
        program: "build/cat",
        args: [~"-A"],
        env: None,
        cwd: None,
        io: io,
    };
    let mut p = Process::new(args).expect("proc fail");
    p.io[0].get_mut_ref().write("\x00\x01\x02".as_bytes());
    p.io[0] = None; // close stdin;
    let out = read_all(p.io[1].get_mut_ref() as &mut Reader);
    assert_eq!(p.wait(), 0);
    assert_eq!(out, ~"^@^A^B");
}

fn test_stdin_number_non_blank() {
    let input = PipeStream::new().unwrap();
    let output = PipeStream::new().unwrap();
    let io = ~[CreatePipe(input, true, false),
               CreatePipe(output, false, true)];
    let args = ProcessConfig {
        program: "build/cat",
        args: [~"-b", ~"-"],
        env: None,
        cwd: None,
        io: io,
    };
    let mut p = Process::new(args).expect("proc fail");
    p.io[0].get_mut_ref().write("\na\nb\n\n\nc".as_bytes());
    p.io[0] = None; // close stdin;
    let out = read_all(p.io[1].get_mut_ref() as &mut Reader);
    assert_eq!(p.wait(), 0);
    assert_eq!(out, ~"\n     1\ta\n     2\tb\n\n\n     3\tc");
}
<commit_msg>Update cat/test for std::rt::io changes. Also, use the higher level std::run over std::rt::io::process.<commit_after>use std::{run, str};

fn main() {
    test_output_multi_files_print_all_chars();
    test_stdin_squeeze();
    test_stdin_number_non_blank();
}

fn test_output_multi_files_print_all_chars() {
    let prog = run::process_output("build/cat",
                                   [~"cat/fixtures/alpha.txt", ~"cat/fixtures/256.txt",
                                    ~"-A", ~"-n"]);
    let out = str::from_utf8_owned(prog.output);
    assert_eq!(out,
               ~"     1\tabcde$\n     2\tfghij$\n     3\tklmno$\n     4\tpqrst$\n     5\tuvwxyz$\n     6\t^@^A^B^C^D^E^F^G^H^I$\n     7\t^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\\^]^^^_ !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~^?M-^@M-^AM-^BM-^CM-^DM-^EM-^FM-^GM-^HM-^IM-^JM-^KM-^LM-^MM-^NM-^OM-^PM-^QM-^RM-^SM-^TM-^UM-^VM-^WM-^XM-^YM-^ZM-^[M-^\\M-^]M-^^M-^_M- M-!M-\"M-#M-$M-%M-&M-\'M-(M-)M-*M-+M-,M--M-.M-/M-0M-1M-2M-3M-4M-5M-6M-7M-8M-9M-:M-;M-<M-=M->M-?M-@M-AM-BM-CM-DM-EM-FM-GM-HM-IM-JM-KM-LM-MM-NM-OM-PM-QM-RM-SM-TM-UM-VM-WM-XM-YM-ZM-[M-\\M-]M-^M-_M-`M-aM-bM-cM-dM-eM-fM-gM-hM-iM-jM-kM-lM-mM-nM-oM-pM-qM-rM-sM-tM-uM-vM-wM-xM-yM-zM-{M-|M-}M-~M-^?");
}

fn test_stdin_squeeze() {
    let mut prog = run::Process::new("build/cat", [~"-A"], run::ProcessOptions::new());

    prog.input().write(bytes!("\x00\x01\x02"));
    prog.close_input();

    let out = str::from_utf8_owned(prog.finish_with_output().output);
    assert_eq!(out, ~"^@^A^B");
}

fn test_stdin_number_non_blank() {
    let mut prog = run::Process::new("build/cat", [~"-b", ~"-"], run::ProcessOptions::new());

    prog.input().write(bytes!("\na\nb\n\n\nc"));
    prog.close_input();

    let out = str::from_utf8_owned(prog.finish_with_output().output);
    assert_eq!(out, ~"\n     1\ta\n     2\tb\n\n\n     3\tc");
}
<|endoftext|>


<commit_before>// Sync available crate categories from `src/categories.txt`.
// Runs when the server is started.

use pg;
use env;
use util::errors::CargoResult;

pub fn sync() -> CargoResult<()> {
    let conn = pg::Connection::connect(&env("DATABASE_URL")[..],
                                             pg::TlsMode::None).unwrap();
    let tx = conn.transaction().unwrap();

    let categories = include_str!("./categories.txt");

    let slug_categories: Vec<_> = categories.lines().map(|c| {
        let mut parts = c.split(' ');
        let slug = parts.next().expect("No slug found!");
        let name = parts.collect::<Vec<_>>().join(" ");
        (slug, name)
    }).collect();

    let insert = slug_categories.iter().map(|&(ref slug, ref name)| {
        format!("(LOWER('{}'), '{}')", slug, name)
    }).collect::<Vec<_>>().join(",");

    let in_clause = slug_categories.iter().map(|&(slug, _)| {
        format!("LOWER('{}')", slug)
    }).collect::<Vec<_>>().join(",");

    try!(tx.batch_execute(
        &format!(" \
            INSERT INTO categories (slug, category) \
            VALUES {} \
            ON CONFLICT (slug) DO UPDATE SET category = EXCLUDED.category; \
            DELETE FROM categories \
            WHERE slug NOT IN ({});",
            insert,
            in_clause
        )[..]
    ));
    tx.set_commit();
    tx.finish().unwrap();
    Ok(())
}
<commit_msg>Use splitn on the category slug/display name pairs<commit_after>// Sync available crate categories from `src/categories.txt`.
// Runs when the server is started.

use pg;
use env;
use util::errors::CargoResult;

pub fn sync() -> CargoResult<()> {
    let conn = pg::Connection::connect(&env("DATABASE_URL")[..],
                                             pg::TlsMode::None).unwrap();
    let tx = conn.transaction().unwrap();

    let categories = include_str!("./categories.txt");

    let slug_categories: Vec<_> = categories.lines().map(|c| {
        let mut parts = c.splitn(2, ' ');
        let slug = parts.next().expect("No slug found!");
        let name = parts.next().expect("No display name found!");
        (slug, name)
    }).collect();

    let insert = slug_categories.iter().map(|&(ref slug, ref name)| {
        format!("(LOWER('{}'), '{}')", slug, name)
    }).collect::<Vec<_>>().join(",");

    let in_clause = slug_categories.iter().map(|&(slug, _)| {
        format!("LOWER('{}')", slug)
    }).collect::<Vec<_>>().join(",");

    try!(tx.batch_execute(
        &format!(" \
            INSERT INTO categories (slug, category) \
            VALUES {} \
            ON CONFLICT (slug) DO UPDATE SET category = EXCLUDED.category; \
            DELETE FROM categories \
            WHERE slug NOT IN ({});",
            insert,
            in_clause
        )[..]
    ));
    tx.set_commit();
    tx.finish().unwrap();
    Ok(())
}
<|endoftext|>


<commit_before>extern crate git2;

use git2::*;
use std::path::Path;
use scratch::Scratch;
use super::Hooks;
use super::RepoHost;
use super::ReviewUploadResult;

pub struct CentralGit
{
    branch: String,
}

impl CentralGit
{
    pub fn new(branch: &str) -> Self
    {
        CentralGit { branch: branch.to_string() }
    }
}

pub fn module_ref(module: &str, branch: &str) -> String
{
    format!("refs/{}/{}/refs/heads/{}",
            "centralgit_0ee845b3_9c3f_41ee_9149_9e98a65ecf35",
            module,
            branch)
}

impl Hooks for CentralGit
{
    fn branch(&self) -> &str
    {
        return &self.branch;
    }

    fn review_upload(&self,
                     scratch: &Scratch,
                     host: &RepoHost,
                     newrev: Object,
                     module: &str)
        -> ReviewUploadResult
    {
        debug!(".\n\n==== Doing review upload for module {}", &module);

        let new = newrev.id();

        let (walk, initial) = if let Some(old) = scratch.tracking(host, &module, &self.branch()) {

            let old = old.id();

            if old == new {
                return ReviewUploadResult::NoChanges;
            }

            match scratch.repo.graph_descendant_of(new, old) {
                Err(_) | Ok(false) => {
                    debug!("graph_descendant_of({},{})", new, old);
                    return ReviewUploadResult::RejectNoFF;
                }
                Ok(true) => (),
            }

            debug!("==== walking commits from {} to {}", old, new);

            let mut walk = scratch.repo.revwalk().expect("walk: can't create revwalk");
            walk.set_sorting(SORT_REVERSE | SORT_TOPOLOGICAL);
            let range = format!("{}..{}", old, new);
            walk.push_range(&range).expect(&format!("walk: invalid range: {}", range));;
            walk.hide(old).expect("walk: can't hide");
            (walk, false)
        }
        else {
            let mut walk = scratch.repo.revwalk().expect("walk: can't create revwalk");
            walk.set_sorting(SORT_REVERSE | SORT_TOPOLOGICAL);
            walk.push(new).expect("walk: can't push");
            (walk, true)
        };

        let mut current =
            scratch.tracking(host, host.central(), &self.branch).expect("no central tracking").id();

        for rev in walk {
            let rev = rev.expect("walk: invalid rev");

            debug!("==== walking commit {}", rev);

            let module_commit = scratch.repo
                .find_commit(rev)
                .expect("walk: object is not actually a commit");

            if module_commit.parents().count() > 1 {
                // TODO: also do this check on pushes to cenral refs/for/branch
                // TODO: invectigate the possibility of allowing merge commits
                return ReviewUploadResult::RejectMerge;
            }

            if module != host.central() {
                debug!("==== Rewriting commit {}", rev);

                let tree = module_commit.tree().expect("walk: commit has no tree");
                let parent =
                    scratch.repo.find_commit(current).expect("walk: current object is no commit");

                let new_tree = scratch.replace_subtree(Path::new(module),
                                                       tree.id(),
                                                       &parent.tree()
                                                           .expect("walk: parent has no tree"));

                current = scratch.rewrite(&module_commit, &vec![&parent], &new_tree);
            }
        }

        if module != host.central() {
            return ReviewUploadResult::Uploaded(current, initial);
        }
        else {
            return ReviewUploadResult::Central;
        }
    }

    fn pre_create_project(&self, scratch: &Scratch, rev: Oid, project: &str)
    {
        if let Ok(_) = scratch.repo.refname_to_id(&module_ref(project, &self.branch())) {
            debug!("=== module ref for {} already exists", project);
        }
        else {
            if let Some(commit) = scratch.split_subdir(&project, rev) {
                scratch.repo
                    .reference(&module_ref(project, &self.branch()),
                               commit,
                               true,
                               "subtree_split")
                    .expect("can't create reference");
            }
            else {
                debug!("=== subdir empty: {}", project);
            }
        }
    }

    fn project_created(&self, scratch: &Scratch, host: &RepoHost, _project: &str)
    {
        if let Some(rev) = scratch.tracking(host, host.central(), &self.branch()) {
            self.central_submit(scratch, host, rev);
        }
    }

    fn central_submit(&self, scratch: &Scratch, host: &RepoHost, newrev: Object)
    {
        debug!(" ---> central_submit (sha1 of commit: {})", &newrev.id());

        let central_commit = newrev.as_commit().expect("could not get commit from obj");
        let central_tree = central_commit.tree().expect("commit has no tree");

        let mut changed = vec![];

        for module in host.projects() {
            if module == host.central() {
                continue;
            }
            debug!("");
            debug!("==== fetching tracking branch for module: {}", &module);
            match scratch.tracking(host, &module, &self.branch()) {
                Some(_) => (),
                None => {
                    debug!("====    no tracking branch for module {} => project does not exist \
                            or is empty",
                           &module);
                    debug!("====    initializing with subdir history");

                    self.pre_create_project(scratch, newrev.id(), &module);
                    changed.push(module.to_string());
                }
            };
            self.pre_create_project(scratch, newrev.id(), &module);

            let module_commit_obj = if let Ok(rev) = scratch.repo
                .revparse_single(&module_ref(&module, &self.branch())) {
                debug!("=== OK module ref : {}", module);
                rev
            }
            else {
                debug!("=== NO module ref : {}", module);
                continue;
            };

            let parents = vec![module_commit_obj.as_commit()
                                   .expect("could not get commit from obj")];

            debug!("==== checking for changes in module: {:?}", module);

            // new tree is sub-tree of complete central tree
            let old_tree_id = if let Ok(tree) = parents[0].tree() {
                tree.id()
            }
            else {
                Oid::from_str("0000000000000000000000000000000000000000").unwrap()
            };

            let new_tree_id = if let Ok(tree_entry) = central_tree.get_path(&Path::new(&module)) {
                tree_entry.id()
            }
            else {
                Oid::from_str("0000000000000000000000000000000000000000").unwrap()
            };

            // if sha1's are equal the content is equal
            if new_tree_id != old_tree_id && !new_tree_id.is_zero() {
                changed.push(module.to_string());
                let new_tree =
                    scratch.repo.find_tree(new_tree_id).expect("central_submit: can't find tree");
                debug!("====    commit changes module => make commit on module");
                let module_commit = scratch.rewrite(central_commit, &parents, &new_tree);
                scratch.repo
                    .reference(&module_ref(&module, &self.branch()),
                               module_commit,
                               true,
                               "rewrite")
                    .expect("can't create reference");
            }
            else {
                debug!("====    commit does not change module => skipping");
            }
        }

        for module in changed {
            if let Ok(module_commit) = scratch.repo
                .refname_to_id(&module_ref(&module, &self.branch())) {
                let output = scratch.push(host,
                                          module_commit,
                                          &module,
                                          &format!("refs/heads/{}", self.branch()));
                debug!("{}", output);
            }
        }
    }
}
<commit_msg>remove obsolete comment<commit_after>extern crate git2;

use git2::*;
use std::path::Path;
use scratch::Scratch;
use super::Hooks;
use super::RepoHost;
use super::ReviewUploadResult;

pub struct CentralGit
{
    branch: String,
}

impl CentralGit
{
    pub fn new(branch: &str) -> Self
    {
        CentralGit { branch: branch.to_string() }
    }
}

pub fn module_ref(module: &str, branch: &str) -> String
{
    format!("refs/{}/{}/refs/heads/{}",
            "centralgit_0ee845b3_9c3f_41ee_9149_9e98a65ecf35",
            module,
            branch)
}

impl Hooks for CentralGit
{
    fn branch(&self) -> &str
    {
        return &self.branch;
    }

    fn review_upload(&self,
                     scratch: &Scratch,
                     host: &RepoHost,
                     newrev: Object,
                     module: &str)
        -> ReviewUploadResult
    {
        debug!(".\n\n==== Doing review upload for module {}", &module);

        let new = newrev.id();

        let (walk, initial) = if let Some(old) = scratch.tracking(host, &module, &self.branch()) {

            let old = old.id();

            if old == new {
                return ReviewUploadResult::NoChanges;
            }

            match scratch.repo.graph_descendant_of(new, old) {
                Err(_) | Ok(false) => {
                    debug!("graph_descendant_of({},{})", new, old);
                    return ReviewUploadResult::RejectNoFF;
                }
                Ok(true) => (),
            }

            debug!("==== walking commits from {} to {}", old, new);

            let mut walk = scratch.repo.revwalk().expect("walk: can't create revwalk");
            walk.set_sorting(SORT_REVERSE | SORT_TOPOLOGICAL);
            let range = format!("{}..{}", old, new);
            walk.push_range(&range).expect(&format!("walk: invalid range: {}", range));;
            walk.hide(old).expect("walk: can't hide");
            (walk, false)
        }
        else {
            let mut walk = scratch.repo.revwalk().expect("walk: can't create revwalk");
            walk.set_sorting(SORT_REVERSE | SORT_TOPOLOGICAL);
            walk.push(new).expect("walk: can't push");
            (walk, true)
        };

        let mut current =
            scratch.tracking(host, host.central(), &self.branch).expect("no central tracking").id();

        for rev in walk {
            let rev = rev.expect("walk: invalid rev");

            debug!("==== walking commit {}", rev);

            let module_commit = scratch.repo
                .find_commit(rev)
                .expect("walk: object is not actually a commit");

            if module_commit.parents().count() > 1 {
                // TODO: invectigate the possibility of allowing merge commits
                return ReviewUploadResult::RejectMerge;
            }

            if module != host.central() {
                debug!("==== Rewriting commit {}", rev);

                let tree = module_commit.tree().expect("walk: commit has no tree");
                let parent =
                    scratch.repo.find_commit(current).expect("walk: current object is no commit");

                let new_tree = scratch.replace_subtree(Path::new(module),
                                                       tree.id(),
                                                       &parent.tree()
                                                           .expect("walk: parent has no tree"));

                current = scratch.rewrite(&module_commit, &vec![&parent], &new_tree);
            }
        }

        if module != host.central() {
            return ReviewUploadResult::Uploaded(current, initial);
        }
        else {
            return ReviewUploadResult::Central;
        }
    }

    fn pre_create_project(&self, scratch: &Scratch, rev: Oid, project: &str)
    {
        if let Ok(_) = scratch.repo.refname_to_id(&module_ref(project, &self.branch())) {
            debug!("=== module ref for {} already exists", project);
        }
        else {
            if let Some(commit) = scratch.split_subdir(&project, rev) {
                scratch.repo
                    .reference(&module_ref(project, &self.branch()),
                               commit,
                               true,
                               "subtree_split")
                    .expect("can't create reference");
            }
            else {
                debug!("=== subdir empty: {}", project);
            }
        }
    }

    fn project_created(&self, scratch: &Scratch, host: &RepoHost, _project: &str)
    {
        if let Some(rev) = scratch.tracking(host, host.central(), &self.branch()) {
            self.central_submit(scratch, host, rev);
        }
    }

    fn central_submit(&self, scratch: &Scratch, host: &RepoHost, newrev: Object)
    {
        debug!(" ---> central_submit (sha1 of commit: {})", &newrev.id());

        let central_commit = newrev.as_commit().expect("could not get commit from obj");
        let central_tree = central_commit.tree().expect("commit has no tree");

        let mut changed = vec![];

        for module in host.projects() {
            if module == host.central() {
                continue;
            }
            debug!("");
            debug!("==== fetching tracking branch for module: {}", &module);
            match scratch.tracking(host, &module, &self.branch()) {
                Some(_) => (),
                None => {
                    debug!("====    no tracking branch for module {} => project does not exist \
                            or is empty",
                           &module);
                    debug!("====    initializing with subdir history");

                    self.pre_create_project(scratch, newrev.id(), &module);
                    changed.push(module.to_string());
                }
            };
            self.pre_create_project(scratch, newrev.id(), &module);

            let module_commit_obj = if let Ok(rev) = scratch.repo
                .revparse_single(&module_ref(&module, &self.branch())) {
                debug!("=== OK module ref : {}", module);
                rev
            }
            else {
                debug!("=== NO module ref : {}", module);
                continue;
            };

            let parents = vec![module_commit_obj.as_commit()
                                   .expect("could not get commit from obj")];

            debug!("==== checking for changes in module: {:?}", module);

            // new tree is sub-tree of complete central tree
            let old_tree_id = if let Ok(tree) = parents[0].tree() {
                tree.id()
            }
            else {
                Oid::from_str("0000000000000000000000000000000000000000").unwrap()
            };

            let new_tree_id = if let Ok(tree_entry) = central_tree.get_path(&Path::new(&module)) {
                tree_entry.id()
            }
            else {
                Oid::from_str("0000000000000000000000000000000000000000").unwrap()
            };

            // if sha1's are equal the content is equal
            if new_tree_id != old_tree_id && !new_tree_id.is_zero() {
                changed.push(module.to_string());
                let new_tree =
                    scratch.repo.find_tree(new_tree_id).expect("central_submit: can't find tree");
                debug!("====    commit changes module => make commit on module");
                let module_commit = scratch.rewrite(central_commit, &parents, &new_tree);
                scratch.repo
                    .reference(&module_ref(&module, &self.branch()),
                               module_commit,
                               true,
                               "rewrite")
                    .expect("can't create reference");
            }
            else {
                debug!("====    commit does not change module => skipping");
            }
        }

        for module in changed {
            if let Ok(module_commit) = scratch.repo
                .refname_to_id(&module_ref(&module, &self.branch())) {
                let output = scratch.push(host,
                                          module_commit,
                                          &module,
                                          &format!("refs/heads/{}", self.branch()));
                debug!("{}", output);
            }
        }
    }
}
<|endoftext|>


<commit_before>use cgmath;
use cgmath::EuclideanVector;
use num;
use std::ops;

pub struct Smooth<S: num::Num> {
	ptr: usize,
	count: usize,
	acc: S,
	last: S,
	values: Vec<S>,
}

impl<S: num::Num + num::NumCast + ::std::marker::Copy> Smooth<S> {
	pub fn new(window_size: usize) -> Smooth<S> {
		Smooth {
			ptr: 0,
			count: 0,
			last: S::zero(),
			acc: S::zero(),
			values: vec![S::zero(); window_size],
		}
	}

	pub fn smooth(&mut self, value: S) -> S {
		let len = self.values.len();
		if self.count < len {
			self.count = self.count + 1;
		} else {
			self.acc = self.acc - self.values[self.ptr];
		}
		self.acc = self.acc + value;
		self.values[self.ptr] = value;
		self.ptr = ((self.ptr + 1) % len) as usize;
		self.last = self.acc / num::cast(self.count).unwrap();
		self.last
	}
}

pub enum Direction {
	Up,
	Down,
	Left,
	Right,
}

pub trait Directional<T: cgmath::BaseFloat> {
	fn push(&mut self, d: Direction);
	fn position(&self) -> cgmath::Vector2<T>;
	fn unit(d: Direction) -> cgmath::Vector2<T> {
		match d {
			Direction::Up => cgmath::Vector2::unit_y(),
			Direction::Down => -cgmath::Vector2::unit_y(),
			Direction::Right => cgmath::Vector2::unit_x(),
			Direction::Left => -cgmath::Vector2::unit_x(),
		}
	}
}

#[derive(Clone)]
pub struct Inertial<T: cgmath::BaseNum + ops::Neg + Copy> {
	impulse: T,
	inertia: T,
	limit: T,
	position: cgmath::Vector2<T>,
	velocity: cgmath::Vector2<T>,
}

impl<T> Default for Inertial<T>
    where T: cgmath::BaseFloat + cgmath::Zero + cgmath::One
{
	fn default() -> Self {
		Inertial {
			impulse: T::one(),
			inertia: T::one(),
			limit: T::one(),
			position: cgmath::Vector::zero(),
			velocity: cgmath::Vector::zero(),
		}
	}
}

impl<T> Directional<T> for Inertial<T>
    where T: cgmath::BaseFloat
{
	fn push(&mut self, d: Direction) {
		let v = Self::unit(d);
		self.velocity = self.velocity + v * self.impulse;
		if self.velocity.length() > self.limit {
			self.velocity.normalize_to(self.limit);
		}
	}
	fn position(&self) -> cgmath::Vector2<T> {
		self.position
	}
}

impl<T> Inertial<T>
    where T: cgmath::BaseFloat
{
	pub fn new(impulse: T, inertia: T, limit: T) -> Self {
		Inertial {
			impulse: impulse,
			inertia: inertia,
			limit: limit,
			..Default::default()
		}
	}

	pub fn reset(&mut self) {
		self.position = cgmath::Vector::zero();
		self.velocity = cgmath::Vector::zero();
	}

	pub fn set(&mut self, position: cgmath::Point2<T>) {
		self.position = cgmath::Point::to_vec(position);
	}

	pub fn stop(&mut self) {
		self.velocity = cgmath::Vector::zero();
	}

	pub fn update(&mut self, dt: T) {
		let one = T::one();
		let damp = one - (-dt / self.inertia).exp();
		self.position = self.position + self.velocity * dt;
		self.velocity = self.velocity * damp;
	}
}
<commit_msg>Inertial dampening formula more clear<commit_after>use cgmath;
use cgmath::EuclideanVector;
use num;
use std::ops;

pub struct Smooth<S: num::Num> {
	ptr: usize,
	count: usize,
	acc: S,
	last: S,
	values: Vec<S>,
}

impl<S: num::Num + num::NumCast + ::std::marker::Copy> Smooth<S> {
	pub fn new(window_size: usize) -> Smooth<S> {
		Smooth {
			ptr: 0,
			count: 0,
			last: S::zero(),
			acc: S::zero(),
			values: vec![S::zero(); window_size],
		}
	}

	pub fn smooth(&mut self, value: S) -> S {
		let len = self.values.len();
		if self.count < len {
			self.count = self.count + 1;
		} else {
			self.acc = self.acc - self.values[self.ptr];
		}
		self.acc = self.acc + value;
		self.values[self.ptr] = value;
		self.ptr = ((self.ptr + 1) % len) as usize;
		self.last = self.acc / num::cast(self.count).unwrap();
		self.last
	}
}

pub enum Direction {
	Up,
	Down,
	Left,
	Right,
}

pub trait Directional<T: cgmath::BaseFloat> {
	fn push(&mut self, d: Direction);
	fn position(&self) -> cgmath::Vector2<T>;
	fn unit(d: Direction) -> cgmath::Vector2<T> {
		match d {
			Direction::Up => cgmath::Vector2::unit_y(),
			Direction::Down => -cgmath::Vector2::unit_y(),
			Direction::Right => cgmath::Vector2::unit_x(),
			Direction::Left => -cgmath::Vector2::unit_x(),
		}
	}
}

#[derive(Clone)]
pub struct Inertial<T: cgmath::BaseNum + ops::Neg + Copy> {
	impulse: T,
	inertia: T,
	limit: T,
	position: cgmath::Vector2<T>,
	velocity: cgmath::Vector2<T>,
}

impl<T> Default for Inertial<T>
    where T: cgmath::BaseFloat + cgmath::Zero + cgmath::One
{
	fn default() -> Self {
		Inertial {
			impulse: T::one(),
			inertia: T::one(),
			limit: T::one(),
			position: cgmath::Vector::zero(),
			velocity: cgmath::Vector::zero(),
		}
	}
}

impl<T> Directional<T> for Inertial<T>
    where T: cgmath::BaseFloat
{
	fn push(&mut self, d: Direction) {
		let v = Self::unit(d);
		self.velocity = self.velocity + v * self.impulse;
		if self.velocity.length() > self.limit {
			self.velocity.normalize_to(self.limit);
		}
	}
	fn position(&self) -> cgmath::Vector2<T> {
		self.position
	}
}

impl<T> Inertial<T>
    where T: cgmath::BaseFloat
{
	pub fn new(impulse: T, inertia: T, limit: T) -> Self {
		Inertial {
			impulse: impulse,
			inertia: inertia,
			limit: limit,
			..Default::default()
		}
	}

	pub fn reset(&mut self) {
		self.position = cgmath::Vector::zero();
		self.velocity = cgmath::Vector::zero();
	}

	pub fn set(&mut self, position: cgmath::Point2<T>) {
		self.position = cgmath::Point::to_vec(position);
	}

	pub fn stop(&mut self) {
		self.velocity = cgmath::Vector::zero();
	}

	pub fn update(&mut self, dt: T) {
		self.position = self.position + self.velocity * dt;
		self.velocity = self.velocity - self.velocity * T::exp(-dt / self.inertia);
	}
}
<|endoftext|>


<commit_before>//! Defines what information a chess move should contain.

use basetypes::*;
use castling_rights::*;

/// Represents a move on the chessboard.
///
/// `Move` contains 3 types of information:
///
/// 1. Information about the played move itself.
///
/// 2. Information needed so as to be able to undo the move and
///    restore the board into the exact same state as before.
///
/// 3. The move score -- moves with higher score are tried
///    first. Ideally the best move should have the highest score.
///
/// `Move` is a 32-bit unsigned number. The lowest 16 bits contain the
/// whole needed information about the move itself (type 1). And is
/// laid out the following way:
///
///  ```text
///   15                                                           0
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  | Move  |    Origin square      |   Destination square  | Aux   |
///  | type  |       6 bits          |        6 bits         | data  |
///  | 2 bits|   |   |   |   |   |   |   |   |   |   |   |   | 2 bits|
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |       |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// There are 4 "move type"s: `0`) en-passant capture; `1`) pawn
/// promotion; `2`) castling; `3`) normal move. "Aux data" encodes the
/// type of the promoted piece if the move type is a pawn promotion,
/// otherwise it encodes castling rights (see below).
///
/// The highest 16 bits contain the rest ot the info:
///
///  ```text
///   31                                                          16
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  | Move  |  Captured | Reser-|  Played   | Cast- |   En-passant  |
///  | score |  piece    |  ved  |  piece    | ling  |      file     |
///  | 2 bits|  3 bits   | 2 bits|  3 bits   | 2 bits|     4 bits    |
///  |   |   |   |   |   |   |   |   |   |   |       |   |   |   |   |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// "En-passant file" tells on what vertical line on the board there
/// was a passing pawn before the move was played. If there was no
/// passing pawn, "en-passant file" should be `8`.
///
/// Castling rights are a bit complex. The castling rights for the side
/// that makes the move, before the move was made, are stored in the
/// "Aux data" field. This is OK, because promoting a pawn never
/// changes the moving player's castling rights. The castling rights
/// for the opposite side are stored in "Castling" field. (A move can
/// change the castling rights for the other side when a rook in the
/// corner is captured.)
///
/// When "Captured piece" is stored, its bits are inverted, so that
/// MVV-LVA (Most valuable victim -- least valuable aggressor)
/// ordering of the moves is preserved, even when the "Move score"
/// field stays the same. The "Reserved" field is used to make the
/// ordering for non-capturing moves more predictable.
#[derive(Debug)]
#[derive(Clone, Copy)]
#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub struct Move(u32);

impl Move {
    /// Creates a new instance of `Move`.
    ///
    /// `us` is the side that makes the move. `castling` are the
    /// castling rights before the move was played. `en_passant_file`
    /// is the file on which there were a passing pawn before the move
    /// was played (or `8` if there was no passing
    /// pawn). `promoted_piece_code` should be a number between `0`
    /// and `3` and is used only when the `move_type` is a pawn
    /// promotion, otherwise it is ignored.
    #[inline]
    pub fn new(us: Color,
               score: usize,
               move_type: MoveType,
               piece: PieceType,
               orig_square: Square,
               dest_square: Square,
               captured_piece: PieceType,
               en_passant_file: File,
               castling: CastlingRights,
               promoted_piece_code: usize)
               -> Move {
        assert!(us <= 1);
        assert!(score <= 0b11);
        assert!(move_type <= 0x11);
        assert!(piece < NO_PIECE);
        assert!(orig_square <= 63);
        assert!(dest_square <= 63);
        assert!(captured_piece != KING && captured_piece <= NO_PIECE);
        assert!(en_passant_file <= 0b1000);
        assert!(promoted_piece_code <= 0b11);

        // We use the reserved field (2 bits) to properly order
        // "quiet" movies. Moves which destination square is more
        // advanced into enemy's territory are tried first.
        let reserved = if captured_piece == NO_PIECE {
            let rank = rank(dest_square);
            let advance = if us == WHITE {
                rank
            } else {
                7 - rank
            };
            match advance {
                0 => 0,
                x if x < 3 => 1,
                x if x < 5 => 2,
                _ => 3,
            }
        } else {
            0
        };

        let aux_data = match move_type {
            MOVE_PROMOTION => promoted_piece_code,
            _ => castling.get_for(us),
        };
        Move((score << M_SHIFT_SCORE | (!captured_piece & 0b111) << M_SHIFT_CAPTURED_PIECE |
              reserved << M_SHIFT_RESERVED | piece << M_SHIFT_PIECE |
              castling.get_for(1 ^ us) << M_SHIFT_CASTLING_DATA |
              en_passant_file << M_SHIFT_ENPASSANT_FILE |
              move_type << M_SHIFT_MOVE_TYPE | orig_square << M_SHIFT_ORIG_SQUARE |
              dest_square << M_SHIFT_DEST_SQUARE |
              aux_data << M_SHIFT_AUX_DATA) as u32)
    }

    /// Sets the "move score" field to a particular value.
    #[inline]
    pub fn set_score(&mut self, score: usize) {
        assert!(score <= 0b11);
        self.0 &= !M_MASK_SCORE;
        self.0 |= (score << M_SHIFT_SCORE) as u32;
    }

    /// Sets a particular bit in the "move score" field to `1`.
    #[inline]
    pub fn set_score_bit(&mut self, b: usize) {
        assert!(b <= 1);
        self.0 |= 1 << b << M_SHIFT_SCORE;
    }

    /// Sets a particular bit in the "move score" field to `0`.
    #[inline]
    pub fn clear_score_bit(&mut self, b: usize) {
        assert!(b <= 1);
        self.0 &= !(1 << b << M_SHIFT_SCORE);
    }

    #[inline]
    pub fn score(&self) -> usize {
        ((self.0 & M_MASK_SCORE) >> M_SHIFT_SCORE) as usize
    }

    #[inline]
    pub fn move_type(&self) -> MoveType {
        ((self.0 & M_MASK_MOVE_TYPE) >> M_SHIFT_MOVE_TYPE) as MoveType
    }

    #[inline]
    pub fn piece(&self) -> PieceType {
        ((self.0 & M_MASK_PIECE) >> M_SHIFT_PIECE) as PieceType
    }

    #[inline]
    pub fn orig_square(&self) -> Square {
        ((self.0 & M_MASK_ORIG_SQUARE) >> M_SHIFT_ORIG_SQUARE) as Square
    }

    #[inline]
    pub fn dest_square(&self) -> Square {
        ((self.0 & M_MASK_DEST_SQUARE) >> M_SHIFT_DEST_SQUARE) as Square
    }

    #[inline]
    pub fn captured_piece(&self) -> PieceType {
        ((!self.0 & M_MASK_CAPTURED_PIECE) >> M_SHIFT_CAPTURED_PIECE) as PieceType
    }

    /// Returns the file on which there were a passing pawn before the
    /// move was played (or `8` if there was no passing pawn).
    #[inline]
    pub fn en_passant_file(&self) -> File {
        ((self.0 & M_MASK_ENPASSANT_FILE) >> M_SHIFT_ENPASSANT_FILE) as File
    }

    /// Returns a 2-bit value representing the castling rights for the
    /// side that does not make the move, as they were before the move
    /// was played.
    #[inline(always)]
    pub fn castling_data(&self) -> usize {
        ((self.0 & M_MASK_CASTLING_DATA) >> M_SHIFT_CASTLING_DATA) as usize
    }

    /// Returns 2-bit value representing auxiliary data.
    ///
    /// When the move type is pawn promotion, "aux data" holds the
    /// promoted piece type encoded with a value from 0 to 3. For all
    /// other move types "aux data" holds the castling rights for the
    /// side that makes the move, as they were before the move was
    /// played.
    #[inline(always)]
    pub fn aux_data(&self) -> usize {
        ((self.0 & M_MASK_AUX_DATA) >> M_SHIFT_AUX_DATA) as usize
    }

    /// Returns the least significant 16 bits of the raw move value.
    ///
    /// The returned value contains the whole information about the
    /// played move itself. The only missing information is the move
    /// ordering information and the information stored so as to be
    /// able undo the move.
    #[inline(always)]
    pub fn move16(&self) -> u16 {
        self.0 as u16
    }

    /// Returns the algebraic notation of the move.
    ///
    /// Examples: `e2e4`, `e7e5`, `e1g1` (white short castling),
    /// `e7e8q` (for promotion).
    pub fn notation(&self) -> String {
        format!("{}{}{}",
                notation(self.orig_square()),
                notation(self.dest_square()),
                match self.move_type() {
                    MOVE_PROMOTION => ["q", "r", "b", "n"][self.aux_data()],
                    _ => "",
                })
    }

    /// Decodes the promoted piece type from the raw value of "aux
    /// data".
    #[inline]
    pub fn piece_from_aux_data(pp_code: usize) -> PieceType {
        assert!(pp_code <= 3);
        match pp_code {
            0 => QUEEN,
            1 => ROOK,
            2 => BISHOP,
            _ => KNIGHT,
        }
    }

    #[allow(dead_code)]
    #[inline]
    fn reserved(&self) -> usize {
        ((self.0 & M_MASK_RESERVED) >> M_SHIFT_RESERVED) as usize
    }
}

/// `MOVE_ENPASSANT`, `MOVE_PROMOTION`, `MOVE_CASTLING`, or
/// `MOVE_NORMAL`.
pub type MoveType = usize;

/// En-passant capture move type.
pub const MOVE_ENPASSANT: MoveType = 0;

/// Pawn promotion move type.
pub const MOVE_PROMOTION: MoveType = 1;

/// Castling move type.
pub const MOVE_CASTLING: MoveType = 2;

/// Normal move type.
pub const MOVE_NORMAL: MoveType = 3;

// Field shifts
const M_SHIFT_SCORE: u32 = 30;
const M_SHIFT_CAPTURED_PIECE: u32 = 27;
const M_SHIFT_RESERVED: u32 = 25;
const M_SHIFT_PIECE: u32 = 22;
const M_SHIFT_CASTLING_DATA: u32 = 20;
const M_SHIFT_ENPASSANT_FILE: u32 = 16;
const M_SHIFT_MOVE_TYPE: u32 = 14;
const M_SHIFT_ORIG_SQUARE: u32 = 8;
const M_SHIFT_DEST_SQUARE: u32 = 2;
const M_SHIFT_AUX_DATA: u32 = 0;

// Field masks
const M_MASK_SCORE: u32 = 0b11 << M_SHIFT_SCORE;
const M_MASK_CAPTURED_PIECE: u32 = 0b111 << M_SHIFT_CAPTURED_PIECE;
const M_MASK_RESERVED: u32 = 0b11 << M_SHIFT_RESERVED;
const M_MASK_PIECE: u32 = 0b111 << M_SHIFT_PIECE;
const M_MASK_CASTLING_DATA: u32 = 0b11 << M_SHIFT_CASTLING_DATA;
const M_MASK_ENPASSANT_FILE: u32 = 0b1111 << M_SHIFT_ENPASSANT_FILE;
const M_MASK_MOVE_TYPE: u32 = 0b11 << M_SHIFT_MOVE_TYPE;
const M_MASK_ORIG_SQUARE: u32 = 0b111111 << M_SHIFT_ORIG_SQUARE;
const M_MASK_DEST_SQUARE: u32 = 0b111111 << M_SHIFT_DEST_SQUARE;
const M_MASK_AUX_DATA: u32 = 0b11 << M_SHIFT_AUX_DATA;

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

    #[test]
    fn test_move() {
        use basetypes::*;
        const NO_ENPASSANT_FILE: File = 8;

        let mut cr = CastlingRights::new();
        cr.set_for(WHITE, 0b10);
        cr.set_for(BLACK, 0b11);
        let mut m = Move::new(WHITE,
                              2,
                              MOVE_NORMAL,
                              PAWN,
                              E2,
                              E4,
                              NO_PIECE,
                              NO_ENPASSANT_FILE,
                              cr,
                              0);
        let n1 = Move::new(WHITE,
                           2,
                           MOVE_NORMAL,
                           PAWN,
                           F3,
                           E4,
                           KNIGHT,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n2 = Move::new(WHITE,
                           2,
                           MOVE_NORMAL,
                           KING,
                           F3,
                           E4,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n3 = Move::new(BLACK,
                           0,
                           MOVE_PROMOTION,
                           PAWN,
                           F2,
                           F1,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           1);
        assert!(n1 > m);
        assert!(n2 < m);
        assert_eq!(m.score(), 2);
        assert_eq!(m.piece(), PAWN);
        assert_eq!(m.captured_piece(), NO_PIECE);
        assert_eq!(m.orig_square(), E2);
        assert_eq!(m.dest_square(), E4);
        assert_eq!(m.en_passant_file(), 8);
        assert_eq!(m.aux_data(), 0b10);
        assert_eq!(m.castling_data(), 0b11);
        let m2 = m;
        assert_eq!(m, m2);
        m.set_score(3);
        assert_eq!(m.score(), 3);
        assert!(m > m2);
        m.clear_score_bit(0);
        assert_eq!(m, m2);
        m.set_score_bit(0);
        assert_eq!(m.score(), 3);
        m.set_score(0);
        assert_eq!(m.score(), 0);
        assert_eq!(n3.aux_data(), 1);
        assert_eq!(n1.reserved(), 0);
        assert_eq!(n1.move16(), (n1.0 & 0xffff) as u16);
    }
}
<commit_msg>comment<commit_after>//! Defines what information a chess move should contain.

use basetypes::*;
use castling_rights::*;

/// Represents a move on the chessboard.
///
/// `Move` contains 3 types of information:
///
/// 1. Information about the played move itself.
///
/// 2. Information needed so as to be able to undo the move and
///    restore the board into the exact same state as before.
///
/// 3. The move score -- moves with higher score are tried
///    first. Ideally the best move should have the highest score.
///
/// `Move` is a 32-bit unsigned number. The lowest 16 bits contain the
/// whole needed information about the move itself (type 1). And is
/// laid out the following way:
///
///  ```text
///   15                                                           0
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  | Move  |    Origin square      |   Destination square  | Aux   |
///  | type  |       6 bits          |        6 bits         | data  |
///  | 2 bits|   |   |   |   |   |   |   |   |   |   |   |   | 2 bits|
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |       |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// There are 4 "move type"s: `0`) en-passant capture; `1`) pawn
/// promotion; `2`) castling; `3`) normal move. "Aux data" encodes the
/// type of the promoted piece if the move type is a pawn promotion,
/// otherwise it encodes castling rights (see below).
///
/// The highest 16 bits contain the rest ot the info:
///
///  ```text
///   31                                                          16
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  | Move  |  Captured | Reser-|  Played   | Cast- |   En-passant  |
///  | score |  piece    |  ved  |  piece    | ling  |      file     |
///  | 2 bits|  3 bits   | 2 bits|  3 bits   | 2 bits|     4 bits    |
///  |   |   |   |   |   |   |   |   |   |   |       |   |   |   |   |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// "En-passant file" tells on what vertical line on the board there
/// was a passing pawn before the move was played. If there was no
/// passing pawn, "en-passant file" should be `8`.
///
/// Castling rights are a bit complex. The castling rights for the side
/// that makes the move, before the move was made, are stored in the
/// "Aux data" field. This is OK, because promoting a pawn never
/// changes the moving player's castling rights. The castling rights
/// for the opposite side are stored in "Castling" field. (A move can
/// change the castling rights for the other side when a rook in the
/// corner is captured.)
///
/// When "Captured piece" is stored, its bits are inverted, so that
/// MVV-LVA (Most valuable victim -- least valuable aggressor)
/// ordering of the moves is preserved, even when the "Move score"
/// field stays the same. The "Reserved" field is used to make the
/// ordering for non-capturing moves more predictable.
#[derive(Debug)]
#[derive(Clone, Copy)]
#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub struct Move(u32);

impl Move {
    /// Creates a new instance of `Move`.
    ///
    /// `us` is the side that makes the move. `castling` are the
    /// castling rights before the move was played. `en_passant_file`
    /// is the file on which there were a passing pawn before the move
    /// was played (or `8` if there was no passing
    /// pawn). `promoted_piece_code` should be a number between `0`
    /// and `3` and is used only when the `move_type` is a pawn
    /// promotion, otherwise it is ignored.
    #[inline]
    pub fn new(us: Color,
               score: usize,
               move_type: MoveType,
               piece: PieceType,
               orig_square: Square,
               dest_square: Square,
               captured_piece: PieceType,
               en_passant_file: File,
               castling: CastlingRights,
               promoted_piece_code: usize)
               -> Move {
        assert!(us <= 1);
        assert!(score <= 0b11);
        assert!(move_type <= 0x11);
        assert!(piece < NO_PIECE);
        assert!(orig_square <= 63);
        assert!(dest_square <= 63);
        assert!(captured_piece != KING && captured_piece <= NO_PIECE);
        assert!(en_passant_file <= 0b1000);
        assert!(promoted_piece_code <= 0b11);

        // We use the reserved field (2 bits) to properly order
        // "quiet" movies. Moves which destination square is more
        // advanced into enemy's territory are tried first.
        let reserved = if captured_piece == NO_PIECE {
            let rank = rank(dest_square);
            let advance = if us == WHITE {
                rank
            } else {
                7 - rank
            };
            match advance {
                0 => 0,
                x if x < 3 => 1,
                x if x < 5 => 2,
                _ => 3,
            }
        } else {
            0
        };

        let aux_data = match move_type {
            MOVE_PROMOTION => promoted_piece_code,
            _ => castling.get_for(us),
        };
        Move((score << M_SHIFT_SCORE | (!captured_piece & 0b111) << M_SHIFT_CAPTURED_PIECE |
              reserved << M_SHIFT_RESERVED | piece << M_SHIFT_PIECE |
              castling.get_for(1 ^ us) << M_SHIFT_CASTLING_DATA |
              en_passant_file << M_SHIFT_ENPASSANT_FILE |
              move_type << M_SHIFT_MOVE_TYPE | orig_square << M_SHIFT_ORIG_SQUARE |
              dest_square << M_SHIFT_DEST_SQUARE |
              aux_data << M_SHIFT_AUX_DATA) as u32)
    }

    /// Sets the "move score" field to a particular value.
    #[inline]
    pub fn set_score(&mut self, score: usize) {
        assert!(score <= 0b11);
        self.0 &= !M_MASK_SCORE;
        self.0 |= (score << M_SHIFT_SCORE) as u32;
    }

    /// Sets a particular bit in the "move score" field to `1`.
    #[inline]
    pub fn set_score_bit(&mut self, b: usize) {
        assert!(b <= 1);
        self.0 |= 1 << b << M_SHIFT_SCORE;
    }

    /// Sets a particular bit in the "move score" field to `0`.
    #[inline]
    pub fn clear_score_bit(&mut self, b: usize) {
        assert!(b <= 1);
        self.0 &= !(1 << b << M_SHIFT_SCORE);
    }

    #[inline]
    pub fn score(&self) -> usize {
        ((self.0 & M_MASK_SCORE) >> M_SHIFT_SCORE) as usize
    }

    #[inline]
    pub fn move_type(&self) -> MoveType {
        ((self.0 & M_MASK_MOVE_TYPE) >> M_SHIFT_MOVE_TYPE) as MoveType
    }

    #[inline]
    pub fn piece(&self) -> PieceType {
        ((self.0 & M_MASK_PIECE) >> M_SHIFT_PIECE) as PieceType
    }

    #[inline]
    pub fn orig_square(&self) -> Square {
        ((self.0 & M_MASK_ORIG_SQUARE) >> M_SHIFT_ORIG_SQUARE) as Square
    }

    #[inline]
    pub fn dest_square(&self) -> Square {
        ((self.0 & M_MASK_DEST_SQUARE) >> M_SHIFT_DEST_SQUARE) as Square
    }

    #[inline]
    pub fn captured_piece(&self) -> PieceType {
        ((!self.0 & M_MASK_CAPTURED_PIECE) >> M_SHIFT_CAPTURED_PIECE) as PieceType
    }

    /// Returns the file on which there were a passing pawn before the
    /// move was played (or `8` if there was no passing pawn).
    #[inline]
    pub fn en_passant_file(&self) -> File {
        ((self.0 & M_MASK_ENPASSANT_FILE) >> M_SHIFT_ENPASSANT_FILE) as File
    }

    /// Returns a 2-bit value representing the castling rights for the
    /// side that does not make the move, as they were before the move
    /// was played.
    #[inline(always)]
    pub fn castling_data(&self) -> usize {
        ((self.0 & M_MASK_CASTLING_DATA) >> M_SHIFT_CASTLING_DATA) as usize
    }

    /// Returns 2-bit value representing auxiliary data.
    ///
    /// When the move type is pawn promotion, "aux data" holds the
    /// promoted piece type encoded with a value from 0 to 3. For all
    /// other move types "aux data" holds the castling rights for the
    /// side that makes the move, as they were before the move was
    /// played.
    #[inline(always)]
    pub fn aux_data(&self) -> usize {
        ((self.0 & M_MASK_AUX_DATA) >> M_SHIFT_AUX_DATA) as usize
    }

    /// Returns the least significant 16 bits of the raw move value.
    ///
    /// The returned value contains the whole information about the
    /// played move itself. The only missing information is the move
    /// ordering information and the information stored so as to be
    /// able undo the move.
    #[inline(always)]
    pub fn move16(&self) -> u16 {
        self.0 as u16
    }

    /// Returns the algebraic notation of the move.
    ///
    /// Examples: `e2e4`, `e7e5`, `e1g1` (white short castling),
    /// `e7e8q` (for promotion).
    pub fn notation(&self) -> String {
        format!("{}{}{}",
                notation(self.orig_square()),
                notation(self.dest_square()),
                match self.move_type() {
                    MOVE_PROMOTION => ["q", "r", "b", "n"][self.aux_data()],
                    _ => "",
                })
    }

    /// Decodes the promoted piece type from the raw value returned by
    /// `aux_data()`.
    #[inline]
    pub fn piece_from_aux_data(pp_code: usize) -> PieceType {
        assert!(pp_code <= 3);
        match pp_code {
            0 => QUEEN,
            1 => ROOK,
            2 => BISHOP,
            _ => KNIGHT,
        }
    }

    #[allow(dead_code)]
    #[inline]
    fn reserved(&self) -> usize {
        ((self.0 & M_MASK_RESERVED) >> M_SHIFT_RESERVED) as usize
    }
}

/// `MOVE_ENPASSANT`, `MOVE_PROMOTION`, `MOVE_CASTLING`, or
/// `MOVE_NORMAL`.
pub type MoveType = usize;

/// En-passant capture move type.
pub const MOVE_ENPASSANT: MoveType = 0;

/// Pawn promotion move type.
pub const MOVE_PROMOTION: MoveType = 1;

/// Castling move type.
pub const MOVE_CASTLING: MoveType = 2;

/// Normal move type.
pub const MOVE_NORMAL: MoveType = 3;

// Field shifts
const M_SHIFT_SCORE: u32 = 30;
const M_SHIFT_CAPTURED_PIECE: u32 = 27;
const M_SHIFT_RESERVED: u32 = 25;
const M_SHIFT_PIECE: u32 = 22;
const M_SHIFT_CASTLING_DATA: u32 = 20;
const M_SHIFT_ENPASSANT_FILE: u32 = 16;
const M_SHIFT_MOVE_TYPE: u32 = 14;
const M_SHIFT_ORIG_SQUARE: u32 = 8;
const M_SHIFT_DEST_SQUARE: u32 = 2;
const M_SHIFT_AUX_DATA: u32 = 0;

// Field masks
const M_MASK_SCORE: u32 = 0b11 << M_SHIFT_SCORE;
const M_MASK_CAPTURED_PIECE: u32 = 0b111 << M_SHIFT_CAPTURED_PIECE;
const M_MASK_RESERVED: u32 = 0b11 << M_SHIFT_RESERVED;
const M_MASK_PIECE: u32 = 0b111 << M_SHIFT_PIECE;
const M_MASK_CASTLING_DATA: u32 = 0b11 << M_SHIFT_CASTLING_DATA;
const M_MASK_ENPASSANT_FILE: u32 = 0b1111 << M_SHIFT_ENPASSANT_FILE;
const M_MASK_MOVE_TYPE: u32 = 0b11 << M_SHIFT_MOVE_TYPE;
const M_MASK_ORIG_SQUARE: u32 = 0b111111 << M_SHIFT_ORIG_SQUARE;
const M_MASK_DEST_SQUARE: u32 = 0b111111 << M_SHIFT_DEST_SQUARE;
const M_MASK_AUX_DATA: u32 = 0b11 << M_SHIFT_AUX_DATA;

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

    #[test]
    fn test_move() {
        use basetypes::*;
        const NO_ENPASSANT_FILE: File = 8;

        let mut cr = CastlingRights::new();
        cr.set_for(WHITE, 0b10);
        cr.set_for(BLACK, 0b11);
        let mut m = Move::new(WHITE,
                              2,
                              MOVE_NORMAL,
                              PAWN,
                              E2,
                              E4,
                              NO_PIECE,
                              NO_ENPASSANT_FILE,
                              cr,
                              0);
        let n1 = Move::new(WHITE,
                           2,
                           MOVE_NORMAL,
                           PAWN,
                           F3,
                           E4,
                           KNIGHT,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n2 = Move::new(WHITE,
                           2,
                           MOVE_NORMAL,
                           KING,
                           F3,
                           E4,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n3 = Move::new(BLACK,
                           0,
                           MOVE_PROMOTION,
                           PAWN,
                           F2,
                           F1,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           1);
        assert!(n1 > m);
        assert!(n2 < m);
        assert_eq!(m.score(), 2);
        assert_eq!(m.piece(), PAWN);
        assert_eq!(m.captured_piece(), NO_PIECE);
        assert_eq!(m.orig_square(), E2);
        assert_eq!(m.dest_square(), E4);
        assert_eq!(m.en_passant_file(), 8);
        assert_eq!(m.aux_data(), 0b10);
        assert_eq!(m.castling_data(), 0b11);
        let m2 = m;
        assert_eq!(m, m2);
        m.set_score(3);
        assert_eq!(m.score(), 3);
        assert!(m > m2);
        m.clear_score_bit(0);
        assert_eq!(m, m2);
        m.set_score_bit(0);
        assert_eq!(m.score(), 3);
        m.set_score(0);
        assert_eq!(m.score(), 0);
        assert_eq!(n3.aux_data(), 1);
        assert_eq!(n1.reserved(), 0);
        assert_eq!(n1.move16(), (n1.0 & 0xffff) as u16);
    }
}
<|endoftext|>


<commit_before>#[macro_use(dbg)]
extern crate cretonne;
extern crate cton_reader;
extern crate cretonne_wasm;
extern crate docopt;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate filecheck;
extern crate num_cpus;
extern crate tempdir;
extern crate term;

use cretonne::VERSION;
use docopt::Docopt;
use std::io::{self, Write};
use std::process;

mod utils;
mod filetest;
mod cat;
mod print_cfg;
mod rsfilecheck;
mod wasm;

const USAGE: &str = "
Cretonne code generator utility

Usage:
    cton-util test [-v] <file>...
    cton-util cat <file>...
    cton-util filecheck [-v] <file>
    cton-util print-cfg <file>...
    cton-util wasm [-cvo] <file>...
    cton-util --help | --version

Options:
    -v, --verbose   be more verbose
    -c, --check     checks the correctness of Cretonne IL translated from WebAssembly
    -o, --optimize  runs otpimization passes on translated WebAssembly functions
    -h, --help      print this help message
    --version       print the Cretonne version

";

#[derive(Deserialize, Debug)]
struct Args {
    cmd_test: bool,
    cmd_cat: bool,
    cmd_filecheck: bool,
    cmd_print_cfg: bool,
    cmd_wasm: bool,
    arg_file: Vec<String>,
    flag_check: bool,
    flag_optimize: bool,
    flag_verbose: bool,
}

/// A command either succeeds or fails with an error message.
pub type CommandResult = Result<(), String>;

/// Parse the command line arguments and run the requested command.
fn cton_util() -> CommandResult {
    // Parse command line arguments.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| {
            d.help(true)
                .version(Some(format!("Cretonne {}", VERSION)))
                .deserialize()
        })
        .unwrap_or_else(|e| e.exit());

    // Find the sub-command to execute.
    if args.cmd_test {
        filetest::run(args.flag_verbose, args.arg_file)
    } else if args.cmd_cat {
        cat::run(args.arg_file)
    } else if args.cmd_filecheck {
        rsfilecheck::run(args.arg_file, args.flag_verbose)
    } else if args.cmd_print_cfg {
        print_cfg::run(args.arg_file)
    } else if args.cmd_wasm {
        wasm::run(
            args.arg_file,
            args.flag_verbose,
            args.flag_optimize,
            args.flag_check,
        )
    } else {
        // Debugging / shouldn't happen with proper command line handling above.
        Err(format!("Unhandled args: {:?}", args))
    }
}

fn main() {
    if let Err(mut msg) = cton_util() {
        if !msg.ends_with('\n') {
            msg.push('\n');
        }
        io::stderr().write(msg.as_bytes()).unwrap();
        process::exit(1);
    }
}
<commit_msg>Remove an unneeded extern crate.<commit_after>#[macro_use(dbg)]
extern crate cretonne;
extern crate cton_reader;
extern crate cretonne_wasm;
extern crate docopt;
#[macro_use]
extern crate serde_derive;
extern crate filecheck;
extern crate num_cpus;
extern crate tempdir;
extern crate term;

use cretonne::VERSION;
use docopt::Docopt;
use std::io::{self, Write};
use std::process;

mod utils;
mod filetest;
mod cat;
mod print_cfg;
mod rsfilecheck;
mod wasm;

const USAGE: &str = "
Cretonne code generator utility

Usage:
    cton-util test [-v] <file>...
    cton-util cat <file>...
    cton-util filecheck [-v] <file>
    cton-util print-cfg <file>...
    cton-util wasm [-cvo] <file>...
    cton-util --help | --version

Options:
    -v, --verbose   be more verbose
    -c, --check     checks the correctness of Cretonne IL translated from WebAssembly
    -o, --optimize  runs otpimization passes on translated WebAssembly functions
    -h, --help      print this help message
    --version       print the Cretonne version

";

#[derive(Deserialize, Debug)]
struct Args {
    cmd_test: bool,
    cmd_cat: bool,
    cmd_filecheck: bool,
    cmd_print_cfg: bool,
    cmd_wasm: bool,
    arg_file: Vec<String>,
    flag_check: bool,
    flag_optimize: bool,
    flag_verbose: bool,
}

/// A command either succeeds or fails with an error message.
pub type CommandResult = Result<(), String>;

/// Parse the command line arguments and run the requested command.
fn cton_util() -> CommandResult {
    // Parse command line arguments.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| {
            d.help(true)
                .version(Some(format!("Cretonne {}", VERSION)))
                .deserialize()
        })
        .unwrap_or_else(|e| e.exit());

    // Find the sub-command to execute.
    if args.cmd_test {
        filetest::run(args.flag_verbose, args.arg_file)
    } else if args.cmd_cat {
        cat::run(args.arg_file)
    } else if args.cmd_filecheck {
        rsfilecheck::run(args.arg_file, args.flag_verbose)
    } else if args.cmd_print_cfg {
        print_cfg::run(args.arg_file)
    } else if args.cmd_wasm {
        wasm::run(
            args.arg_file,
            args.flag_verbose,
            args.flag_optimize,
            args.flag_check,
        )
    } else {
        // Debugging / shouldn't happen with proper command line handling above.
        Err(format!("Unhandled args: {:?}", args))
    }
}

fn main() {
    if let Err(mut msg) = cton_util() {
        if !msg.ends_with('\n') {
            msg.push('\n');
        }
        io::stderr().write(msg.as_bytes()).unwrap();
        process::exit(1);
    }
}
<|endoftext|>


<commit_before>//! Data for tracking user information.
use std::str::FromStr;

/// IRC User data.
#[deriving(Clone, Show)]
pub struct User {
    /// The user's nickname.
    name: String,
    /// The user's access level.
    /// For simplicity, this is not used to determine the equality of two users.
    /// That is a user is equal if and only if their nickname is the same.
    access_level: AccessLevel,
}

impl User {
    /// Creates a new User.
    pub fn new(name: &str) -> User {
        let rank = from_str(name);
        User {
            name: if let Some(AccessLevel::Member) = rank {
                name.into_string()
            } else {
                name[1..].into_string()
            },
            access_level: rank.unwrap(),
        }
    }

    /// Gets the nickname of the user.
    pub fn get_name(&self) -> &str {
        self.name[]
    }

    /// Gets the user's access level.
    pub fn access_level(&self) -> AccessLevel {
        self.access_level
    }

    /// Updates the user's access level.
    pub fn update_access_level(&mut self, mode: &str) {
        self.access_level = match mode {
            "+q" => AccessLevel::Owner,
            "-q" => AccessLevel::Member,
            "+a" => AccessLevel::Admin,
            "-a" => AccessLevel::Member,
            "+o" => AccessLevel::Oper,
            "-o" => AccessLevel::Member,
            "+h" => AccessLevel::HalfOp,
            "-h" => AccessLevel::Member,
            "+v" => AccessLevel::Voice,
            "-v" => AccessLevel::Member,
            _ => self.access_level,
        }
    }
}

impl PartialEq for User {
    fn eq(&self, other: &User) -> bool {
        self.name == other.name
    }
}

/// The user's access level.
#[deriving(PartialEq, Clone, Show)]
pub enum AccessLevel {
    /// The channel owner (~).
    Owner,
    /// A channel administrator (&).
    Admin,
    /// A channel operator (@),
    Oper,
    /// A channel half-oper (%),
    HalfOp,
    /// A user with voice (+),
    Voice,
    /// A normal user,
    Member,
}

impl FromStr for AccessLevel {
    fn from_str(s: &str) -> Option<AccessLevel> {
        if s.len() == 0 { Some(AccessLevel::Member) } else {
            Some(match s.char_at(0) {
                '~' => AccessLevel::Owner,
                '&' => AccessLevel::Admin,
                '@' => AccessLevel::Oper,
                '%' => AccessLevel::HalfOp,
                '+' => AccessLevel::Voice,
                 _  => AccessLevel::Member,
            })
        }
    }
}

#[cfg(test)]
mod test {
    use super::{AccessLevel, User};
    use super::AccessLevel::{Admin, HalfOp, Member, Oper, Owner, Voice};

    #[test]
    fn access_level_from_str() {
        assert_eq!(from_str::<AccessLevel>("member").unwrap(), Member);
        assert_eq!(from_str::<AccessLevel>("~owner").unwrap(), Owner);
        assert_eq!(from_str::<AccessLevel>("&admin").unwrap(), Admin);
        assert_eq!(from_str::<AccessLevel>("@oper").unwrap(), Oper);
        assert_eq!(from_str::<AccessLevel>("%halfop").unwrap(), HalfOp);
        assert_eq!(from_str::<AccessLevel>("+voice").unwrap(), Voice);
        assert_eq!(from_str::<AccessLevel>("").unwrap(), Member);
    }

    #[test]
    fn create_user() {
        let user = User::new("~owner");
        let exp = User {
            name: format!("owner"),
            access_level: Owner,
        };
        assert_eq!(user, exp);
        assert_eq!(user.access_level, exp.access_level);
    }

    #[test]
    fn update_user_rank() {
        let mut user = User::new("user");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+q");
        assert_eq!(user.access_level, Owner);
        user.update_access_level("-q");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+a");
        assert_eq!(user.access_level, Admin);
        user.update_access_level("-a");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+o");
        assert_eq!(user.access_level, Oper);
        user.update_access_level("-o");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+h");
        assert_eq!(user.access_level, HalfOp);
        user.update_access_level("-h");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+v");
        assert_eq!(user.access_level, Voice);
        user.update_access_level("-v");
        assert_eq!(user.access_level, Member);
    }
}
<commit_msg>Added extra unit tests to User.<commit_after>//! Data for tracking user information.
use std::str::FromStr;

/// IRC User data.
#[deriving(Clone, Show)]
pub struct User {
    /// The user's nickname.
    name: String,
    /// The user's access level.
    /// For simplicity, this is not used to determine the equality of two users.
    /// That is a user is equal if and only if their nickname is the same.
    access_level: AccessLevel,
}

impl User {
    /// Creates a new User.
    pub fn new(name: &str) -> User {
        let rank = from_str(name);
        User {
            name: if let Some(AccessLevel::Member) = rank {
                name.into_string()
            } else {
                name[1..].into_string()
            },
            access_level: rank.unwrap(),
        }
    }

    /// Gets the nickname of the user.
    pub fn get_name(&self) -> &str {
        self.name[]
    }

    /// Gets the user's access level.
    pub fn access_level(&self) -> AccessLevel {
        self.access_level
    }

    /// Updates the user's access level.
    pub fn update_access_level(&mut self, mode: &str) {
        self.access_level = match mode {
            "+q" => AccessLevel::Owner,
            "-q" => AccessLevel::Member,
            "+a" => AccessLevel::Admin,
            "-a" => AccessLevel::Member,
            "+o" => AccessLevel::Oper,
            "-o" => AccessLevel::Member,
            "+h" => AccessLevel::HalfOp,
            "-h" => AccessLevel::Member,
            "+v" => AccessLevel::Voice,
            "-v" => AccessLevel::Member,
            _ => self.access_level,
        }
    }
}

impl PartialEq for User {
    fn eq(&self, other: &User) -> bool {
        self.name == other.name
    }
}

/// The user's access level.
#[deriving(PartialEq, Clone, Show)]
pub enum AccessLevel {
    /// The channel owner (~).
    Owner,
    /// A channel administrator (&).
    Admin,
    /// A channel operator (@),
    Oper,
    /// A channel half-oper (%),
    HalfOp,
    /// A user with voice (+),
    Voice,
    /// A normal user,
    Member,
}

impl FromStr for AccessLevel {
    fn from_str(s: &str) -> Option<AccessLevel> {
        if s.len() == 0 { Some(AccessLevel::Member) } else {
            Some(match s.char_at(0) {
                '~' => AccessLevel::Owner,
                '&' => AccessLevel::Admin,
                '@' => AccessLevel::Oper,
                '%' => AccessLevel::HalfOp,
                '+' => AccessLevel::Voice,
                 _  => AccessLevel::Member,
            })
        }
    }
}

#[cfg(test)]
mod test {
    use super::{AccessLevel, User};
    use super::AccessLevel::{Admin, HalfOp, Member, Oper, Owner, Voice};

    #[test]
    fn access_level_from_str() {
        assert_eq!(from_str::<AccessLevel>("member").unwrap(), Member);
        assert_eq!(from_str::<AccessLevel>("~owner").unwrap(), Owner);
        assert_eq!(from_str::<AccessLevel>("&admin").unwrap(), Admin);
        assert_eq!(from_str::<AccessLevel>("@oper").unwrap(), Oper);
        assert_eq!(from_str::<AccessLevel>("%halfop").unwrap(), HalfOp);
        assert_eq!(from_str::<AccessLevel>("+voice").unwrap(), Voice);
        assert_eq!(from_str::<AccessLevel>("").unwrap(), Member);
    }

    #[test]
    fn create_user() {
        let user = User::new("~owner");
        let exp = User {
            name: format!("owner"),
            access_level: Owner,
        };
        assert_eq!(user, exp);
        assert_eq!(user.access_level, exp.access_level);
    }

    #[test]
    fn get_name() {
        let user = User::new("~owner");
        assert_eq!(user.get_name(), "owner");
    }

    #[test]
    fn access_level() {
        let user = User::new("~owner");
        assert_eq!(user.access_level(), Owner);
    }

    #[test]
    fn update_user_rank() {
        let mut user = User::new("user");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+q");
        assert_eq!(user.access_level, Owner);
        user.update_access_level("-q");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+a");
        assert_eq!(user.access_level, Admin);
        user.update_access_level("-a");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+o");
        assert_eq!(user.access_level, Oper);
        user.update_access_level("-o");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+h");
        assert_eq!(user.access_level, HalfOp);
        user.update_access_level("-h");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+v");
        assert_eq!(user.access_level, Voice);
        user.update_access_level("-v");
        assert_eq!(user.access_level, Member);
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Ilkka Rauta
//
// 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.

#[allow(dead_code,non_camel_case_types,non_snake_case)]
mod ffi;

use std::path::Path;
use libc::{c_uint,c_ulong};

#[allow(dead_code,non_camel_case_types,non_snake_case)]
mod enums {
    use super::ffi as ffi;

    include!(concat!(env!("OUT_DIR"), "/demux-enums.rs"));
}

pub use self::enums::{Input,Output,PesType};

pub struct Demux {
    device: DeviceFileDescriptor
}

use super::device::{DeviceFileDescriptor,BlockMode,ReadWriteMode,DeviceResult};

impl Demux {
    pub fn open(file: &Path, rw_mode: ReadWriteMode, block_mode: BlockMode) -> DeviceResult<Demux> {
        let device = try!(DeviceFileDescriptor::open(file, rw_mode, block_mode));
        Ok(Demux { device: device })
    }

    pub fn read(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    // Should this even exist here?
    pub fn write(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn start(&self) -> DeviceResult<()> {
        self.device.ioctl_argumentless(ffi::DMX_START as c_ulong)
    }

    pub fn stop(&self) -> DeviceResult<()> {
        self.device.ioctl_argumentless(ffi::DMX_STOP as c_ulong)
    }

    pub fn set_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_pes_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_buffer_size(&self, buffer_size: u32) -> DeviceResult<()> {
        let mut ffi_size = buffer_size as c_ulong;
        self.device.ioctl_pointer(ffi::DMX_SET_BUFFER_SIZE as c_ulong, &mut ffi_size)
    }

    pub fn get_system_time_counter(&self, num: u32) -> DeviceResult<SystemTimeCounter> {
        let mut ffi_stc = ffi::Struct_dmx_stc { num: num as c_uint, base: 0, stc: 0 };
        try!(self.device.ioctl_pointer(ffi::DMX_GET_STC as c_ulong, &mut ffi_stc));
        Ok(SystemTimeCounter { base: ffi_stc.base, counter: ffi_stc.stc })
    }

    pub fn get_pes_pids(&self) -> DeviceResult<[u16; 5]> {
        let mut ffi_pids = [0u16; 5];
        try!(self.device.ioctl_pointer(ffi::DMX_GET_PES_PIDS as c_ulong, ffi_pids.as_mut_ptr()));
        Ok(ffi_pids)
    }

    /// This function is undocumented in the official, and doesn't seem to be actually in use.
    /// It is still nevertheless included here, if it is used by out-of-tree DVB drivers.
    pub fn get_caps(&self) -> DeviceResult<DemuxCaps> {
        let mut ffi_caps = ffi::Struct_dmx_caps { caps: 0, num_decoders: 0 };
        try!(self.device.ioctl_pointer(ffi::DMX_GET_CAPS as c_ulong, &mut ffi_caps));
        Ok(DemuxCaps { caps: ffi_caps.caps, num_decoders: ffi_caps.num_decoders as i32 })
    }

    pub fn set_source(&self, source: enums::DemuxSource) -> DeviceResult<()> {
        let mut ffi_source: ffi::dmx_source_t =  source.into();
        self.device.ioctl_pointer(ffi::DMX_SET_SOURCE as c_ulong, &mut ffi_source)
    }

    pub fn add_pid(&self, pid: u16) -> DeviceResult<()> {
        let mut ffi_pid = pid;
        self.device.ioctl_pointer(ffi::DMX_ADD_PID as c_ulong, &mut ffi_pid)
    }

    pub fn remove_pid(&self, pid: u16) -> DeviceResult<()> {
        let mut ffi_pid = pid;
        self.device.ioctl_pointer(ffi::DMX_REMOVE_PID as c_ulong, &mut ffi_pid)
    }
}

pub struct DemuxCaps {
    pub caps: u32,
    pub num_decoders: i32
}

pub struct SystemTimeCounter {
    pub base: u32,
    pub counter: u64
}

pub struct DemuxFilter {
    pub filter: [u8; ffi::DMX_FILTER_SIZE as usize],
    pub mask: [u8; ffi::DMX_FILTER_SIZE as usize],
    pub mode: [u8; ffi::DMX_FILTER_SIZE as usize],
}

pub struct SectionFilterParams {
    pub pid: u16,
    pub filter: DemuxFilter,
    pub timeout: u32,
    // pub flags: flags::SectionFilterFlags
}

pub struct PesFilterParams {
    pub pid: u16,
    pub input: Input,
    pub output: Output,
    pub pes_type: PesType,
    pub flags: u32
}<commit_msg>Comment functions not implemented in kernel(?).<commit_after>// Copyright 2015 Ilkka Rauta
//
// 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.

#[allow(dead_code,non_camel_case_types,non_snake_case)]
mod ffi;

use std::path::Path;
use libc::{c_uint,c_ulong};

#[allow(dead_code,non_camel_case_types,non_snake_case)]
mod enums {
    use super::ffi as ffi;

    include!(concat!(env!("OUT_DIR"), "/demux-enums.rs"));
}

pub use self::enums::{Input,Output,PesType};

pub struct Demux {
    device: DeviceFileDescriptor
}

use super::device::{DeviceFileDescriptor,BlockMode,ReadWriteMode,DeviceResult};

impl Demux {
    pub fn open(file: &Path, rw_mode: ReadWriteMode, block_mode: BlockMode) -> DeviceResult<Demux> {
        let device = try!(DeviceFileDescriptor::open(file, rw_mode, block_mode));
        Ok(Demux { device: device })
    }

    pub fn read(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    // Should this even exist here?
    pub fn write(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn start(&self) -> DeviceResult<()> {
        self.device.ioctl_argumentless(ffi::DMX_START as c_ulong)
    }

    pub fn stop(&self) -> DeviceResult<()> {
        self.device.ioctl_argumentless(ffi::DMX_STOP as c_ulong)
    }

    pub fn set_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_pes_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_buffer_size(&self, buffer_size: u32) -> DeviceResult<()> {
        let mut ffi_size = buffer_size as c_ulong;
        self.device.ioctl_pointer(ffi::DMX_SET_BUFFER_SIZE as c_ulong, &mut ffi_size)
    }

    pub fn get_system_time_counter(&self, num: u32) -> DeviceResult<SystemTimeCounter> {
        let mut ffi_stc = ffi::Struct_dmx_stc { num: num as c_uint, base: 0, stc: 0 };
        try!(self.device.ioctl_pointer(ffi::DMX_GET_STC as c_ulong, &mut ffi_stc));
        Ok(SystemTimeCounter { base: ffi_stc.base, counter: ffi_stc.stc })
    }

    pub fn get_pes_pids(&self) -> DeviceResult<[u16; 5]> {
        let mut ffi_pids = [0u16; 5];
        try!(self.device.ioctl_pointer(ffi::DMX_GET_PES_PIDS as c_ulong, ffi_pids.as_mut_ptr()));
        Ok(ffi_pids)
    }

    /// This function is undocumented in the official documentation, and doesn't seem to be
    /// actually in use. It is still nevertheless included here, if it is used by out-of-tree DVB
    /// drivers.
    pub fn get_caps(&self) -> DeviceResult<DemuxCaps> {
        let mut ffi_caps = ffi::Struct_dmx_caps { caps: 0, num_decoders: 0 };
        try!(self.device.ioctl_pointer(ffi::DMX_GET_CAPS as c_ulong, &mut ffi_caps));
        Ok(DemuxCaps { caps: ffi_caps.caps, num_decoders: ffi_caps.num_decoders as i32 })
    }

    /// Like get_caps(), this doesn't seem to be actively in use in Linux, but is still implemented.
    pub fn set_source(&self, source: enums::DemuxSource) -> DeviceResult<()> {
        let mut ffi_source: ffi::dmx_source_t =  source.into();
        self.device.ioctl_pointer(ffi::DMX_SET_SOURCE as c_ulong, &mut ffi_source)
    }

    pub fn add_pid(&self, pid: u16) -> DeviceResult<()> {
        let mut ffi_pid = pid;
        self.device.ioctl_pointer(ffi::DMX_ADD_PID as c_ulong, &mut ffi_pid)
    }

    pub fn remove_pid(&self, pid: u16) -> DeviceResult<()> {
        let mut ffi_pid = pid;
        self.device.ioctl_pointer(ffi::DMX_REMOVE_PID as c_ulong, &mut ffi_pid)
    }
}

pub struct DemuxCaps {
    pub caps: u32,
    pub num_decoders: i32
}

pub struct SystemTimeCounter {
    pub base: u32,
    pub counter: u64
}

pub struct DemuxFilter {
    pub filter: [u8; ffi::DMX_FILTER_SIZE as usize],
    pub mask: [u8; ffi::DMX_FILTER_SIZE as usize],
    pub mode: [u8; ffi::DMX_FILTER_SIZE as usize],
}

pub struct SectionFilterParams {
    pub pid: u16,
    pub filter: DemuxFilter,
    pub timeout: u32,
    // pub flags: flags::SectionFilterFlags
}

pub struct PesFilterParams {
    pub pid: u16,
    pub input: Input,
    pub output: Output,
    pub pes_type: PesType,
    pub flags: u32
}<|endoftext|>


<commit_before>use nom::{Err, IResult, Needed};

use std::io;
use std::io::Read;
use std::ptr;
use std::cmp;

use super::StreamProducer;

#[derive(Debug)]
pub enum ErrorKind {
  IO(io::Error),
  Incomplete(usize),
  Consumed(usize),
  EndOfInput,
  Unknown,
}

// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        if let Err::Position(_, i) = e {
          let consumed = self.len() - i.len();

          self.offset += consumed;

          Err(ErrorKind::Consumed(consumed))
        } else {
          Err(ErrorKind::Unknown)
        }
      }
    }
  }
}

pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity();

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      if let Err::Position(_, i) = e {
        Err(ErrorKind::Consumed(buffer.len() - i.len()))
      } else {
        Err(ErrorKind::Unknown)
      }
    }
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(ErrorKind::IO));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        match kind {
          ErrorKind::Incomplete(needed) => self.needed = needed,
          ErrorKind::Consumed(consumed) => buffer.consume(consumed),
          _                             => (),
        }

        Err(kind)
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::be_u32;

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<commit_msg>Add documentation for `ReadStream`<commit_after>use nom::{Err, IResult, Needed};

use std::io;
use std::io::Read;
use std::ptr;
use std::cmp;

use super::StreamProducer;

#[derive(Debug)]
pub enum ErrorKind {
  IO(io::Error),
  Incomplete(usize),
  Consumed(usize),
  EndOfInput,
  Unknown,
}

// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        if let Err::Position(_, i) = e {
          let consumed = self.len() - i.len();

          self.offset += consumed;

          Err(ErrorKind::Consumed(consumed))
        } else {
          Err(ErrorKind::Unknown)
        }
      }
    }
  }
}

pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

// Structure that hold a reader for a source of bytes.
pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity();

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      if let Err::Position(_, i) = e {
        Err(ErrorKind::Consumed(buffer.len() - i.len()))
      } else {
        Err(ErrorKind::Unknown)
      }
    }
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(ErrorKind::IO));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        match kind {
          ErrorKind::Incomplete(needed) => self.needed = needed,
          ErrorKind::Consumed(consumed) => buffer.consume(consumed),
          _                             => (),
        }

        Err(kind)
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::be_u32;

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<|endoftext|>