<commit_before>#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![feature(rustc_private)]

// FIXME: switch to something more ergonomic here, once available.
// (Currently there is no way to opt into sysroot crates without `extern crate`.)
#[allow(unused_extern_crates)]
extern crate rustc_driver;
#[allow(unused_extern_crates)]
extern crate rustc_interface;

use rustc_interface::interface;
use rustc_tools_util::*;

use std::path::{Path, PathBuf};
use std::process::{exit, Command};

mod lintlist;

/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
/// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
fn arg_value<'a>(
    args: impl IntoIterator<Item = &'a String>,
    find_arg: &str,
    pred: impl Fn(&str) -> bool,
) -> Option<&'a str> {
    let mut args = args.into_iter().map(String::as_str);

    while let Some(arg) = args.next() {
        let arg: Vec<_> = arg.splitn(2, '=').collect();
        if arg.get(0) != Some(&find_arg) {
            continue;
        }

        let value = arg.get(1).cloned().or_else(|| args.next());
        if value.as_ref().map_or(false, |p| pred(p)) {
            return value;
        }
    }
    None
}

#[test]
fn test_arg_value() {
    let args: Vec<_> = ["--bar=bar", "--foobar", "123", "--foo"]
        .iter()
        .map(std::string::ToString::to_string)
        .collect();

    assert_eq!(arg_value(None, "--foobar", |_| true), None);
    assert_eq!(arg_value(&args, "--bar", |_| false), None);
    assert_eq!(arg_value(&args, "--bar", |_| true), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "bar"), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "123"), Some("123"));
    assert_eq!(arg_value(&args, "--foo", |_| true), None);
}

#[allow(clippy::too_many_lines)]

struct ClippyCallbacks;

impl rustc_driver::Callbacks for ClippyCallbacks {
    fn after_parsing(&mut self, compiler: &interface::Compiler) -> rustc_driver::Compilation {
        let sess = compiler.session();
        let mut registry = rustc_driver::plugin::registry::Registry::new(
            sess,
            compiler
                .parse()
                .expect(
                    "at this compilation stage \
                     the crate must be parsed",
                )
                .peek()
                .span,
        );
        registry.args_hidden = Some(Vec::new());

        let conf = clippy_lints::read_conf(&registry);
        clippy_lints::register_plugins(&mut registry, &conf);

        let rustc_driver::plugin::registry::Registry {
            early_lint_passes,
            late_lint_passes,
            lint_groups,
            llvm_passes,
            attributes,
            ..
        } = registry;
        let mut ls = sess.lint_store.borrow_mut();
        for pass in early_lint_passes {
            ls.register_early_pass(Some(sess), true, false, pass);
        }
        for pass in late_lint_passes {
            ls.register_late_pass(Some(sess), true, false, false, pass);
        }

        for (name, (to, deprecated_name)) in lint_groups {
            ls.register_group(Some(sess), true, name, deprecated_name, to);
        }
        clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf);
        clippy_lints::register_renamed(&mut ls);

        sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
        sess.plugin_attributes.borrow_mut().extend(attributes);

        // Continue execution
        rustc_driver::Compilation::Continue
    }
}

#[allow(clippy::find_map, clippy::filter_map)]
fn describe_lints() {
    use lintlist::*;
    use std::collections::HashSet;

    println!(
        "
Available lint options:
    -W <foo>           Warn about <foo>
    -A <foo>           Allow <foo>
    -D <foo>           Deny <foo>
    -F <foo>           Forbid <foo> (deny <foo> and all attempts to override)

"
    );

    let lint_level = |lint: &Lint| {
        LINT_LEVELS
            .iter()
            .find(|level_mapping| level_mapping.0 == lint.group)
            .map(|(_, level)| match level {
                Level::Allow => "allow",
                Level::Warn => "warn",
                Level::Deny => "deny",
            })
            .unwrap()
    };

    let mut lints: Vec<_> = ALL_LINTS.iter().collect();
    // The sort doesn't case-fold but it's doubtful we care.
    lints.sort_by_cached_key(|x: &&Lint| (lint_level(x), x.name));

    let max_lint_name_len = lints
        .iter()
        .map(|lint| lint.name.len())
        .map(|len| len + "clippy::".len())
        .max()
        .unwrap_or(0);

    let padded = |x: &str| {
        let mut s = " ".repeat(max_lint_name_len - x.chars().count());
        s.push_str(x);
        s
    };

    let scoped = |x: &str| format!("clippy::{}", x);

    let lint_groups: HashSet<_> = lints.iter().map(|lint| lint.group).collect();

    println!("Lint checks provided by clippy:\n");
    println!("    {}  {:7.7}  meaning", padded("name"), "default");
    println!("    {}  {:7.7}  -------", padded("----"), "-------");

    let print_lints = |lints: &[&Lint]| {
        for lint in lints {
            let name = lint.name.replace("_", "-");
            println!(
                "    {}  {:7.7}  {}",
                padded(&scoped(&name)),
                lint_level(lint),
                lint.desc
            );
        }
        println!("\n");
    };

    print_lints(&lints);

    let max_group_name_len = std::cmp::max(
        "clippy::all".len(),
        lint_groups
            .iter()
            .map(|group| group.len())
            .map(|len| len + "clippy::".len())
            .max()
            .unwrap_or(0),
    );

    let padded_group = |x: &str| {
        let mut s = " ".repeat(max_group_name_len - x.chars().count());
        s.push_str(x);
        s
    };

    println!("Lint groups provided by clippy:\n");
    println!("    {}  sub-lints", padded_group("name"));
    println!("    {}  ---------", padded_group("----"));
    println!("    {}  the set of all clippy lints", padded_group("clippy::all"));

    let print_lint_groups = || {
        for group in lint_groups {
            let name = group.to_lowercase().replace("_", "-");
            let desc = lints
                .iter()
                .filter(|&lint| lint.group == group)
                .map(|lint| lint.name)
                .map(|name| name.replace("_", "-"))
                .collect::<Vec<String>>()
                .join(", ");
            println!("    {}  {}", padded_group(&scoped(&name)), desc);
        }
        println!("\n");
    };

    print_lint_groups();
}

fn display_help() {
    println!(
        "\
Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    -V, --version            Print version info and exit

Other options are the same as `cargo check`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

You can use tool lints to allow or deny lints from your code, eg.:

    #[allow(clippy::needless_lifetimes)]
"
    );
}

pub fn main() {
    rustc_driver::init_rustc_env_logger();
    exit(
        rustc_driver::report_ices_to_stderr_if_any(move || {
            use std::env;

            if std::env::args().any(|a| a == "--version" || a == "-V") {
                let version_info = rustc_tools_util::get_version_info!();
                println!("{}", version_info);
                exit(0);
            }

            let mut orig_args: Vec<String> = env::args().collect();

            // Get the sysroot, looking from most specific to this invocation to the least:
            // - command line
            // - runtime environment
            //    - SYSROOT
            //    - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN
            // - sysroot from rustc in the path
            // - compile-time environment
            let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true);
            let have_sys_root_arg = sys_root_arg.is_some();
            let sys_root = sys_root_arg
                .map(PathBuf::from)
                .or_else(|| std::env::var("SYSROOT").ok().map(PathBuf::from))
                .or_else(|| {
                    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
                    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
                    home.and_then(|home| {
                        toolchain.map(|toolchain| {
                            let mut path = PathBuf::from(home);
                            path.push("toolchains");
                            path.push(toolchain);
                            path
                        })
                    })
                })
                .or_else(|| {
                    Command::new("rustc")
                        .arg("--print")
                        .arg("sysroot")
                        .output()
                        .ok()
                        .and_then(|out| String::from_utf8(out.stdout).ok())
                        .map(|s| PathBuf::from(s.trim()))
                })
                .or_else(|| option_env!("SYSROOT").map(PathBuf::from))
                .map(|pb| pb.to_string_lossy().to_string())
                .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");

            // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
            // We're invoking the compiler programmatically, so we ignore this/
            let wrapper_mode = Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref());

            if wrapper_mode {
                // we still want to be able to invoke it normally though
                orig_args.remove(1);
            }

            if !wrapper_mode && std::env::args().any(|a| a == "--help" || a == "-h") {
                display_help();
                exit(0);
            }

            let should_describe_lints = || {
                let args: Vec<_> = std::env::args().collect();
                args.windows(2).any(|args| {
                    args[1] == "help"
                        && match args[0].as_str() {
                            "-W" | "-A" | "-D" | "-F" => true,
                            _ => false,
                        }
                })
            };

            if !wrapper_mode && should_describe_lints() {
                describe_lints();
                exit(0);
            }

            // this conditional check for the --sysroot flag is there so users can call
            // `clippy_driver` directly
            // without having to pass --sysroot or anything
            let mut args: Vec<String> = if have_sys_root_arg {
                orig_args.clone()
            } else {
                orig_args
                    .clone()
                    .into_iter()
                    .chain(Some("--sysroot".to_owned()))
                    .chain(Some(sys_root))
                    .collect()
            };

            // this check ensures that dependencies are built but not linted and the final
            // crate is
            // linted but not built
            let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true")
                || arg_value(&orig_args, "--emit", |val| val.split(',').any(|e| e == "metadata")).is_some();

            if clippy_enabled {
                args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
                if let Ok(extra_args) = env::var("CLIPPY_ARGS") {
                    args.extend(extra_args.split("__CLIPPY_HACKERY__").filter_map(|s| {
                        if s.is_empty() {
                            None
                        } else {
                            Some(s.to_string())
                        }
                    }));
                }
            }

            let mut clippy = ClippyCallbacks;
            let mut default = rustc_driver::DefaultCallbacks;
            let callbacks: &mut (dyn rustc_driver::Callbacks + Send) =
                if clippy_enabled { &mut clippy } else { &mut default };
            let args = args;
            rustc_driver::run_compiler(&args, callbacks, None, None)
        })
        .and_then(|result| result)
        .is_err() as i32,
    )
}
<commit_msg>Changes to catch_fatal_errors in rustc driver<commit_after>#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![feature(rustc_private)]

// FIXME: switch to something more ergonomic here, once available.
// (Currently there is no way to opt into sysroot crates without `extern crate`.)
#[allow(unused_extern_crates)]
extern crate rustc_driver;
#[allow(unused_extern_crates)]
extern crate rustc_interface;

use rustc_interface::interface;
use rustc_tools_util::*;

use std::path::{Path, PathBuf};
use std::process::{exit, Command};

mod lintlist;

/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
/// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
fn arg_value<'a>(
    args: impl IntoIterator<Item = &'a String>,
    find_arg: &str,
    pred: impl Fn(&str) -> bool,
) -> Option<&'a str> {
    let mut args = args.into_iter().map(String::as_str);

    while let Some(arg) = args.next() {
        let arg: Vec<_> = arg.splitn(2, '=').collect();
        if arg.get(0) != Some(&find_arg) {
            continue;
        }

        let value = arg.get(1).cloned().or_else(|| args.next());
        if value.as_ref().map_or(false, |p| pred(p)) {
            return value;
        }
    }
    None
}

#[test]
fn test_arg_value() {
    let args: Vec<_> = ["--bar=bar", "--foobar", "123", "--foo"]
        .iter()
        .map(std::string::ToString::to_string)
        .collect();

    assert_eq!(arg_value(None, "--foobar", |_| true), None);
    assert_eq!(arg_value(&args, "--bar", |_| false), None);
    assert_eq!(arg_value(&args, "--bar", |_| true), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "bar"), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "123"), Some("123"));
    assert_eq!(arg_value(&args, "--foo", |_| true), None);
}

#[allow(clippy::too_many_lines)]

struct ClippyCallbacks;

impl rustc_driver::Callbacks for ClippyCallbacks {
    fn after_parsing(&mut self, compiler: &interface::Compiler) -> rustc_driver::Compilation {
        let sess = compiler.session();
        let mut registry = rustc_driver::plugin::registry::Registry::new(
            sess,
            compiler
                .parse()
                .expect(
                    "at this compilation stage \
                     the crate must be parsed",
                )
                .peek()
                .span,
        );
        registry.args_hidden = Some(Vec::new());

        let conf = clippy_lints::read_conf(&registry);
        clippy_lints::register_plugins(&mut registry, &conf);

        let rustc_driver::plugin::registry::Registry {
            early_lint_passes,
            late_lint_passes,
            lint_groups,
            llvm_passes,
            attributes,
            ..
        } = registry;
        let mut ls = sess.lint_store.borrow_mut();
        for pass in early_lint_passes {
            ls.register_early_pass(Some(sess), true, false, pass);
        }
        for pass in late_lint_passes {
            ls.register_late_pass(Some(sess), true, false, false, pass);
        }

        for (name, (to, deprecated_name)) in lint_groups {
            ls.register_group(Some(sess), true, name, deprecated_name, to);
        }
        clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf);
        clippy_lints::register_renamed(&mut ls);

        sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
        sess.plugin_attributes.borrow_mut().extend(attributes);

        // Continue execution
        rustc_driver::Compilation::Continue
    }
}

#[allow(clippy::find_map, clippy::filter_map)]
fn describe_lints() {
    use lintlist::*;
    use std::collections::HashSet;

    println!(
        "
Available lint options:
    -W <foo>           Warn about <foo>
    -A <foo>           Allow <foo>
    -D <foo>           Deny <foo>
    -F <foo>           Forbid <foo> (deny <foo> and all attempts to override)

"
    );

    let lint_level = |lint: &Lint| {
        LINT_LEVELS
            .iter()
            .find(|level_mapping| level_mapping.0 == lint.group)
            .map(|(_, level)| match level {
                Level::Allow => "allow",
                Level::Warn => "warn",
                Level::Deny => "deny",
            })
            .unwrap()
    };

    let mut lints: Vec<_> = ALL_LINTS.iter().collect();
    // The sort doesn't case-fold but it's doubtful we care.
    lints.sort_by_cached_key(|x: &&Lint| (lint_level(x), x.name));

    let max_lint_name_len = lints
        .iter()
        .map(|lint| lint.name.len())
        .map(|len| len + "clippy::".len())
        .max()
        .unwrap_or(0);

    let padded = |x: &str| {
        let mut s = " ".repeat(max_lint_name_len - x.chars().count());
        s.push_str(x);
        s
    };

    let scoped = |x: &str| format!("clippy::{}", x);

    let lint_groups: HashSet<_> = lints.iter().map(|lint| lint.group).collect();

    println!("Lint checks provided by clippy:\n");
    println!("    {}  {:7.7}  meaning", padded("name"), "default");
    println!("    {}  {:7.7}  -------", padded("----"), "-------");

    let print_lints = |lints: &[&Lint]| {
        for lint in lints {
            let name = lint.name.replace("_", "-");
            println!(
                "    {}  {:7.7}  {}",
                padded(&scoped(&name)),
                lint_level(lint),
                lint.desc
            );
        }
        println!("\n");
    };

    print_lints(&lints);

    let max_group_name_len = std::cmp::max(
        "clippy::all".len(),
        lint_groups
            .iter()
            .map(|group| group.len())
            .map(|len| len + "clippy::".len())
            .max()
            .unwrap_or(0),
    );

    let padded_group = |x: &str| {
        let mut s = " ".repeat(max_group_name_len - x.chars().count());
        s.push_str(x);
        s
    };

    println!("Lint groups provided by clippy:\n");
    println!("    {}  sub-lints", padded_group("name"));
    println!("    {}  ---------", padded_group("----"));
    println!("    {}  the set of all clippy lints", padded_group("clippy::all"));

    let print_lint_groups = || {
        for group in lint_groups {
            let name = group.to_lowercase().replace("_", "-");
            let desc = lints
                .iter()
                .filter(|&lint| lint.group == group)
                .map(|lint| lint.name)
                .map(|name| name.replace("_", "-"))
                .collect::<Vec<String>>()
                .join(", ");
            println!("    {}  {}", padded_group(&scoped(&name)), desc);
        }
        println!("\n");
    };

    print_lint_groups();
}

fn display_help() {
    println!(
        "\
Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    -V, --version            Print version info and exit

Other options are the same as `cargo check`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

You can use tool lints to allow or deny lints from your code, eg.:

    #[allow(clippy::needless_lifetimes)]
"
    );
}

pub fn main() {
    rustc_driver::init_rustc_env_logger();
    rustc_driver::install_ice_hook();
    exit(
        rustc_driver::catch_fatal_errors(move || {
            use std::env;

            if std::env::args().any(|a| a == "--version" || a == "-V") {
                let version_info = rustc_tools_util::get_version_info!();
                println!("{}", version_info);
                exit(0);
            }

            let mut orig_args: Vec<String> = env::args().collect();

            // Get the sysroot, looking from most specific to this invocation to the least:
            // - command line
            // - runtime environment
            //    - SYSROOT
            //    - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN
            // - sysroot from rustc in the path
            // - compile-time environment
            let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true);
            let have_sys_root_arg = sys_root_arg.is_some();
            let sys_root = sys_root_arg
                .map(PathBuf::from)
                .or_else(|| std::env::var("SYSROOT").ok().map(PathBuf::from))
                .or_else(|| {
                    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
                    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
                    home.and_then(|home| {
                        toolchain.map(|toolchain| {
                            let mut path = PathBuf::from(home);
                            path.push("toolchains");
                            path.push(toolchain);
                            path
                        })
                    })
                })
                .or_else(|| {
                    Command::new("rustc")
                        .arg("--print")
                        .arg("sysroot")
                        .output()
                        .ok()
                        .and_then(|out| String::from_utf8(out.stdout).ok())
                        .map(|s| PathBuf::from(s.trim()))
                })
                .or_else(|| option_env!("SYSROOT").map(PathBuf::from))
                .map(|pb| pb.to_string_lossy().to_string())
                .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");

            // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
            // We're invoking the compiler programmatically, so we ignore this/
            let wrapper_mode = Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref());

            if wrapper_mode {
                // we still want to be able to invoke it normally though
                orig_args.remove(1);
            }

            if !wrapper_mode && std::env::args().any(|a| a == "--help" || a == "-h") {
                display_help();
                exit(0);
            }

            let should_describe_lints = || {
                let args: Vec<_> = std::env::args().collect();
                args.windows(2).any(|args| {
                    args[1] == "help"
                        && match args[0].as_str() {
                            "-W" | "-A" | "-D" | "-F" => true,
                            _ => false,
                        }
                })
            };

            if !wrapper_mode && should_describe_lints() {
                describe_lints();
                exit(0);
            }

            // this conditional check for the --sysroot flag is there so users can call
            // `clippy_driver` directly
            // without having to pass --sysroot or anything
            let mut args: Vec<String> = if have_sys_root_arg {
                orig_args.clone()
            } else {
                orig_args
                    .clone()
                    .into_iter()
                    .chain(Some("--sysroot".to_owned()))
                    .chain(Some(sys_root))
                    .collect()
            };

            // this check ensures that dependencies are built but not linted and the final
            // crate is
            // linted but not built
            let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true")
                || arg_value(&orig_args, "--emit", |val| val.split(',').any(|e| e == "metadata")).is_some();

            if clippy_enabled {
                args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
                if let Ok(extra_args) = env::var("CLIPPY_ARGS") {
                    args.extend(extra_args.split("__CLIPPY_HACKERY__").filter_map(|s| {
                        if s.is_empty() {
                            None
                        } else {
                            Some(s.to_string())
                        }
                    }));
                }
            }

            let mut clippy = ClippyCallbacks;
            let mut default = rustc_driver::DefaultCallbacks;
            let callbacks: &mut (dyn rustc_driver::Callbacks + Send) =
                if clippy_enabled { &mut clippy } else { &mut default };
            let args = args;
            rustc_driver::run_compiler(&args, callbacks, None, None)
        })
        .and_then(|result| result)
        .is_err() as i32,
    )
}
<|endoftext|>


<commit_before>use async::engine::{self, EngineMessage};
use async::transform::Transform;
use std::f32::consts::PI;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};

#[derive(Debug)]
pub struct Camera {
    data: *mut CameraData,
    _phantom: PhantomData<CameraData>,
}

impl Camera {
    pub fn new(transform: &Transform) -> Camera {
        let mut camera_data = Box::new(CameraData::default());

        let ptr = &mut *camera_data as *mut _;

        engine::send_message(EngineMessage::Camera(camera_data, transform.inner()));

        Camera {
            data: ptr,
            _phantom: PhantomData,
        }
    }
}

impl Deref for Camera {
    type Target = CameraData;

    fn deref(&self) -> &CameraData { unsafe { &*self.data } }
}

impl DerefMut for Camera {
    fn deref_mut(&mut self) -> &mut CameraData { unsafe { &mut *self.data } }
}

#[derive(Debug)]
pub struct CameraData {
    fov: f32,
    aspect: f32,
    near: f32,
    far: f32,
}

impl CameraData {
    pub fn fov(&self) -> f32 { self.fov }

    pub fn aspect(&self) -> f32 { self.aspect }

    pub fn near(&self) -> f32 { self.near }

    pub fn far(&self) -> f32 { self.far }
}

impl Default for CameraData {
    fn default() -> CameraData {
        CameraData {
            fov: PI / 3.0,
            aspect: 1.0,
            near: 0.001,
            far: 1_000.0,
        }
    }
}
<commit_msg>Make Camera Send<commit_after>use async::engine::{self, EngineMessage};
use async::transform::Transform;
use std::f32::consts::PI;
use std::fmt::{self, Debug, Formatter};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::ptr::Unique;

pub struct Camera {
    data: Unique<CameraData>,

    // Pretend `Camera` owns a raw pointer to default implementation for `Sync`.
    // TODO: Remove this once negative trait bounds are stabilized.
    _phantom: PhantomData<*mut ()>,
}

impl Camera {
    pub fn new(transform: &Transform) -> Camera {
        let mut camera_data = Box::new(CameraData::default());

        let ptr = &mut *camera_data as *mut _;

        engine::send_message(EngineMessage::Camera(camera_data, transform.inner()));

        Camera {
            data: unsafe { Unique::new(ptr) },
            _phantom: PhantomData,
        }
    }
}

unsafe impl Send for Camera {}

impl Debug for Camera {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        let data = unsafe { self.data.get() };

        fmt.debug_struct("Camera")
            .field("fov", &data.fov)
            .field("aspect", &data.aspect)
            .field("near", &data.near)
            .field("far", &data.far)
            .finish()
    }
}

impl Deref for Camera {
    type Target = CameraData;

    fn deref(&self) -> &CameraData { unsafe { self.data.get() } }
}

impl DerefMut for Camera {
    fn deref_mut(&mut self) -> &mut CameraData { unsafe { self.data.get_mut() } }
}

#[derive(Debug)]
pub struct CameraData {
    fov: f32,
    aspect: f32,
    near: f32,
    far: f32,
}

impl CameraData {
    pub fn fov(&self) -> f32 { self.fov }

    pub fn aspect(&self) -> f32 { self.aspect }

    pub fn near(&self) -> f32 { self.near }

    pub fn far(&self) -> f32 { self.far }
}

impl Default for CameraData {
    fn default() -> CameraData {
        CameraData {
            fov: PI / 3.0,
            aspect: 1.0,
            near: 0.001,
            far: 1_000.0,
        }
    }
}
<|endoftext|>


<commit_before>use std::thread::{JoinHandle, Builder};
use std::sync::{Arc, Mutex};
use std::sync::mpsc::channel;
use std::sync::mpsc::{Sender, Receiver};

use notice::Notice;
use config::Config;
use sync_sender::SyncSender;

pub struct AsyncSender {
    workers: Vec<JoinHandle<()>>,
    tx: Sender<Option<Notice>>,
}

impl AsyncSender {
    pub fn new(config: &Config) -> AsyncSender {
        let (tx, rx) = channel();
        let rx = Arc::new(Mutex::new(rx));

        AsyncSender {
            workers: AsyncSender::spawn_workers(config, rx),
            tx: tx,
        }
    }

    pub fn send(&self, notice: Notice) {
        self.tx.send(Some(notice)).unwrap();
    }

    pub fn close(&mut self) {
        for _ in 0..self.workers.len() {
            self.tx.send(None).unwrap();
        }

        for _ in 0..self.workers.len() {
            let worker = self.workers.pop().unwrap();
            worker.join().unwrap();
        }
    }

    fn spawn_workers(config: &Config,
                     rx: Arc<Mutex<Receiver<Option<Notice>>>>) -> Vec<JoinHandle<()>> {
        let mut workers = vec![];

        for i in 0..config.workers {
            let sync_sender = SyncSender::new(config);
            let rx = rx.clone();

            workers.push(Builder::new().name(i.to_string()).spawn(move || {
                debug!("**Airbrake: spawning thread {:?}", thread::current());

                loop {
                    let message = {
                        let lock = rx.lock().unwrap();
                        lock.recv()
                    };

                    match message {
                        Ok(Some(notice)) => {
                            debug!("**Airbrake: sending {:?}", notice);
                            sync_sender.send(notice);
                        },
                        Ok(None) | Err(..) => {
                            debug!("**Airbrake: terminating thread {:?}", thread::current());
                            break;
                        },
                    };
                }
            }).unwrap());
        }

        workers
    }
}
<commit_msg>Fix build<commit_after>use std::thread;
use std::thread::{JoinHandle, Builder};
use std::sync::{Arc, Mutex};
use std::sync::mpsc::channel;
use std::sync::mpsc::{Sender, Receiver};

use notice::Notice;
use config::Config;
use sync_sender::SyncSender;

pub struct AsyncSender {
    workers: Vec<JoinHandle<()>>,
    tx: Sender<Option<Notice>>,
}

impl AsyncSender {
    pub fn new(config: &Config) -> AsyncSender {
        let (tx, rx) = channel();
        let rx = Arc::new(Mutex::new(rx));

        AsyncSender {
            workers: AsyncSender::spawn_workers(config, rx),
            tx: tx,
        }
    }

    pub fn send(&self, notice: Notice) {
        self.tx.send(Some(notice)).unwrap();
    }

    pub fn close(&mut self) {
        for _ in 0..self.workers.len() {
            self.tx.send(None).unwrap();
        }

        for _ in 0..self.workers.len() {
            let worker = self.workers.pop().unwrap();
            worker.join().unwrap();
        }
    }

    fn spawn_workers(config: &Config,
                     rx: Arc<Mutex<Receiver<Option<Notice>>>>) -> Vec<JoinHandle<()>> {
        let mut workers = vec![];

        for i in 0..config.workers {
            let sync_sender = SyncSender::new(config);
            let rx = rx.clone();

            workers.push(Builder::new().name(i.to_string()).spawn(move || {
                debug!("**Airbrake: spawning thread {:?}", thread::current());

                loop {
                    let message = {
                        let lock = rx.lock().unwrap();
                        lock.recv()
                    };

                    match message {
                        Ok(Some(notice)) => {
                            debug!("**Airbrake: sending {:?}", notice);
                            sync_sender.send(notice);
                        },
                        Ok(None) | Err(..) => {
                            debug!("**Airbrake: terminating thread {:?}", thread::current());
                            break;
                        },
                    };
                }
            }).unwrap());
        }

        workers
    }
}
<|endoftext|>


<commit_before>extern crate byteorder;

use std::io;
use std::io::{BufWriter, ErrorKind, Write, Seek, SeekFrom, Result, Error};
use std::result;
use self::byteorder::{ByteOrder, WriteBytesExt, LittleEndian};

use definitions::*;

// We limit how far copy back-references can go, the same as the C++ code.
const MAX_OFFSET: usize = 1 << 15;

// The Max Encoded Length of the Max Chunk of 65536 bytes
const MAX_BUFFER_SIZE: usize = 76_490;

pub struct Compressor<W: Write> {
    inner: BufWriter<W>,
    pos: u64,
    buf: [u8; MAX_BUFFER_SIZE],
    wroteHeader: bool,
}

impl <W: Write> Compressor<W> {

    pub fn new(inner: W) -> Compressor<W> {
        Compressor {
            inner: BufWriter::new(inner),
            pos: 0,
            buf: [0; MAX_BUFFER_SIZE],
            wroteHeader: false,
        }
    }
}

impl <W: Write> Write for Compressor<W> {
    // Implement Write
    // Source Buffer -> Destination (Inner) Buffer
    fn write(&mut self, src: &[u8]) -> Result<usize> {

        if !self.wroteHeader {
            // Write Stream Literal
            // (Future) Handle Error
            self.inner.write(&MAGIC_CHUNK).unwrap();
            self.wroteHeader = true;
        }

        // Split source into chunks of 65536 bytes each.
        for srcChunk in src.chunks(MAX_UNCOMPRESSED_CHUNK_LEN as usize) {

            let chunkBody : &[u8];

            // Create Checksum
            // TODO
            // let checksum = srcChunk;

            // Compress the buffer, discarding the result if the improvement
            // isn't at least 12.5%.
            if compress(&self.buf, scrChunk).unwrap() >= srcChunk.len()*(7/8) {
                chunkBody = srcChunk;
            } else {
                chunkBody = &self.buf;
            }

            // TODO
            // Write Checksum into `mut& self.inner.BufWriter`

        }

        unimplemented!();

    }
    // Implement Flush
    fn flush(&mut self) -> Result<()> {
        unimplemented!()
    }
}

// If Compressor is Given a Cursor or Seekable Writer
// This Gives the BufWriter the seek method
impl <W: Write + Seek> Seek for Compressor<W> {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
        self.inner.seek(pos).and_then(|res: u64| {
            self.pos = res;
            Ok(res)
        })
    }
}

// Encode returns the encoded form of src. The returned slice may be a sub-
// slice of dst if dst was large enough to hold the entire encoded block.
// Otherwise, a newly allocated slice will be returned.
// It is valid to pass a nil dst.

// (Future) Include a Legacy Compress??
pub fn compress(dst: &mut[u8], src: &[u8]) -> io::Result<usize> {
    if dst.len() < Max_Encoded_Len(src.len()) {
        return Err(Error::new(ErrorKind::InvalidInput, "snappy: destination buffer is too short"));
    }

    // Start Block with varint-encoded length of decompressed bytes
    dst.as_mut().write_u64::<LittleEndian>(src.len() as u64).unwrap();

    let mut d: usize = 4;

    // Return early if src is short
    if src.len() <= 4 {
        if src.len() != 0 {
            // TODO Handle Error
            d += emit_literal(dst.split_at_mut(d).1, src).unwrap();
        }
        return Ok(d)
    }

    // Initialize the hash table. Its size ranges from 1<<8 to 1<<14 inclusive.
    const MAX_TABLE_SIZE: usize = 1 << 14;
    let mut shift: u32 = 24;
    let mut tableSize: usize = 1<<8;

    while tableSize < MAX_TABLE_SIZE && tableSize < src.len() {
        shift -= 1;
        tableSize *= 2;
    }

    let mut table: Vec<i32> = Vec::with_capacity(MAX_TABLE_SIZE);

    // Iterate over the source bytes
    let mut s: usize = 0;
    let mut t: usize;
    let mut lit: usize = 0;

    // (Future) Iterate in chunks of 4?
    while s+3 < src.len() {
        // Update the hash table.
        let mut b : (u8, u8, u8, u8) = (src[s], src[s+1], src[s+2], src[s+3]);
        let h : u32 = (b.0 as u32) | ((b.1 as u32) <<8) | ((b.2 as u32) <<16) | ((b.3 as u32) <<24);
        // (Future) Handle Unwrap!
        // ??? what's with `0x1e35a7bd`??
        let p: &mut i32 = table.get_mut(((h*0x1e35a7bd) >> shift) as usize).unwrap();

        // We need to to store values in [-1, inf) in table. To save
        // some initialization time, (re)use the table's zero value
        // and shift the values against this zero: add 1 on writes,
        // subtract 1 on reads.
        t = (*p-1) as usize;
        let mut p = s+1;
        // If t is invalid or src[s:s+4] differs from src[t:t+4], accumulate a literal byte.
        if t < 0 || s-t >= MAX_OFFSET || b.0 != src[t] || b.1 != src[t+1] || b.2 != src[t+2] || b.3 != src[t+3] {
            s += 1;
            continue;
        }

        // Otherwise, we have a match. First, emit any pending literal bytes.
        if lit != s {
            d += emit_literal(dst.split_at_mut(d).1, src.split_at(lit).1.split_at(s).0).unwrap();
        }

        // Extend the match to be as long as possible
        let s0 = s;
        s += 4;
        t += 4;
        while s < src.len() && src[s] == src[t] {
            s += 1;
            t += 1;
        }

        // Emit the copied bytes.
        d += emit_copy(dst.split_at_mut(d).1, s-t, s-s0);
        lit = s;
    }

    // Emit any final pending literal bytes and return.
    if lit != src.len() {
        d += emit_literal(dst.split_at_mut(d).1, src.split_at(lit).1).unwrap();
    }

    Ok(d)
}

// emitLiteral writes a literal chunk and returns the number of bytes written.
fn emit_literal(dst: &mut [u8], lit: &[u8]) -> io::Result<usize> {

    let mut i: usize;
    let n: u64 = (lit.len() - 1) as u64;

    if n < 60 {
        dst[0] = (n as u8) << 2 | TAG_LITERAL;
        i = 1;
    } else if n < 1 << 8 {
        dst[0] = 60 << 2 | TAG_LITERAL;
        dst[1] = n as u8;
        i = 2;
    } else if n < 1 << 16 {
        dst[0] = 61 << 2 | TAG_LITERAL;
        dst[1] = n as u8;
        dst[2] = (n >> 8) as u8;
        i = 3;
    } else if n < 1 << 24 {
        dst[0] = 62 << 2 | TAG_LITERAL;
        dst[1] = n as u8;
        dst[2] = (n >> 8) as u8;
        dst[3] = (n >> 16) as u8;
        i = 4;
    } else if n < 1 << 32 {
        dst[0] = 63 << 2 | TAG_LITERAL;
        dst[1] = n as u8;
        dst[2] = (n >> 8) as u8;
        dst[3] = (n >> 16) as u8;
        dst[4] = (n >> 24) as u8;
        i = 5;
    } else {
        return Err(Error::new(ErrorKind::InvalidInput, "snappy: source buffer is too long"));
    }

    let mut s = 0;
    for (d, l) in dst.split_at_mut(i).1.iter_mut().zip(lit.iter()) {
        *d = *l;
        s += 1;
    }

    if (s == lit.len()) {
        Ok(i + lit.len())
    } else {
        return Err(Error::new(ErrorKind::InvalidInput, "snappy: destination buffer is too short"));
    }
}

// emitCopy writes a copy chunk and returns the number of bytes written.
fn emit_copy(dst: &mut [u8], offset: usize, mut length: usize) -> usize {

    let mut i: usize = 0;

    while length > 0 {
        let mut x = length - 4;
        if 0 <= x && x < 1 << 3 && offset < 1 << 11 {
            dst[i] = ((offset >> 8) as u8) & 0x07 << 5 | (x as u8) << 2 | TAG_COPY_1;
            dst[i + 1] = offset as u8;
            i += 2;
            break;
        }
        x = length;
        if x > 1 << 6 {
            x = 1 << 6;
        }
        dst[i] = ((x as u8) - 1) << 2 | TAG_COPY_2;
        dst[i + 1] = offset as u8;
        dst[i + 2] = (offset >> 8) as u8;
        i += 3;
        length -= x;
    }
    // (Future) Return a `Result<usize>` Instead??
    i
}

// Max_Encoded_Len returns the maximum length of a snappy block, given its
// uncompressed length.
pub fn Max_Encoded_Len(srcLen: usize) -> usize {
    32 + srcLen + srcLen / 6
}

// Encode returns the encoded form of src. The returned slice may be a sub-
// slice of dst if dst was large enough to hold the entire encoded block.
// Otherwise, a newly allocated slice will be returned.
// It is valid to pass a nil dst.
// pub fn Encode(dst: &'a mut [u8], src: &mut [u8]) -> Result<&'a mut [u8],
// &'static str> {

// 	// Ok(dst.split_at_mut(i).1)
// }
<commit_msg>Split Inner Buffer into Header and Body<commit_after>extern crate byteorder;

use std::io;
use std::io::{BufWriter, ErrorKind, Write, Seek, SeekFrom, Result, Error};
use std::result;
use self::byteorder::{ByteOrder, WriteBytesExt, LittleEndian};

use definitions::*;

// We limit how far copy back-references can go, the same as the C++ code.
const MAX_OFFSET: usize = 1 << 15;

// The Max Encoded Length of the Max Chunk of 65536 bytes
const MAX_BUFFER_SIZE: usize = 76_490;

pub struct Compressor<W: Write> {
    inner: BufWriter<W>,
    pos: u64,
    buf_body: [u8; MAX_BUFFER_SIZE],
    buf_header : [u8; (CHECK_SUM_SIZE + CHUNK_HEADER_SIZE) as usize],
    wroteHeader: bool,
}

impl <W: Write> Compressor<W> {

    pub fn new(inner: W) -> Compressor<W> {
        Compressor {
            inner: BufWriter::new(inner),
            pos: 0,
            buf_body: [0; MAX_BUFFER_SIZE],
            buf_header: [0; (CHECK_SUM_SIZE + CHUNK_HEADER_SIZE) as usize],
            wroteHeader: false,
        }
    }
}

impl <W: Write> Write for Compressor<W> {
    // Implement Write
    // Source Buffer -> Destination (Inner) Buffer
    fn write(&mut self, src: &[u8]) -> Result<usize> {

        let mut written: usize = 0;

        if !self.wroteHeader {
            // Write Stream Literal
            // (Future) Handle Error
            written += self.inner.write(&MAGIC_CHUNK).unwrap();
            self.wroteHeader = true;
        }

        // Split source into chunks of 65536 bytes each.
        for srcChunk in src.chunks(MAX_UNCOMPRESSED_CHUNK_LEN as usize) {

            let chunkBody : &[u8];
            let chunkType: u8;

            // Create Checksum
            // TODO
            // let checksum = srcChunk;

            // Compress the buffer, discarding the result if the improvement
            // isn't at least 12.5%.
            if compress(&mut self.buf_body, srcChunk).unwrap() >= srcChunk.len()*(7/8) {
                chunkType = CHUNK_TYPE_UNCOMPRESSED_DATA;
                chunkBody = srcChunk;
            } else {
                chunkType = CHUNK_TYPE_COMPRESSED_DATA;
                chunkBody = &self.buf_body;
            }

            // TODO
            // Write Checksum into `mut& self.inner.BufWriter`
            let chunkLen = chunkBody.len() + 4;

            // Write Chunk Type
            self.buf_header[0] = chunkType;
            // Write Chunk Length
            self.buf_header[1] = (chunkLen >> 0) as u8;
            self.buf_header[2] = (chunkLen >> 8) as u8;
            self.buf_header[3] = (chunkLen >> 16) as u8;
            // Write Chunk Checksum
            // self.buf_header[4] = (checksum >> 0) as u8
            // self.buf_header[5] = (checksum >> 8) as u8
            // self.buf_header[6] = (checksum >> 16) as u8
            // self.buf_header[7] = (checksum >> 24) as u8

            // TODO
            // Write Chunk Header
            // Handle Errors
            written += self.inner.write(&self.buf_header).unwrap();

            // TODO
            // Write Chunk Body
            // Handle Errors
            written += self.inner.write(chunkBody).unwrap();

        }

        Ok(written)
    }
    // Implement Flush
    fn flush(&mut self) -> Result<()> {
        unimplemented!()
    }
}

// If Compressor is Given a Cursor or Seekable Writer
// This Gives the BufWriter the seek method
impl <W: Write + Seek> Seek for Compressor<W> {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
        self.inner.seek(pos).and_then(|res: u64| {
            self.pos = res;
            Ok(res)
        })
    }
}

// Encode returns the encoded form of src. The returned slice may be a sub-
// slice of dst if dst was large enough to hold the entire encoded block.
// Otherwise, a newly allocated slice will be returned.
// It is valid to pass a nil dst.

// (Future) Include a Legacy Compress??
pub fn compress(dst: &mut[u8], src: &[u8]) -> io::Result<usize> {
    if dst.len() < Max_Encoded_Len(src.len()) {
        return Err(Error::new(ErrorKind::InvalidInput, "snappy: destination buffer is too short"));
    }

    // Start Block with varint-encoded length of decompressed bytes
    dst.as_mut().write_u64::<LittleEndian>(src.len() as u64).unwrap();

    let mut d: usize = 4;

    // Return early if src is short
    if src.len() <= 4 {
        if src.len() != 0 {
            // TODO Handle Error
            d += emit_literal(dst.split_at_mut(d).1, src).unwrap();
        }
        return Ok(d)
    }

    // Initialize the hash table. Its size ranges from 1<<8 to 1<<14 inclusive.
    const MAX_TABLE_SIZE: usize = 1 << 14;
    let mut shift: u32 = 24;
    let mut tableSize: usize = 1<<8;

    while tableSize < MAX_TABLE_SIZE && tableSize < src.len() {
        shift -= 1;
        tableSize *= 2;
    }

    let mut table: Vec<i32> = Vec::with_capacity(MAX_TABLE_SIZE);

    // Iterate over the source bytes
    let mut s: usize = 0;
    let mut t: usize;
    let mut lit: usize = 0;

    // (Future) Iterate in chunks of 4?
    while s+3 < src.len() {
        // Update the hash table.
        let b : (u8, u8, u8, u8) = (src[s], src[s+1], src[s+2], src[s+3]);
        let h : u32 = (b.0 as u32) | ((b.1 as u32) <<8) | ((b.2 as u32) <<16) | ((b.3 as u32) <<24);
        // (Future) Handle Unwrap!
        // ??? what's with `0x1e35a7bd`??
        let p: &mut i32 = table.get_mut(((h*0x1e35a7bd) >> shift) as usize).unwrap();

        // We need to to store values in [-1, inf) in table. To save
        // some initialization time, (re)use the table's zero value
        // and shift the values against this zero: add 1 on writes,
        // subtract 1 on reads.
        t = (*p-1) as usize;
        *p = (s+1) as i32;
        // If t is invalid or src[s:s+4] differs from src[t:t+4], accumulate a literal byte.
        if t < 0 || s-t >= MAX_OFFSET || b.0 != src[t] || b.1 != src[t+1] || b.2 != src[t+2] || b.3 != src[t+3] {
            s += 1;
            continue;
        }

        // Otherwise, we have a match. First, emit any pending literal bytes.
        if lit != s {
            d += emit_literal(dst.split_at_mut(d).1, src.split_at(lit).1.split_at(s).0).unwrap();
        }

        // Extend the match to be as long as possible
        let s0 = s;
        s += 4;
        t += 4;
        while s < src.len() && src[s] == src[t] {
            s += 1;
            t += 1;
        }

        // Emit the copied bytes.
        d += emit_copy(dst.split_at_mut(d).1, s-t, s-s0);
        lit = s;
    }

    // Emit any final pending literal bytes and return.
    if lit != src.len() {
        d += emit_literal(dst.split_at_mut(d).1, src.split_at(lit).1).unwrap();
    }

    Ok(d)
}

// emitLiteral writes a literal chunk and returns the number of bytes written.
fn emit_literal(dst: &mut [u8], lit: &[u8]) -> io::Result<usize> {

    let mut i: usize;
    let n: u64 = (lit.len() - 1) as u64;

    if n < 60 {
        dst[0] = (n as u8) << 2 | TAG_LITERAL;
        i = 1;
    } else if n < 1 << 8 {
        dst[0] = 60 << 2 | TAG_LITERAL;
        dst[1] = n as u8;
        i = 2;
    } else if n < 1 << 16 {
        dst[0] = 61 << 2 | TAG_LITERAL;
        dst[1] = n as u8;
        dst[2] = (n >> 8) as u8;
        i = 3;
    } else if n < 1 << 24 {
        dst[0] = 62 << 2 | TAG_LITERAL;
        dst[1] = n as u8;
        dst[2] = (n >> 8) as u8;
        dst[3] = (n >> 16) as u8;
        i = 4;
    } else if n < 1 << 32 {
        dst[0] = 63 << 2 | TAG_LITERAL;
        dst[1] = n as u8;
        dst[2] = (n >> 8) as u8;
        dst[3] = (n >> 16) as u8;
        dst[4] = (n >> 24) as u8;
        i = 5;
    } else {
        return Err(Error::new(ErrorKind::InvalidInput, "snappy: source buffer is too long"));
    }

    let mut s = 0;
    for (d, l) in dst.split_at_mut(i).1.iter_mut().zip(lit.iter()) {
        *d = *l;
        s += 1;
    }

    if (s == lit.len()) {
        Ok(i + lit.len())
    } else {
        return Err(Error::new(ErrorKind::InvalidInput, "snappy: destination buffer is too short"));
    }
}

// emitCopy writes a copy chunk and returns the number of bytes written.
fn emit_copy(dst: &mut [u8], offset: usize, mut length: usize) -> usize {

    let mut i: usize = 0;

    while length > 0 {
        let mut x = length - 4;
        if 0 <= x && x < 1 << 3 && offset < 1 << 11 {
            dst[i] = ((offset >> 8) as u8) & 0x07 << 5 | (x as u8) << 2 | TAG_COPY_1;
            dst[i + 1] = offset as u8;
            i += 2;
            break;
        }
        x = length;
        if x > 1 << 6 {
            x = 1 << 6;
        }
        dst[i] = ((x as u8) - 1) << 2 | TAG_COPY_2;
        dst[i + 1] = offset as u8;
        dst[i + 2] = (offset >> 8) as u8;
        i += 3;
        length -= x;
    }
    // (Future) Return a `Result<usize>` Instead??
    i
}

// Max_Encoded_Len returns the maximum length of a snappy block, given its
// uncompressed length.
pub fn Max_Encoded_Len(srcLen: usize) -> usize {
    32 + srcLen + srcLen / 6
}

// Encode returns the encoded form of src. The returned slice may be a sub-
// slice of dst if dst was large enough to hold the entire encoded block.
// Otherwise, a newly allocated slice will be returned.
// It is valid to pass a nil dst.
// pub fn Encode(dst: &'a mut [u8], src: &mut [u8]) -> Result<&'a mut [u8],
// &'static str> {

// 	// Ok(dst.split_at_mut(i).1)
// }
<|endoftext|>


<commit_before>//! Command-line iterface to substudy.

extern crate rustc_serialize;
extern crate docopt;
extern crate env_logger;

extern crate substudy;

use docopt::Docopt;
use std::path::Path;
use std::process::exit;

use substudy::err::Result;
use substudy::srt::SubtitleFile;
use substudy::align::combine_files;
use substudy::video;
use substudy::export;

const USAGE: &'static str = "
Subtitle processing tools for students of foreign languages

Usage: substudy clean <subs>
       substudy combine <foreign-subs> <native-subs>
       substudy export review <video> <foreign-subs> [<native-subs>]
       substudy tracks <video>
       substudy --help

For now, all subtitles must be in *.srt format. Many common encodings
will be automatically detected, but try converting to UTF-8 if you
have problems.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_clean: bool,
    cmd_combine: bool,
    cmd_tracks: bool,
    cmd_export: bool,
    arg_subs: String,
    arg_foreign_subs: String,
    arg_native_subs: Option<String>,
    arg_video: String,
}

// Choose and run the appropriate command.
fn run(args: &Args) -> Result<()> {
    match *args {
        Args{cmd_clean: true, arg_subs: ref path, ..} =>
            cmd_clean(&Path::new(path)),
        Args{cmd_combine: true, arg_foreign_subs: ref path1,
             arg_native_subs: Some(ref path2), ..} =>
            cmd_combine(&Path::new(path1), &Path::new(path2)),
        Args{cmd_tracks: true, arg_video: ref path, ..} =>
            cmd_tracks(&Path::new(path)),
        Args{cmd_export: true, arg_video: ref video_path,
             arg_foreign_subs: ref foreign_path,
             arg_native_subs: ref native_path, ..} => {
            match native_path {
                &None =>
                    cmd_export(&Path::new(video_path),
                               &Path::new(foreign_path),
                               None),
                &Some(ref native) =>
                    cmd_export(&Path::new(video_path),
                               &Path::new(foreign_path),
                               Some(&Path::new(native))),
            }
        }
        _ => panic!("Unexpected argument combination: {:?}", args)
    }
}

fn cmd_clean(path: &Path) -> Result<()> {
    let file1 = try!(SubtitleFile::cleaned_from_path(path));
    print!("{}", file1.to_string());
    Ok(())
}

fn cmd_combine(path1: &Path, path2: &Path) -> Result<()> {
    let file1 = try!(SubtitleFile::cleaned_from_path(path1));
    let file2 = try!(SubtitleFile::cleaned_from_path(path2));
    print!("{}", combine_files(&file1, &file2).to_string());
    Ok(())
}

fn cmd_tracks(path: &Path) -> Result<()> {
    let v = try!(video::Video::new(path));
    for stream in v.streams() {
        let lang: &str = match stream.tags.get("language") {
            Some(ref code) => code,
            None => "unknown",
        };
        println!("#{} {} {:?}", stream.index, lang, stream.codec_type);
    }
    Ok(())
}

fn cmd_export(video_path: &Path, foreign_sub_path: &Path,
              native_sub_path: Option<&Path>) ->
    Result<()>
{
    // Load our input files.
    let video = try!(video::Video::new(video_path));
    let foreign_subs = try!(SubtitleFile::cleaned_from_path(foreign_sub_path));
    let native_subs = match native_sub_path {
        None => None,
        Some(p) => Some(try!(SubtitleFile::cleaned_from_path(p))),
    };

    let request = export::ExportRequest {
        video: video,
        foreign_subtitles: foreign_subs,
        native_subtitles: native_subs,
    };
    try!(export::export(&request));

    Ok(())
}

fn main() {
    env_logger::init().unwrap();

    // Parse our command-line arguments using docopt (very shiny).
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    // Decide which command to run, and run it.
    if let Err(ref err) = run(&args) {
        // Print any error and exit with an error status.
        println!("{}", err);
        exit(1);
    }
}
<commit_msg>Rename "tracks" command to "list tracks"<commit_after>//! Command-line iterface to substudy.

extern crate rustc_serialize;
extern crate docopt;
extern crate env_logger;

extern crate substudy;

use docopt::Docopt;
use std::path::Path;
use std::process::exit;

use substudy::err::Result;
use substudy::srt::SubtitleFile;
use substudy::align::combine_files;
use substudy::video;
use substudy::export;

const USAGE: &'static str = "
Subtitle processing tools for students of foreign languages

Usage: substudy clean <subs>
       substudy combine <foreign-subs> <native-subs>
       substudy export review <video> <foreign-subs> [<native-subs>]
       substudy list tracks <video>
       substudy --help

For now, all subtitles must be in *.srt format. Many common encodings
will be automatically detected, but try converting to UTF-8 if you
have problems.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_clean: bool,
    cmd_combine: bool,
    cmd_tracks: bool,
    cmd_export: bool,
    arg_subs: String,
    arg_foreign_subs: String,
    arg_native_subs: Option<String>,
    arg_video: String,
}

// Choose and run the appropriate command.
fn run(args: &Args) -> Result<()> {
    match *args {
        Args{cmd_clean: true, arg_subs: ref path, ..} =>
            cmd_clean(&Path::new(path)),
        Args{cmd_combine: true, arg_foreign_subs: ref path1,
             arg_native_subs: Some(ref path2), ..} =>
            cmd_combine(&Path::new(path1), &Path::new(path2)),
        Args{cmd_tracks: true, arg_video: ref path, ..} =>
            cmd_tracks(&Path::new(path)),
        Args{cmd_export: true, arg_video: ref video_path,
             arg_foreign_subs: ref foreign_path,
             arg_native_subs: ref native_path, ..} => {
            match native_path {
                &None =>
                    cmd_export(&Path::new(video_path),
                               &Path::new(foreign_path),
                               None),
                &Some(ref native) =>
                    cmd_export(&Path::new(video_path),
                               &Path::new(foreign_path),
                               Some(&Path::new(native))),
            }
        }
        _ => panic!("Unexpected argument combination: {:?}", args)
    }
}

fn cmd_clean(path: &Path) -> Result<()> {
    let file1 = try!(SubtitleFile::cleaned_from_path(path));
    print!("{}", file1.to_string());
    Ok(())
}

fn cmd_combine(path1: &Path, path2: &Path) -> Result<()> {
    let file1 = try!(SubtitleFile::cleaned_from_path(path1));
    let file2 = try!(SubtitleFile::cleaned_from_path(path2));
    print!("{}", combine_files(&file1, &file2).to_string());
    Ok(())
}

fn cmd_tracks(path: &Path) -> Result<()> {
    let v = try!(video::Video::new(path));
    for stream in v.streams() {
        let lang: &str = match stream.tags.get("language") {
            Some(ref code) => code,
            None => "unknown",
        };
        println!("#{} {} {:?}", stream.index, lang, stream.codec_type);
    }
    Ok(())
}

fn cmd_export(video_path: &Path, foreign_sub_path: &Path,
              native_sub_path: Option<&Path>) ->
    Result<()>
{
    // Load our input files.
    let video = try!(video::Video::new(video_path));
    let foreign_subs = try!(SubtitleFile::cleaned_from_path(foreign_sub_path));
    let native_subs = match native_sub_path {
        None => None,
        Some(p) => Some(try!(SubtitleFile::cleaned_from_path(p))),
    };

    let request = export::ExportRequest {
        video: video,
        foreign_subtitles: foreign_subs,
        native_subtitles: native_subs,
    };
    try!(export::export(&request));

    Ok(())
}

fn main() {
    env_logger::init().unwrap();

    // Parse our command-line arguments using docopt (very shiny).
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    // Decide which command to run, and run it.
    if let Err(ref err) = run(&args) {
        // Print any error and exit with an error status.
        println!("{}", err);
        exit(1);
    }
}
<|endoftext|>


<commit_before>use cocoa::base::id;

/// The `MTLLibrary` protocol defines the interface for an object that represents a library of Metal
/// shader functions. A `MTLLibrary` object can contain Metal shading language code that is compiled
/// during the app build process or at runtime from a text string containing Metal shading language
/// source code. Your app does not define classes that implement this protocol.
///
/// Use a `MTLDevice` method (not standard allocation and initialization techniques) to create a
/// `MTLLibrary` object. To create a `MTLLibrary` object from a Metal library binary, call one of
/// these MTLDevice methods:
///
/// * `newDefaultLibrary`
///
/// * `newLibraryWithFile:error:`
///
/// * `newLibraryWithData:error:`
///
/// To create a `MTLLibrary` object by compiling source code, call one of these `MTLDevice` methods:
///
/// * `newLibraryWithSource:options:error:`
///
/// * `newLibraryWithSource:options:completionHandler:`
///
/// The `newFunctionWithName:` method is used to fetch functions from the library, which makes that
/// code available as a shader for either a `MTLRenderPipelineState` object for a render command
/// encoder or for a `MTLComputePipelineState` for a compute command encoder.
pub trait MTLLibrary {
    /// Returns a function object that represents an entry point in the library.
    ///
    /// # Parameters
    ///
    /// * `functionName` - The name of an entry point.
    ///
    /// # Return Value
    ///
    /// A function object for the named entry point, or nil if the named function is not found in
    /// the library.
    unsafe fn newFunctionWithName(self, functionName: id) -> id;

    /// A list of all entry points in the library. (read-only)
    ///
    /// # Discussion
    ///
    /// An array of `NSString` objects. Each string is the name of an entry point.
    unsafe fn functionNames(self) -> id;

    /// The device from which this library was created. (read-only)
    ///
    /// # Discussion
    ///
    /// This library can only be used with this device.
    unsafe fn device(self) -> id;

    /// A string to help identify the library object.
    unsafe fn label(self) -> id;
    unsafe fn setLabel(self, id);
}

impl MTLLibrary for id {
    unsafe fn newFunctionWithName(self, functionName: id) -> id {
        msg_send![self, newFunctionWithName:functionName]
    }

    unsafe fn functionNames(self) -> id {
        msg_send![self, functionNames]
    }

    unsafe fn device(self) -> id {
        msg_send![self, device]
    }

    unsafe fn label(self) -> id {
        msg_send![self, label]
    }

    unsafe fn setLabel(self, label: id) {
        msg_send![self, setLabel:label]
    }
}

/// Error conditions that can result from the creation of a `MTLLibrary` or `MTLFunction` object.
#[repr(C, usize)]
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub enum MTLLibraryError {
    /// The action is unsupported. For example, the requested library file has improper formatting,
    /// or the requested library is not accessible.
    MTLLibraryErrorUnsupported = 1,

    /// The action causes an internal error.
    MTLLibraryErrorInternal = 2,

    /// Compilation fails
    MTLLibraryErrorCompileFailure = 3,

    /// Compilation succeeds without error, but there are compiler warnings.
    MTLLibraryErrorCompileWarning = 4
}

#[link(name = "Metal", kind = "framework")]
extern "C" {
    /// Constant to identify the `MTLLibrary` error domain.
    pub static MTLLibraryErrorDomain: id;
}

/// Error conditions that can result from the creation of a `MTLRenderPipelineState` object.
#[repr(C, usize)]
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub enum MTLRenderPipelineError {
    /// The action causes an internal error.
    MTLRenderPipelineErrorInternal = 1,

    /// The action is unsupported.
    MTLRenderPipelineErrorUnsupported = 2,

    /// The input values are invalid.
    MTLRenderPipelineErrorInvalidInput = 3
}

#[link(name = "Metal", kind = "framework")]
extern "C" {
    /// Constant to identify the `MTLRenderPipelineState` error domain.
    pub static MTLRenderPipelineErrorDomain: id;
}

#[repr(C, usize)]
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub enum MTLLanguageVersion {
    /// Version 1.0
    MTLLanguageVersion1_0 = (1 << 16),

    /// Version 1.1
    MTLLanguageVersion1_1 = (1 << 16) + 1,

    #[doc(hidden)]
    _non_unary_compile_dummy = -1
}
<commit_msg>non-unary dummy member of `MTLLanguageVersion` no longer needed<commit_after>use cocoa::base::id;

/// The `MTLLibrary` protocol defines the interface for an object that represents a library of Metal
/// shader functions. A `MTLLibrary` object can contain Metal shading language code that is compiled
/// during the app build process or at runtime from a text string containing Metal shading language
/// source code. Your app does not define classes that implement this protocol.
///
/// Use a `MTLDevice` method (not standard allocation and initialization techniques) to create a
/// `MTLLibrary` object. To create a `MTLLibrary` object from a Metal library binary, call one of
/// these MTLDevice methods:
///
/// * `newDefaultLibrary`
///
/// * `newLibraryWithFile:error:`
///
/// * `newLibraryWithData:error:`
///
/// To create a `MTLLibrary` object by compiling source code, call one of these `MTLDevice` methods:
///
/// * `newLibraryWithSource:options:error:`
///
/// * `newLibraryWithSource:options:completionHandler:`
///
/// The `newFunctionWithName:` method is used to fetch functions from the library, which makes that
/// code available as a shader for either a `MTLRenderPipelineState` object for a render command
/// encoder or for a `MTLComputePipelineState` for a compute command encoder.
pub trait MTLLibrary {
    /// Returns a function object that represents an entry point in the library.
    ///
    /// # Parameters
    ///
    /// * `functionName` - The name of an entry point.
    ///
    /// # Return Value
    ///
    /// A function object for the named entry point, or nil if the named function is not found in
    /// the library.
    unsafe fn newFunctionWithName(self, functionName: id) -> id;

    /// A list of all entry points in the library. (read-only)
    ///
    /// # Discussion
    ///
    /// An array of `NSString` objects. Each string is the name of an entry point.
    unsafe fn functionNames(self) -> id;

    /// The device from which this library was created. (read-only)
    ///
    /// # Discussion
    ///
    /// This library can only be used with this device.
    unsafe fn device(self) -> id;

    /// A string to help identify the library object.
    unsafe fn label(self) -> id;
    unsafe fn setLabel(self, id);
}

impl MTLLibrary for id {
    unsafe fn newFunctionWithName(self, functionName: id) -> id {
        msg_send![self, newFunctionWithName:functionName]
    }

    unsafe fn functionNames(self) -> id {
        msg_send![self, functionNames]
    }

    unsafe fn device(self) -> id {
        msg_send![self, device]
    }

    unsafe fn label(self) -> id {
        msg_send![self, label]
    }

    unsafe fn setLabel(self, label: id) {
        msg_send![self, setLabel:label]
    }
}

/// Error conditions that can result from the creation of a `MTLLibrary` or `MTLFunction` object.
#[repr(C, usize)]
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub enum MTLLibraryError {
    /// The action is unsupported. For example, the requested library file has improper formatting,
    /// or the requested library is not accessible.
    MTLLibraryErrorUnsupported = 1,

    /// The action causes an internal error.
    MTLLibraryErrorInternal = 2,

    /// Compilation fails
    MTLLibraryErrorCompileFailure = 3,

    /// Compilation succeeds without error, but there are compiler warnings.
    MTLLibraryErrorCompileWarning = 4
}

#[link(name = "Metal", kind = "framework")]
extern "C" {
    /// Constant to identify the `MTLLibrary` error domain.
    pub static MTLLibraryErrorDomain: id;
}

/// Error conditions that can result from the creation of a `MTLRenderPipelineState` object.
#[repr(C, usize)]
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub enum MTLRenderPipelineError {
    /// The action causes an internal error.
    MTLRenderPipelineErrorInternal = 1,

    /// The action is unsupported.
    MTLRenderPipelineErrorUnsupported = 2,

    /// The input values are invalid.
    MTLRenderPipelineErrorInvalidInput = 3
}

#[link(name = "Metal", kind = "framework")]
extern "C" {
    /// Constant to identify the `MTLRenderPipelineState` error domain.
    pub static MTLRenderPipelineErrorDomain: id;
}

#[repr(C, usize)]
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub enum MTLLanguageVersion {
    /// Version 1.0
    MTLLanguageVersion1_0 = (1 << 16),

    /// Version 1.1
    MTLLanguageVersion1_1 = (1 << 16) + 1
}
<|endoftext|>


<commit_before>/// Black-Scholes formula parameters
/// s0 - underlying price (USD per share)
/// x - strike price (USD per share)
/// sigma - volatility (%)
/// r - continuously compounded risk-free interest rate (%)
/// q - continously compounded dividend yield (%)
/// t - time to expiration (% of year)
use std::f64::consts::E;
use stats::cnd;

pub fn delta_call(s0: f64, x: f64, t: f64, r: f64, q: f64, sigma: f64) -> f64 {
    let d1 = d1(s0, x, t, r, q, sigma);
    let cnd = cnd(d1);
    let e = E.powf(-(q * t));
    return e * cnd;
}

pub fn delta_put(s0: f64, x: f64, t: f64, r: f64, q: f64, sigma: f64) -> f64 {
    let d1 = d1(s0, x, t, r, q, sigma);
    let cnd = cnd(d1);
    let e = E.powf(-(q * t));
    return e * (cnd - 1.0);
}

pub fn d1(s0: f64, x: f64, t: f64, r: f64, q: f64, sigma: f64) -> f64 {
    let ln = (s0 / x).ln();
    let t_num = t * (r - q + (sigma.powf(2f64) / 2f64));
    return (ln + t_num) / (sigma * t.sqrt());
}

pub fn d2(s0: f64, x: f64, t: f64, r: f64, q: f64, sigma: f64) -> f64 {
    let d1 = d1(s0, x, t, r, q, sigma);
    return d1 - (t.sqrt() * sigma);
}

#[cfg(test)]
mod tests {

    use greeks::*;

    const UNDERLYING: f64 = 36.07;
    const STRIKE: f64 = 35.00;
    const VOL: f64 = 0.4825;
    const INTEREST_RATE: f64 = 0.01;
    const DIV_YIELD: f64 = 0.00;
    const TIME_TO_EXPIRY: f64 = 26.0 / 365.0;

    #[test]
    fn test_d1() {
        let expected_d1: f64 = 0.3038;
        let d1 = d1(UNDERLYING,
                    STRIKE,
                    TIME_TO_EXPIRY,
                    INTEREST_RATE,
                    DIV_YIELD,
                    VOL);
        let abs = (d1 - expected_d1).abs();
        assert!(abs < 0.001);
    }

    #[test]
    fn test_d2() {
        let expected_d2 = 0.1751;
        let d2 = d2(UNDERLYING,
                    STRIKE,
                    TIME_TO_EXPIRY,
                    INTEREST_RATE,
                    DIV_YIELD,
                    VOL);
        let abs = (d2 - expected_d2).abs();
        assert!(abs < 0.001);
    }

    #[test]
    fn test_delta_call() {
        let expected_delta = 0.6194;
        let call_delta = delta_call(UNDERLYING,
                                    STRIKE,
                                    TIME_TO_EXPIRY,
                                    INTEREST_RATE,
                                    DIV_YIELD,
                                    VOL);
        let abs = (call_delta - expected_delta).abs();
        assert!(abs < 0.001);
    }

    #[test]
    fn test_delta_put() {
        let expected_delta = -0.3806;
        let put_delta = delta_put(UNDERLYING,
                                  STRIKE,
                                  TIME_TO_EXPIRY,
                                  INTEREST_RATE,
                                  DIV_YIELD,
                                  VOL);
        let abs = (put_delta - expected_delta).abs();
        println!("{}", put_delta);
        assert!(abs < 0.001);
    }
}
<commit_msg>added gamma calculation<commit_after>/// Black-Scholes formula parameters
/// s0 - underlying price (USD per share)
/// x - strike price (USD per share)
/// sigma - volatility (%)
/// r - continuously compounded risk-free interest rate (%)
/// q - continously compounded dividend yield (%)
/// t - time to expiration (% of year)
use std::f64::consts::E;
use std::f64::consts::PI;
use stats::cnd;

pub fn delta_call(s0: f64, x: f64, t: f64, r: f64, q: f64, sigma: f64) -> f64 {
    let d1 = d1(s0, x, t, r, q, sigma);
    let cnd = cnd(d1);
    let e = E.powf(-(q * t));
    return e * cnd;
}

pub fn delta_put(s0: f64, x: f64, t: f64, r: f64, q: f64, sigma: f64) -> f64 {
    let d1 = d1(s0, x, t, r, q, sigma);
    let cnd = cnd(d1);
    let e = E.powf(-(q * t));
    return e * (cnd - 1.0);
}

pub fn gamma(s0: f64, x: f64, t: f64, r: f64, q: f64, sigma: f64) -> f64 {
    let d1 = d1(s0, x, t, r, q, sigma);
    let arg1 = E.powf(-(q * t)) / (s0 * sigma * (t.sqrt()));
    let arg2 = 1.0 / ((2.0 * PI).sqrt());
    let arg3 = E.powf((-d1).powf(2.0)) / 2.0;
    return arg1 * arg2 * arg3;
}

pub fn d1(s0: f64, x: f64, t: f64, r: f64, q: f64, sigma: f64) -> f64 {
    let ln = (s0 / x).ln();
    let t_num = t * (r - q + (sigma.powf(2f64) / 2f64));
    return (ln + t_num) / (sigma * t.sqrt());
}

pub fn d2(s0: f64, x: f64, t: f64, r: f64, q: f64, sigma: f64) -> f64 {
    let d1 = d1(s0, x, t, r, q, sigma);
    return d1 - (t.sqrt() * sigma);
}

#[cfg(test)]
mod tests {

    use greeks::*;

    const UNDERLYING: f64 = 64.68;
    const STRIKE: f64 = 65.00;
    const VOL: f64 = 0.5051;
    const INTEREST_RATE: f64 = 0.0150;
    const DIV_YIELD: f64 = 0.0210;
    const TIME_TO_EXPIRY: f64 = 23.0 / 365.0;

    const E_D1: f64 = -0.1053;
    const E_D2: f64 = 0.02149;
    const E_CALL_DELTA: f64 = 0.5079;
    const E_PUT_DELTA: f64 = -0.4908;
    const E_GAMMA: f64 = 0.0486;

    #[test]
    fn test_d1() {
        let d1 = d1(UNDERLYING,
                    STRIKE,
                    TIME_TO_EXPIRY,
                    INTEREST_RATE,
                    DIV_YIELD,
                    VOL);
        println!("{}", d1);
        let abs = (d1 - E_D1).abs();
        assert!(abs < 0.001);
    }

    #[test]
    fn test_d2() {
        let d2 = d2(UNDERLYING,
                    STRIKE,
                    TIME_TO_EXPIRY,
                    INTEREST_RATE,
                    DIV_YIELD,
                    VOL);
        let abs = (d2 - E_D2).abs();
        assert!(abs < 0.001);
    }

    #[test]
    fn test_delta_call() {
        let call_delta = delta_call(UNDERLYING,
                                    STRIKE,
                                    TIME_TO_EXPIRY,
                                    INTEREST_RATE,
                                    DIV_YIELD,
                                    VOL);
        let abs = (call_delta - E_CALL_DELTA).abs();
        assert!(abs < 0.001);
    }

    #[test]
    fn test_delta_put() {
        let put_delta = delta_put(UNDERLYING,
                                  STRIKE,
                                  TIME_TO_EXPIRY,
                                  INTEREST_RATE,
                                  DIV_YIELD,
                                  VOL);
        let abs = (put_delta - E_PUT_DELTA).abs();
        assert!(abs < 0.001);
    }

    #[test]
    fn test_gamma() {
        let gamma = gamma(UNDERLYING,
                          STRIKE,
                          TIME_TO_EXPIRY,
                          INTEREST_RATE,
                          DIV_YIELD,
                          VOL);
        let abs = (gamma - E_GAMMA).abs();
        println!("{}", gamma);
        assert!(abs < 0.001);
    }
}
<|endoftext|>


<commit_before>use std::cell::{Cell, RefCell};
use std::ops::{Deref, DerefMut};

use object::{Handle, Obj};

pub const HANDLE_SIZE: usize = 256;

pub struct HandleMemory {
    /// all buffers, Box is important since HandleBuffer
    /// is a big struct that needs to get moved/copied on resizes
    buffers: RefCell<Vec<Box<HandleBuffer>>>,

    // store addresses of inserted borders
    borders: RefCell<Vec<BorderData>>,

    // index of next free position in buffer
    free: Cell<usize>,
}

impl HandleMemory {
    pub fn new() -> HandleMemory {
        let buffer = box HandleBuffer::new();

        HandleMemory {
            buffers: RefCell::new(vec![buffer]),
            borders: RefCell::new(Vec::new()),
            free: Cell::new(0),
        }
    }

    pub fn root(&self, obj: Handle<Obj>) -> Rooted<Obj> {
        if self.free.get() >= HANDLE_SIZE {
            self.push_buffer();
            self.free.set(0);
        }

        let mut buffers = self.buffers.borrow_mut();
        let buffer = buffers.last_mut().unwrap();
        let elem = &mut buffer.elements[self.free.get()];

        *elem = obj;

        Rooted(elem)
    }

    fn push_buffer(&self) {
        self.buffers.borrow_mut().push(box HandleBuffer::new());
    }

    pub fn push_border(&self) {
        let buffer = self.buffers.borrow().len();
        let element = self.free.get();

        self.borders.borrow_mut().push(BorderData {
            buffer: buffer,
            element: element,
        });
    }

    pub fn pop_border(&self) {
        let border = self.borders.borrow_mut().pop().expect("no border left");

        self.buffers.borrow_mut().truncate(border.buffer);
        self.free.set(border.element);
    }

    pub fn iter(&self) -> HandleMemoryIter {
        let len = self.buffers.borrow().len();

        HandleMemoryIter {
            mem: self,
            buffer_idx: 0,
            element_idx: 0,
            full_buffer_len: if len == 0 { 0 } else { len - 1 },
            last_buffer_len: self.free.get(),
        }
    }
}

struct HandleBuffer {
    elements: [Handle<Obj>; HANDLE_SIZE],
}

impl HandleBuffer {
    fn new() -> HandleBuffer {
        HandleBuffer { elements: [Handle::null(); HANDLE_SIZE] }
    }
}

struct BorderData {
    buffer: usize,
    element: usize,
}

#[derive(Copy, Clone)]
pub struct Rooted<T>(*mut Handle<T>);

impl<T> Rooted<T> {
    pub fn direct(self) -> Handle<T> {
        unsafe { *self.0 }
    }

    pub fn raw(self) -> *mut Handle<T> {
        self.0
    }

    pub fn cast<R>(&self) -> Rooted<R> {
        Rooted(self.0 as *mut Handle<R>)
    }
}

impl<T> Deref for Rooted<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.0 }.deref()
    }
}

impl<T> DerefMut for Rooted<T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.0 }.deref_mut()
    }
}

pub struct HandleMemoryIter<'a> {
    mem: &'a HandleMemory,
    buffer_idx: usize,
    element_idx: usize,
    full_buffer_len: usize,
    last_buffer_len: usize,
}

impl<'a> Iterator for HandleMemoryIter<'a> {
    type Item = Rooted<Obj>;

    fn next(&mut self) -> Option<Rooted<Obj>> {
        if self.buffer_idx < self.full_buffer_len {
            if self.element_idx < HANDLE_SIZE {
                let idx = self.element_idx;
                self.element_idx += 1;

                let mut buffers = self.mem.buffers.borrow_mut();
                let buffer = &mut buffers[self.buffer_idx];
                return Some(Rooted(&mut buffer.elements[idx] as *mut Handle<Obj>));

            } else {
                self.buffer_idx += 1;
                self.element_idx = 0;
            }
        }

        if self.buffer_idx == self.full_buffer_len {
            if self.element_idx < self.last_buffer_len {
                let idx = self.element_idx;
                self.element_idx += 1;

                let mut buffers = self.mem.buffers.borrow_mut();
                let buffer = &mut buffers[self.buffer_idx];
                return Some(Rooted(&mut buffer.elements[idx] as *mut Handle<Obj>));

            } else {
                return None;
            }
        }

        None
    }
}<commit_msg>root() increases value of free<commit_after>use std::cell::{Cell, RefCell};
use std::ops::{Deref, DerefMut};

use object::{Handle, Obj};

pub const HANDLE_SIZE: usize = 256;

pub struct HandleMemory {
    /// all buffers, Box is important since HandleBuffer
    /// is a big struct that needs to get moved/copied on resizes
    buffers: RefCell<Vec<Box<HandleBuffer>>>,

    // store addresses of inserted borders
    borders: RefCell<Vec<BorderData>>,

    // index of next free position in buffer
    free: Cell<usize>,
}

impl HandleMemory {
    pub fn new() -> HandleMemory {
        let buffer = box HandleBuffer::new();

        HandleMemory {
            buffers: RefCell::new(vec![buffer]),
            borders: RefCell::new(Vec::new()),
            free: Cell::new(0),
        }
    }

    pub fn root(&self, obj: Handle<Obj>) -> Rooted<Obj> {
        if self.free.get() >= HANDLE_SIZE {
            self.push_buffer();
            self.free.set(0);
        }

        let mut buffers = self.buffers.borrow_mut();
        let buffer = buffers.last_mut().unwrap();

        let idx = self.free.get();
        let elem = &mut buffer.elements[idx];
        self.free.set(idx+1);

        *elem = obj;

        Rooted(elem)
    }

    fn push_buffer(&self) {
        self.buffers.borrow_mut().push(box HandleBuffer::new());
    }

    pub fn push_border(&self) {
        let buffer = self.buffers.borrow().len();
        let element = self.free.get();

        self.borders.borrow_mut().push(BorderData {
            buffer: buffer,
            element: element,
        });
    }

    pub fn pop_border(&self) {
        let border = self.borders.borrow_mut().pop().expect("no border left");

        self.buffers.borrow_mut().truncate(border.buffer);
        self.free.set(border.element);
    }

    pub fn iter(&self) -> HandleMemoryIter {
        let len = self.buffers.borrow().len();

        HandleMemoryIter {
            mem: self,
            buffer_idx: 0,
            element_idx: 0,
            full_buffer_len: if len == 0 { 0 } else { len - 1 },
            last_buffer_len: self.free.get(),
        }
    }
}

struct HandleBuffer {
    elements: [Handle<Obj>; HANDLE_SIZE],
}

impl HandleBuffer {
    fn new() -> HandleBuffer {
        HandleBuffer { elements: [Handle::null(); HANDLE_SIZE] }
    }
}

struct BorderData {
    buffer: usize,
    element: usize,
}

#[derive(Copy, Clone)]
pub struct Rooted<T>(*mut Handle<T>);

impl<T> Rooted<T> {
    pub fn direct(self) -> Handle<T> {
        unsafe { *self.0 }
    }

    pub fn raw(self) -> *mut Handle<T> {
        self.0
    }

    pub fn cast<R>(&self) -> Rooted<R> {
        Rooted(self.0 as *mut Handle<R>)
    }
}

impl<T> Deref for Rooted<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.0 }.deref()
    }
}

impl<T> DerefMut for Rooted<T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.0 }.deref_mut()
    }
}

pub struct HandleMemoryIter<'a> {
    mem: &'a HandleMemory,
    buffer_idx: usize,
    element_idx: usize,
    full_buffer_len: usize,
    last_buffer_len: usize,
}

impl<'a> Iterator for HandleMemoryIter<'a> {
    type Item = Rooted<Obj>;

    fn next(&mut self) -> Option<Rooted<Obj>> {
        if self.buffer_idx < self.full_buffer_len {
            if self.element_idx < HANDLE_SIZE {
                let idx = self.element_idx;
                self.element_idx += 1;

                let mut buffers = self.mem.buffers.borrow_mut();
                let buffer = &mut buffers[self.buffer_idx];
                return Some(Rooted(&mut buffer.elements[idx] as *mut Handle<Obj>));

            } else {
                self.buffer_idx += 1;
                self.element_idx = 0;
            }
        }

        if self.buffer_idx == self.full_buffer_len {
            if self.element_idx < self.last_buffer_len {
                let idx = self.element_idx;
                self.element_idx += 1;

                let mut buffers = self.mem.buffers.borrow_mut();
                let buffer = &mut buffers[self.buffer_idx];
                return Some(Rooted(&mut buffer.elements[idx] as *mut Handle<Obj>));

            } else {
                return None;
            }
        }

        None
    }
}<|endoftext|>