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

//! # The Rust Standard Library
//!
//! The Rust Standard Library provides the essential runtime
//! functionality for building portable Rust software.
//! It is linked to all Rust crates by default.
//!
//! ## Intrinsic types and operations
//!
//! The [`ptr`](ptr/index.html) and [`mem`](mem/index.html)
//! modules deal with unsafe pointers and memory manipulation.
//! [`marker`](marker/index.html) defines the special built-in traits,
//! and [`raw`](raw/index.html) the runtime representation of Rust types.
//! These are some of the lowest-level building blocks in Rust.
//!
//! ## Math on primitive types and math traits
//!
//! Although basic operations on primitive types are implemented
//! directly by the compiler, the standard library additionally
//! defines many common operations through traits defined in
//! mod [`num`](num/index.html).
//!
//! ## Pervasive types
//!
//! The [`option`](option/index.html) and [`result`](result/index.html)
//! modules define optional and error-handling types, `Option` and `Result`.
//! [`iter`](iter/index.html) defines Rust's iterator protocol
//! along with a wide variety of iterators.
//! [`Cell` and `RefCell`](cell/index.html) are for creating types that
//! manage their own mutability.
//!
//! ## Vectors, slices and strings
//!
//! The common container type, `Vec`, a growable vector backed by an
//! array, lives in the [`vec`](vec/index.html) module. References to
//! arrays, `&[T]`, more commonly called "slices", are built-in types
//! for which the [`slice`](slice/index.html) module defines many
//! methods.
//!
//! `&str`, a UTF-8 string, is a built-in type, and the standard library
//! defines methods for it on a variety of traits in the
//! [`str`](str/index.html) module. Rust strings are immutable;
//! use the `String` type defined in [`string`](string/index.html)
//! for a mutable string builder.
//!
//! For converting to strings use the [`format!`](fmt/index.html)
//! macro, and for converting from strings use the
//! [`FromStr`](str/trait.FromStr.html) trait.
//!
//! ## Platform abstractions
//!
//! Besides basic data types, the standard library is largely concerned
//! with abstracting over differences in common platforms, most notably
//! Windows and Unix derivatives. The [`os`](os/index.html) module
//! provides a number of basic functions for interacting with the
//! operating environment, including program arguments, environment
//! variables, and directory navigation. The [`path`](path/index.html)
//! module encapsulates the platform-specific rules for dealing
//! with file paths.
//!
//! `std` also includes modules for interoperating with the
//! C language: [`c_str`](c_str/index.html) and
//! [`c_vec`](c_vec/index.html).
//!
//! ## Concurrency, I/O, and the runtime
//!
//! The [`thread`](thread/index.html) module contains Rust's threading abstractions.
//! [`sync`](sync/index.html) contains further, primitive, shared memory types,
//! including [`atomic`](sync/atomic/index.html), and [`mpsc`](sync/mpmc/index.html),
//! which contains the channel types for message passing.
//!
//! Common types of I/O, including files, TCP, UDP, pipes, Unix domain sockets,
//! timers, and process spawning, are defined in the
//! [`old_io`](old_io/index.html) module.
//!
//! Rust's I/O and concurrency depends on a small runtime interface
//! that lives, along with its support code, in mod [`rt`](rt/index.html).
//! While a notable part of the standard library's architecture, this
//! module is not intended for public use.
//!
//! ## The Rust prelude and macros
//!
//! Finally, the [`prelude`](prelude/index.html) defines a
//! common set of traits, types, and functions that are made available
//! to all code by default. [`macros`](macros/index.html) contains
//! all the standard macros, such as `assert!`, `panic!`, `println!`,
//! and `format!`, also available to all Rust code.
// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "std"]
#![stable(feature = "rust1", since = "1.0.0")]
#![staged_api]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/",
       html_playground_url = "http://play.rust-lang.org/")]

#![feature(alloc)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
#![feature(hash)]
#![feature(lang_items)]
#![feature(libc)]
#![feature(linkage, thread_local, asm)]
#![feature(old_impl_check)]
#![feature(optin_builtin_traits)]
#![feature(rand)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unsafe_destructor)]
#![feature(unsafe_no_drop_flag)]
#![feature(macro_reexport)]
#![feature(hash)]
#![feature(int_uint)]
#![feature(unique)]
#![feature(allow_internal_unstable)]
#![feature(str_char)]
#![cfg_attr(test, feature(test, rustc_private))]

// Don't link to std. We are std.
#![feature(no_std)]
#![no_std]

#![deny(missing_docs)]

#[cfg(test)] extern crate test;
#[cfg(test)] #[macro_use] extern crate log;

#[macro_use]
#[macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq,
    unreachable, unimplemented, write, writeln)]
extern crate core;

#[macro_use]
#[macro_reexport(vec, format)]
extern crate "collections" as core_collections;

#[allow(deprecated)] extern crate "rand" as core_rand;
extern crate alloc;
extern crate unicode;
extern crate libc;

#[macro_use] #[no_link] extern crate rustc_bitflags;

// Make std testable by not duplicating lang items. See #2912
#[cfg(test)] extern crate "std" as realstd;
#[cfg(test)] pub use realstd::marker;
#[cfg(test)] pub use realstd::ops;
#[cfg(test)] pub use realstd::cmp;
#[cfg(test)] pub use realstd::boxed;

// NB: These reexports are in the order they should be listed in rustdoc

pub use core::any;
pub use core::cell;
pub use core::clone;
#[cfg(not(test))] pub use core::cmp;
pub use core::default;
#[allow(deprecated)]
pub use core::finally;
pub use core::hash;
pub use core::intrinsics;
pub use core::iter;
#[cfg(not(test))] pub use core::marker;
pub use core::mem;
#[cfg(not(test))] pub use core::ops;
pub use core::ptr;
pub use core::raw;
pub use core::simd;
pub use core::result;
pub use core::option;
pub use core::error;

#[cfg(not(test))] pub use alloc::boxed;
pub use alloc::rc;

pub use core_collections::borrow;
pub use core_collections::fmt;
pub use core_collections::slice;
pub use core_collections::str;
pub use core_collections::string;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core_collections::vec;

pub use unicode::char;

/* Exported macros */

#[macro_use]
mod macros;

mod rtdeps;

/* The Prelude. */

pub mod prelude;

/* Primitive types */

#[path = "num/float_macros.rs"]
#[macro_use]
mod float_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/uint_macros.rs"]
#[macro_use]
mod uint_macros;

#[path = "num/isize.rs"]  pub mod isize;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

pub mod ascii;
pub mod thunk;

/* Common traits */

pub mod num;

/* Runtime and platform support */

#[macro_use]
pub mod thread_local;

pub mod dynamic_lib;
pub mod ffi;
pub mod old_io;
pub mod io;
pub mod fs;
pub mod net;
pub mod os;
pub mod env;
pub mod path;
pub mod old_path;
pub mod process;
pub mod rand;
pub mod time;

/* Common data structures */

pub mod collections;

/* Threads and communication */

pub mod thread;
pub mod sync;

#[macro_use]
#[path = "sys/common/mod.rs"] mod sys_common;

#[cfg(unix)]
#[path = "sys/unix/mod.rs"] mod sys;
#[cfg(windows)]
#[path = "sys/windows/mod.rs"] mod sys;

pub mod rt;
mod panicking;

// Documentation for primitive types

mod bool;
mod unit;
mod tuple;

// A curious inner-module that's not exported that contains the binding
// 'std' so that macro-expanded references to std::error and such
// can be resolved within libstd.
#[doc(hidden)]
mod std {
    pub use sync; // used for select!()
    pub use error; // used for try!()
    pub use fmt; // used for any formatting strings
    #[allow(deprecated)]
    pub use old_io; // used for println!()
    pub use option; // used for bitflags!{}
    pub use rt; // used for panic!()
    pub use vec; // used for vec![]
    pub use cell; // used for tls!
    pub use thread_local; // used for thread_local!
    pub use marker;  // used for tls!
    pub use ops; // used for bitflags!

    // The test runner calls ::std::env::args() but really wants realstd
    #[cfg(test)] pub use realstd::env as env;
    // The test runner requires std::slice::Vector, so re-export std::slice just for it.
    //
    // It is also used in vec![]
    pub use slice;

    pub use boxed; // used for vec![]
}
<commit_msg>Clarify that slices don't just point to arrays<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # The Rust Standard Library
//!
//! The Rust Standard Library provides the essential runtime
//! functionality for building portable Rust software.
//! It is linked to all Rust crates by default.
//!
//! ## Intrinsic types and operations
//!
//! The [`ptr`](ptr/index.html) and [`mem`](mem/index.html)
//! modules deal with unsafe pointers and memory manipulation.
//! [`marker`](marker/index.html) defines the special built-in traits,
//! and [`raw`](raw/index.html) the runtime representation of Rust types.
//! These are some of the lowest-level building blocks in Rust.
//!
//! ## Math on primitive types and math traits
//!
//! Although basic operations on primitive types are implemented
//! directly by the compiler, the standard library additionally
//! defines many common operations through traits defined in
//! mod [`num`](num/index.html).
//!
//! ## Pervasive types
//!
//! The [`option`](option/index.html) and [`result`](result/index.html)
//! modules define optional and error-handling types, `Option` and `Result`.
//! [`iter`](iter/index.html) defines Rust's iterator protocol
//! along with a wide variety of iterators.
//! [`Cell` and `RefCell`](cell/index.html) are for creating types that
//! manage their own mutability.
//!
//! ## Vectors, slices and strings
//!
//! The common container type, `Vec`, a growable vector backed by an array,
//! lives in the [`vec`](vec/index.html) module. Contiguous, unsized regions
//! of memory, `[T]`, commonly called "slices", and their borrowed versions,
//! `&[T]`, commonly called "borrowed slices", are built-in types for which the
//! for which the [`slice`](slice/index.html) module defines many methods.
//!
//! `&str`, a UTF-8 string, is a built-in type, and the standard library
//! defines methods for it on a variety of traits in the
//! [`str`](str/index.html) module. Rust strings are immutable;
//! use the `String` type defined in [`string`](string/index.html)
//! for a mutable string builder.
//!
//! For converting to strings use the [`format!`](fmt/index.html)
//! macro, and for converting from strings use the
//! [`FromStr`](str/trait.FromStr.html) trait.
//!
//! ## Platform abstractions
//!
//! Besides basic data types, the standard library is largely concerned
//! with abstracting over differences in common platforms, most notably
//! Windows and Unix derivatives. The [`os`](os/index.html) module
//! provides a number of basic functions for interacting with the
//! operating environment, including program arguments, environment
//! variables, and directory navigation. The [`path`](path/index.html)
//! module encapsulates the platform-specific rules for dealing
//! with file paths.
//!
//! `std` also includes modules for interoperating with the
//! C language: [`c_str`](c_str/index.html) and
//! [`c_vec`](c_vec/index.html).
//!
//! ## Concurrency, I/O, and the runtime
//!
//! The [`thread`](thread/index.html) module contains Rust's threading abstractions.
//! [`sync`](sync/index.html) contains further, primitive, shared memory types,
//! including [`atomic`](sync/atomic/index.html), and [`mpsc`](sync/mpmc/index.html),
//! which contains the channel types for message passing.
//!
//! Common types of I/O, including files, TCP, UDP, pipes, Unix domain sockets,
//! timers, and process spawning, are defined in the
//! [`old_io`](old_io/index.html) module.
//!
//! Rust's I/O and concurrency depends on a small runtime interface
//! that lives, along with its support code, in mod [`rt`](rt/index.html).
//! While a notable part of the standard library's architecture, this
//! module is not intended for public use.
//!
//! ## The Rust prelude and macros
//!
//! Finally, the [`prelude`](prelude/index.html) defines a
//! common set of traits, types, and functions that are made available
//! to all code by default. [`macros`](macros/index.html) contains
//! all the standard macros, such as `assert!`, `panic!`, `println!`,
//! and `format!`, also available to all Rust code.
// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "std"]
#![stable(feature = "rust1", since = "1.0.0")]
#![staged_api]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/",
       html_playground_url = "http://play.rust-lang.org/")]

#![feature(alloc)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
#![feature(hash)]
#![feature(lang_items)]
#![feature(libc)]
#![feature(linkage, thread_local, asm)]
#![feature(old_impl_check)]
#![feature(optin_builtin_traits)]
#![feature(rand)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unsafe_destructor)]
#![feature(unsafe_no_drop_flag)]
#![feature(macro_reexport)]
#![feature(hash)]
#![feature(int_uint)]
#![feature(unique)]
#![feature(allow_internal_unstable)]
#![feature(str_char)]
#![cfg_attr(test, feature(test, rustc_private))]

// Don't link to std. We are std.
#![feature(no_std)]
#![no_std]

#![deny(missing_docs)]

#[cfg(test)] extern crate test;
#[cfg(test)] #[macro_use] extern crate log;

#[macro_use]
#[macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq,
    unreachable, unimplemented, write, writeln)]
extern crate core;

#[macro_use]
#[macro_reexport(vec, format)]
extern crate "collections" as core_collections;

#[allow(deprecated)] extern crate "rand" as core_rand;
extern crate alloc;
extern crate unicode;
extern crate libc;

#[macro_use] #[no_link] extern crate rustc_bitflags;

// Make std testable by not duplicating lang items. See #2912
#[cfg(test)] extern crate "std" as realstd;
#[cfg(test)] pub use realstd::marker;
#[cfg(test)] pub use realstd::ops;
#[cfg(test)] pub use realstd::cmp;
#[cfg(test)] pub use realstd::boxed;

// NB: These reexports are in the order they should be listed in rustdoc

pub use core::any;
pub use core::cell;
pub use core::clone;
#[cfg(not(test))] pub use core::cmp;
pub use core::default;
#[allow(deprecated)]
pub use core::finally;
pub use core::hash;
pub use core::intrinsics;
pub use core::iter;
#[cfg(not(test))] pub use core::marker;
pub use core::mem;
#[cfg(not(test))] pub use core::ops;
pub use core::ptr;
pub use core::raw;
pub use core::simd;
pub use core::result;
pub use core::option;
pub use core::error;

#[cfg(not(test))] pub use alloc::boxed;
pub use alloc::rc;

pub use core_collections::borrow;
pub use core_collections::fmt;
pub use core_collections::slice;
pub use core_collections::str;
pub use core_collections::string;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core_collections::vec;

pub use unicode::char;

/* Exported macros */

#[macro_use]
mod macros;

mod rtdeps;

/* The Prelude. */

pub mod prelude;

/* Primitive types */

#[path = "num/float_macros.rs"]
#[macro_use]
mod float_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/uint_macros.rs"]
#[macro_use]
mod uint_macros;

#[path = "num/isize.rs"]  pub mod isize;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

pub mod ascii;
pub mod thunk;

/* Common traits */

pub mod num;

/* Runtime and platform support */

#[macro_use]
pub mod thread_local;

pub mod dynamic_lib;
pub mod ffi;
pub mod old_io;
pub mod io;
pub mod fs;
pub mod net;
pub mod os;
pub mod env;
pub mod path;
pub mod old_path;
pub mod process;
pub mod rand;
pub mod time;

/* Common data structures */

pub mod collections;

/* Threads and communication */

pub mod thread;
pub mod sync;

#[macro_use]
#[path = "sys/common/mod.rs"] mod sys_common;

#[cfg(unix)]
#[path = "sys/unix/mod.rs"] mod sys;
#[cfg(windows)]
#[path = "sys/windows/mod.rs"] mod sys;

pub mod rt;
mod panicking;

// Documentation for primitive types

mod bool;
mod unit;
mod tuple;

// A curious inner-module that's not exported that contains the binding
// 'std' so that macro-expanded references to std::error and such
// can be resolved within libstd.
#[doc(hidden)]
mod std {
    pub use sync; // used for select!()
    pub use error; // used for try!()
    pub use fmt; // used for any formatting strings
    #[allow(deprecated)]
    pub use old_io; // used for println!()
    pub use option; // used for bitflags!{}
    pub use rt; // used for panic!()
    pub use vec; // used for vec![]
    pub use cell; // used for tls!
    pub use thread_local; // used for thread_local!
    pub use marker;  // used for tls!
    pub use ops; // used for bitflags!

    // The test runner calls ::std::env::args() but really wants realstd
    #[cfg(test)] pub use realstd::env as env;
    // The test runner requires std::slice::Vector, so re-export std::slice just for it.
    //
    // It is also used in vec![]
    pub use slice;

    pub use boxed; // used for vec![]
}
<|endoftext|>


<commit_before>use nodejs_sys as napi;

use raw::{Env, Local};

pub unsafe extern "C" fn to_object(out: &mut Local, env: Env, value: Local) -> bool {
    let status = napi::napi_coerce_to_object(env, value, out as *mut _);

    status == napi::napi_status::napi_ok
}

pub unsafe extern "C" fn to_string(out: &mut Local, env: Env, value: Local) -> bool {
    let status = napi::napi_coerce_to_string(env, value, out as *mut _);

    status == napi::napi_status::napi_ok
}
<commit_msg>napi: mark to_object as unused<commit_after>use nodejs_sys as napi;

use raw::{Env, Local};

/// This API is currently unused, see https://github.com/neon-bindings/neon/issues/572
pub unsafe extern "C" fn to_object(out: &mut Local, env: Env, value: Local) -> bool {
    let status = napi::napi_coerce_to_object(env, value, out as *mut _);

    status == napi::napi_status::napi_ok
}

pub unsafe extern "C" fn to_string(out: &mut Local, env: Env, value: Local) -> bool {
    let status = napi::napi_coerce_to_string(env, value, out as *mut _);

    status == napi::napi_status::napi_ok
}
<|endoftext|>


<commit_before>pub use self::material_font_icons::*;

pub mod material_font_icons;
<commit_msg>vector_graphics: update code to incorporate new material_icons_fonts<commit_after>pub use self::{
    material_icons_font_ttf::*,
    material_icons_font::*,
    material_icons_round_font::*,
    material_icons_sharp_font::*,
    material_icons_twotone_font::*,
};

// ttf mappings
pub mod material_icons_font_ttf;

// woff2 mappings
pub mod material_icons_font;
pub mod material_icons_round_font;
pub mod material_icons_sharp_font;
pub mod material_icons_twotone_font;
<|endoftext|>


<commit_before>use baseline::codegen::CondCode;
use cpu::asm;
use cpu::*;
use masm::MacroAssembler;

impl MacroAssembler {
    pub fn prolog(&mut self, stacksize: i32) {
        asm::emit_pushq_reg(self, RBP);
        asm::emit_movq_reg_reg(self, RSP, RBP);

        if stacksize > 0 {
            asm::emit_subq_imm_reg(self, stacksize, RSP);
        }
    }

    pub fn epilog(&mut self, stacksize: i32) {
        if stacksize > 0 {
            asm::emit_addq_imm_reg(self, stacksize, RSP);
        }

        asm::emit_popq_reg(self, RBP);
        asm::emit_retq(self);
    }

    pub fn set(&mut self, dest: Reg, op: CondCode) {
        asm::emit_setb_reg(self, op, dest);
        asm::emit_movzbl_reg_reg(self, dest, dest);
    }
}<commit_msg>moved code into MacroAssembler<commit_after>use baseline::codegen::CondCode;
use cpu::asm;
use cpu::emit;
use cpu::*;
use lexer::position::Position;
use masm::{MacroAssembler, Label};
use mem::ptr_width;
use object::IntArray;
use ty::MachineMode;
use vtable::VTable;

impl MacroAssembler {
    pub fn prolog(&mut self, stacksize: i32) {
        asm::emit_pushq_reg(self, RBP);
        asm::emit_movq_reg_reg(self, RSP, RBP);

        if stacksize > 0 {
            asm::emit_subq_imm_reg(self, stacksize, RSP);
        }
    }

    pub fn epilog(&mut self, stacksize: i32) {
        if stacksize > 0 {
            asm::emit_addq_imm_reg(self, stacksize, RSP);
        }

        asm::emit_popq_reg(self, RBP);
        asm::emit_retq(self);
    }

    pub fn direct_call(&mut self, ptr: *const u8) {
        let disp = self.add_addr(ptr);
        let pos = self.pos() as i32;

        emit::load_constpool(self, REG_RESULT, disp + pos);
        emit::call_reg(self, REG_RESULT);
    }

    pub fn indirect_call(&mut self, index: u32) {
        let obj = REG_PARAMS[0];

        // REG_RESULT = [obj] (load vtable)
        emit::load_mem(self, MachineMode::Ptr, REG_RESULT, Mem::Base(obj, 0));

        // calculate offset of VTable entry
        let disp = VTable::offset_of_method_table() + (index as i32) * ptr_width();

        // load vtable entry
        emit::load_mem(self, MachineMode::Ptr, REG_RESULT, Mem::Base(REG_RESULT, disp));

        // call *REG_RESULT
        emit::call_reg(self, REG_RESULT);
    }

    pub fn load_array_elem(&mut self, mode: MachineMode, dest: Reg, array: Reg, index: Reg) {
        assert!(mode == MachineMode::Int32);

        emit::load_mem(self, mode, dest, Mem::Index(array, index,
                       mode.size(), IntArray::offset_of_data()));
    }

    pub fn store_array_elem(&mut self, mode: MachineMode, array: Reg, index: Reg, value: Reg) {
        assert!(mode == MachineMode::Int32);

        emit::store_mem(self, MachineMode::Int32, Mem::Index(array, index,
                        4, IntArray::offset_of_data()), value);
    }

    pub fn test_if_nil_bailout(&mut self, pos: Position, reg: Reg) {
        asm::emit_testq_reg_reg(self, reg, reg);

        let lbl = self.create_label();
        emit::jump_if(self, CondCode::Zero, lbl);
        self.emit_bailout(lbl, trap::NIL, pos);
    }

    pub fn test_if_nil(&mut self, reg: Reg) -> Label {
        asm::emit_testq_reg_reg(self, reg, reg);

        let lbl = self.create_label();
        emit::jump_if(self, CondCode::Zero, lbl);

        lbl
    }

    pub fn set(&mut self, dest: Reg, op: CondCode) {
        asm::emit_setb_reg(self, op, dest);
        asm::emit_movzbl_reg_reg(self, dest, dest);
    }

    pub fn cmp_mem(&mut self, mode: MachineMode, mem: Mem, rhs: Reg) {
        match mem {
            Mem::Local(offset) => asm::emit_cmp_mem_reg(self, mode, REG_FP, offset, rhs),
            Mem::Base(base, disp) => asm::emit_cmp_mem_reg(self, mode, base, disp, rhs),
            Mem::Index(base, index, scale, disp) =>
                asm::emit_cmp_memindex_reg(self, mode, base, index, scale, disp, rhs)
        }
    }

    pub fn cmp_mem_imm(&mut self, mode: MachineMode, mem: Mem, imm: i32) {
        match mem {
            Mem::Local(_) => unimplemented!(),
            Mem::Base(base, disp) => asm::emit_cmp_mem_imm(self, mode, base, disp, imm),
            Mem::Index(_, _, _, _) => unimplemented!(),
        }
    }

    pub fn cmp_reg(&mut self, mode: MachineMode, lhs: Reg, rhs: Reg) {
        match mode {
            MachineMode::Int8
                | MachineMode::Int32 => asm::emit_cmpl_reg_reg(self, rhs, lhs),
            MachineMode::Ptr => asm::emit_cmpq_reg_reg(self, rhs, lhs),
        }
    }
}<|endoftext|>


<commit_before>//! Cretonne instruction builder.
//!
//! A `Builder` provides a convenient interface for inserting instructions into a Cretonne
//! function. Many of its methods are generated from the meta language instruction definitions.

use ir::{types, instructions};
use ir::{InstructionData, DataFlowGraph, Cursor};
use ir::{Opcode, Type, Inst, Value, Ebb, JumpTable, VariableArgs, SigRef, FuncRef};
use ir::immediates::{Imm64, Uimm8, Ieee32, Ieee64, ImmVector};
use ir::condcodes::{IntCC, FloatCC};

/// Base trait for instruction builders.
///
/// The `InstBuilderBase` trait provides the basic functionality required by the methods of the
/// generated `InstBuilder` trait. These methods should not normally be used directly. Use the
/// methods in the `InstBuilder trait instead.
///
/// Any data type that implements `InstBuilderBase` also gets all the methods of the `InstBuilder`
/// trait.
pub trait InstBuilderBase {
    /// Get an immutable reference to the data flow graph that will hold the constructed
    /// instructions.
    fn data_flow_graph(&self) -> &DataFlowGraph;

    /// Insert a simple instruction and return a reference to it.
    ///
    /// A 'simple' instruction has at most one result, and the `data.ty` field must contain the
    /// result type or `VOID` for an instruction with no result values.
    fn simple_instruction(&mut self, data: InstructionData) -> Inst;

    /// Insert a simple instruction and return a reference to it.
    ///
    /// A 'complex' instruction may produce multiple results, and the result types may depend on a
    /// controlling type variable. For non-polymorphic instructions with multiple results, pass
    /// `VOID` for the `ctrl_typevar` argument.
    fn complex_instruction(&mut self, data: InstructionData, ctrl_typevar: Type) -> Inst;
}

// Include trait code generated by `meta/gen_instr.py`.
//
// This file defines the `InstBuilder` trait as an extension of `InstBuilderBase` with methods per
// instruction format and per opcode.
include!(concat!(env!("OUT_DIR"), "/builder.rs"));

/// Any type implementing `InstBuilderBase` gets all the `InstBuilder` methods for free.
impl<T: InstBuilderBase> InstBuilder for T {}

/// Instruction builder.
///
/// A `Builder` holds mutable references to a data flow graph and a layout cursor. It provides
/// convenience method for creating and inserting instructions at the current cursor position.
pub struct Builder<'a> {
    pub dfg: &'a mut DataFlowGraph,
    pub pos: &'a mut Cursor<'a>,
}

impl<'a> Builder<'a> {
    /// Create a new builder which inserts instructions at `pos`.
    /// The `dfg` and `pos.layout` references should be from the same `Function`.
    pub fn new(dfg: &'a mut DataFlowGraph, pos: &'a mut Cursor<'a>) -> Builder<'a> {
        Builder {
            dfg: dfg,
            pos: pos,
        }
    }

    /// Create and insert an EBB. Further instructions will be inserted into the new EBB.
    pub fn ebb(&mut self) -> Ebb {
        let ebb = self.dfg.make_ebb();
        self.insert_ebb(ebb);
        ebb
    }

    /// Insert an existing EBB at the current position. Further instructions will be inserted into
    /// the new EBB.
    pub fn insert_ebb(&mut self, ebb: Ebb) {
        self.pos.insert_ebb(ebb);
    }
}

impl<'a> InstBuilderBase for Builder<'a> {
    fn data_flow_graph(&self) -> &DataFlowGraph {
        self.dfg
    }

    fn simple_instruction(&mut self, data: InstructionData) -> Inst {
        let inst = self.dfg.make_inst(data);
        self.pos.insert_inst(inst);
        inst
    }

    fn complex_instruction(&mut self, data: InstructionData, ctrl_typevar: Type) -> Inst {
        let inst = self.dfg.make_inst(data);
        self.dfg.make_inst_results(inst, ctrl_typevar);
        self.pos.insert_inst(inst);
        inst
    }
}
<commit_msg>Use more precise lifetimes for Builder.<commit_after>//! Cretonne instruction builder.
//!
//! A `Builder` provides a convenient interface for inserting instructions into a Cretonne
//! function. Many of its methods are generated from the meta language instruction definitions.

use ir::{types, instructions};
use ir::{InstructionData, DataFlowGraph, Cursor};
use ir::{Opcode, Type, Inst, Value, Ebb, JumpTable, VariableArgs, SigRef, FuncRef};
use ir::immediates::{Imm64, Uimm8, Ieee32, Ieee64, ImmVector};
use ir::condcodes::{IntCC, FloatCC};

/// Base trait for instruction builders.
///
/// The `InstBuilderBase` trait provides the basic functionality required by the methods of the
/// generated `InstBuilder` trait. These methods should not normally be used directly. Use the
/// methods in the `InstBuilder trait instead.
///
/// Any data type that implements `InstBuilderBase` also gets all the methods of the `InstBuilder`
/// trait.
pub trait InstBuilderBase {
    /// Get an immutable reference to the data flow graph that will hold the constructed
    /// instructions.
    fn data_flow_graph(&self) -> &DataFlowGraph;

    /// Insert a simple instruction and return a reference to it.
    ///
    /// A 'simple' instruction has at most one result, and the `data.ty` field must contain the
    /// result type or `VOID` for an instruction with no result values.
    fn simple_instruction(&mut self, data: InstructionData) -> Inst;

    /// Insert a simple instruction and return a reference to it.
    ///
    /// A 'complex' instruction may produce multiple results, and the result types may depend on a
    /// controlling type variable. For non-polymorphic instructions with multiple results, pass
    /// `VOID` for the `ctrl_typevar` argument.
    fn complex_instruction(&mut self, data: InstructionData, ctrl_typevar: Type) -> Inst;
}

// Include trait code generated by `meta/gen_instr.py`.
//
// This file defines the `InstBuilder` trait as an extension of `InstBuilderBase` with methods per
// instruction format and per opcode.
include!(concat!(env!("OUT_DIR"), "/builder.rs"));

/// Any type implementing `InstBuilderBase` gets all the `InstBuilder` methods for free.
impl<T: InstBuilderBase> InstBuilder for T {}

/// Instruction builder.
///
/// A `Builder` holds mutable references to a data flow graph and a layout cursor. It provides
/// convenience method for creating and inserting instructions at the current cursor position.
pub struct Builder<'c, 'fc: 'c, 'fd> {
    pub pos: &'c mut Cursor<'fc>,
    pub dfg: &'fd mut DataFlowGraph,
}

impl<'c, 'fc, 'fd> Builder<'c, 'fc, 'fd> {
    /// Create a new builder which inserts instructions at `pos`.
    /// The `dfg` and `pos.layout` references should be from the same `Function`.
    pub fn new(dfg: &'fd mut DataFlowGraph, pos: &'c mut Cursor<'fc>) -> Builder<'c, 'fc, 'fd> {
        Builder {
            dfg: dfg,
            pos: pos,
        }
    }

    /// Create and insert an EBB. Further instructions will be inserted into the new EBB.
    pub fn ebb(&mut self) -> Ebb {
        let ebb = self.dfg.make_ebb();
        self.insert_ebb(ebb);
        ebb
    }

    /// Insert an existing EBB at the current position. Further instructions will be inserted into
    /// the new EBB.
    pub fn insert_ebb(&mut self, ebb: Ebb) {
        self.pos.insert_ebb(ebb);
    }
}

impl<'c, 'fc, 'fd> InstBuilderBase for Builder<'c, 'fc, 'fd> {
    fn data_flow_graph(&self) -> &DataFlowGraph {
        self.dfg
    }

    fn simple_instruction(&mut self, data: InstructionData) -> Inst {
        let inst = self.dfg.make_inst(data);
        self.pos.insert_inst(inst);
        inst
    }

    fn complex_instruction(&mut self, data: InstructionData, ctrl_typevar: Type) -> Inst {
        let inst = self.dfg.make_inst(data);
        self.dfg.make_inst_results(inst, ctrl_typevar);
        self.pos.insert_inst(inst);
        inst
    }
}
<|endoftext|>


<commit_before>pub mod basic_particle;
pub use self::basic_particle::*;

extern crate num;
use self::num::Float;
use super::vector::*;

//An object that has quanta
pub trait Quanta<D> {
    //Retrieve the quanta of a physics particle
    fn quanta(&self) -> D;
}

//An object that has inertia
pub trait Inertia<D> {
    //Retrieve the inertia of a physics particle
    fn inertia(&self) -> D;
}

//An opject with a location
pub trait Position<V> {
    //Get position of particle
    fn position(&self) -> V;
}

//An object that has a simple particle motion interface
pub trait Particle<V, D>: Position<V> + Inertia<D> + Quanta<D> {
    //Get velocity of particle
    fn velocity(&self) -> V;
    //Accelerate particle
    fn accelerate(&mut self, vec: &V);
    //Advance particle (update position and velocity)
    fn advance(&mut self, time: D);
}

pub trait PhysicsParticle<V, D>: Particle<V, D> + Quanta<D> + Inertia<D>
    where V: Vector<D>, D: Float
{
    //Convert a PhysicsParticle into a "basic particle" that implements PhysicsParticle but has the minimum members
    fn basic_form(&self) -> BasicParticle<V, D> {
        BasicParticle::new(self.quanta(), self.position(), self.velocity(), self.inertia())
    }

    //Apply drag forces to a particle
    fn drag(&mut self, magnitude: D) {
        let acceleration = -self.velocity() * magnitude / self.inertia();
        self.accelerate(&acceleration);
    }

    //Apply proper attraction between two physics particles based on their quanta and position
    fn gravitate<T: ?Sized>(lhs: &mut Self, rhs: &mut T, magnitude: D)
        where T: PhysicsParticle<V, D>
    {
        //Create delta vector between the two positions
        let delta = rhs.position() - lhs.position();
        //Find the distance of the delta vector
        let distance = delta.displacement();
        //Dividing the delta vector by the distance cubed computes attractive force as per the inverse square law.
        //The extra degree normalizes the direction vector to a unit vector.
        let force = delta * magnitude / distance.powi(3) *
        //Multiply by the two quanta of the objects to compute the final force.
        lhs.quanta() * rhs.quanta();

        //Accelerate lhs in the direction of force and divide it by the inertia
        let acceleration = force / lhs.inertia();
        lhs.accelerate(&acceleration);
        //Apply the inverse force to the rhs similarly
        let acceleration = -force / rhs.inertia();
        rhs.accelerate(&acceleration);
    }

    /*
    If gravitating at a distance greater than the radius, then gravitational interaction is applied as if the
    particles are point particles. If the distance is less than the radius, then the interaction happens as if the
    gravitational quanta (mass) is evenly distributed and gravitational flux is used instead, which causes the
    interaction to become proportional to the radius, meaning that as the radius approaches zero, so does the force.

    The radius is passed squared for internal efficiency reasons.
    */
    fn gravitate_radius_squared<T: ?Sized>(lhs: &mut Self, rhs: &mut T, radius_squared: D, magnitude: D)
        where T: PhysicsParticle<V, D>
    {
        let delta = rhs.position() - lhs.position();
        let distance_squared = delta.displacement_squared();
        //Force is the only thing that changes from normal gravitation
        let force = delta * magnitude * lhs.quanta() * rhs.quanta() / if distance_squared > radius_squared {
            distance_squared.sqrt().powi(3)
        } else {
            radius_squared
        };
        let acceleration = force / lhs.inertia();
        lhs.accelerate(&acceleration);
        let acceleration = -force / rhs.inertia();
        rhs.accelerate(&acceleration);
    }

    //This function exists so that if an optimization is possible later, it can be specially implemented.
    //Presently it just acts as a frontend to its squared counterpart. Prefer squared version if possible.
    fn gravitate_radius<T: ?Sized>(lhs: &mut Self, rhs: &mut T, radius: D, magnitude: D)
        where T: PhysicsParticle<V, D>
    {
        Self::gravitate_radius_squared(lhs, rhs, radius * radius, magnitude);
    }

    //Apply proper attraction to a single physics particle towards a location and with a magnitude
    fn gravitate_to(&mut self, location: V, magnitude: D) {
        //Create delta vector from the particle to the center of attraction
        let delta = location - self.position();
        let distance = delta.displacement();
        let acceleration = delta / distance.powi(3) * magnitude * self.quanta() / self.inertia();
        self.accelerate(&acceleration);
    }

    //Works the same as gravitate_radius_squared and gravitate_to
    fn gravitate_radius_squared_to(&mut self, location: V, radius_squared: D, magnitude: D) {
        //Create delta vector from the particle to the center of attraction
        let delta = location - self.position();
        let distance_squared = delta.displacement_squared();
        let acceleration = delta * magnitude * self.quanta() / (
                self.inertia() *
                if distance_squared > radius_squared {
                    distance_squared.sqrt().powi(3)
                } else {
                    radius_squared
                }
            );
        self.accelerate(&acceleration);
    }

    //This function exists so that if an optimization is possible later, it can be specially implemented.
    //Presently it just acts as a frontend to its squared counterpart. Prefer squared version if possible.
    fn gravitate_radius_to(&mut self, location: V, radius: D, magnitude: D) {
        self.gravitate_radius_squared_to(location, radius * radius, magnitude);
    }

    //Apply spring forces between two particles
    fn hooke<T: ?Sized>(lhs: &mut Self, rhs: &mut T, magnitude: D)
        where T: PhysicsParticle<V, D>
    {
        let delta = rhs.position() - lhs.position();
        let force = delta.normalized() * magnitude * delta.displacement() * lhs.quanta() * rhs.quanta();
        let acceleration = force / lhs.inertia();
        lhs.accelerate(&acceleration);
        let acceleration = -force / rhs.inertia();
        rhs.accelerate(&acceleration);
    }

    //Apply spring forces between two particles with specified equilibrium distance
    fn hooke_equilibrium<T: ?Sized>(lhs: &mut Self, rhs: &mut T, equilibrium: D, magnitude: D)
        where T: PhysicsParticle<V, D>
    {
        let delta = rhs.position() - lhs.position();
        let force = delta.normalized() * magnitude *
            //We scale such that if displacement is greater than equilibrium, the particles attract proportionally
            //Particles with a displacement smaller than equilibrium repel each other
            (delta.displacement() - equilibrium) *
            lhs.quanta() * rhs.quanta();
        let acceleration = force / lhs.inertia();
        lhs.accelerate(&acceleration);
        let acceleration = -force / rhs.inertia();
        rhs.accelerate(&acceleration);
    }

    //Apply spring forces between one particle and a position with a magnitude
    fn hooke_to(&mut self, location: V, magnitude: D) {
        let delta = location - self.position();
        let acceleration = delta.normalized() * delta.displacement() *
            magnitude * self.quanta() / self.inertia();
        self.accelerate(&acceleration);
    }

    //Apply spring forces between one particle and a position with an equilibrium and magnitude
    fn hooke_equilibrium_to(&mut self, location: V, equilibrium: D, magnitude: D) {
        let delta = location - self.position();
        let acceleration = delta.normalized() * (delta.displacement() - equilibrium) *
            magnitude * self.quanta() / self.inertia();
        self.accelerate(&acceleration);
    }

    //Apply lorentz forces between two PhysicsParticle objects based on quanta, position, and velocity
    fn lorentz<T: ?Sized>(lhs: &mut Self, rhs: &mut T, magnitude: D)
        where V: CrossVector, T: PhysicsParticle<V, D>
    {
        let delta = rhs.position() - lhs.position();
        let distance = delta.displacement();
        let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) *
            lhs.quanta() * rhs.quanta() / distance.powi(3) * magnitude;

        let acceleration = -force / lhs.inertia();
        lhs.accelerate(&acceleration);
        let acceleration = force / rhs.inertia();
        rhs.accelerate(&acceleration);
    }

    //Apply lorentz forces between two PhysicsParticle objects with a radius_squared
    fn lorentz_radius_squared<T: ?Sized>(lhs: &mut Self, rhs: &mut T, radius_squared: D, magnitude: D)
        where V: CrossVector, T: PhysicsParticle<V, D>
    {
        let delta = rhs.position() - lhs.position();
        let distance_squared = delta.displacement_squared();
        let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) * magnitude *
            lhs.quanta() * rhs.quanta() /
            if distance_squared > radius_squared {
                distance_squared.sqrt().powi(3)
            } else {
                radius_squared
            };

        let acceleration = -force / lhs.inertia();
        lhs.accelerate(&acceleration);
        let acceleration = force / rhs.inertia();
        rhs.accelerate(&acceleration);
    }

    //This function exists so that if an optimization is possible later, it can be specially implemented.
    //Presently it just acts as a frontend to its squared counterpart. Prefer squared version if possible.
    fn lorentz_radius<T: ?Sized>(lhs: &mut Self, rhs: &mut T, radius: D, magnitude: D)
        where V: CrossVector, T: PhysicsParticle<V, D>
    {
        Self::lorentz_radius_squared(lhs, rhs, radius * radius, magnitude);
    }

    //Apply lorentz force to a particle in a field given by a vector with the magnitude and direction of the field
    fn lorentz_field(&mut self, field: &V)
        where V: CrossVector
    {
        let acceleration = V::cross(&self.velocity(), field) * self.quanta() / self.inertia();
        self.accelerate(&acceleration);
    }
}
<commit_msg>removed quanta from particle<commit_after>pub mod basic_particle;
pub use self::basic_particle::*;

extern crate num;
use self::num::Float;
use super::vector::*;

//An object that has quanta
pub trait Quanta<D> {
    //Retrieve the quanta of a physics particle
    fn quanta(&self) -> D;
}

//An object that has inertia
pub trait Inertia<D> {
    //Retrieve the inertia of a physics particle
    fn inertia(&self) -> D;
}

//An opject with a location
pub trait Position<V> {
    //Get position of particle
    fn position(&self) -> V;
}

//An object that has a simple particle motion interface
pub trait Particle<V, D>: Position<V> + Inertia<D> {
    //Get velocity of particle
    fn velocity(&self) -> V;
    //Accelerate particle
    fn accelerate(&mut self, vec: &V);
    //Advance particle (update position and velocity)
    fn advance(&mut self, time: D);
}

pub trait PhysicsParticle<V, D>: Particle<V, D> + Quanta<D> + Inertia<D>
    where V: Vector<D>, D: Float
{
    //Convert a PhysicsParticle into a "basic particle" that implements PhysicsParticle but has the minimum members
    fn basic_form(&self) -> BasicParticle<V, D> {
        BasicParticle::new(self.quanta(), self.position(), self.velocity(), self.inertia())
    }

    //Apply drag forces to a particle
    fn drag(&mut self, magnitude: D) {
        let acceleration = -self.velocity() * magnitude / self.inertia();
        self.accelerate(&acceleration);
    }

    //Apply proper attraction between two physics particles based on their quanta and position
    fn gravitate<T: ?Sized>(lhs: &mut Self, rhs: &mut T, magnitude: D)
        where T: PhysicsParticle<V, D>
    {
        //Create delta vector between the two positions
        let delta = rhs.position() - lhs.position();
        //Find the distance of the delta vector
        let distance = delta.displacement();
        //Dividing the delta vector by the distance cubed computes attractive force as per the inverse square law.
        //The extra degree normalizes the direction vector to a unit vector.
        let force = delta * magnitude / distance.powi(3) *
        //Multiply by the two quanta of the objects to compute the final force.
        lhs.quanta() * rhs.quanta();

        //Accelerate lhs in the direction of force and divide it by the inertia
        let acceleration = force / lhs.inertia();
        lhs.accelerate(&acceleration);
        //Apply the inverse force to the rhs similarly
        let acceleration = -force / rhs.inertia();
        rhs.accelerate(&acceleration);
    }

    /*
    If gravitating at a distance greater than the radius, then gravitational interaction is applied as if the
    particles are point particles. If the distance is less than the radius, then the interaction happens as if the
    gravitational quanta (mass) is evenly distributed and gravitational flux is used instead, which causes the
    interaction to become proportional to the radius, meaning that as the radius approaches zero, so does the force.

    The radius is passed squared for internal efficiency reasons.
    */
    fn gravitate_radius_squared<T: ?Sized>(lhs: &mut Self, rhs: &mut T, radius_squared: D, magnitude: D)
        where T: PhysicsParticle<V, D>
    {
        let delta = rhs.position() - lhs.position();
        let distance_squared = delta.displacement_squared();
        //Force is the only thing that changes from normal gravitation
        let force = delta * magnitude * lhs.quanta() * rhs.quanta() / if distance_squared > radius_squared {
            distance_squared.sqrt().powi(3)
        } else {
            radius_squared
        };
        let acceleration = force / lhs.inertia();
        lhs.accelerate(&acceleration);
        let acceleration = -force / rhs.inertia();
        rhs.accelerate(&acceleration);
    }

    //This function exists so that if an optimization is possible later, it can be specially implemented.
    //Presently it just acts as a frontend to its squared counterpart. Prefer squared version if possible.
    fn gravitate_radius<T: ?Sized>(lhs: &mut Self, rhs: &mut T, radius: D, magnitude: D)
        where T: PhysicsParticle<V, D>
    {
        Self::gravitate_radius_squared(lhs, rhs, radius * radius, magnitude);
    }

    //Apply proper attraction to a single physics particle towards a location and with a magnitude
    fn gravitate_to(&mut self, location: V, magnitude: D) {
        //Create delta vector from the particle to the center of attraction
        let delta = location - self.position();
        let distance = delta.displacement();
        let acceleration = delta / distance.powi(3) * magnitude * self.quanta() / self.inertia();
        self.accelerate(&acceleration);
    }

    //Works the same as gravitate_radius_squared and gravitate_to
    fn gravitate_radius_squared_to(&mut self, location: V, radius_squared: D, magnitude: D) {
        //Create delta vector from the particle to the center of attraction
        let delta = location - self.position();
        let distance_squared = delta.displacement_squared();
        let acceleration = delta * magnitude * self.quanta() / (
                self.inertia() *
                if distance_squared > radius_squared {
                    distance_squared.sqrt().powi(3)
                } else {
                    radius_squared
                }
            );
        self.accelerate(&acceleration);
    }

    //This function exists so that if an optimization is possible later, it can be specially implemented.
    //Presently it just acts as a frontend to its squared counterpart. Prefer squared version if possible.
    fn gravitate_radius_to(&mut self, location: V, radius: D, magnitude: D) {
        self.gravitate_radius_squared_to(location, radius * radius, magnitude);
    }

    //Apply spring forces between two particles
    fn hooke<T: ?Sized>(lhs: &mut Self, rhs: &mut T, magnitude: D)
        where T: PhysicsParticle<V, D>
    {
        let delta = rhs.position() - lhs.position();
        let force = delta.normalized() * magnitude * delta.displacement() * lhs.quanta() * rhs.quanta();
        let acceleration = force / lhs.inertia();
        lhs.accelerate(&acceleration);
        let acceleration = -force / rhs.inertia();
        rhs.accelerate(&acceleration);
    }

    //Apply spring forces between two particles with specified equilibrium distance
    fn hooke_equilibrium<T: ?Sized>(lhs: &mut Self, rhs: &mut T, equilibrium: D, magnitude: D)
        where T: PhysicsParticle<V, D>
    {
        let delta = rhs.position() - lhs.position();
        let force = delta.normalized() * magnitude *
            //We scale such that if displacement is greater than equilibrium, the particles attract proportionally
            //Particles with a displacement smaller than equilibrium repel each other
            (delta.displacement() - equilibrium) *
            lhs.quanta() * rhs.quanta();
        let acceleration = force / lhs.inertia();
        lhs.accelerate(&acceleration);
        let acceleration = -force / rhs.inertia();
        rhs.accelerate(&acceleration);
    }

    //Apply spring forces between one particle and a position with a magnitude
    fn hooke_to(&mut self, location: V, magnitude: D) {
        let delta = location - self.position();
        let acceleration = delta.normalized() * delta.displacement() *
            magnitude * self.quanta() / self.inertia();
        self.accelerate(&acceleration);
    }

    //Apply spring forces between one particle and a position with an equilibrium and magnitude
    fn hooke_equilibrium_to(&mut self, location: V, equilibrium: D, magnitude: D) {
        let delta = location - self.position();
        let acceleration = delta.normalized() * (delta.displacement() - equilibrium) *
            magnitude * self.quanta() / self.inertia();
        self.accelerate(&acceleration);
    }

    //Apply lorentz forces between two PhysicsParticle objects based on quanta, position, and velocity
    fn lorentz<T: ?Sized>(lhs: &mut Self, rhs: &mut T, magnitude: D)
        where V: CrossVector, T: PhysicsParticle<V, D>
    {
        let delta = rhs.position() - lhs.position();
        let distance = delta.displacement();
        let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) *
            lhs.quanta() * rhs.quanta() / distance.powi(3) * magnitude;

        let acceleration = -force / lhs.inertia();
        lhs.accelerate(&acceleration);
        let acceleration = force / rhs.inertia();
        rhs.accelerate(&acceleration);
    }

    //Apply lorentz forces between two PhysicsParticle objects with a radius_squared
    fn lorentz_radius_squared<T: ?Sized>(lhs: &mut Self, rhs: &mut T, radius_squared: D, magnitude: D)
        where V: CrossVector, T: PhysicsParticle<V, D>
    {
        let delta = rhs.position() - lhs.position();
        let distance_squared = delta.displacement_squared();
        let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) * magnitude *
            lhs.quanta() * rhs.quanta() /
            if distance_squared > radius_squared {
                distance_squared.sqrt().powi(3)
            } else {
                radius_squared
            };

        let acceleration = -force / lhs.inertia();
        lhs.accelerate(&acceleration);
        let acceleration = force / rhs.inertia();
        rhs.accelerate(&acceleration);
    }

    //This function exists so that if an optimization is possible later, it can be specially implemented.
    //Presently it just acts as a frontend to its squared counterpart. Prefer squared version if possible.
    fn lorentz_radius<T: ?Sized>(lhs: &mut Self, rhs: &mut T, radius: D, magnitude: D)
        where V: CrossVector, T: PhysicsParticle<V, D>
    {
        Self::lorentz_radius_squared(lhs, rhs, radius * radius, magnitude);
    }

    //Apply lorentz force to a particle in a field given by a vector with the magnitude and direction of the field
    fn lorentz_field(&mut self, field: &V)
        where V: CrossVector
    {
        let acceleration = V::cross(&self.velocity(), field) * self.quanta() / self.inertia();
        self.accelerate(&acceleration);
    }
}
<|endoftext|>


<commit_before>//! An extension trait that provides the ability to strip IRC colors from a string
use std::borrow::Cow;

#[derive(PartialEq)]
enum ParserState {
    Text,
    ColorCode,
    Foreground1,
    Foreground2,
    Comma,
    Background1,
}
struct Parser {
    state: ParserState,
}

/// An extension trait giving strings a function to strip IRC colors
pub trait FormattedStringExt<'a> {

    /// Returns true if the string contains color, bold, underline or italics
    fn is_formatted(&self) -> bool;

    /// Returns the string with all color, bold, underline and italics stripped
    fn strip_formatting(self) -> Cow<'a, str>;

}

const FORMAT_CHARACTERS: &[char] = &[
    '\x02', // bold
    '\x1F', // underline
    '\x16', // reverse
    '\x0F', // normal
    '\x03', // color
];

impl<'a> FormattedStringExt<'a> for &'a str {
    fn is_formatted(&self) -> bool {
        self.contains(FORMAT_CHARACTERS)
    }

    fn strip_formatting(self) -> Cow<'a, str> {
        if !self.is_formatted() {
            return Cow::Borrowed(self);
        }
        let mut s = String::from(self);
        strip_formatting(&mut s);
        Cow::Owned(s)
    }
}

fn strip_formatting(buf: &mut String) {
    let mut parser = Parser {
        state: ParserState::Text,
    };
    let mut prev: char = '\x00';
    buf.retain(|cur| {
        let result = match parser.state {
            ParserState::Text | ParserState::Foreground1 | ParserState::Foreground2 if cur == '\x03' => {
                parser.state = ParserState::ColorCode;
                false
            },
            ParserState::Text => !FORMAT_CHARACTERS.contains(&cur),
            ParserState::ColorCode if cur.is_digit(10) => {
                parser.state = ParserState::Foreground1;
                false
            },
            ParserState::Foreground1 if cur.is_digit(6) => {
                // can only consume another digit if previous char was 1.
                if prev == '1' {
                    parser.state = ParserState::Foreground2;
                    false
                } else {
                    parser.state = ParserState::Text;
                    true
                }
            },
            ParserState::Foreground1 if cur == ','  => {
                parser.state = ParserState::Comma;
                false
            },
            ParserState::Foreground2 if cur == ',' => {
                parser.state = ParserState::Comma;
                false
            },
            ParserState::Comma if (cur.is_digit(10)) => {
                parser.state = ParserState::Background1;
                false
            },
            ParserState::Background1 if cur.is_digit(6) => {
                // can only consume another digit if previous char was 1.
                parser.state = ParserState::Text;
                if prev == '1' {
                    false
                } else {
                    true
                }
            }
            _ => {
                parser.state = ParserState::Text;
                true
            }
        };
        prev = cur;
        return result
    });
}

impl FormattedStringExt<'static> for String {
    fn is_formatted(&self) -> bool {
        self.as_str().is_formatted()
    }
    fn strip_formatting(mut self) -> Cow<'static, str> {
        if !self.is_formatted() {
            return Cow::Owned(self);
        }
        strip_formatting(&mut self);
        Cow::Owned(self)
    }
}

#[cfg(test)]
mod test {
    use std::borrow::Cow;
    use proto::colors::FormattedStringExt;

    macro_rules! test_formatted_string_ext {
        { $( $name:ident ( $($line:tt)* ), )* } => {
            $(
            mod $name {
                use super::*;
                test_formatted_string_ext!(@ $($line)*);
            }
            )*
        };
        (@ $text:expr, should stripped into $expected:expr) => {
            #[test]
            fn test_formatted() {
                assert!($text.is_formatted());
            }
            #[test]
            fn test_strip() {
                assert_eq!($text.strip_formatting(), $expected);
            }
        };
        (@ $text:expr, is not formatted) => {
            #[test]
            fn test_formatted() {
                assert!(!$text.is_formatted());
            }
            #[test]
            fn test_strip() {
                assert_eq!($text.strip_formatting(), $text);
            }
        }
    }

    test_formatted_string_ext! {
        blank("", is not formatted),
        blank2("    ", is not formatted),
        blank3("\t\r\n", is not formatted),
        bold("l\x02ol", should stripped into "lol"),
        bold_from_string(String::from("l\x02ol"), should stripped into "lol"),
        bold_hangul("우왕\x02굳", should stripped into "우왕굳"),
        fg_color("l\x033ol", should stripped into "lol"),
        fg_color2("l\x0312ol", should stripped into "lol"),
        fg_bg_11("l\x031,2ol", should stripped into "lol"),
        fg_bg_21("l\x0312,3ol", should stripped into "lol"),
        fg_bg_12("l\x031,12ol", should stripped into "lol"),
        fg_bg_22("l\x0312,13ol", should stripped into "lol"),
        string_with_multiple_colors("hoo\x034r\x033a\x0312y", should stripped into "hooray"),
        string_with_digit_after_color("\x0344\x0355\x0366", should stripped into "456"),
        string_with_multiple_2digit_colors("hoo\x0310r\x0311a\x0312y", should stripped into "hooray"),
        string_with_digit_after_2digit_color("\x031212\x031111\x031010", should stripped into "121110"),
        thinking("🤔...", is not formatted),
        unformatted("a plain text", is not formatted),
    }

    #[test]
    fn test_strip_no_allocation_for_unformatted_text() {
        if let Cow::Borrowed(formatted) = "plain text".strip_formatting() {
            assert_eq!(formatted, "plain text");
        } else {
            panic!("allocation detected");
        }
    }
}
<commit_msg>Polish the parser<commit_after>//! An extension trait that provides the ability to strip IRC colors from a string
use std::borrow::Cow;

enum ParserState {
    Text,
    ColorCode,
    Foreground1(char),
    Foreground2,
    Comma,
    Background1(char),
}
struct Parser {
    state: ParserState,
}

/// An extension trait giving strings a function to strip IRC colors
pub trait FormattedStringExt<'a> {

    /// Returns true if the string contains color, bold, underline or italics
    fn is_formatted(&self) -> bool;

    /// Returns the string with all color, bold, underline and italics stripped
    fn strip_formatting(self) -> Cow<'a, str>;

}

const FORMAT_CHARACTERS: &[char] = &[
    '\x02', // bold
    '\x1F', // underline
    '\x16', // reverse
    '\x0F', // normal
    '\x03', // color
];

impl<'a> FormattedStringExt<'a> for &'a str {
    fn is_formatted(&self) -> bool {
        self.contains(FORMAT_CHARACTERS)
    }

    fn strip_formatting(self) -> Cow<'a, str> {
        if !self.is_formatted() {
            return Cow::Borrowed(self);
        }
        let mut s = String::from(self);
        strip_formatting(&mut s);
        Cow::Owned(s)
    }
}

fn strip_formatting(buf: &mut String) {
    let mut parser = Parser::new();
    buf.retain(|cur| parser.next(cur));
}

impl Parser {
    fn new() -> Self {
        Parser  {
            state: ParserState::Text,
        }
    }

    fn next(&mut self, cur: char) -> bool {
        use self::ParserState::*;
        match self.state {
            Text | Foreground1(_) | Foreground2 if cur == '\x03' => {
                self.state = ColorCode;
                false
            }
            Text => {
                !FORMAT_CHARACTERS.contains(&cur)
            }
            ColorCode if cur.is_digit(10) => {
                self.state = Foreground1(cur);
                false
            }
            Foreground1('1') if cur.is_digit(6) => {
                // can only consume another digit if previous char was 1.
                self.state = Foreground2;
                false
            }
            Foreground1(_) if cur.is_digit(6) => {
                self.state = Text;
                true
            }
            Foreground1(_) if cur == ',' => {
                self.state = Comma;
                false
            }
            Foreground2 if cur == ',' => {
                self.state = Comma;
                false
            }
            Comma if (cur.is_digit(10)) => {
                self.state = Background1(cur);
                false
            }
            Background1(prev) if cur.is_digit(6) => {
                // can only consume another digit if previous char was 1.
                self.state = Text;
                prev != '1'
            }
            _ => {
                self.state = Text;
                true
            }
        }
    }
}

impl FormattedStringExt<'static> for String {
    fn is_formatted(&self) -> bool {
        self.as_str().is_formatted()
    }
    fn strip_formatting(mut self) -> Cow<'static, str> {
        if !self.is_formatted() {
            return Cow::Owned(self);
        }
        strip_formatting(&mut self);
        Cow::Owned(self)
    }
}

#[cfg(test)]
mod test {
    use std::borrow::Cow;
    use proto::colors::FormattedStringExt;

    macro_rules! test_formatted_string_ext {
        { $( $name:ident ( $($line:tt)* ), )* } => {
            $(
            mod $name {
                use super::*;
                test_formatted_string_ext!(@ $($line)*);
            }
            )*
        };
        (@ $text:expr, should stripped into $expected:expr) => {
            #[test]
            fn test_formatted() {
                assert!($text.is_formatted());
            }
            #[test]
            fn test_strip() {
                assert_eq!($text.strip_formatting(), $expected);
            }
        };
        (@ $text:expr, is not formatted) => {
            #[test]
            fn test_formatted() {
                assert!(!$text.is_formatted());
            }
            #[test]
            fn test_strip() {
                assert_eq!($text.strip_formatting(), $text);
            }
        }
    }

    test_formatted_string_ext! {
        blank("", is not formatted),
        blank2("    ", is not formatted),
        blank3("\t\r\n", is not formatted),
        bold("l\x02ol", should stripped into "lol"),
        bold_from_string(String::from("l\x02ol"), should stripped into "lol"),
        bold_hangul("우왕\x02굳", should stripped into "우왕굳"),
        fg_color("l\x033ol", should stripped into "lol"),
        fg_color2("l\x0312ol", should stripped into "lol"),
        fg_bg_11("l\x031,2ol", should stripped into "lol"),
        fg_bg_21("l\x0312,3ol", should stripped into "lol"),
        fg_bg_12("l\x031,12ol", should stripped into "lol"),
        fg_bg_22("l\x0312,13ol", should stripped into "lol"),
        string_with_multiple_colors("hoo\x034r\x033a\x0312y", should stripped into "hooray"),
        string_with_digit_after_color("\x0344\x0355\x0366", should stripped into "456"),
        string_with_multiple_2digit_colors("hoo\x0310r\x0311a\x0312y", should stripped into "hooray"),
        string_with_digit_after_2digit_color("\x031212\x031111\x031010", should stripped into "121110"),
        thinking("🤔...", is not formatted),
        unformatted("a plain text", is not formatted),
    }

    #[test]
    fn test_strip_no_allocation_for_unformatted_text() {
        if let Cow::Borrowed(formatted) = "plain text".strip_formatting() {
            assert_eq!(formatted, "plain text");
        } else {
            panic!("allocation detected");
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
pub struct Memory
{
    bytes: [u8;65536]
}

impl Memory
{
    pub fn new() -> Memory
    {
        Memory
        {
            bytes: [0;0x10000] // 64k memory
        }
    }

    pub fn reset(&mut self)
    {
        self.write_byte(0x0000, 0xFF);
        self.write_byte(0x0001, 0x07);
    }

    // Write a byte to memory
    pub fn write_byte(&mut self, addr: u16, value: u8)
    {
        self.bytes[addr as usize] = value;
    }

    // Read a byte from memory
    pub fn read_byte(&mut self, addr: u16) -> u8
    {
        self.bytes[addr as usize]
    }

    // Read a word from memory (stored in little endian)
    pub fn read_word_le(&mut self, addr: u16) -> u16
    {
        let value_be: u16 = ((self.bytes[addr as usize] as u16) << 8 & 0xFF00) |
                            ((self.bytes[(addr + 0x0001) as usize] as u16) & 0x00FF);

        let value_le: u16 = ((value_be << 8) & 0xFF00) | ((value_be >> 8) & 0x00FF);
        value_le
    }

    // Read a word from memory (stored in big endian: swap low<->high)
    pub fn read_word_be(&mut self, addr: u16) -> u16
    {
        let value_le: u16 = ((self.bytes[addr as usize] as u16) << 8 & 0xFF00) |
                            ((self.bytes[(addr + 0x0001) as usize] as u16) & 0x00FF);
        value_le
    }

    // Write word in little endian format (low/high)
    pub fn write_word_le(&mut self, addr: u16, value: u16)
    {
        let value_le_lo: u8 = (((value << 8) & 0xFF00) >> 8 & 0xFF) as u8;
        let value_le_hi: u8 = ((value >> 8) & 0x00FF) as u8;

        self.bytes[addr as usize] = value_le_lo;
        self.bytes[(addr + 0x0001) as usize] = value_le_hi;
    }

    // Write word in big endian format (high/low)
    pub fn write_word_be(&mut self, addr: u16, value: u16)
    {
        let value_le_lo: u8 = (((value << 8) & 0xFF00) >> 8 & 0xFF) as u8;
        let value_le_hi: u8 = ((value >> 8) & 0x00FF) as u8;

        self.bytes[addr as usize] = value_le_hi;
        self.bytes[(addr + 0x0001) as usize] = value_le_lo;
    }
}

<commit_msg>separate storage for ram and rom<commit_after>#![allow(dead_code)]
use utils;
pub struct Memory
{
    // RAM
    ram: [u8;65536],
    // ROM
    kernal: [u8;8192],
    basic:  [u8;8192],
    chargen: [u8;4096]
}

impl Memory
{
    pub fn new() -> Memory
    {
        let mut memory = Memory
        {
            ram: [0;0x10000],   // 64k
            kernal: [0;0x2000], // 8k
            basic: [0;0x2000],  // 8k
            chargen: [0;0x1000] // 4k
        };

        // load kernal
        let kernal = utils::open_file("rom/kernal.rom");
        for i in (0..0x2000)
        {
            memory.kernal[i] = kernal[i];
        }

        // load basic
        let basic = utils::open_file("rom/basic.rom");
        for i in (0..0x2000)
        {
            memory.basic[i] = basic[i];
        }

        // load chargen
        let chargen = utils::open_file("rom/chargen.rom");
        for i in (0..0x1000)
        {
            memory.chargen[i] = chargen[i];
        }

        memory
    }

    pub fn reset(&mut self)
    {
        self.write_byte(0x0000, 0xFF);
        self.write_byte(0x0001, 0x07); // enable kernal, chargen and basic access
    }

    // Write a byte to memory
    pub fn write_byte(&mut self, addr: u16, value: u8)
    {
        self.ram[addr as usize] = value;
    }

    // Read a byte from memory
    pub fn read_byte(&mut self, addr: u16) -> u8
    {
        self.ram[addr as usize]
    }

    // Read a word from memory (stored in little endian)
    pub fn read_word_le(&mut self, addr: u16) -> u16
    {
        let value_be: u16 = ((self.ram[addr as usize] as u16) << 8 & 0xFF00) |
                            ((self.ram[(addr + 0x0001) as usize] as u16) & 0x00FF);

        let value_le: u16 = ((value_be << 8) & 0xFF00) | ((value_be >> 8) & 0x00FF);
        value_le
    }

    // Read a word from memory (stored in big endian: swap low<->high)
    pub fn read_word_be(&mut self, addr: u16) -> u16
    {
        let value_le: u16 = ((self.ram[addr as usize] as u16) << 8 & 0xFF00) |
                            ((self.ram[(addr + 0x0001) as usize] as u16) & 0x00FF);
        value_le
    }

    // Write word in little endian format (low/high)
    pub fn write_word_le(&mut self, addr: u16, value: u16)
    {
        let value_le_lo: u8 = (((value << 8) & 0xFF00) >> 8 & 0xFF) as u8;
        let value_le_hi: u8 = ((value >> 8) & 0x00FF) as u8;

        self.ram[addr as usize] = value_le_lo;
        self.ram[(addr + 0x0001) as usize] = value_le_hi;
    }

    // Write word in big endian format (high/low)
    pub fn write_word_be(&mut self, addr: u16, value: u16)
    {
        let value_le_lo: u8 = (((value << 8) & 0xFF00) >> 8 & 0xFF) as u8;
        let value_le_hi: u8 = ((value >> 8) & 0x00FF) as u8;

        self.ram[addr as usize] = value_le_hi;
        self.ram[(addr + 0x0001) as usize] = value_le_lo;
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2015 David Stainton <dstainton415@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! TCP packet abstraction

use packet::Packet;
use packet::ip::IpNextHeaderProtocol;

use pnet_macros::types::*;

use std::net::{Ipv4Addr, Ipv6Addr};

/// Represents a TCP Packet
#[packet]
pub struct Tcp {
    source: u16be,
    destination: u16be,
    length: u16be,
    checksum: u16be,
    #[payload]
    payload: Vec<u8>
}

/// Calculate the checksum for a packet built on IPv4
pub fn ipv4_checksum<'a>(packet: &TcpPacket<'a>,
                         ipv4_source: Ipv4Addr,
                         ipv4_destination: Ipv4Addr,
                         next_level_protocol: IpNextHeaderProtocol)
-> u16be {
    let IpNextHeaderProtocol(next_level_protocol) = next_level_protocol;
    let mut sum = 0u32;

    // Checksum pseudo-header
    // IPv4 source
    match ipv4_source.octets() {
        [a, b, c, d] => {
            sum = sum + ((a as u32) << 8 | b as u32);
            sum = sum + ((c as u32) << 8 | d as u32);
        }
    }

    // IPv4 destination
    match ipv4_destination.octets() {
        [a, b, c, d] => {
            sum = sum + ((a as u32) << 8 | b as u32);
            sum = sum + ((c as u32) << 8 | d as u32);
        }
    }

    // IPv4 Next level protocol
    sum = sum + next_level_protocol as u32;

    // TCP Length
    sum = sum + ((packet.packet()[4] as u32) << 8 |
                  packet.packet()[5] as u32);

    // Checksum TCP header/packet
    let mut i = 0;
    let len = packet.get_length() as usize;
    while i < len && i + 1 < packet.packet().len() {
        let word = (packet.packet()[i] as u32) << 8 | packet.packet()[i + 1] as u32;
        sum = sum + word;
        i = i + 2;
    }
    // If the length is odd, make sure to checksum the final byte
    if len & 1 != 0 && len <= packet.packet().len() {
        sum = sum + ((packet.packet()[len - 1] as u32) << 8);
    }
    while sum >> 16 != 0 {
        sum = (sum >> 16) + (sum & 0xFFFF);
    }

    return !sum as u16;
}

#[test]
fn tcp_header_ipv4_test() {
    use pnet::packet::ip::IpNextHeaderProtocols;
    use pnet::packet::ipv4::MutableIpv4Packet;

    let mut packet = [0u8; 20 + 8 + 4];
    let ipv4_source = Ipv4Addr::new(192, 168, 0, 1);
    let ipv4_destination = Ipv4Addr::new(192, 168, 0, 199);
    let next_level_protocol = IpNextHeaderProtocols::Tcp;
    {
        let mut ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
        ip_header.set_next_level_protocol(next_level_protocol);
        ip_header.set_source(ipv4_source);
        ip_header.set_destination(ipv4_destination);
    }

    // Set data
    packet[20 + 8 + 0] = 't' as u8;
    packet[20 + 8 + 1] = 'e' as u8;
    packet[20 + 8 + 2] = 's' as u8;
    packet[20 + 8 + 3] = 't' as u8;

    {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[20..]).unwrap();
        tcp_header.set_source(12345);
        assert_eq!(tcp_header.get_source(), 12345);

        tcp_header.set_destination(54321);
        assert_eq!(tcp_header.get_destination(), 54321);

        tcp_header.set_length(8 + 4);
        assert_eq!(tcp_header.get_length(), 8 + 4);

        let checksum = ipv4_checksum(&tcp_header.to_immutable(),
                                     ipv4_source,
                                     ipv4_destination,
                                     next_level_protocol);
        tcp_header.set_checksum(checksum);
        assert_eq!(tcp_header.get_checksum(), 0x9183);
    }

    let ref_packet = [0x30, 0x39, /* source */
                     0xd4, 0x31, /* destination */
                     0x00, 0x0c, /* length */
                     0x91, 0x83  /* checksum*/];
    assert_eq!(&ref_packet[..], &packet[20 .. 28]);
}

/// Calculate the checksum for a packet built on IPv6
pub fn ipv6_checksum<'a>(packet: &TcpPacket<'a>,
                         ipv6_source: Ipv6Addr,
                         ipv6_destination: Ipv6Addr,
                         next_header: IpNextHeaderProtocol) -> u16be {
    let IpNextHeaderProtocol(next_header) = next_header;
    let mut sum = 0u32;

    // Checksum pseudo-header
    // IPv6 source
    match ipv6_source.segments() {
        [a, b, c, d, e, f, g, h] => {
            sum = sum + a as u32;
            sum = sum + b as u32;
            sum = sum + c as u32;
            sum = sum + d as u32;
            sum = sum + e as u32;
            sum = sum + f as u32;
            sum = sum + g as u32;
            sum = sum + h as u32;
        }
    }

    // IPv6 destination
    match ipv6_destination.segments() {
        [a, b, c, d, e, f, g, h] => {
            sum = sum + a as u32;
            sum = sum + b as u32;
            sum = sum + c as u32;
            sum = sum + d as u32;
            sum = sum + e as u32;
            sum = sum + f as u32;
            sum = sum + g as u32;
            sum = sum + h as u32;
        }
    }

    // IPv6 Next header
    sum = sum + next_header as u32;

    // TCPP Length
    sum = sum + packet.get_length() as u32;

    // Checksum TCP header/packet
    let mut i = 0;
    let len = packet.get_length() as usize;
    while i < len && i + 1 < packet.packet().len() {
        let word = (packet.packet()[i] as u32) << 8 | packet.packet()[i + 1] as u32;
        sum = sum + word;
        i = i + 2;
    }
    // If the length is odd, make sure to checksum the final byte
    if len & 1 != 0 && len <= packet.packet().len() {
        sum = sum + (packet.packet()[len - 1] as u32) << 8;
    }

    while sum >> 16 != 0 {
        sum = (sum >> 16) + (sum & 0xFFFF);
    }

    return !sum as u16;
}

#[test]
fn tcp_header_ipv6_test() {
    use packet::ip::{IpNextHeaderProtocols};
    use packet::ipv6::{MutableIpv6Packet};

    let mut packet = [0u8; 40 + 8 + 4];
    let next_header = IpNextHeaderProtocols::Tcp;
    let ipv6_source = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
    let ipv6_destination = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
    {
        let mut ip_header = MutableIpv6Packet::new(&mut packet[..]).unwrap();
        ip_header.set_next_header(next_header);
        ip_header.set_source(ipv6_source);
        ip_header.set_destination(ipv6_destination);
    }

    // Set data
    packet[40 + 8 + 0] = 't' as u8;
    packet[40 + 8 + 1] = 'e' as u8;
    packet[40 + 8 + 2] = 's' as u8;
    packet[40 + 8 + 3] = 't' as u8;

    {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[40..]).unwrap();
        tcp_header.set_source(12345);
        assert_eq!(tcp_header.get_source(), 12345);

        tcp_header.set_destination(54321);
        assert_eq!(tcp_header.get_destination(), 54321);

        tcp_header.set_length(8 + 4);
        assert_eq!(tcp_header.get_length(), 8 + 4);

        let checksum = ipv6_checksum(&tcp_header.to_immutable(),
                                     ipv6_source,
                                     ipv6_destination,
                                     next_header);
        tcp_header.set_checksum(checksum);
        assert_eq!(tcp_header.get_checksum(), 0x139b);
    }

    let ref_packet = [0x30, 0x39, /* source */
                     0xd4, 0x31, /* destination */
                     0x00, 0x0c, /* length */
                     0x13, 0x9b  /* checksum*/];
    assert_eq!(&ref_packet[..], &packet[40 .. 48]);
}
<commit_msg>Remove checksum code borrowed from udp.rs<commit_after>// Copyright (c) 2015 David Stainton <dstainton415@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! TCP packet abstraction

use packet::Packet;
use packet::ip::IpNextHeaderProtocol;

use pnet_macros::types::*;

use std::net::{Ipv4Addr, Ipv6Addr};

/// Represents a TCP Packet
#[packet]
pub struct Tcp {
    source: u16be,
    destination: u16be,
    length: u16be,
    #[payload]
    payload: Vec<u8>
}

#[test]
fn tcp_header_ipv4_test() {
    use pnet::packet::ip::IpNextHeaderProtocols;
    use pnet::packet::ipv4::MutableIpv4Packet;

    let mut packet = [0u8; 20 + 8 + 4];
    let ipv4_source = Ipv4Addr::new(192, 168, 0, 1);
    let ipv4_destination = Ipv4Addr::new(192, 168, 0, 199);
    let next_level_protocol = IpNextHeaderProtocols::Tcp;
    {
        let mut ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
        ip_header.set_next_level_protocol(next_level_protocol);
        ip_header.set_source(ipv4_source);
        ip_header.set_destination(ipv4_destination);
    }

    // Set data
    packet[20 + 8 + 0] = 't' as u8;
    packet[20 + 8 + 1] = 'e' as u8;
    packet[20 + 8 + 2] = 's' as u8;
    packet[20 + 8 + 3] = 't' as u8;

    {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[20..]).unwrap();
        tcp_header.set_source(12345);
        assert_eq!(tcp_header.get_source(), 12345);

        tcp_header.set_destination(54321);
        assert_eq!(tcp_header.get_destination(), 54321);

        tcp_header.set_length(8 + 4);
        assert_eq!(tcp_header.get_length(), 8 + 4);
    }

    let ref_packet = [0x30, 0x39, /* source */
                     0xd4, 0x31,  /* destination */
                     0x00, 0x0c]; /* length */
    assert_eq!(&ref_packet[..], &packet[20 .. 26]);
}

#[test]
fn tcp_header_ipv6_test() {
    use packet::ip::{IpNextHeaderProtocols};
    use packet::ipv6::{MutableIpv6Packet};

    let mut packet = [0u8; 40 + 8 + 4];
    let next_header = IpNextHeaderProtocols::Tcp;
    let ipv6_source = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
    let ipv6_destination = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
    {
        let mut ip_header = MutableIpv6Packet::new(&mut packet[..]).unwrap();
        ip_header.set_next_header(next_header);
        ip_header.set_source(ipv6_source);
        ip_header.set_destination(ipv6_destination);
    }

    // Set data
    packet[40 + 8 + 0] = 't' as u8;
    packet[40 + 8 + 1] = 'e' as u8;
    packet[40 + 8 + 2] = 's' as u8;
    packet[40 + 8 + 3] = 't' as u8;

    {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[40..]).unwrap();
        tcp_header.set_source(12345);
        assert_eq!(tcp_header.get_source(), 12345);

        tcp_header.set_destination(54321);
        assert_eq!(tcp_header.get_destination(), 54321);

        tcp_header.set_length(8 + 4);
        assert_eq!(tcp_header.get_length(), 8 + 4);
    }

    let ref_packet = [0x30, 0x39, /* source */
                     0xd4, 0x31,  /* destination */
                     0x00, 0x0c]; /* length */
    assert_eq!(&ref_packet[..], &packet[40 .. 46]);
}
<|endoftext|>


<commit_before>use rocket::http::{Cookies, Status};
use rocket::request::{self, FromRequest, Request};
use rocket::{Outcome, State};
use rocket_contrib::json::Json;
use std::sync::Arc;

use config::{self, Config};
use db::DB;
use errors;
use index;
use user;

const CURRENT_MAJOR_VERSION: i32 = 2;
const CURRENT_MINOR_VERSION: i32 = 2;

pub fn get_routes() -> Vec<rocket::Route> {
	routes![version, initial_setup, get_settings, put_settings, trigger_index]
}

struct Auth {
	username: String,
}

impl<'a, 'r> FromRequest<'a, 'r> for Auth {
	type Error = ();

	fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, ()> {
		let mut cookies = request.guard::<Cookies>().unwrap();
		match cookies.get_private("username") {
			Some(u) => Outcome::Success(Auth {
				username: u.to_string(),
			}),
			_ => Outcome::Failure((Status::Forbidden, ())),
		}
	}
}

struct AdminRights {}
impl<'a, 'r> FromRequest<'a, 'r> for AdminRights {
	type Error = ();

	fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, ()> {
		let db = request.guard::<State<DB>>()?;

		match user::count::<DB>(&db) {
			Err(_) => return Outcome::Failure((Status::InternalServerError, ())),
			Ok(0) => return Outcome::Success(AdminRights {}),
			_ => (),
		};

		let auth = request.guard::<Auth>()?;
		match user::is_admin::<DB>(&db, &auth.username) {
			Err(_) => Outcome::Failure((Status::InternalServerError, ())),
			Ok(true) => Outcome::Success(AdminRights {}),
			Ok(false) => Outcome::Failure((Status::Forbidden, ())),
		}
	}
}

#[derive(Serialize)]
struct Version {
	major: i32,
	minor: i32,
}

#[get("/version")]
fn version() -> Json<Version> {
	let current_version = Version {
		major: CURRENT_MAJOR_VERSION,
		minor: CURRENT_MINOR_VERSION,
	};
	Json(current_version)
}

#[derive(Serialize)]
struct InitialSetup {
	has_any_users: bool,
}

#[get("/initial_setup")]
fn initial_setup(db: State<DB>) -> Result<Json<InitialSetup>, errors::Error> {
	let initial_setup = InitialSetup {
		has_any_users: user::count::<DB>(&db)? > 0,
	};
	Ok(Json(initial_setup))
}

#[get("/settings")]
fn get_settings(db: State<DB>, _admin_rights: AdminRights) -> Result<Json<Config>, errors::Error> {
	let config = config::read::<DB>(&db)?;
	Ok(Json(config))
}

#[put("/settings", data = "<config>")]
fn put_settings(db: State<DB>, _admin_rights: AdminRights, config: Json<Config>) -> Result<(), errors::Error> {
	config::amend::<DB>(&db, &config)?;
	Ok(())
}

#[post("/trigger_index")]
fn trigger_index(command_sender: State<Arc<index::CommandSender>>) -> Result<(), errors::Error> {
	command_sender.trigger_reindex()?;
	Ok(())
}
<commit_msg>Require admin rights to trigger reindex<commit_after>use rocket::http::{Cookies, Status};
use rocket::request::{self, FromRequest, Request};
use rocket::{Outcome, State};
use rocket_contrib::json::Json;
use std::sync::Arc;

use config::{self, Config};
use db::DB;
use errors;
use index;
use user;

const CURRENT_MAJOR_VERSION: i32 = 2;
const CURRENT_MINOR_VERSION: i32 = 2;

pub fn get_routes() -> Vec<rocket::Route> {
	routes![version, initial_setup, get_settings, put_settings, trigger_index]
}

struct Auth {
	username: String,
}

impl<'a, 'r> FromRequest<'a, 'r> for Auth {
	type Error = ();

	fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, ()> {
		let mut cookies = request.guard::<Cookies>().unwrap();
		match cookies.get_private("username") {
			Some(u) => Outcome::Success(Auth {
				username: u.to_string(),
			}),
			_ => Outcome::Failure((Status::Forbidden, ())),
		}
	}
}

struct AdminRights {}
impl<'a, 'r> FromRequest<'a, 'r> for AdminRights {
	type Error = ();

	fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, ()> {
		let db = request.guard::<State<DB>>()?;

		match user::count::<DB>(&db) {
			Err(_) => return Outcome::Failure((Status::InternalServerError, ())),
			Ok(0) => return Outcome::Success(AdminRights {}),
			_ => (),
		};

		let auth = request.guard::<Auth>()?;
		match user::is_admin::<DB>(&db, &auth.username) {
			Err(_) => Outcome::Failure((Status::InternalServerError, ())),
			Ok(true) => Outcome::Success(AdminRights {}),
			Ok(false) => Outcome::Failure((Status::Forbidden, ())),
		}
	}
}

#[derive(Serialize)]
struct Version {
	major: i32,
	minor: i32,
}

#[get("/version")]
fn version() -> Json<Version> {
	let current_version = Version {
		major: CURRENT_MAJOR_VERSION,
		minor: CURRENT_MINOR_VERSION,
	};
	Json(current_version)
}

#[derive(Serialize)]
struct InitialSetup {
	has_any_users: bool,
}

#[get("/initial_setup")]
fn initial_setup(db: State<DB>) -> Result<Json<InitialSetup>, errors::Error> {
	let initial_setup = InitialSetup {
		has_any_users: user::count::<DB>(&db)? > 0,
	};
	Ok(Json(initial_setup))
}

#[get("/settings")]
fn get_settings(db: State<DB>, _admin_rights: AdminRights) -> Result<Json<Config>, errors::Error> {
	let config = config::read::<DB>(&db)?;
	Ok(Json(config))
}

#[put("/settings", data = "<config>")]
fn put_settings(db: State<DB>, _admin_rights: AdminRights, config: Json<Config>) -> Result<(), errors::Error> {
	config::amend::<DB>(&db, &config)?;
	Ok(())
}

#[post("/trigger_index")]
fn trigger_index(command_sender: State<Arc<index::CommandSender>>, _admin_rights: AdminRights) -> Result<(), errors::Error> {
	command_sender.trigger_reindex()?;
	Ok(())
}
<|endoftext|>


<commit_before>use std::{error, fmt};

use serde::{ser, de};

use token::Token;

#[derive(Clone, PartialEq, Debug)]
pub enum Error {
    Custom(String),
    EndOfStream,
    UnknownField(String),
    UnknownVariant(String),
    MissingField(&'static str),
    DuplicateField(&'static str),
    InvalidName(&'static str),
    InvalidValue(String),
    UnexpectedToken(Token<'static>),
    Value(de::value::Error),
}

impl ser::Error for Error {
    fn custom<T: Into<String>>(msg: T) -> Error {
        Error::Custom(msg.into())
    }

    fn invalid_value(msg: &str) -> Error {
        Error::InvalidValue(msg.to_owned())
    }
}

impl de::Error for Error {
    fn custom<T: Into<String>>(msg: T) -> Error {
        Error::Custom(msg.into())
    }

    fn end_of_stream() -> Error {
        Error::EndOfStream
    }

    fn invalid_value(msg: &str) -> Error {
        Error::InvalidValue(msg.to_owned())
    }

    fn unknown_field(field: &str) -> Error {
        Error::UnknownField(field.to_owned())
    }

    fn unknown_variant(variant: &str) -> Error {
        Error::UnknownVariant(variant.to_owned())
    }

    fn missing_field(field: &'static str) -> Error {
        Error::MissingField(field)
    }

    fn duplicate_field(field: &'static str) -> Error {
        Error::DuplicateField(field)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        formatter.write_str(format!("{:?}", self).as_ref())
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        "Serde Error"
    }

    fn cause(&self) -> Option<&error::Error> {
        None
    }
}
<commit_msg>Round out the Error variants<commit_after>use std::{error, fmt};

use serde::{ser, de};

use token::Token;

#[derive(Clone, PartialEq, Debug)]
pub enum Error {
    // Shared
    Custom(String),
    InvalidValue(String),

    // De
    EndOfStream,
    InvalidType(de::Type),
    InvalidLength(usize),
    UnknownVariant(String),
    UnknownField(String),
    MissingField(&'static str),
    DuplicateField(&'static str),
    InvalidName(&'static str),
    UnexpectedToken(Token<'static>),
}

impl ser::Error for Error {
    fn custom<T: Into<String>>(msg: T) -> Error {
        Error::Custom(msg.into())
    }

    fn invalid_value(msg: &str) -> Error {
        Error::InvalidValue(msg.to_owned())
    }
}

impl de::Error for Error {
    fn custom<T: Into<String>>(msg: T) -> Error {
        Error::Custom(msg.into())
    }

    fn end_of_stream() -> Error {
        Error::EndOfStream
    }

    fn invalid_type(ty: de::Type) -> Error {
        Error::InvalidType(ty)
    }

    fn invalid_value(msg: &str) -> Error {
        Error::InvalidValue(msg.to_owned())
    }

    fn invalid_length(len: usize) -> Error {
        Error::InvalidLength(len)
    }

    fn unknown_variant(variant: &str) -> Error {
        Error::UnknownVariant(variant.to_owned())
    }

    fn unknown_field(field: &str) -> Error {
        Error::UnknownField(field.to_owned())
    }

    fn missing_field(field: &'static str) -> Error {
        Error::MissingField(field)
    }

    fn duplicate_field(field: &'static str) -> Error {
        Error::DuplicateField(field)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        formatter.write_str(format!("{:?}", self).as_ref())
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        "Serde Error"
    }

    fn cause(&self) -> Option<&error::Error> {
        None
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::path::Path;
use std::error::Error;
use std::io::prelude::*;

pub fn read_in(file_path: &str) -> String
{
    let path = Path::new(file_path);
    let display = path.display();

    let mut file = match File::open(&path)
    {
        Err(why) => panic!("couldn't open {}: {}", display, Error::description(&why)),
        Ok(file) => file,
    };

    let mut file_as_string = String::new();
    match file.read_to_string(&mut file_as_string) {
        Err(why) => panic!("couldn't read {}: {}", display, Error::description(&why)),
        Ok(_) => {},
    }

    file_as_string
}

pub fn dump(file_path: &str, data: String)
{
    let path = Path::new(file_path);
    let display = path.display();

    let mut file = match File::create(&path)
    {
        Err(why) => panic!("couldn't create {}: {}", display, Error::description(&why)),
        Ok(file) => file,
    };

    match file.write_all(data.as_bytes())
    {
        Err(why) => {panic!("couldn't write to {}: {}", display, Error::description(&why))},
        Ok(_) => println!("successfully output to {}", display),
    }
}
<commit_msg>add delete_file method<commit_after>use std::fs;
use std::fs::File;
use std::path::Path;
use std::error::Error;
use std::io::prelude::*;

pub fn read_in(file_path: &str) -> String
{
    let path = Path::new(file_path);
    let display = path.display();

    let mut file = match File::open(&path)
    {
        Err(why) => panic!("couldn't open {}: {}", display, Error::description(&why)),
        Ok(file) => file,
    };

    let mut file_as_string = String::new();
    match file.read_to_string(&mut file_as_string) {
        Err(why) => panic!("couldn't read {}: {}", display, Error::description(&why)),
        Ok(_) => {},
    }

    file_as_string
}

pub fn dump(file_path: &str, data: String)
{
    let path = Path::new(file_path);
    let display = path.display();

    match fs::create_dir_all(path.parent().unwrap()) {
            Err(why) => println!("! {:?}", why.kind()),
            Ok(_) => {println!("Folder already created")},
        }

    let mut file = match File::create(&path)
    {
        Err(why) => panic!("couldn't create {}: {}", display, Error::description(&why)),
        Ok(file) => file,
    };

    match file.write_all(data.as_bytes())
    {
        Err(why) => {panic!("couldn't write to {}: {}", display, Error::description(&why))},
        Ok(_) => println!("successfully output to {}", display),
    }
}

///
pub fn delete_file(file_path: &str)
{
    let path = Path::new(file_path);

    match fs::remove_file(file_path) {
            Err(why) => println!("! {:?}", why.kind()),
            Ok(_) => {},
        }
}
<|endoftext|>


<commit_before>use std::mem;
use libc::{uint32_t, c_void};
use std::raw;

#[allow(non_camel_case_types)]
pub mod ll {
    use libc::{uint32_t, uint64_t, c_void, c_int};

    //SDL_timer.h
    pub type SDL_TimerCallback =
        ::std::option::Option<extern "C" fn(arg1: uint32_t, arg2: *const c_void)
                                            -> uint32_t>;
    pub type SDL_TimerID = c_int;
    extern "C" {
        pub fn SDL_GetTicks() -> uint32_t;
        pub fn SDL_GetPerformanceCounter() -> uint64_t;
        pub fn SDL_GetPerformanceFrequency() -> uint64_t;
        pub fn SDL_Delay(ms: uint32_t);

        pub fn SDL_AddTimer(interval: uint32_t, callback: SDL_TimerCallback,
                            param: *const c_void) -> SDL_TimerID;
        pub fn SDL_RemoveTimer(id: SDL_TimerID) -> c_int;
    }
}

pub fn get_ticks() -> uint {
    unsafe { ll::SDL_GetTicks() as uint }
}

pub fn get_performance_counter() -> u64 {
    unsafe { ll::SDL_GetPerformanceCounter() }
}

pub fn get_performance_frequency() -> u64 {
    unsafe { ll::SDL_GetPerformanceFrequency() }
}

pub fn delay(ms: uint) {
    unsafe { ll::SDL_Delay(ms as u32) }
}

pub struct Timer<'a> {
    delay: uint,
    raw: ll::SDL_TimerID,
    closure: raw::Closure,
    remove_on_drop: bool,
}

impl<'a> Timer<'a> {
    pub fn new<'a>(delay: uint, callback: ||: 'a -> uint, remove_on_drop: bool) -> Timer<'a> {
        unsafe {
            let c_param = mem::transmute::<_, raw::Closure>(callback);
            Timer { delay: delay, raw: 0, closure: c_param, remove_on_drop: remove_on_drop }
        }
    }

    pub fn start(&mut self) {
        unsafe {
            let timer_id = ll::SDL_AddTimer(self.delay as u32, Some(c_timer_callback), mem::transmute(&self.closure));
            self.raw = timer_id;
        }
    }

    pub fn remove(&mut self) -> bool {
        let ret = unsafe { ll::SDL_RemoveTimer(self.raw) };
        if self.raw != 0 {
            self.raw = 0
        }
        ret == 1
    }
}

impl<'a> Drop for Timer<'a> {
    fn drop(&mut self) {
        if self.remove_on_drop {
            let ret = unsafe { ll::SDL_RemoveTimer(self.raw) };
            if ret != 1 {
                println!("error dropping timer {}, maybe already removed.", self.raw);
            }
        }
    }
}

extern "C" fn c_timer_callback(_interval: uint32_t, param: *const c_void) -> uint32_t {
    let f : &mut || -> uint = unsafe { mem::transmute(param) };
    (*f)() as uint32_t
}
<commit_msg>Timer needed unsafe_destructor annotation<commit_after>use std::mem;
use libc::{uint32_t, c_void};
use std::raw;

#[allow(non_camel_case_types)]
pub mod ll {
    use libc::{uint32_t, uint64_t, c_void, c_int};

    //SDL_timer.h
    pub type SDL_TimerCallback =
        ::std::option::Option<extern "C" fn(arg1: uint32_t, arg2: *const c_void)
                                            -> uint32_t>;
    pub type SDL_TimerID = c_int;
    extern "C" {
        pub fn SDL_GetTicks() -> uint32_t;
        pub fn SDL_GetPerformanceCounter() -> uint64_t;
        pub fn SDL_GetPerformanceFrequency() -> uint64_t;
        pub fn SDL_Delay(ms: uint32_t);

        pub fn SDL_AddTimer(interval: uint32_t, callback: SDL_TimerCallback,
                            param: *const c_void) -> SDL_TimerID;
        pub fn SDL_RemoveTimer(id: SDL_TimerID) -> c_int;
    }
}

pub fn get_ticks() -> uint {
    unsafe { ll::SDL_GetTicks() as uint }
}

pub fn get_performance_counter() -> u64 {
    unsafe { ll::SDL_GetPerformanceCounter() }
}

pub fn get_performance_frequency() -> u64 {
    unsafe { ll::SDL_GetPerformanceFrequency() }
}

pub fn delay(ms: uint) {
    unsafe { ll::SDL_Delay(ms as u32) }
}

pub struct Timer<'a> {
    delay: uint,
    raw: ll::SDL_TimerID,
    closure: raw::Closure,
    remove_on_drop: bool,
}

impl<'a> Timer<'a> {
    pub fn new<'a>(delay: uint, callback: ||: 'a -> uint, remove_on_drop: bool) -> Timer<'a> {
        unsafe {
            let c_param = mem::transmute::<_, raw::Closure>(callback);
            Timer { delay: delay, raw: 0, closure: c_param, remove_on_drop: remove_on_drop }
        }
    }

    pub fn start(&mut self) {
        unsafe {
            let timer_id = ll::SDL_AddTimer(self.delay as u32, Some(c_timer_callback), mem::transmute(&self.closure));
            self.raw = timer_id;
        }
    }

    pub fn remove(&mut self) -> bool {
        let ret = unsafe { ll::SDL_RemoveTimer(self.raw) };
        if self.raw != 0 {
            self.raw = 0
        }
        ret == 1
    }
}

#[unsafe_destructor]
impl<'a> Drop for Timer<'a> {
    fn drop(&mut self) {
        if self.remove_on_drop {
            let ret = unsafe { ll::SDL_RemoveTimer(self.raw) };
            if ret != 1 {
                println!("error dropping timer {}, maybe already removed.", self.raw);
            }
        }
    }
}

extern "C" fn c_timer_callback(_interval: uint32_t, param: *const c_void) -> uint32_t {
    let f : &mut || -> uint = unsafe { mem::transmute(param) };
    (*f)() as uint32_t
}
<|endoftext|>