<commit_before>
use std::marker::PhantomData;
use std::default::Default;
use std::ops::{AddAssign, MulAssign};
use std::convert::TryInto;

use num::BigUint;

use Construct;
use Count;
use Data;
use Of;
use ToPos;
use ToIndex;
use Zero;

/// Dimension is natural number, position is a list of numbers.
pub struct Permutation<T = Data>(PhantomData<T>);

impl<T> Construct for Permutation<T> {
    fn new() -> Permutation<T> {
        Permutation(PhantomData)
    }
}

impl Count<usize> for Permutation<Data> {
    type N = usize;
    fn count(&self, dim: &usize) -> usize {
        let mut res = 1;
        for x in 1..dim + 1 {
            res *= x;
        }
        res
    }
}

impl Count<BigUint> for Permutation<Data> {
    type N = BigUint;
    fn count(&self, dim: &BigUint) -> BigUint {
        let _1: BigUint = 1usize.into();
        let mut res: BigUint = _1.clone();
        let mut x = _1.clone();
        loop {
            if &x > dim {break}
            res *= &x;
            x += &_1;
        }
        res
    }
}

impl<T, U> Count<U> for Permutation<Of<T>>
    where
        T: Construct + Count<U>,
        for<'a> <T as Count<U>>::N: From<usize> + Clone + Ord +
            AddAssign<&'a <T as Count<U>>::N> +
            MulAssign<&'a <T as Count<U>>::N>
{
    type N = <T as Count<U>>::N;
    fn count(&self, dim: &U) -> Self::N {
        let of: T = Construct::new();
        let _1: Self::N = 1usize.into();
        let mut x = _1.clone();
        let mut res = _1.clone();
        let of_count = of.count(dim);
        loop {
            if &x > &of_count {break}
            res *= &x;
            x += &_1;
        }
        res
    }
}

impl Zero<usize, Vec<usize>> for Permutation<Data> {
    fn zero(&self, dim: &usize) -> Vec<usize> {
        vec![0; *dim]
    }
}

impl Zero<BigUint, Vec<BigUint>> for Permutation<Data> {
    fn zero(&self, dim: &BigUint) -> Vec<BigUint> {
        let dim: usize = dim.try_into().unwrap();
        vec![0usize.into(); dim]
    }
}

impl<T, U, V> Zero<U, Vec<V>> for Permutation<Of<T>>
    where
        T: Construct + Count<U> + Zero<U, V>,
        <T as Count<U>>::N: TryInto<usize>,
        V: Clone
{
    fn zero(&self, dim: &U) -> Vec<V> {
        let of: T = Construct::new();
        let count = match of.count(dim).try_into() {
            Ok(x) => x,
            Err(_) => panic!("Out of range"),
        };
        vec![of.zero(dim); count]
    }
}

impl ToIndex<usize, Vec<usize>> for Permutation<Data> {
    fn to_index(&self, dim: &usize, pos: &Vec<usize>) -> usize {
        let mut index = 0;
        let mut count = 1;
        for (i, &x) in pos.iter().enumerate().rev() {
            let lower = pos[..i].iter().filter(|&&y| y < x).count();
            index += count * (x - lower);
            count *= dim - i;
        }
        index
    }
}

impl<T, U, V> ToIndex<U, Vec<V>> for Permutation<Of<T>>
    where
        T: Construct + ToIndex<U, V> + Count<U, N = usize>,
        V: Clone
{
    fn to_index(&self, dim: &U, pos: &Vec<V>) -> usize {
        let of: T = Construct::new();
        let mut index = 0;
        let dim_count = of.count(dim);
        let mut count = 1;
        for (i, x) in pos.iter()
            .map(|x| of.to_index(dim, x))
            .enumerate().rev() {
            let lower = pos[..i].iter()
                .map(|y| of.to_index(dim, y))
                .filter(|&y| y < x).count();
            index += count * (x - lower);
            count *= dim_count - i;
        }
        index
    }
}

impl ToPos<usize, Vec<usize>> for Permutation<Data> {
    fn to_pos(&self, dim: &usize, mut index: usize, pos: &mut Vec<usize>) {
        unsafe { pos.set_len(0); }

        let mut count = 1;
        for (j, x) in (1..dim + 1).enumerate() {
            count *= x;
            pos.push(j);
        }

        for i in 0..*dim {
            let block = count / (dim - i);
            let ind = index / block;
            let item = pos.remove(ind);
            pos.push(item);
            count /= dim - i;
            index -= ind * block;
        }
    }
}

impl<T, U, V> ToPos<U, Vec<V>> for Permutation<Of<T>>
    where
        T: Construct + Count<U, N = usize> + ToPos<U, V> + Zero<U, V>
{
    fn to_pos(&self, dim: &U, mut index: usize, pos: &mut Vec<V>) {
        let of: T = Construct::new();
        let of_count = of.count(dim);
        pos.clear();

        let mut count = 1;
        for (j, x) in (1..of_count + 1).enumerate() {
            count *= x;
            let mut new_pos: V = of.zero(&dim);
            of.to_pos(dim, j, &mut new_pos);
            pos.push(new_pos);
        }

        for i in 0..of_count {
            let block = count / (of_count - i);
            let ind = index / block;
            let item = pos.remove(ind);
            pos.push(item);
            count /= of_count - i;
            index -= ind * block;
        }
    }
}

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

    #[test]
    fn features() {
        is_complete::<Permutation, usize, Vec<usize>>();
        is_complete::<Permutation<Of<Pair>>, usize, Vec<(usize, usize)>>();
    }

    #[test]
    fn data() {
        let permutation: Permutation = Construct::new();
        assert_eq!(permutation.count(&1), 1);
        assert_eq!(permutation.count(&2), 2);
        assert_eq!(permutation.count(&3), 6);
        assert_eq!(permutation.count(&4), 24);

        let mut pos = Vec::new();
        let ref dim = 4;
        let count = permutation.count(dim);
        for i in 0..count {
            permutation.to_pos(dim, i, &mut pos);
            let index = permutation.to_index(dim, &pos);
            assert_eq!(index, i);
        }
    }

    #[test]
    fn of() {
        let space: Permutation<Of<Pair>> = Construct::new();
        let ref dim = 3;
        let count = space.count(dim);
        let mut pos = Vec::new();
        for i in 0..count {
            space.to_pos(dim, i, &mut pos);
            let index = space.to_index(dim, &pos);
            assert_eq!(index, i);
        }
    }
}
<commit_msg>Removed unused import<commit_after>
use std::marker::PhantomData;
use std::ops::{AddAssign, MulAssign};
use std::convert::TryInto;

use num::BigUint;

use Construct;
use Count;
use Data;
use Of;
use ToPos;
use ToIndex;
use Zero;

/// Dimension is natural number, position is a list of numbers.
pub struct Permutation<T = Data>(PhantomData<T>);

impl<T> Construct for Permutation<T> {
    fn new() -> Permutation<T> {
        Permutation(PhantomData)
    }
}

impl Count<usize> for Permutation<Data> {
    type N = usize;
    fn count(&self, dim: &usize) -> usize {
        let mut res = 1;
        for x in 1..dim + 1 {
            res *= x;
        }
        res
    }
}

impl Count<BigUint> for Permutation<Data> {
    type N = BigUint;
    fn count(&self, dim: &BigUint) -> BigUint {
        let _1: BigUint = 1usize.into();
        let mut res: BigUint = _1.clone();
        let mut x = _1.clone();
        loop {
            if &x > dim {break}
            res *= &x;
            x += &_1;
        }
        res
    }
}

impl<T, U> Count<U> for Permutation<Of<T>>
    where
        T: Construct + Count<U>,
        for<'a> <T as Count<U>>::N: From<usize> + Clone + Ord +
            AddAssign<&'a <T as Count<U>>::N> +
            MulAssign<&'a <T as Count<U>>::N>
{
    type N = <T as Count<U>>::N;
    fn count(&self, dim: &U) -> Self::N {
        let of: T = Construct::new();
        let _1: Self::N = 1usize.into();
        let mut x = _1.clone();
        let mut res = _1.clone();
        let of_count = of.count(dim);
        loop {
            if &x > &of_count {break}
            res *= &x;
            x += &_1;
        }
        res
    }
}

impl Zero<usize, Vec<usize>> for Permutation<Data> {
    fn zero(&self, dim: &usize) -> Vec<usize> {
        vec![0; *dim]
    }
}

impl Zero<BigUint, Vec<BigUint>> for Permutation<Data> {
    fn zero(&self, dim: &BigUint) -> Vec<BigUint> {
        let dim: usize = dim.try_into().unwrap();
        vec![0usize.into(); dim]
    }
}

impl<T, U, V> Zero<U, Vec<V>> for Permutation<Of<T>>
    where
        T: Construct + Count<U> + Zero<U, V>,
        <T as Count<U>>::N: TryInto<usize>,
        V: Clone
{
    fn zero(&self, dim: &U) -> Vec<V> {
        let of: T = Construct::new();
        let count = match of.count(dim).try_into() {
            Ok(x) => x,
            Err(_) => panic!("Out of range"),
        };
        vec![of.zero(dim); count]
    }
}

impl ToIndex<usize, Vec<usize>> for Permutation<Data> {
    fn to_index(&self, dim: &usize, pos: &Vec<usize>) -> usize {
        let mut index = 0;
        let mut count = 1;
        for (i, &x) in pos.iter().enumerate().rev() {
            let lower = pos[..i].iter().filter(|&&y| y < x).count();
            index += count * (x - lower);
            count *= dim - i;
        }
        index
    }
}

impl<T, U, V> ToIndex<U, Vec<V>> for Permutation<Of<T>>
    where
        T: Construct + ToIndex<U, V> + Count<U, N = usize>,
        V: Clone
{
    fn to_index(&self, dim: &U, pos: &Vec<V>) -> usize {
        let of: T = Construct::new();
        let mut index = 0;
        let dim_count = of.count(dim);
        let mut count = 1;
        for (i, x) in pos.iter()
            .map(|x| of.to_index(dim, x))
            .enumerate().rev() {
            let lower = pos[..i].iter()
                .map(|y| of.to_index(dim, y))
                .filter(|&y| y < x).count();
            index += count * (x - lower);
            count *= dim_count - i;
        }
        index
    }
}

impl ToPos<usize, Vec<usize>> for Permutation<Data> {
    fn to_pos(&self, dim: &usize, mut index: usize, pos: &mut Vec<usize>) {
        unsafe { pos.set_len(0); }

        let mut count = 1;
        for (j, x) in (1..dim + 1).enumerate() {
            count *= x;
            pos.push(j);
        }

        for i in 0..*dim {
            let block = count / (dim - i);
            let ind = index / block;
            let item = pos.remove(ind);
            pos.push(item);
            count /= dim - i;
            index -= ind * block;
        }
    }
}

impl<T, U, V> ToPos<U, Vec<V>> for Permutation<Of<T>>
    where
        T: Construct + Count<U, N = usize> + ToPos<U, V> + Zero<U, V>
{
    fn to_pos(&self, dim: &U, mut index: usize, pos: &mut Vec<V>) {
        let of: T = Construct::new();
        let of_count = of.count(dim);
        pos.clear();

        let mut count = 1;
        for (j, x) in (1..of_count + 1).enumerate() {
            count *= x;
            let mut new_pos: V = of.zero(&dim);
            of.to_pos(dim, j, &mut new_pos);
            pos.push(new_pos);
        }

        for i in 0..of_count {
            let block = count / (of_count - i);
            let ind = index / block;
            let item = pos.remove(ind);
            pos.push(item);
            count /= of_count - i;
            index -= ind * block;
        }
    }
}

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

    #[test]
    fn features() {
        is_complete::<Permutation, usize, Vec<usize>>();
        is_complete::<Permutation<Of<Pair>>, usize, Vec<(usize, usize)>>();
    }

    #[test]
    fn data() {
        let permutation: Permutation = Construct::new();
        assert_eq!(permutation.count(&1), 1);
        assert_eq!(permutation.count(&2), 2);
        assert_eq!(permutation.count(&3), 6);
        assert_eq!(permutation.count(&4), 24);

        let mut pos = Vec::new();
        let ref dim = 4;
        let count = permutation.count(dim);
        for i in 0..count {
            permutation.to_pos(dim, i, &mut pos);
            let index = permutation.to_index(dim, &pos);
            assert_eq!(index, i);
        }
    }

    #[test]
    fn of() {
        let space: Permutation<Of<Pair>> = Construct::new();
        let ref dim = 3;
        let count = space.count(dim);
        let mut pos = Vec::new();
        for i in 0..count {
            space.to_pos(dim, i, &mut pos);
            let index = space.to_index(dim, &pos);
            assert_eq!(index, i);
        }
    }
}
<|endoftext|>


<commit_before>use std::fs;
use std::fs::OpenOptions;
use std::io::prelude::*;
use std::path::PathBuf;
use std::vec::Vec;
use std::str::FromStr;

use time;

#[cfg(test)] use rand;
#[cfg(test)] use rand::Rng;
#[cfg(test)] use test_library::PathPrefix;

use crypto::sha1::Sha1;
use crypto::digest::Digest;

use rustc_serialize::base64::FromBase64;

use message::PackageId;

// TODO: refactor into submodules

pub struct Transfer {
    pub package: PackageId,
    pub checksum: String,
    pub transferred_chunks: Vec<u64>,
    pub prefix_dir: String,
    pub last_chunk_received: i64
}

impl Transfer {
    pub fn new(prefix: String, package: PackageId, checksum: String)
        -> Transfer {
        Transfer {
            package: package,
            checksum: checksum,
            transferred_chunks: Vec::new(),
            prefix_dir: prefix,
            last_chunk_received: time::get_time().sec
        }
    }

    #[cfg(test)]
    pub fn new_test(prefix: &PathPrefix) -> Transfer {
        Transfer {
            package: PackageId {
                name: "".to_string(),
                version: "".to_string()
            },
            checksum: "".to_string(),
            transferred_chunks: Vec::new(),
            prefix_dir: prefix.to_string(),
            last_chunk_received: time::get_time().sec
        }
    }

    #[cfg(test)]
    pub fn randomize(&mut self, i: usize) -> PackageId {
        let name = rand::thread_rng()
            .gen_ascii_chars().take(i).collect::<String>();
        let version = rand::thread_rng()
            .gen_ascii_chars().take(i).collect::<String>();

        trace!("Testing with:");
        trace!("  name: {}\n  version {}", name, version);

        self.package.name = name.clone();
        self.package.version = version.clone();

        PackageId {
            name: name,
            version: version
        }
    }

    pub fn assemble_package(&self) -> bool {
        trace!("Finalizing package {}", self.package);
        try_or!(self.assemble_chunks(), return false);
        self.checksum()
    }

    pub fn write_chunk(&mut self,
                       msg: &str,
                       index: u64) -> bool {
        let success = msg.from_base64().map_err(|e| {
            error!("Could not decode chunk {} for package {}", index, self.package);
            error!("{}", e)
        }).and_then(|msg| self.get_chunk_path(index).map_err(|e| {
            error!("Could not get path for chunk {}", index);
            error!("{}", e)
        }).map(|path| {
            trace!("Saving chunk to {}", path.display());
            if write_new_file(&path, &msg) {
                self.transferred_chunks.push(index);
                true
            } else {
                error!("Couldn't write chunk {} for package {}", index, self.package);
                false
            }
        })).unwrap_or(false);

        self.last_chunk_received = time::get_time().sec;
        success
    }

    fn get_chunk_path(&self, index: u64) -> Result<PathBuf, String> {
        let mut path = try!(self.get_chunk_dir());
        let filename = index.to_string();

        trace!("Using filename {}", filename);
        path.push(filename);
        Ok(path)
    }

    fn get_package_path(&self) -> Result<PathBuf, String> {
        let mut path = try!(self.get_package_dir());
        path.push(format!("{}.spkg", self.package));
        Ok(path)
    }

    fn assemble_chunks(&self) -> Result<(), String> {
        let package_path = try!(self.get_package_path());

        trace!("Saving package {} to {}", self.package, package_path.display());

        let mut file = try!(OpenOptions::new()
                               .write(true).append(true)
                               .create(true).truncate(true)
                               .open(package_path)
                               .map_err(|x| format!("Couldn't open file: {}", x)));

        let path: PathBuf = try!(self.get_chunk_dir());

        let mut indices = Vec::new();
        for entry in try!(read_dir(&path)) {
            let entry = try!(entry.map_err(|x| format!("No entries: {}", x)));
            let name  = entry.file_name().into_string()
                .unwrap_or("unknown".to_string());

            let chunk_index =
                try!(u64::from_str(&name)
                     .map_err(|_| "Couldn't parse chunk index from filename"
                              .to_string()));
            indices.push(chunk_index);
        }
        indices.sort();

        for index in indices {
            let name = index.to_string();
            let mut chunk_path = path.clone();
            chunk_path.push(&name);
            let mut chunk =
                try!(OpenOptions::new().open(chunk_path)
                     .map_err(|x| format!("Couldn't open file: {}", x)));

            let mut buf = Vec::new();
            try!(chunk.read_to_end(&mut buf)
                 .map_err(|x| format!("Couldn't read file {}: {}", name, x)));
            try!(file.write(&mut buf)
                 .map_err(|x| format!("Couldn't write chunk {} to file {}: {}",
                                      name, self.package, x)));

            trace!("Wrote chunk {} to package {}", name, self.package);
        }
        Ok(())
    }

    fn get_chunk_dir(&self) -> Result<PathBuf, String> {
        let mut path = PathBuf::from(&self.prefix_dir);
        path.push("downloads");
        path.push(format!("{}", self.package));

        fs::create_dir_all(&path).map_err(|e| {
            let path_str = path.to_str().unwrap_or("unknown");
            format!("Couldn't create chunk dir at '{}': {}", path_str, e)
        }).map(|_| path)
    }

    fn checksum(&self) -> bool {
        let path = try_or!(self.get_package_path(), return false);
        let mut file = try_or!(OpenOptions::new().open(path), return false);
        let mut data = Vec::new();

        // TODO: avoid reading in the whole file at once
        try_msg_or!(file.read_to_end(&mut data),
                    "Couldn't read file to check",
                    return false);

        let mut hasher = Sha1::new();
        hasher.input(&data);
        let hash = hasher.result_str();

        if hash == self.checksum {
            true
        } else {
            error!("Checksums didn't match for package {}", self.package);
            error!("    Expected: {}", self.checksum);
            error!("    Got: {}", hash);
            false
        }
    }

    fn get_package_dir(&self) -> Result<PathBuf, String> {
        let mut path = PathBuf::from(&self.prefix_dir);
        path.push("packages");

        fs::create_dir_all(&path).map_err(|e| {
            let path_str = path.to_str().unwrap_or("unknown");
            format!("Couldn't create packges dir at '{}': {}", path_str, e)
        }).map(|_| path)
    }
}

impl Drop for Transfer {
    fn drop(&mut self) {
        let dir = try_or!(self.get_chunk_dir(), return);
        trace!("Dropping transfer for package {}", self.package);

        for entry in try_or!(read_dir(&dir), return) {
            let entry = try_or!(entry, continue);
            let _ = entry.file_name().into_string().map_err(|_|
                error!("Found a malformed entry!")
            ).map(|name| {
                trace!("Dropping chunk file {}", name);
                try_or!(fs::remove_file(entry.path()), return);
            });
        }

        try_or!(fs::remove_dir(dir), return);
    }
}

fn write_new_file(path: &PathBuf, data: &Vec<u8>) -> bool {
    let mut file = try_or!(OpenOptions::new()
                           .write(true).create(true)
                           .truncate(true).open(path),
                           return false);

    try_or!(file.write_all(data), return false);
    try_or!(file.flush(), return false);
    true
}

fn read_dir(path: &PathBuf) -> Result<fs::ReadDir, String> {
    fs::read_dir(path).map_err(|e| {
        let path_str = path.to_str().unwrap_or("unknown");
        format!("Couldn't read dir at '{}': {}", path_str, e)
    })
}

#[cfg(test)]
mod test {
    use super::*;
    use test_library::*;

    use std::path::PathBuf;
    use std::fs;
    use std::fs::OpenOptions;
    use std::io::prelude::*;

    use rand;
    use rand::Rng;
    use rustc_serialize::base64;
    use rustc_serialize::base64::ToBase64;

    fn create_tmp_directories(prefix: &PathPrefix) {
        for i in 1..20 {
            let mut transfer = Transfer::new_test(prefix);
            let package = transfer.randomize(i);
            let chunk_dir: PathBuf = transfer.get_chunk_dir().unwrap();
            let path = format!("{}/downloads/{}-{}", prefix,
                               package.name, package.version);
            assert_eq!(chunk_dir.to_str().unwrap(), path);

            let path = PathBuf::from(path);
            // This also makes sure it's a directory
            let dir = fs::read_dir(&path).unwrap();

            for _ in dir {
                panic!("Found non-empty directory!");
            }
        }
    }

    #[test]
    fn it_creates_a_tmp_directory() {
        test_init!();
        let prefix = PathPrefix::new();
        create_tmp_directories(&prefix);
    }

    #[test]
    fn it_cleans_up_the_tmp_directories() {
        test_init!();
        let prefix = PathPrefix::new();
        create_tmp_directories(&prefix);
        let path = PathBuf::from(format!("{}/downloads/", prefix));
        let dir = fs::read_dir(&path).unwrap();

        for _ in dir {
            panic!("Found non-empty directory!");
        }
    }

    #[test]
    fn it_creates_a_persistent_directory_per_package() {
        test_init!();
        let prefix = PathPrefix::new();
        for i in 1..20 {
            let mut transfer = Transfer::new_test(&prefix);
            let package = transfer.randomize(i);

            let chunk_dir: PathBuf = transfer.get_package_path().unwrap();
            let path = format!("{}/packages/{}-{}.spkg", prefix,
                               package.name, package.version);
            assert_eq!(chunk_dir.to_str().unwrap(), path);
        }
    }

    macro_rules! assert_chunk_written {
        ($transfer:ident,
         $prefix:ident,
         $package:ident,
         $index:ident,
         $data:ident) => {{
            trace!("Testing with: {}", $data);

            let b64_data = $data.as_bytes().to_base64(
                base64::Config {
                    char_set: base64::CharacterSet::UrlSafe,
                    newline: base64::Newline::LF,
                    pad: true,
                    line_length: None
                });

            trace!("Encoded as: {}", b64_data);

            $transfer.write_chunk(&b64_data, $index as u64);

            let path = format!("{}/downloads/{}-{}/{}", $prefix,
                                $package.name, $package.version, $index);

            trace!("Expecting file at: {}", path);

            let mut from_disk = Vec::new();
            OpenOptions::new()
                .open(PathBuf::from(path))
                .unwrap()
                .read_to_end(&mut from_disk)
                .unwrap();

            assert_eq!($data.into_bytes(), from_disk);
        }}
    }

    #[test]
    fn it_writes_decoded_data_to_disk() {
        test_init!();
        let prefix = PathPrefix::new();
        for i in 1..20 {
            let mut transfer = Transfer::new_test(&prefix);
            let package = transfer.randomize(i);
            for i in 1..20 {
                let data = rand::thread_rng()
                    .gen_ascii_chars().take(i).collect::<String>();
                assert_chunk_written!(transfer, prefix, package, i, data);
            }
        }
    }

    #[test]
    fn it_correctly_assembles_stored_chunks() {
        test_init!();
        let prefix = PathPrefix::new();
        for i in 1..20 {
            let mut transfer = Transfer::new_test(&prefix);
            let package = transfer.randomize(i);
            let mut full_data = String::new();
            for i in 1..20 {
                let data = rand::thread_rng()
                    .gen_ascii_chars().take(i).collect::<String>();
                full_data.push_str(&data);

                assert_chunk_written!(transfer, prefix, package, i, data);
            }

            transfer.assemble_chunks().unwrap();

            let path = format!("{}/packages/{}-{}.spkg", prefix,
                               package.name, package.version);

            trace!("Expecting assembled file at: {}", path);

            let mut from_disk = Vec::new();
            OpenOptions::new()
                .open(PathBuf::from(path))
                .unwrap()
                .read_to_end(&mut from_disk)
                .unwrap();

            assert_eq!(full_data.into_bytes(), from_disk);
        }
    }

    fn checksum_matching(data: String, checksum: String) -> bool {
            let prefix = PathPrefix::new();
            let mut transfer = Transfer::new_test(&prefix);
            let package = transfer.randomize(20);
            let index = 0;
            assert_chunk_written!(transfer, prefix, package, index, data);
            transfer.assemble_chunks().unwrap();

            transfer.checksum = checksum;
            transfer.checksum()
    }

    #[test]
    fn it_returns_true_for_correct_checksums() {
        test_init!();
        assert!(checksum_matching("test\n".to_string(),
        "4e1243bd22c66e76c2ba9eddc1f91394e57f9f83".to_string()));
    }

    #[test]
    fn it_returns_false_for_incorrect_checksums() {
        test_init!();
        assert!(!checksum_matching("test\n".to_string(),
        "fa7c4d75bae3a641d1f9ab5df028175bfb8a69ca".to_string()));
    }

    #[test]
    fn it_returns_false_for_invalid_checksums() {
        test_init!();
        assert!(!checksum_matching("test\n".to_string(),
        "invalid".to_string()));
    }
}
<commit_msg>Don't send duplicates in chunk_index<commit_after>use std::fs;
use std::fs::OpenOptions;
use std::io::prelude::*;
use std::path::PathBuf;
use std::vec::Vec;
use std::str::FromStr;

use time;

#[cfg(test)] use rand;
#[cfg(test)] use rand::Rng;
#[cfg(test)] use test_library::PathPrefix;

use crypto::sha1::Sha1;
use crypto::digest::Digest;

use rustc_serialize::base64::FromBase64;

use message::PackageId;

// TODO: refactor into submodules

pub struct Transfer {
    pub package: PackageId,
    pub checksum: String,
    pub transferred_chunks: Vec<u64>,
    pub prefix_dir: String,
    pub last_chunk_received: i64
}

impl Transfer {
    pub fn new(prefix: String, package: PackageId, checksum: String)
        -> Transfer {
        Transfer {
            package: package,
            checksum: checksum,
            transferred_chunks: Vec::new(),
            prefix_dir: prefix,
            last_chunk_received: time::get_time().sec
        }
    }

    #[cfg(test)]
    pub fn new_test(prefix: &PathPrefix) -> Transfer {
        Transfer {
            package: PackageId {
                name: "".to_string(),
                version: "".to_string()
            },
            checksum: "".to_string(),
            transferred_chunks: Vec::new(),
            prefix_dir: prefix.to_string(),
            last_chunk_received: time::get_time().sec
        }
    }

    #[cfg(test)]
    pub fn randomize(&mut self, i: usize) -> PackageId {
        let name = rand::thread_rng()
            .gen_ascii_chars().take(i).collect::<String>();
        let version = rand::thread_rng()
            .gen_ascii_chars().take(i).collect::<String>();

        trace!("Testing with:");
        trace!("  name: {}\n  version {}", name, version);

        self.package.name = name.clone();
        self.package.version = version.clone();

        PackageId {
            name: name,
            version: version
        }
    }

    pub fn assemble_package(&self) -> bool {
        trace!("Finalizing package {}", self.package);
        try_or!(self.assemble_chunks(), return false);
        self.checksum()
    }

    pub fn write_chunk(&mut self,
                       msg: &str,
                       index: u64) -> bool {
        let success = msg.from_base64().map_err(|e| {
            error!("Could not decode chunk {} for package {}", index, self.package);
            error!("{}", e)
        }).and_then(|msg| self.get_chunk_path(index).map_err(|e| {
            error!("Could not get path for chunk {}", index);
            error!("{}", e)
        }).map(|path| {
            trace!("Saving chunk to {}", path.display());
            if write_new_file(&path, &msg) {
                self.transferred_chunks.push(index);
                self.transferred_chunks.sort();
                self.transferred_chunks.dedup();
                true
            } else {
                error!("Couldn't write chunk {} for package {}", index, self.package);
                false
            }
        })).unwrap_or(false);

        self.last_chunk_received = time::get_time().sec;
        success
    }

    fn get_chunk_path(&self, index: u64) -> Result<PathBuf, String> {
        let mut path = try!(self.get_chunk_dir());
        let filename = index.to_string();

        trace!("Using filename {}", filename);
        path.push(filename);
        Ok(path)
    }

    fn get_package_path(&self) -> Result<PathBuf, String> {
        let mut path = try!(self.get_package_dir());
        path.push(format!("{}.spkg", self.package));
        Ok(path)
    }

    fn assemble_chunks(&self) -> Result<(), String> {
        let package_path = try!(self.get_package_path());

        trace!("Saving package {} to {}", self.package, package_path.display());

        let mut file = try!(OpenOptions::new()
                               .write(true).append(true)
                               .create(true).truncate(true)
                               .open(package_path)
                               .map_err(|x| format!("Couldn't open file: {}", x)));

        let path: PathBuf = try!(self.get_chunk_dir());

        let mut indices = Vec::new();
        for entry in try!(read_dir(&path)) {
            let entry = try!(entry.map_err(|x| format!("No entries: {}", x)));
            let name  = entry.file_name().into_string()
                .unwrap_or("unknown".to_string());

            let chunk_index =
                try!(u64::from_str(&name)
                     .map_err(|_| "Couldn't parse chunk index from filename"
                              .to_string()));
            indices.push(chunk_index);
        }
        indices.sort();

        for index in indices {
            let name = index.to_string();
            let mut chunk_path = path.clone();
            chunk_path.push(&name);
            let mut chunk =
                try!(OpenOptions::new().open(chunk_path)
                     .map_err(|x| format!("Couldn't open file: {}", x)));

            let mut buf = Vec::new();
            try!(chunk.read_to_end(&mut buf)
                 .map_err(|x| format!("Couldn't read file {}: {}", name, x)));
            try!(file.write(&mut buf)
                 .map_err(|x| format!("Couldn't write chunk {} to file {}: {}",
                                      name, self.package, x)));

            trace!("Wrote chunk {} to package {}", name, self.package);
        }
        Ok(())
    }

    fn get_chunk_dir(&self) -> Result<PathBuf, String> {
        let mut path = PathBuf::from(&self.prefix_dir);
        path.push("downloads");
        path.push(format!("{}", self.package));

        fs::create_dir_all(&path).map_err(|e| {
            let path_str = path.to_str().unwrap_or("unknown");
            format!("Couldn't create chunk dir at '{}': {}", path_str, e)
        }).map(|_| path)
    }

    fn checksum(&self) -> bool {
        let path = try_or!(self.get_package_path(), return false);
        let mut file = try_or!(OpenOptions::new().open(path), return false);
        let mut data = Vec::new();

        // TODO: avoid reading in the whole file at once
        try_msg_or!(file.read_to_end(&mut data),
                    "Couldn't read file to check",
                    return false);

        let mut hasher = Sha1::new();
        hasher.input(&data);
        let hash = hasher.result_str();

        if hash == self.checksum {
            true
        } else {
            error!("Checksums didn't match for package {}", self.package);
            error!("    Expected: {}", self.checksum);
            error!("    Got: {}", hash);
            false
        }
    }

    fn get_package_dir(&self) -> Result<PathBuf, String> {
        let mut path = PathBuf::from(&self.prefix_dir);
        path.push("packages");

        fs::create_dir_all(&path).map_err(|e| {
            let path_str = path.to_str().unwrap_or("unknown");
            format!("Couldn't create packges dir at '{}': {}", path_str, e)
        }).map(|_| path)
    }
}

impl Drop for Transfer {
    fn drop(&mut self) {
        let dir = try_or!(self.get_chunk_dir(), return);
        trace!("Dropping transfer for package {}", self.package);

        for entry in try_or!(read_dir(&dir), return) {
            let entry = try_or!(entry, continue);
            let _ = entry.file_name().into_string().map_err(|_|
                error!("Found a malformed entry!")
            ).map(|name| {
                trace!("Dropping chunk file {}", name);
                try_or!(fs::remove_file(entry.path()), return);
            });
        }

        try_or!(fs::remove_dir(dir), return);
    }
}

fn write_new_file(path: &PathBuf, data: &Vec<u8>) -> bool {
    let mut file = try_or!(OpenOptions::new()
                           .write(true).create(true)
                           .truncate(true).open(path),
                           return false);

    try_or!(file.write_all(data), return false);
    try_or!(file.flush(), return false);
    true
}

fn read_dir(path: &PathBuf) -> Result<fs::ReadDir, String> {
    fs::read_dir(path).map_err(|e| {
        let path_str = path.to_str().unwrap_or("unknown");
        format!("Couldn't read dir at '{}': {}", path_str, e)
    })
}

#[cfg(test)]
mod test {
    use super::*;
    use test_library::*;

    use std::path::PathBuf;
    use std::fs;
    use std::fs::OpenOptions;
    use std::io::prelude::*;

    use rand;
    use rand::Rng;
    use rustc_serialize::base64;
    use rustc_serialize::base64::ToBase64;

    fn create_tmp_directories(prefix: &PathPrefix) {
        for i in 1..20 {
            let mut transfer = Transfer::new_test(prefix);
            let package = transfer.randomize(i);
            let chunk_dir: PathBuf = transfer.get_chunk_dir().unwrap();
            let path = format!("{}/downloads/{}-{}", prefix,
                               package.name, package.version);
            assert_eq!(chunk_dir.to_str().unwrap(), path);

            let path = PathBuf::from(path);
            // This also makes sure it's a directory
            let dir = fs::read_dir(&path).unwrap();

            for _ in dir {
                panic!("Found non-empty directory!");
            }
        }
    }

    #[test]
    fn it_creates_a_tmp_directory() {
        test_init!();
        let prefix = PathPrefix::new();
        create_tmp_directories(&prefix);
    }

    #[test]
    fn it_cleans_up_the_tmp_directories() {
        test_init!();
        let prefix = PathPrefix::new();
        create_tmp_directories(&prefix);
        let path = PathBuf::from(format!("{}/downloads/", prefix));
        let dir = fs::read_dir(&path).unwrap();

        for _ in dir {
            panic!("Found non-empty directory!");
        }
    }

    #[test]
    fn it_creates_a_persistent_directory_per_package() {
        test_init!();
        let prefix = PathPrefix::new();
        for i in 1..20 {
            let mut transfer = Transfer::new_test(&prefix);
            let package = transfer.randomize(i);

            let chunk_dir: PathBuf = transfer.get_package_path().unwrap();
            let path = format!("{}/packages/{}-{}.spkg", prefix,
                               package.name, package.version);
            assert_eq!(chunk_dir.to_str().unwrap(), path);
        }
    }

    macro_rules! assert_chunk_written {
        ($transfer:ident,
         $prefix:ident,
         $package:ident,
         $index:ident,
         $data:ident) => {{
            trace!("Testing with: {}", $data);

            let b64_data = $data.as_bytes().to_base64(
                base64::Config {
                    char_set: base64::CharacterSet::UrlSafe,
                    newline: base64::Newline::LF,
                    pad: true,
                    line_length: None
                });

            trace!("Encoded as: {}", b64_data);

            $transfer.write_chunk(&b64_data, $index as u64);

            let path = format!("{}/downloads/{}-{}/{}", $prefix,
                                $package.name, $package.version, $index);

            trace!("Expecting file at: {}", path);

            let mut from_disk = Vec::new();
            OpenOptions::new()
                .open(PathBuf::from(path))
                .unwrap()
                .read_to_end(&mut from_disk)
                .unwrap();

            assert_eq!($data.into_bytes(), from_disk);
        }}
    }

    #[test]
    fn it_writes_decoded_data_to_disk() {
        test_init!();
        let prefix = PathPrefix::new();
        for i in 1..20 {
            let mut transfer = Transfer::new_test(&prefix);
            let package = transfer.randomize(i);
            for i in 1..20 {
                let data = rand::thread_rng()
                    .gen_ascii_chars().take(i).collect::<String>();
                assert_chunk_written!(transfer, prefix, package, i, data);
            }
        }
    }

    #[test]
    fn it_correctly_assembles_stored_chunks() {
        test_init!();
        let prefix = PathPrefix::new();
        for i in 1..20 {
            let mut transfer = Transfer::new_test(&prefix);
            let package = transfer.randomize(i);
            let mut full_data = String::new();
            for i in 1..20 {
                let data = rand::thread_rng()
                    .gen_ascii_chars().take(i).collect::<String>();
                full_data.push_str(&data);

                assert_chunk_written!(transfer, prefix, package, i, data);
            }

            transfer.assemble_chunks().unwrap();

            let path = format!("{}/packages/{}-{}.spkg", prefix,
                               package.name, package.version);

            trace!("Expecting assembled file at: {}", path);

            let mut from_disk = Vec::new();
            OpenOptions::new()
                .open(PathBuf::from(path))
                .unwrap()
                .read_to_end(&mut from_disk)
                .unwrap();

            assert_eq!(full_data.into_bytes(), from_disk);
        }
    }

    fn checksum_matching(data: String, checksum: String) -> bool {
            let prefix = PathPrefix::new();
            let mut transfer = Transfer::new_test(&prefix);
            let package = transfer.randomize(20);
            let index = 0;
            assert_chunk_written!(transfer, prefix, package, index, data);
            transfer.assemble_chunks().unwrap();

            transfer.checksum = checksum;
            transfer.checksum()
    }

    #[test]
    fn it_returns_true_for_correct_checksums() {
        test_init!();
        assert!(checksum_matching("test\n".to_string(),
        "4e1243bd22c66e76c2ba9eddc1f91394e57f9f83".to_string()));
    }

    #[test]
    fn it_returns_false_for_incorrect_checksums() {
        test_init!();
        assert!(!checksum_matching("test\n".to_string(),
        "fa7c4d75bae3a641d1f9ab5df028175bfb8a69ca".to_string()));
    }

    #[test]
    fn it_returns_false_for_invalid_checksums() {
        test_init!();
        assert!(!checksum_matching("test\n".to_string(),
        "invalid".to_string()));
    }
}
<|endoftext|>


<commit_before>extern crate test;

use std::old_io::fs::PathExtensions;
use std::os::getenv;
use std::old_io::File;
use self::test::Bencher;
use racer::codecleaner::code_chunks;
use racer::codeiter::iter_stmts;
use racer::scopes::mask_comments;

fn get_rust_file_str(path: &[&str]) -> String {

    let mut src_path = match getenv("RUST_SRC_PATH") {
        Some(env) => { Path::new(&env[]) },
        None => panic!("Cannot find $RUST_SRC_PATH")
    };
    for &s in path.iter() { src_path.push(s); }

    File::open(&src_path).read_to_string().unwrap()
}

#[bench]
fn bench_code_chunks(b: &mut Bencher) {
    let src = &get_rust_file_str(&["libcollections", "bit.rs"])[];
    b.iter(|| {
        let chunks = code_chunks(src).collect::<Vec<_>>();
    });
}

#[bench]
fn bench_iter_stmts(b: &mut Bencher) {
    let src = &get_rust_file_str(&["libcollections", "bit.rs"])[];
    b.iter(|| {
        let chunks = iter_stmts(src).collect::<Vec<_>>();
    });
}

#[bench]
fn bench_mask_comments(b: &mut Bencher) {
    let src = &get_rust_file_str(&["libcollections", "bit.rs"])[];
    b.iter(|| {
        mask_comments(src);
    });
}

<commit_msg>Add bench_sub_scopes<commit_after>extern crate test;

use std::old_io::fs::PathExtensions;
use std::os::getenv;
use std::old_io::File;
use self::test::Bencher;
use racer::codecleaner::code_chunks;
use racer::codeiter::iter_stmts;
use racer::scopes::{mask_comments, mask_sub_scopes};

fn get_rust_file_str(path: &[&str]) -> String {

    let mut src_path = match getenv("RUST_SRC_PATH") {
        Some(env) => { Path::new(&env[]) },
        None => panic!("Cannot find $RUST_SRC_PATH")
    };
    for &s in path.iter() { src_path.push(s); }

    File::open(&src_path).read_to_string().unwrap()
}

#[bench]
fn bench_code_chunks(b: &mut Bencher) {
    let src = &get_rust_file_str(&["libcollections", "bit.rs"])[];
    b.iter(|| {
        let chunks = code_chunks(src).collect::<Vec<_>>();
    });
}

#[bench]
fn bench_iter_stmts(b: &mut Bencher) {
    let src = &get_rust_file_str(&["libcollections", "bit.rs"])[];
    b.iter(|| {
        let chunks = iter_stmts(src).collect::<Vec<_>>();
    });
}

#[bench]
fn bench_mask_comments(b: &mut Bencher) {
    let src = &get_rust_file_str(&["libcollections", "bit.rs"])[];
    b.iter(|| {
        mask_comments(src);
    });
}

#[bench]
fn bench_mask_sub_scopes(b: &mut Bencher) {
    let src = &get_rust_file_str(&["libcollections", "bit.rs"])[];
    b.iter(|| {
        mask_sub_scopes(src);
    });
}

<|endoftext|>


<commit_before>use modular_flow::graph::*;
use modular_flow::context::*;
use sdl2;
use sdl2::pixels::PixelFormatEnum;
use sdl2::rect::Rect;
use sdl2::event::{Event, WindowEvent};
use sdl2::keyboard::Keycode;
use std::thread;
use std::process;

pub struct Rainbowgram {
    pub id: NodeID,
    pub channels: usize,
}

impl Rainbowgram {
    pub fn new(graph: &mut Graph, channels: usize) -> Rainbowgram {
        Rainbowgram {
            id: graph.add_node(channels, 0),
            channels,
        }
    }
    pub fn run(self, context: &Context) {
        let node_ctx = context.node_ctx(self.id).unwrap();
        const fft_size: usize = 2048;
        const height: u32 = 1024;

        thread::spawn(move || {
            let sdl_context = sdl2::init().unwrap();
            let video_subsystem = sdl_context.video().unwrap();

            let window = video_subsystem.window("rainbowgram", fft_size as u32/2, height)
                .opengl()
                //.resizable()
                .build()
                .unwrap();

            let mut canvas = window.into_canvas().build().unwrap();
            let texture_creator = canvas.texture_creator();

            let mut texture = texture_creator.create_texture_streaming(PixelFormatEnum::RGB24, (fft_size/2) as u32, height)
                .unwrap();

            let mut event_pump = sdl_context.event_pump().unwrap();

            use rustfft::FFTplanner;
            use rustfft::num_complex::Complex;
            use rustfft::num_traits::Zero;

            let mut fft_input:  Vec<Complex<f32>> = vec![Complex::zero(); fft_size];
            let mut fft_output: Vec<Complex<f32>> = vec![Complex::zero(); fft_size];

            let mut planner = FFTplanner::new(false);
            let fft = planner.plan_fft(fft_size);

            let mut time = 0;

            'mainloop: loop {
                let mut lock = node_ctx.lock();
                lock.wait(|x| x.available::<f32>(InPortID(0)) >= fft_size);
                let data = lock.read_n::<f32>(InPortID(0), fft_size).unwrap();
                drop(lock);
                for i in 0..fft_size {
                    fft_input[i].re = data[i];
                }
                fft.process(&mut fft_input, &mut fft_output);

                for event in event_pump.poll_iter() {
                    match event {
                        Event::Quit {..} |
                            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'mainloop,
                            Event::Window{win_event: WindowEvent::Resized(x, y), ..} => {
                                // TODO
                            }
                        _ => {}
                    }
                }

                let scroll_pos = time % (height as i32 / 2);
                time += 1;

                texture.with_lock(None, |buffer: &mut [u8], pitch: usize| {
                    let y = scroll_pos as usize;
                    for x in 0..fft_size/2 {
                        let value = ((1.0 + fft_output[x].norm()).ln() * 128.0).min(255.0) as u8;
                        let offset = y * pitch + x * 3;
                        buffer[offset] = value;
                        buffer[offset+1] = value;
                        buffer[offset+2] = value;
                        let offset = (y+height as usize/2) * pitch + x * 3;
                        buffer[offset] = value;
                        buffer[offset+1] = value;
                        buffer[offset+2] = value;
                    }
                }).unwrap();

                canvas.clear();
                canvas.copy(&texture, Some(Rect::new(0, scroll_pos+1, (fft_size/2) as u32, height/2)), None).unwrap();
                canvas.present();

                //::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
            }

            process::exit(0);
        });
    }
}
<commit_msg>Mix down before spectrogram<commit_after>use modular_flow::graph::*;
use modular_flow::context::*;
use sdl2;
use sdl2::pixels::PixelFormatEnum;
use sdl2::rect::Rect;
use sdl2::event::{Event, WindowEvent};
use sdl2::keyboard::Keycode;
use std::thread;
use std::process;

pub struct Rainbowgram {
    pub id: NodeID,
    pub channels: usize,
}

impl Rainbowgram {
    pub fn new(graph: &mut Graph, channels: usize) -> Rainbowgram {
        Rainbowgram {
            id: graph.add_node(channels, 0),
            channels,
        }
    }
    pub fn run(self, context: &Context) {
        let node_ctx = context.node_ctx(self.id).unwrap();
        const fft_size: usize = 2048;
        const height: u32 = 512;

        thread::spawn(move || {
            let sdl_context = sdl2::init().unwrap();
            let video_subsystem = sdl_context.video().unwrap();

            let window = video_subsystem.window("rainbowgram", fft_size as u32/2, height)
                .opengl()
                //.resizable()
                .build()
                .unwrap();

            let mut canvas = window.into_canvas().build().unwrap();
            let texture_creator = canvas.texture_creator();

            let mut texture = texture_creator.create_texture_streaming(PixelFormatEnum::RGB24, (fft_size/2) as u32, height)
                .unwrap();

            let mut event_pump = sdl_context.event_pump().unwrap();

            use rustfft::FFTplanner;
            use rustfft::num_complex::Complex;
            use rustfft::num_traits::Zero;

            let mut fft_input:  Vec<Complex<f32>> = vec![Complex::zero(); fft_size];
            let mut fft_output: Vec<Complex<f32>> = vec![Complex::zero(); fft_size];

            let mut planner = FFTplanner::new(false);
            let fft = planner.plan_fft(fft_size);

            let mut time = 0;

            'mainloop: loop {
                let mut lock = node_ctx.lock();
                lock.wait(|x| (0..self.channels).all(|id| x.available::<f32>(InPortID(id)) >= fft_size));
                let data: Vec<_> = (0..self.channels).map(|id| lock.read_n::<f32>(InPortID(id), fft_size).unwrap()).collect();
                drop(lock);

                for i in 0..fft_size {
                    fft_input[i].re = 0.0;
                    fft_input[i].im = 0.0;
                    for j in 0..self.channels {
                        fft_input[i].re += data[j][i];
                    }
                }
                fft.process(&mut fft_input, &mut fft_output);

                for event in event_pump.poll_iter() {
                    match event {
                        Event::Quit {..} |
                            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'mainloop,
                            Event::Window{win_event: WindowEvent::Resized(x, y), ..} => {
                                // TODO
                            }
                        _ => {}
                    }
                }

                let scroll_pos = time % (height as i32 / 2);
                time += 1;

                texture.with_lock(None, |buffer: &mut [u8], pitch: usize| {
                    let y = scroll_pos as usize;
                    for x in 0..fft_size/2 {
                        let value = ((1.0 + fft_output[x].norm()).ln() * 128.0).min(255.0) as u8;
                        let offset = y * pitch + x * 3;
                        buffer[offset] = value;
                        buffer[offset+1] = value;
                        buffer[offset+2] = value;
                        let offset = (y+height as usize/2) * pitch + x * 3;
                        buffer[offset] = value;
                        buffer[offset+1] = value;
                        buffer[offset+2] = value;
                    }
                }).unwrap();

                canvas.clear();
                canvas.copy(&texture, Some(Rect::new(0, scroll_pos+1, (fft_size/2) as u32, height/2)), None).unwrap();
                canvas.present();

                //::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
            }

            process::exit(0);
        });
    }
}
<|endoftext|>


<commit_before>use super::bitmask::BitMask;
use super::EMPTY;
use core::{mem, ptr};

// Use the native word size as the group size. Using a 64-bit group size on
// a 32-bit architecture will just end up being more expensive because
// shifts and multiplies will need to be emulated.
#[cfg(any(
    target_pointer_width = "64",
    target_arch = "aarch64",
    target_arch = "x86_64",
))]
type GroupWord = u64;
#[cfg(all(
    target_pointer_width = "32",
    not(target_arch = "aarch64"),
    not(target_arch = "x86_64"),
))]
type GroupWord = u32;

pub type BitMaskWord = GroupWord;
pub const BITMASK_STRIDE: usize = 8;
// We only care about the highest bit of each byte for the mask.
#[allow(clippy::cast_possible_truncation, clippy::unnecessary_cast)]
pub const BITMASK_MASK: BitMaskWord = 0x8080_8080_8080_8080_u64 as GroupWord;

/// Helper function to replicate a byte across a `GroupWord`.
#[inline]
fn repeat(byte: u8) -> GroupWord {
    let repeat = GroupWord::from(byte);
    let repeat = repeat | repeat.wrapping_shl(8);
    let repeat = repeat | repeat.wrapping_shl(16);
    // This last line is a no-op with a 32-bit GroupWord
    repeat | repeat.wrapping_shl(32)
}

/// Abstraction over a group of control bytes which can be scanned in
/// parallel.
///
/// This implementation uses a word-sized integer.
#[derive(Copy, Clone)]
pub struct Group(GroupWord);

// We perform all operations in the native endianess, and convert to
// little-endian just before creating a BitMask. The can potentially
// enable the compiler to eliminate unnecessary byte swaps if we are
// only checking whether a BitMask is empty.
#[allow(clippy::use_self)]
impl Group {
    /// Number of bytes in the group.
    pub const WIDTH: usize = mem::size_of::<Self>();

    /// Returns a full group of empty bytes, suitable for use as the initial
    /// value for an empty hash table. This value is explicitly declared as
    /// a static variable to ensure the address is consistent across dylibs.
    ///
    /// This is guaranteed to be aligned to the group size.
    #[inline]
    pub fn static_empty() -> &'static [u8] {
        union AlignedBytes {
            _align: Group,
            bytes: [u8; Group::WIDTH],
        };
        static ALIGNED_BYTES: AlignedBytes = AlignedBytes {
            bytes: [EMPTY; Group::WIDTH],
        };
        unsafe { &ALIGNED_BYTES.bytes }
    }

    /// Loads a group of bytes starting at the given address.
    #[inline]
    #[allow(clippy::cast_ptr_alignment)] // unaligned load
    pub unsafe fn load(ptr: *const u8) -> Self {
        Group(ptr::read_unaligned(ptr as *const _))
    }

    /// Loads a group of bytes starting at the given address, which must be
    /// aligned to `mem::align_of::<Group>()`.
    #[inline]
    #[allow(clippy::cast_ptr_alignment)]
    pub unsafe fn load_aligned(ptr: *const u8) -> Self {
        // FIXME: use align_offset once it stabilizes
        debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
        Group(ptr::read(ptr as *const _))
    }

    /// Stores the group of bytes to the given address, which must be
    /// aligned to `mem::align_of::<Group>()`.
    #[inline]
    #[allow(clippy::cast_ptr_alignment)]
    pub unsafe fn store_aligned(self, ptr: *mut u8) {
        // FIXME: use align_offset once it stabilizes
        debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
        ptr::write(ptr as *mut _, self.0);
    }

    /// Returns a `BitMask` indicating all bytes in the group which *may*
    /// have the given value.
    ///
    /// This function may return a false positive in certain cases where
    /// the byte in the group differs from the searched value only in its
    /// lowest bit. This is fine because:
    /// - This never happens for `EMPTY` and `DELETED`, only full entries.
    /// - The check for key equality will catch these.
    /// - This only happens if there is at least 1 true match.
    /// - The chance of this happening is very low (< 1% chance per byte).
    #[inline]
    pub fn match_byte(self, byte: u8) -> BitMask {
        // This algorithm is derived from
        // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord
        let cmp = self.0 ^ repeat(byte);
        BitMask((cmp.wrapping_sub(repeat(0x01)) & !cmp & repeat(0x80)).to_le())
    }

    /// Returns a `BitMask` indicating all bytes in the group which are
    /// `EMPTY`.
    #[inline]
    pub fn match_empty(self) -> BitMask {
        // If the high bit is set, then the byte must be either:
        // 1111_1111 (EMPTY) or 1000_0000 (DELETED).
        // So we can just check if the top two bits are 1 by ANDing them.
        BitMask((self.0 & (self.0 << 1) & repeat(0x80)).to_le())
    }

    /// Returns a `BitMask` indicating all bytes in the group which are
    /// `EMPTY` or `DELETED`.
    #[inline]
    pub fn match_empty_or_deleted(self) -> BitMask {
        // A byte is EMPTY or DELETED iff the high bit is set
        BitMask((self.0 & repeat(0x80)).to_le())
    }

    /// Returns a `BitMask` indicating all bytes in the group which are full.
    #[inline]
    pub fn match_full(self) -> BitMask {
        self.match_empty_or_deleted().invert()
    }

    /// Performs the following transformation on all bytes in the group:
    /// - `EMPTY => EMPTY`
    /// - `DELETED => EMPTY`
    /// - `FULL => DELETED`
    #[inline]
    pub fn convert_special_to_empty_and_full_to_deleted(self) -> Self {
        // Map high_bit = 1 (EMPTY or DELETED) to 1111_1111
        // and high_bit = 0 (FULL) to 1000_0000
        //
        // Here's this logic expanded to concrete values:
        //   let full = 1000_0000 (true) or 0000_0000 (false)
        //   !1000_0000 + 1 = 0111_1111 + 1 = 1000_0000 (no carry)
        //   !0000_0000 + 0 = 1111_1111 + 0 = 1111_1111 (no carry)
        let full = !self.0 & repeat(0x80);
        Group(!full + (full >> 7))
    }
}
<commit_msg>Auto merge of #150 - andjo403:repeat, r=Amanieu<commit_after>use super::bitmask::BitMask;
use super::EMPTY;
use core::{mem, ptr};

// Use the native word size as the group size. Using a 64-bit group size on
// a 32-bit architecture will just end up being more expensive because
// shifts and multiplies will need to be emulated.
#[cfg(any(
    target_pointer_width = "64",
    target_arch = "aarch64",
    target_arch = "x86_64",
))]
type GroupWord = u64;
#[cfg(all(
    target_pointer_width = "32",
    not(target_arch = "aarch64"),
    not(target_arch = "x86_64"),
))]
type GroupWord = u32;

pub type BitMaskWord = GroupWord;
pub const BITMASK_STRIDE: usize = 8;
// We only care about the highest bit of each byte for the mask.
#[allow(clippy::cast_possible_truncation, clippy::unnecessary_cast)]
pub const BITMASK_MASK: BitMaskWord = 0x8080_8080_8080_8080_u64 as GroupWord;

/// Helper function to replicate a byte across a `GroupWord`.
#[inline]
fn repeat(byte: u8) -> GroupWord {
    GroupWord::from_ne_bytes([byte; Group::WIDTH])
}

/// Abstraction over a group of control bytes which can be scanned in
/// parallel.
///
/// This implementation uses a word-sized integer.
#[derive(Copy, Clone)]
pub struct Group(GroupWord);

// We perform all operations in the native endianess, and convert to
// little-endian just before creating a BitMask. The can potentially
// enable the compiler to eliminate unnecessary byte swaps if we are
// only checking whether a BitMask is empty.
#[allow(clippy::use_self)]
impl Group {
    /// Number of bytes in the group.
    pub const WIDTH: usize = mem::size_of::<Self>();

    /// Returns a full group of empty bytes, suitable for use as the initial
    /// value for an empty hash table. This value is explicitly declared as
    /// a static variable to ensure the address is consistent across dylibs.
    ///
    /// This is guaranteed to be aligned to the group size.
    #[inline]
    pub fn static_empty() -> &'static [u8] {
        union AlignedBytes {
            _align: Group,
            bytes: [u8; Group::WIDTH],
        };
        static ALIGNED_BYTES: AlignedBytes = AlignedBytes {
            bytes: [EMPTY; Group::WIDTH],
        };
        unsafe { &ALIGNED_BYTES.bytes }
    }

    /// Loads a group of bytes starting at the given address.
    #[inline]
    #[allow(clippy::cast_ptr_alignment)] // unaligned load
    pub unsafe fn load(ptr: *const u8) -> Self {
        Group(ptr::read_unaligned(ptr as *const _))
    }

    /// Loads a group of bytes starting at the given address, which must be
    /// aligned to `mem::align_of::<Group>()`.
    #[inline]
    #[allow(clippy::cast_ptr_alignment)]
    pub unsafe fn load_aligned(ptr: *const u8) -> Self {
        // FIXME: use align_offset once it stabilizes
        debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
        Group(ptr::read(ptr as *const _))
    }

    /// Stores the group of bytes to the given address, which must be
    /// aligned to `mem::align_of::<Group>()`.
    #[inline]
    #[allow(clippy::cast_ptr_alignment)]
    pub unsafe fn store_aligned(self, ptr: *mut u8) {
        // FIXME: use align_offset once it stabilizes
        debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
        ptr::write(ptr as *mut _, self.0);
    }

    /// Returns a `BitMask` indicating all bytes in the group which *may*
    /// have the given value.
    ///
    /// This function may return a false positive in certain cases where
    /// the byte in the group differs from the searched value only in its
    /// lowest bit. This is fine because:
    /// - This never happens for `EMPTY` and `DELETED`, only full entries.
    /// - The check for key equality will catch these.
    /// - This only happens if there is at least 1 true match.
    /// - The chance of this happening is very low (< 1% chance per byte).
    #[inline]
    pub fn match_byte(self, byte: u8) -> BitMask {
        // This algorithm is derived from
        // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord
        let cmp = self.0 ^ repeat(byte);
        BitMask((cmp.wrapping_sub(repeat(0x01)) & !cmp & repeat(0x80)).to_le())
    }

    /// Returns a `BitMask` indicating all bytes in the group which are
    /// `EMPTY`.
    #[inline]
    pub fn match_empty(self) -> BitMask {
        // If the high bit is set, then the byte must be either:
        // 1111_1111 (EMPTY) or 1000_0000 (DELETED).
        // So we can just check if the top two bits are 1 by ANDing them.
        BitMask((self.0 & (self.0 << 1) & repeat(0x80)).to_le())
    }

    /// Returns a `BitMask` indicating all bytes in the group which are
    /// `EMPTY` or `DELETED`.
    #[inline]
    pub fn match_empty_or_deleted(self) -> BitMask {
        // A byte is EMPTY or DELETED iff the high bit is set
        BitMask((self.0 & repeat(0x80)).to_le())
    }

    /// Returns a `BitMask` indicating all bytes in the group which are full.
    #[inline]
    pub fn match_full(self) -> BitMask {
        self.match_empty_or_deleted().invert()
    }

    /// Performs the following transformation on all bytes in the group:
    /// - `EMPTY => EMPTY`
    /// - `DELETED => EMPTY`
    /// - `FULL => DELETED`
    #[inline]
    pub fn convert_special_to_empty_and_full_to_deleted(self) -> Self {
        // Map high_bit = 1 (EMPTY or DELETED) to 1111_1111
        // and high_bit = 0 (FULL) to 1000_0000
        //
        // Here's this logic expanded to concrete values:
        //   let full = 1000_0000 (true) or 0000_0000 (false)
        //   !1000_0000 + 1 = 0111_1111 + 1 = 1000_0000 (no carry)
        //   !0000_0000 + 0 = 1111_1111 + 0 = 1111_1111 (no carry)
        let full = !self.0 & repeat(0x80);
        Group(!full + (full >> 7))
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// 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.

use device::dev;
use a = device::attrib;

pub type MaterialHandle = int;  //placeholder
pub type VertexCount = u16;
pub type ElementCount = u16;

/// Describes a single attribute of a vertex buffer, including its type, name, etc.
#[deriving(Clone, PartialEq, Show)]
pub struct Attribute {
    /// Vertex buffer to contain the data
    pub buffer: super::BufferHandle,
    /// Number of elements per vertex
    pub elem_count: a::Count,
    /// Type of a single element
    pub elem_type: a::Type,
    /// Offset in bytes to the first vertex
    pub offset: a::Offset,
    /// Stride in bytes between consecutive vertices
    pub stride: a::Stride,
    /// A name to match the shader input
    pub name: String,
}

/// A trait implemented automatically for user vertex structure by
/// `#[vertex_format] attribute
pub trait VertexFormat {
    fn generate(Option<Self>, super::BufferHandle) -> Vec<Attribute>;
}

/// Describes what geometric primitives are created from vertex data.
#[deriving(Clone, Show)]
pub enum PrimitiveType {
    /// Each vertex represents a single point.
    Point,
    /// Each pair of vertices represent a single line segment. For example, with `[a, b, c, d,
    /// e]`, `a` and `b` form a line, `c` and `d` form a line, and `e` is discarded.
    Line,
    /// Every two consecutive vertices represent a single line segment. Visually forms a "path" of
    /// lines, as they are all connected. For example, with `[a, b, c]`, `a` and `b` form a line
    /// line, and `b` and `c` form a line.
    LineStrip,
    /// Each triplet of vertices represent a single triangle. For example, with `[a, b, c, d, e]`,
    /// `a`, `b`, and `c` form a triangle, `d` and `e` are discarded.
    TriangleList,
    /// Every three consecutive vertices represent a single triangle. For example, with `[a, b, c,
    /// d]`, `a`, `b`, and `c` form a triangle, and `b`, `c`, and `d` form a triangle.
    TriangleStrip,
    //Quad,
}

/// Describes geometry to render.
///
/// The best way to create a `Mesh` is to use the `Builder` in this module.
#[deriving(Clone, Show)]
pub struct Mesh {
    /// What primitives to form out of the vertex data.
    pub prim_type: PrimitiveType,
    /// Number of vertices in the mesh.
    pub num_vertices: VertexCount,
    /// Vertex attributes to use.
    pub attributes: Vec<Attribute>,
}

impl Mesh {
    /// Create a new mesh, which is a `TriangleList` with no attributes and `nv` vertices.
    pub fn new(nv: VertexCount) -> Mesh {
        Mesh {
            prim_type: TriangleList,
            num_vertices: nv,
            attributes: Vec::new(),
        }
    }

    /// Create a new `Mesh` from a struct that implements `VertexFormat` and a buffer.
    pub fn from<V: VertexFormat>(buf: super::BufferHandle, nv: VertexCount) -> Mesh {
        Mesh {
            prim_type: TriangleList,
            num_vertices: nv,
            attributes: VertexFormat::generate(None::<V>, buf),
        }
    }
}

/// Description of a piece of a `Mesh` data to render.
#[deriving(Clone, Show)]
pub enum Slice  {
    /// Render vertex data directly from the `Mesh`'s buffer, using only the vertices between the two
    /// endpoints.
    VertexSlice(VertexCount, VertexCount),
    /// The `IndexSlice` buffer contains a list of indices into the `Mesh` data, so every vertex
    /// attribute does not need to be duplicated, only its position in the `Mesh`.  For example,
    /// when drawing a square, two triangles are needed.  Using only `VertexSlice`, one would need
    /// 6 separate vertices, 3 for each triangle. However, two of the vertices will be identical,
    /// wasting space for the duplicated attributes.  Instead, the `Mesh` can store 4 vertices and
    /// an `IndexSlice` can be used instead.
    IndexSlice(dev::Buffer, ElementCount, ElementCount),
}

/// A slice of a mesh, with a given material.
#[deriving(Clone, Show)]
pub struct SubMesh {
    pub mesh: Mesh,
    pub material: MaterialHandle,
    pub slice: Slice,
}
<commit_msg>Clarify `Slice`<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// 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.

use device::dev;
use a = device::attrib;

pub type MaterialHandle = int;  //placeholder
pub type VertexCount = u16;
pub type ElementCount = u16;

/// Describes a single attribute of a vertex buffer, including its type, name, etc.
#[deriving(Clone, PartialEq, Show)]
pub struct Attribute {
    /// Vertex buffer to contain the data
    pub buffer: super::BufferHandle,
    /// Number of elements per vertex
    pub elem_count: a::Count,
    /// Type of a single element
    pub elem_type: a::Type,
    /// Offset in bytes to the first vertex
    pub offset: a::Offset,
    /// Stride in bytes between consecutive vertices
    pub stride: a::Stride,
    /// A name to match the shader input
    pub name: String,
}

/// A trait implemented automatically for user vertex structure by
/// `#[vertex_format] attribute
pub trait VertexFormat {
    fn generate(Option<Self>, super::BufferHandle) -> Vec<Attribute>;
}

/// Describes what geometric primitives are created from vertex data.
#[deriving(Clone, Show)]
pub enum PrimitiveType {
    /// Each vertex represents a single point.
    Point,
    /// Each pair of vertices represent a single line segment. For example, with `[a, b, c, d,
    /// e]`, `a` and `b` form a line, `c` and `d` form a line, and `e` is discarded.
    Line,
    /// Every two consecutive vertices represent a single line segment. Visually forms a "path" of
    /// lines, as they are all connected. For example, with `[a, b, c]`, `a` and `b` form a line
    /// line, and `b` and `c` form a line.
    LineStrip,
    /// Each triplet of vertices represent a single triangle. For example, with `[a, b, c, d, e]`,
    /// `a`, `b`, and `c` form a triangle, `d` and `e` are discarded.
    TriangleList,
    /// Every three consecutive vertices represent a single triangle. For example, with `[a, b, c,
    /// d]`, `a`, `b`, and `c` form a triangle, and `b`, `c`, and `d` form a triangle.
    TriangleStrip,
    //Quad,
}

/// Describes geometry to render.
///
/// The best way to create a `Mesh` is to use the `Builder` in this module.
#[deriving(Clone, Show)]
pub struct Mesh {
    /// What primitives to form out of the vertex data.
    pub prim_type: PrimitiveType,
    /// Number of vertices in the mesh.
    pub num_vertices: VertexCount,
    /// Vertex attributes to use.
    pub attributes: Vec<Attribute>,
}

impl Mesh {
    /// Create a new mesh, which is a `TriangleList` with no attributes and `nv` vertices.
    pub fn new(nv: VertexCount) -> Mesh {
        Mesh {
            prim_type: TriangleList,
            num_vertices: nv,
            attributes: Vec::new(),
        }
    }

    /// Create a new `Mesh` from a struct that implements `VertexFormat` and a buffer.
    pub fn from<V: VertexFormat>(buf: super::BufferHandle, nv: VertexCount) -> Mesh {
        Mesh {
            prim_type: TriangleList,
            num_vertices: nv,
            attributes: VertexFormat::generate(None::<V>, buf),
        }
    }
}

/// Description of a subset of `Mesh` data to render.
#[deriving(Clone, Show)]
pub enum Slice  {
    /// Render vertex data directly from the `Mesh`'s buffer, using only the vertices between the two
    /// endpoints.
    VertexSlice(VertexCount, VertexCount),
    /// The `IndexSlice` buffer contains a list of indices into the `Mesh` data, so every vertex
    /// attribute does not need to be duplicated, only its position in the `Mesh`.  For example,
    /// when drawing a square, two triangles are needed.  Using only `VertexSlice`, one would need
    /// 6 separate vertices, 3 for each triangle. However, two of the vertices will be identical,
    /// wasting space for the duplicated attributes.  Instead, the `Mesh` can store 4 vertices and
    /// an `IndexSlice` can be used instead.
    IndexSlice(dev::Buffer, ElementCount, ElementCount),
}

/// A slice of a mesh, with a given material.
#[deriving(Clone, Show)]
pub struct SubMesh {
    pub mesh: Mesh,
    pub material: MaterialHandle,
    pub slice: Slice,
}
<|endoftext|>


<commit_before>use std::env;
use std::rc::Rc;
use std::cell::RefCell;
use sfml::graphics::{RenderWindow, RenderTarget, Font};
use sfml::window::{ContextSettings, VideoMode, Close};
use sfml::window::event;
use sfml::window::keyboard::Key;
use sfml::window::mouse::MouseButton;
use sfml::graphics::Color;
use sfml::system::vector2::Vector2i;
use na::{Pnt2, Pnt3, Iso2};
use na;
use nphysics::world::World;
use nphysics::object::RigidBody;
use nphysics::detection::joint::{Fixed, Anchor};
use camera::Camera;
use fps::Fps;
use engine::GraphicsManager;
use draw_helper;

fn usage(exe_name: &str) {
    println!("Usage: {} [OPTION] ", exe_name);
    println!("");
    println!("Options:");
    println!("    --help  - prints this help message and exits.");
    println!("    --pause - do not start the simulation right away.");
    println!("");
    println!("The following keyboard commands are supported:");
    println!("    t     - pause/continue the simulation.");
    println!("    s     - pause then execute only one simulation step.");
    println!("    space - display/hide contacts.");
}

#[derive(PartialEq)]
enum RunMode {
    Running,
    Stop,
    Step
}

pub struct Testbed<'a> {
    world:    World,
    window:   RenderWindow,
    graphics: GraphicsManager<'a>
}

struct TestbedState<'a> {
    running: RunMode,
    draw_colls: bool,
    camera: Camera,
    fps: Fps<'a>,
    grabbed_object: Option<Rc<RefCell<RigidBody>>>,
    grabbed_object_joint: Option<Rc<RefCell<Fixed>>>,
}

impl<'a> TestbedState<'a> {
    fn new(fnt: &'a Font) -> TestbedState<'a> {
        TestbedState{
            running: RunMode::Running,
            draw_colls: false,
            camera: Camera::new(),
            fps: Fps::new(&fnt),
            grabbed_object: None,
            grabbed_object_joint: None,
        }
    }
}

impl<'a> Testbed<'a> {
    pub fn new_empty() -> Testbed<'a> {
        let mode    = VideoMode::new_init(800, 600, 32);
        let setting = ContextSettings {
            depth_bits:         10,
            stencil_bits:       10,
            antialiasing_level: 2,
            major_version:      0,
            minor_version:      1
        };
        let window =
            match RenderWindow::new(mode, "nphysics 2d demo", Close, &setting) {
                Some(rwindow) => rwindow,
                None          => panic!("Error on creating the sfml window.")
            };
        let graphics = GraphicsManager::new();

        Testbed {
            world:    World::new(),
            window:   window,
            graphics: graphics
        }
    }

    pub fn new(world: World) -> Testbed<'a> {
        let mut res = Testbed::new_empty();

        res.set_world(world);

        res
    }

    pub fn set_world(&mut self, world: World) {
        self.world = world;
        self.graphics.clear();

        for rb in self.world.bodies() {
            self.graphics.add(rb.clone());
        }
    }

    pub fn set_color(&mut self, body: &Rc<RefCell<RigidBody>>, color: Pnt3<f32>) {
        let color = Pnt3::new(
            (color.x * 255.0) as u8,
            (color.y * 255.0) as u8,
            (color.z * 255.0) as u8
        );

        self.graphics.set_color(body, color);
    }

    pub fn run(&mut self) {
        let font_mem = include_bytes!("Inconsolata.otf");
        let     fnt  = Font::new_from_memory(font_mem).unwrap();

        let mut state = TestbedState::new(&fnt);

        let mut args    = env::args();

        if args.len() > 1 {
            let exname = args.next().unwrap();
            for arg in args {
                if &arg[..] == "--help" || &arg[..] == "-h" {
                    usage(&exname[..]);
                    return;
                }
                else if &arg[..] == "--pause" {
                    state.running = RunMode::Stop;
                }
            }
        }

        self.window.set_framerate_limit(60);

        self.foo(state);

        self.window.close();
    }

    fn foo(&mut self, mut state: TestbedState) {
        while self.window.is_open() {
            self.process_events(&mut state);

            self.window.clear(&Color::black());

            state.fps.reset();

            if state.running != RunMode::Stop {
                self.world.step(0.016);
            }

            if state.running == RunMode::Step {
                state.running = RunMode::Stop;
            }
            state.fps.register_delta();
            self.graphics.draw(&mut self.window, &state.camera);

            state.camera.activate_scene(&mut self.window);
            if state.draw_colls {
                draw_helper::draw_colls(&mut self.window, &mut self.world);
            }

            state.camera.activate_ui(&mut self.window);
            state.fps.draw_registered(&mut self.window);

            self.window.display();
        }
    }

    fn process_events(&mut self, mut state: &mut TestbedState) {
        loop {
            match self.window.poll_event() {
                event::KeyPressed{code, ..} => self.process_key_press(&mut state, code),
                event::MouseButtonPressed{button, x, y} => self.process_mouse_press(&mut state, button, x, y),
                event::MouseButtonReleased{button, x, y} => self.process_mouse_release(&mut state, button, x, y),
                event::MouseMoved{x, y} => self.process_mouse_moved(&mut state, x, y),
                event::Closed  => self.window.close(),
                event::NoEvent => break,
                e              => state.camera.handle_event(&e)
            }
        }
    }

    fn process_key_press(&mut self, state: &mut TestbedState, code: Key) {
        match code {
            Key::Escape => self.window.close(),
            Key::S      => state.running = RunMode::Step,
            Key::Space  => state.draw_colls = !state.draw_colls,
            Key::T      => {
                if state.running == RunMode::Stop {
                    state.running = RunMode::Running;
                }
                else {
                    state.running = RunMode::Stop;
                }
            },
            _                => { }
        }
    }

    fn process_mouse_press(&mut self, state: &mut TestbedState, button: MouseButton, x: i32, y: i32) {
        match button {
            MouseButton::MouseLeft => {
                let mapped_coords = state.camera.map_pixel_to_coords(Vector2i::new(x, y));
                let mapped_point = Pnt2::new(mapped_coords.x, mapped_coords.y);
                self.world.interferences_with_point(&mapped_point, |b| {
                    if b.borrow().can_move() {
                        state.grabbed_object = Some(b.clone())
                    }
                });

                match state.grabbed_object {
                    Some(ref b) => {
                        for node in self.graphics.body_to_scene_node(b).unwrap().iter_mut() {
                            match state.grabbed_object_joint {
                                Some(ref j) => self.world.remove_fixed(j),
                                None        => { }
                            }

                            let _1: Iso2<f32> = na::one();
                            let attach2 = na::append_translation(&_1, mapped_point.as_vec());
                            let attach1 = na::inv(&na::transformation(b.borrow().position())).unwrap() * attach2;
                            let anchor1 = Anchor::new(Some(state.grabbed_object.as_ref().unwrap().clone()), attach1);
                            let anchor2 = Anchor::new(None, attach2);
                            let joint = Fixed::new(anchor1, anchor2);
                            state.grabbed_object_joint = Some(self.world.add_fixed(joint));
                            node.select()
                        }
                    },
                    None => { }
                }
            },
            _ => {
                state.camera.handle_event(&event::MouseButtonPressed{ button: button, x: x, y: y })
            }
        }
    }

    fn process_mouse_release(&mut self, state: &mut TestbedState, button: MouseButton, x: i32, y: i32) {
        match button {
            MouseButton::MouseLeft => {
                match state.grabbed_object {
                    Some(ref b) => {
                        for node in self.graphics.body_to_scene_node(b).unwrap().iter_mut() {
                            node.unselect()
                        }
                    },
                    None => { }
                }

                match state.grabbed_object_joint {
                    Some(ref j) => self.world.remove_fixed(j),
                    None => { }
                }

                state.grabbed_object = None;
                state.grabbed_object_joint = None;
            },
            _ => {
                state.camera.handle_event(&event::MouseButtonReleased{ button: button, x: x, y: y })
            }
        }
    }

    fn process_mouse_moved(&mut self, state: &mut TestbedState, x: i32, y: i32) {
        let mapped_coords = state.camera.map_pixel_to_coords(Vector2i::new(x, y));
        let mapped_point = Pnt2::new(mapped_coords.x, mapped_coords.y);
        let _1: Iso2<f32> = na::one();
        let attach2 = na::append_translation(&_1, (mapped_point).as_vec());
        match state.grabbed_object {
            Some(_) => {
                let joint = state.grabbed_object_joint.as_ref().unwrap();
                joint.borrow_mut().set_local2(attach2);
            },
            None => state.camera.handle_event(&event::MouseMoved{x: x, y: y})
        };
    }
}
<commit_msg>Factor out branching statements to unify abstraction level of main loop<commit_after>use std::env;
use std::rc::Rc;
use std::cell::RefCell;
use sfml::graphics::{RenderWindow, RenderTarget, Font};
use sfml::window::{ContextSettings, VideoMode, Close};
use sfml::window::event;
use sfml::window::keyboard::Key;
use sfml::window::mouse::MouseButton;
use sfml::graphics::Color;
use sfml::system::vector2::Vector2i;
use na::{Pnt2, Pnt3, Iso2};
use na;
use nphysics::world::World;
use nphysics::object::RigidBody;
use nphysics::detection::joint::{Fixed, Anchor};
use camera::Camera;
use fps::Fps;
use engine::GraphicsManager;
use draw_helper;

fn usage(exe_name: &str) {
    println!("Usage: {} [OPTION] ", exe_name);
    println!("");
    println!("Options:");
    println!("    --help  - prints this help message and exits.");
    println!("    --pause - do not start the simulation right away.");
    println!("");
    println!("The following keyboard commands are supported:");
    println!("    t     - pause/continue the simulation.");
    println!("    s     - pause then execute only one simulation step.");
    println!("    space - display/hide contacts.");
}

#[derive(PartialEq)]
enum RunMode {
    Running,
    Stop,
    Step
}

pub struct Testbed<'a> {
    world:    World,
    window:   RenderWindow,
    graphics: GraphicsManager<'a>
}

struct TestbedState<'a> {
    running: RunMode,
    draw_colls: bool,
    camera: Camera,
    fps: Fps<'a>,
    grabbed_object: Option<Rc<RefCell<RigidBody>>>,
    grabbed_object_joint: Option<Rc<RefCell<Fixed>>>,
}

impl<'a> TestbedState<'a> {
    fn new(fnt: &'a Font) -> TestbedState<'a> {
        TestbedState{
            running: RunMode::Running,
            draw_colls: false,
            camera: Camera::new(),
            fps: Fps::new(&fnt),
            grabbed_object: None,
            grabbed_object_joint: None,
        }
    }
}

impl<'a> Testbed<'a> {
    pub fn new_empty() -> Testbed<'a> {
        let mode    = VideoMode::new_init(800, 600, 32);
        let setting = ContextSettings {
            depth_bits:         10,
            stencil_bits:       10,
            antialiasing_level: 2,
            major_version:      0,
            minor_version:      1
        };
        let window =
            match RenderWindow::new(mode, "nphysics 2d demo", Close, &setting) {
                Some(rwindow) => rwindow,
                None          => panic!("Error on creating the sfml window.")
            };
        let graphics = GraphicsManager::new();

        Testbed {
            world:    World::new(),
            window:   window,
            graphics: graphics
        }
    }

    pub fn new(world: World) -> Testbed<'a> {
        let mut res = Testbed::new_empty();

        res.set_world(world);

        res
    }

    pub fn set_world(&mut self, world: World) {
        self.world = world;
        self.graphics.clear();

        for rb in self.world.bodies() {
            self.graphics.add(rb.clone());
        }
    }

    pub fn set_color(&mut self, body: &Rc<RefCell<RigidBody>>, color: Pnt3<f32>) {
        let color = Pnt3::new(
            (color.x * 255.0) as u8,
            (color.y * 255.0) as u8,
            (color.z * 255.0) as u8
        );

        self.graphics.set_color(body, color);
    }

    pub fn run(&mut self) {
        let font_mem = include_bytes!("Inconsolata.otf");
        let     fnt  = Font::new_from_memory(font_mem).unwrap();

        let mut state = TestbedState::new(&fnt);

        let mut args    = env::args();

        if args.len() > 1 {
            let exname = args.next().unwrap();
            for arg in args {
                if &arg[..] == "--help" || &arg[..] == "-h" {
                    usage(&exname[..]);
                    return;
                }
                else if &arg[..] == "--pause" {
                    state.running = RunMode::Stop;
                }
            }
        }

        self.window.set_framerate_limit(60);

        self.foo(state);

        self.window.close();
    }

    fn foo(&mut self, mut state: TestbedState) {
        while self.window.is_open() {
            self.process_events(&mut state);

            self.window.clear(&Color::black());

            state.fps.reset();

            self.progress_world(&mut state);

            state.fps.register_delta();

            self.graphics.draw(&mut self.window, &state.camera);

            state.camera.activate_scene(&mut self.window);
            self.draw_collisions(&mut state);

            state.camera.activate_ui(&mut self.window);
            state.fps.draw_registered(&mut self.window);

            self.window.display();
        }
    }

    fn process_events(&mut self, mut state: &mut TestbedState) {
        loop {
            match self.window.poll_event() {
                event::KeyPressed{code, ..} => self.process_key_press(&mut state, code),
                event::MouseButtonPressed{button, x, y} => self.process_mouse_press(&mut state, button, x, y),
                event::MouseButtonReleased{button, x, y} => self.process_mouse_release(&mut state, button, x, y),
                event::MouseMoved{x, y} => self.process_mouse_moved(&mut state, x, y),
                event::Closed  => self.window.close(),
                event::NoEvent => break,
                e              => state.camera.handle_event(&e)
            }
        }
    }

    fn process_key_press(&mut self, state: &mut TestbedState, code: Key) {
        match code {
            Key::Escape => self.window.close(),
            Key::S      => state.running = RunMode::Step,
            Key::Space  => state.draw_colls = !state.draw_colls,
            Key::T      => {
                if state.running == RunMode::Stop {
                    state.running = RunMode::Running;
                }
                else {
                    state.running = RunMode::Stop;
                }
            },
            _                => { }
        }
    }

    fn process_mouse_press(&mut self, state: &mut TestbedState, button: MouseButton, x: i32, y: i32) {
        match button {
            MouseButton::MouseLeft => {
                let mapped_coords = state.camera.map_pixel_to_coords(Vector2i::new(x, y));
                let mapped_point = Pnt2::new(mapped_coords.x, mapped_coords.y);
                self.world.interferences_with_point(&mapped_point, |b| {
                    if b.borrow().can_move() {
                        state.grabbed_object = Some(b.clone())
                    }
                });

                match state.grabbed_object {
                    Some(ref b) => {
                        for node in self.graphics.body_to_scene_node(b).unwrap().iter_mut() {
                            match state.grabbed_object_joint {
                                Some(ref j) => self.world.remove_fixed(j),
                                None        => { }
                            }

                            let _1: Iso2<f32> = na::one();
                            let attach2 = na::append_translation(&_1, mapped_point.as_vec());
                            let attach1 = na::inv(&na::transformation(b.borrow().position())).unwrap() * attach2;
                            let anchor1 = Anchor::new(Some(state.grabbed_object.as_ref().unwrap().clone()), attach1);
                            let anchor2 = Anchor::new(None, attach2);
                            let joint = Fixed::new(anchor1, anchor2);
                            state.grabbed_object_joint = Some(self.world.add_fixed(joint));
                            node.select()
                        }
                    },
                    None => { }
                }
            },
            _ => {
                state.camera.handle_event(&event::MouseButtonPressed{ button: button, x: x, y: y })
            }
        }
    }

    fn process_mouse_release(&mut self, state: &mut TestbedState, button: MouseButton, x: i32, y: i32) {
        match button {
            MouseButton::MouseLeft => {
                match state.grabbed_object {
                    Some(ref b) => {
                        for node in self.graphics.body_to_scene_node(b).unwrap().iter_mut() {
                            node.unselect()
                        }
                    },
                    None => { }
                }

                match state.grabbed_object_joint {
                    Some(ref j) => self.world.remove_fixed(j),
                    None => { }
                }

                state.grabbed_object = None;
                state.grabbed_object_joint = None;
            },
            _ => {
                state.camera.handle_event(&event::MouseButtonReleased{ button: button, x: x, y: y })
            }
        }
    }

    fn process_mouse_moved(&mut self, state: &mut TestbedState, x: i32, y: i32) {
        let mapped_coords = state.camera.map_pixel_to_coords(Vector2i::new(x, y));
        let mapped_point = Pnt2::new(mapped_coords.x, mapped_coords.y);
        let _1: Iso2<f32> = na::one();
        let attach2 = na::append_translation(&_1, (mapped_point).as_vec());
        match state.grabbed_object {
            Some(_) => {
                let joint = state.grabbed_object_joint.as_ref().unwrap();
                joint.borrow_mut().set_local2(attach2);
            },
            None => state.camera.handle_event(&event::MouseMoved{x: x, y: y})
        };
    }

    fn progress_world(&mut self, state: &mut TestbedState) {
        if state.running != RunMode::Stop {
            self.world.step(0.016);
        }

        if state.running == RunMode::Step {
            state.running = RunMode::Stop;
        }
    }

    fn draw_collisions(&mut self, state: &mut TestbedState) {
        if state.draw_colls {
            draw_helper::draw_colls(&mut self.window, &mut self.world);
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Optimize parsing of ranges<commit_after><|endoftext|>


<commit_before>
pub mod error;
pub use self::error::ParseError;
<commit_msg>rfc5322: Token and Streamable traits<commit_after>
pub mod error;
pub use self::error::ParseError;

use std::io::Write;
use std::io::Error as IoError;

pub trait Parsable: Sized {
    /// Parse the object off of the beginning of the `input`.  If found, returns Some object,
    /// and a slice containing the remainer of the input.
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError>;
}

pub trait Streamable {
    /// Serializes and sends the content out to `w`, returning the number of bytes written.
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError>;
}
<|endoftext|>