<commit_before>//! Library for parsing and converting bencoded data.
//!
//! # Examples
//!
//! Decoding bencoded data:
//!
//! ```rust
//!     extern crate bip_bencode;
//!
//!     use std::default::Default;
//!     use bip_bencode::{BencodeRef, BRefAccess, BDecodeOpt};
//!
//!     fn main() {
//!         let data = b"d12:lucky_numberi7ee";
//!         let bencode = BencodeRef::decode(data, BDecodeOpt::default()).unwrap();
//!
//!         assert_eq!(7, bencode.dict().unwrap().lookup("lucky_number".as_bytes())
//!             .unwrap().int().unwrap());
//!     }
//! ```
//!
//! Encoding bencoded data:
//!
//! ```rust
//!     #[macro_use]
//!     extern crate bip_bencode;
//!
//!     fn main() {
//!         let message = (ben_map!{
//!             "lucky_number" => ben_int!(7),
//!             "lucky_string" => ben_bytes!("7")
//!         }).encode();
//!
//!         assert_eq!(&b"d12:lucky_numberi7e12:lucky_string1:7e"[..], &message[..]);
//!     }
//! ```

#[macro_use]
extern crate error_chain;

mod access;
mod cow;
mod mutable;
mod reference;
mod error;

/// Traits for implementation functionality.
pub mod inner {
    pub use cow::BCowConvert;
}

/// Traits for extended functionality.
pub mod ext {
    pub use access::convert::{BConvertExt};
    pub use access::bencode::{BRefAccessExt};
}

pub use reference::bencode_ref::{BencodeRef};
pub use mutable::bencode_mut::{BencodeMut};
pub use access::bencode::{BRefAccess, BencodeRefKind, BMutAccess, BencodeMutKind};
pub use access::convert::{BConvert};
pub use access::dict::BDictAccess;
pub use access::list::BListAccess;
pub use reference::decode_opt::BDecodeOpt;
pub use error::{BencodeParseError, BencodeParseErrorKind, BencodeParseResult};
pub use error::{BencodeConvertError, BencodeConvertErrorKind, BencodeConvertResult};

const BEN_END: u8 = b'e';
const DICT_START: u8 = b'd';
const LIST_START: u8 = b'l';
const INT_START: u8 = b'i';

const BYTE_LEN_LOW: u8 = b'0';
const BYTE_LEN_HIGH: u8 = b'9';
const BYTE_LEN_END: u8 = b':';

/// Construct a `BencodeMut` map by supplying string references as keys and `BencodeMut` as values.
#[macro_export]
macro_rules! ben_map {
( $($key:expr => $val:expr),* ) => {
        {
            use bip_bencode::{BMutAccess, BencodeMut};
            use bip_bencode::inner::BCowConvert;

            let mut bencode_map = BencodeMut::new_dict();
            {
                let map = bencode_map.dict_mut().unwrap();
                $(
                    map.insert(BCowConvert::convert($key), $val);
                )*
            }

            bencode_map
        }
    }
}

/// Construct a `BencodeMut` list by supplying a list of `BencodeMut` values.
#[macro_export]
macro_rules! ben_list {
    ( $($ben:expr),* ) => {
        {
            use bip_bencode::{BencodeMut, BMutAccess};

            let mut bencode_list = BencodeMut::new_list();
            {
                let mut list = bencode_list.list_mut().unwrap();
                $(
                    list.push($ben);
                )*
            }

            bencode_list
        }
    }
}

/// Construct `BencodeMut` bytes by supplying a type convertible to `Vec<u8>`.
#[macro_export]
macro_rules! ben_bytes {
    ( $ben:expr ) => {
        {
            use bip_bencode::{BencodeMut};
            use bip_bencode::inner::BCowConvert;

            BencodeMut::new_bytes(BCowConvert::convert($ben))
        }
    }
}

/// Construct a `BencodeMut` integer by supplying an `i64`.
#[macro_export]
macro_rules! ben_int {
    ( $ben:expr ) => {
        {
            use bip_bencode::{BencodeMut};

            BencodeMut::new_int($ben)
        }
    }
}
<commit_msg>Remove unused mut for ben_list macro<commit_after>//! Library for parsing and converting bencoded data.
//!
//! # Examples
//!
//! Decoding bencoded data:
//!
//! ```rust
//!     extern crate bip_bencode;
//!
//!     use std::default::Default;
//!     use bip_bencode::{BencodeRef, BRefAccess, BDecodeOpt};
//!
//!     fn main() {
//!         let data = b"d12:lucky_numberi7ee";
//!         let bencode = BencodeRef::decode(data, BDecodeOpt::default()).unwrap();
//!
//!         assert_eq!(7, bencode.dict().unwrap().lookup("lucky_number".as_bytes())
//!             .unwrap().int().unwrap());
//!     }
//! ```
//!
//! Encoding bencoded data:
//!
//! ```rust
//!     #[macro_use]
//!     extern crate bip_bencode;
//!
//!     fn main() {
//!         let message = (ben_map!{
//!             "lucky_number" => ben_int!(7),
//!             "lucky_string" => ben_bytes!("7")
//!         }).encode();
//!
//!         assert_eq!(&b"d12:lucky_numberi7e12:lucky_string1:7e"[..], &message[..]);
//!     }
//! ```

#[macro_use]
extern crate error_chain;

mod access;
mod cow;
mod mutable;
mod reference;
mod error;

/// Traits for implementation functionality.
pub mod inner {
    pub use cow::BCowConvert;
}

/// Traits for extended functionality.
pub mod ext {
    pub use access::convert::{BConvertExt};
    pub use access::bencode::{BRefAccessExt};
}

pub use reference::bencode_ref::{BencodeRef};
pub use mutable::bencode_mut::{BencodeMut};
pub use access::bencode::{BRefAccess, BencodeRefKind, BMutAccess, BencodeMutKind};
pub use access::convert::{BConvert};
pub use access::dict::BDictAccess;
pub use access::list::BListAccess;
pub use reference::decode_opt::BDecodeOpt;
pub use error::{BencodeParseError, BencodeParseErrorKind, BencodeParseResult};
pub use error::{BencodeConvertError, BencodeConvertErrorKind, BencodeConvertResult};

const BEN_END: u8 = b'e';
const DICT_START: u8 = b'd';
const LIST_START: u8 = b'l';
const INT_START: u8 = b'i';

const BYTE_LEN_LOW: u8 = b'0';
const BYTE_LEN_HIGH: u8 = b'9';
const BYTE_LEN_END: u8 = b':';

/// Construct a `BencodeMut` map by supplying string references as keys and `BencodeMut` as values.
#[macro_export]
macro_rules! ben_map {
( $($key:expr => $val:expr),* ) => {
        {
            use bip_bencode::{BMutAccess, BencodeMut};
            use bip_bencode::inner::BCowConvert;

            let mut bencode_map = BencodeMut::new_dict();
            {
                let map = bencode_map.dict_mut().unwrap();
                $(
                    map.insert(BCowConvert::convert($key), $val);
                )*
            }

            bencode_map
        }
    }
}

/// Construct a `BencodeMut` list by supplying a list of `BencodeMut` values.
#[macro_export]
macro_rules! ben_list {
    ( $($ben:expr),* ) => {
        {
            use bip_bencode::{BencodeMut, BMutAccess};

            let mut bencode_list = BencodeMut::new_list();
            {
                let list = bencode_list.list_mut().unwrap();
                $(
                    list.push($ben);
                )*
            }

            bencode_list
        }
    }
}

/// Construct `BencodeMut` bytes by supplying a type convertible to `Vec<u8>`.
#[macro_export]
macro_rules! ben_bytes {
    ( $ben:expr ) => {
        {
            use bip_bencode::{BencodeMut};
            use bip_bencode::inner::BCowConvert;

            BencodeMut::new_bytes(BCowConvert::convert($ben))
        }
    }
}

/// Construct a `BencodeMut` integer by supplying an `i64`.
#[macro_export]
macro_rules! ben_int {
    ( $ben:expr ) => {
        {
            use bip_bencode::{BencodeMut};

            BencodeMut::new_int($ben)
        }
    }
}
<|endoftext|>


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

use std::env;
use std::path::{Path, PathBuf};

fn main() {
    let themis = get_themis();

    let whitelist = "(THEMIS|themis|secure_(comparator|session)|STATE)_.*";
    let bindings = bindgen::Builder::default()
        .clang_args(clang_include_paths(&themis))
        .clang_args(clang_library_paths(&themis))
        .header("src/wrapper.h")
        .whitelist_function(whitelist)
        .whitelist_type(whitelist)
        .whitelist_var(whitelist)
        .rustified_enum("themis_key_kind")
        .generate()
        .expect("generating bindings");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("writing bindings!");
}

struct Library {
    include_paths: Vec<PathBuf>,
    link_paths: Vec<PathBuf>,
}

/// Embarks on an incredible adventure and returns with a suitable Themis (or dies trying).
fn get_themis() -> Library {
    #[cfg(feature = "vendored")]
    libthemis_src::make();

    let mut pkg_config = pkg_config::Config::new();
    pkg_config.env_metadata(true);

    #[cfg(feature = "vendored")]
    pkg_config.statik(true);

    match pkg_config.probe("libthemis") {
        Ok(library) => {
            return Library {
                include_paths: library.include_paths,
                link_paths: library.link_paths,
            };
        }
        Err(error) => {
            eprintln!(
                "
`libthemis-sys` could not find Themis installation in your system.

Please make sure you have appropriate development package installed.
On Linux it's called `libthemis-dev`, not just `libthemis`.
On macOS Homebrew formula is called `libthemis`.

Please refer to the documentation for installation instructions:

    https://github.com/cossacklabs/themis#quickstart

This crate uses `pkg-config` to locate the library. If you use
non-standard installation of Themis then you can help pkg-config
to locate your library by setting the PKG_CONFIG_PATH environment
variable to the path where `libthemis.pc` file is located.
"
            );
            eprintln!("{}", error);

            if let Some(library) = try_system_themis() {
                eprintln!(
                    "\
`libthemis-sys` tried using standard system paths and it seems that Themis
is available on your system. (However, pkg-config failed to find it.)
We will link against the system library.
"
                );
                return library;
            } else {
                eprintln!(
                    "\
`libthemis-sys` also tried to use standard system paths, but without success.
It seems that Themis is really not installed in your system.
"
                );
            }

            panic!("Themis Core not installed");
        }
    }
}

fn clang_include_paths(library: &Library) -> Vec<String> {
    library
        .include_paths
        .iter()
        .map(|p| format!("-I{}", p.display()))
        .collect()
}

fn clang_library_paths(library: &Library) -> Vec<String> {
    library
        .link_paths
        .iter()
        .map(|p| format!("-L{}", p.display()))
        .collect()
}

trait CCBuildEx {
    fn includes<I>(&mut self, dirs: I) -> &mut Self
    where
        I: IntoIterator,
        I::Item: AsRef<Path>;
}

impl CCBuildEx for cc::Build {
    fn includes<I>(&mut self, dirs: I) -> &mut Self
    where
        I: IntoIterator,
        I::Item: AsRef<Path>,
    {
        for dir in dirs {
            self.include(dir);
        }
        self
    }
}

fn try_system_themis() -> Option<Library> {
    let mut build = cc::Build::new();
    build.file("src/dummy.c");
    build.flag("-lthemis");

    match build.try_compile("dummy") {
        Ok(_) => {
            println!("cargo:rustc-link-lib=dylib=themis");

            // Use only system paths for header and library lookup.
            Some(Library {
                include_paths: vec![],
                link_paths: vec![],
            })
        }
        Err(_) => None,
    }
}
<commit_msg>Avoid needless return (#591)<commit_after>// Copyright 2018 (c) rust-themis developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::env;
use std::path::{Path, PathBuf};

fn main() {
    let themis = get_themis();

    let whitelist = "(THEMIS|themis|secure_(comparator|session)|STATE)_.*";
    let bindings = bindgen::Builder::default()
        .clang_args(clang_include_paths(&themis))
        .clang_args(clang_library_paths(&themis))
        .header("src/wrapper.h")
        .whitelist_function(whitelist)
        .whitelist_type(whitelist)
        .whitelist_var(whitelist)
        .rustified_enum("themis_key_kind")
        .generate()
        .expect("generating bindings");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("writing bindings!");
}

struct Library {
    include_paths: Vec<PathBuf>,
    link_paths: Vec<PathBuf>,
}

/// Embarks on an incredible adventure and returns with a suitable Themis (or dies trying).
fn get_themis() -> Library {
    #[cfg(feature = "vendored")]
    libthemis_src::make();

    let mut pkg_config = pkg_config::Config::new();
    pkg_config.env_metadata(true);

    #[cfg(feature = "vendored")]
    pkg_config.statik(true);

    match pkg_config.probe("libthemis") {
        Ok(library) => Library {
            include_paths: library.include_paths,
            link_paths: library.link_paths,
        },
        Err(error) => {
            eprintln!(
                "
`libthemis-sys` could not find Themis installation in your system.

Please make sure you have appropriate development package installed.
On Linux it's called `libthemis-dev`, not just `libthemis`.
On macOS Homebrew formula is called `libthemis`.

Please refer to the documentation for installation instructions:

    https://github.com/cossacklabs/themis#quickstart

This crate uses `pkg-config` to locate the library. If you use
non-standard installation of Themis then you can help pkg-config
to locate your library by setting the PKG_CONFIG_PATH environment
variable to the path where `libthemis.pc` file is located.
"
            );
            eprintln!("{}", error);

            if let Some(library) = try_system_themis() {
                eprintln!(
                    "\
`libthemis-sys` tried using standard system paths and it seems that Themis
is available on your system. (However, pkg-config failed to find it.)
We will link against the system library.
"
                );
                return library;
            } else {
                eprintln!(
                    "\
`libthemis-sys` also tried to use standard system paths, but without success.
It seems that Themis is really not installed in your system.
"
                );
            }

            panic!("Themis Core not installed");
        }
    }
}

fn clang_include_paths(library: &Library) -> Vec<String> {
    library
        .include_paths
        .iter()
        .map(|p| format!("-I{}", p.display()))
        .collect()
}

fn clang_library_paths(library: &Library) -> Vec<String> {
    library
        .link_paths
        .iter()
        .map(|p| format!("-L{}", p.display()))
        .collect()
}

trait CCBuildEx {
    fn includes<I>(&mut self, dirs: I) -> &mut Self
    where
        I: IntoIterator,
        I::Item: AsRef<Path>;
}

impl CCBuildEx for cc::Build {
    fn includes<I>(&mut self, dirs: I) -> &mut Self
    where
        I: IntoIterator,
        I::Item: AsRef<Path>,
    {
        for dir in dirs {
            self.include(dir);
        }
        self
    }
}

fn try_system_themis() -> Option<Library> {
    let mut build = cc::Build::new();
    build.file("src/dummy.c");
    build.flag("-lthemis");

    match build.try_compile("dummy") {
        Ok(_) => {
            println!("cargo:rustc-link-lib=dylib=themis");

            // Use only system paths for header and library lookup.
            Some(Library {
                include_paths: vec![],
                link_paths: vec![],
            })
        }
        Err(_) => None,
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Data needed by the layout task.

use css::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};

use geom::{Rect, Size2D};
use gfx::display_list::OpaqueNode;
use gfx::font_context::FontContext;
use gfx::font_cache_task::FontCacheTask;
use script::layout_interface::LayoutChan;
use script_traits::UntrustedNodeAddress;
use servo_msg::constellation_msg::ConstellationChan;
use servo_net::local_image_cache::LocalImageCache;
use servo_util::geometry::Au;
use std::cell::Cell;
use std::mem;
use std::ptr;
use std::sync::{Arc, Mutex};
use style::Stylist;
use url::Url;

struct LocalLayoutContext {
    font_context: FontContext,
    applicable_declarations_cache: ApplicableDeclarationsCache,
    style_sharing_candidate_cache: StyleSharingCandidateCache,
}

thread_local!(static LOCAL_CONTEXT_KEY: Cell<*mut LocalLayoutContext> = Cell::new(ptr::null_mut()))

fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext) -> *mut LocalLayoutContext {
    LOCAL_CONTEXT_KEY.with(|ref r| {
        if r.get().is_null() {
            let context = box LocalLayoutContext {
                font_context: FontContext::new(shared_layout_context.font_cache_task.clone()),
                applicable_declarations_cache: ApplicableDeclarationsCache::new(),
                style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
            };
            r.set(unsafe { mem::transmute(context) });
        }

        r.get()
    })
}

pub struct SharedLayoutContext {
    /// The local image cache.
    pub image_cache: Arc<Mutex<LocalImageCache<UntrustedNodeAddress>>>,

    /// The current screen size.
    pub screen_size: Size2D<Au>,

    /// A channel up to the constellation.
    pub constellation_chan: ConstellationChan,

    /// A channel up to the layout task.
    pub layout_chan: LayoutChan,

    /// Interface to the font cache task.
    pub font_cache_task: FontCacheTask,

    /// The CSS selector stylist.
    ///
    /// FIXME(#2604): Make this no longer an unsafe pointer once we have fast `RWArc`s.
    pub stylist: *const Stylist,

    /// The root node at which we're starting the layout.
    pub reflow_root: OpaqueNode,

    /// The URL.
    pub url: Url,

    /// The dirty rectangle, used during display list building.
    pub dirty: Rect<Au>,

    /// Starts at zero, and increased by one every time a layout completes.
    /// This can be used to easily check for invalid stale data.
    pub generation: uint,
}

pub struct LayoutContext<'a> {
    pub shared: &'a SharedLayoutContext,
    cached_local_layout_context: *mut LocalLayoutContext,
}

impl<'a> LayoutContext<'a> {
    pub fn new(shared_layout_context: &'a SharedLayoutContext) -> LayoutContext<'a> {

        let local_context = create_or_get_local_context(shared_layout_context);

        LayoutContext {
            shared: shared_layout_context,
            cached_local_layout_context: local_context,
        }
    }

    #[inline(always)]
    pub fn font_context<'a>(&'a self) -> &'a mut FontContext {
        unsafe {
            let cached_context = &*self.cached_local_layout_context;
            mem::transmute(&cached_context.font_context)
        }
    }

    #[inline(always)]
    pub fn applicable_declarations_cache<'a>(&'a self) -> &'a mut ApplicableDeclarationsCache {
        unsafe {
            let cached_context = &*self.cached_local_layout_context;
            mem::transmute(&cached_context.applicable_declarations_cache)
        }
    }

    #[inline(always)]
    pub fn style_sharing_candidate_cache<'a>(&'a self) -> &'a mut StyleSharingCandidateCache {
        unsafe {
            let cached_context = &*self.cached_local_layout_context;
            mem::transmute(&cached_context.style_sharing_candidate_cache)
        }
    }
}
<commit_msg>Remove transmutes in LayoutContext.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Data needed by the layout task.

use css::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};

use geom::{Rect, Size2D};
use gfx::display_list::OpaqueNode;
use gfx::font_context::FontContext;
use gfx::font_cache_task::FontCacheTask;
use script::layout_interface::LayoutChan;
use script_traits::UntrustedNodeAddress;
use servo_msg::constellation_msg::ConstellationChan;
use servo_net::local_image_cache::LocalImageCache;
use servo_util::geometry::Au;
use std::cell::Cell;
use std::mem;
use std::ptr;
use std::sync::{Arc, Mutex};
use style::Stylist;
use url::Url;

struct LocalLayoutContext {
    font_context: FontContext,
    applicable_declarations_cache: ApplicableDeclarationsCache,
    style_sharing_candidate_cache: StyleSharingCandidateCache,
}

thread_local!(static LOCAL_CONTEXT_KEY: Cell<*mut LocalLayoutContext> = Cell::new(ptr::null_mut()))

fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext) -> *mut LocalLayoutContext {
    LOCAL_CONTEXT_KEY.with(|ref r| {
        if r.get().is_null() {
            let context = box LocalLayoutContext {
                font_context: FontContext::new(shared_layout_context.font_cache_task.clone()),
                applicable_declarations_cache: ApplicableDeclarationsCache::new(),
                style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
            };
            r.set(unsafe { mem::transmute(context) });
        }

        r.get()
    })
}

pub struct SharedLayoutContext {
    /// The local image cache.
    pub image_cache: Arc<Mutex<LocalImageCache<UntrustedNodeAddress>>>,

    /// The current screen size.
    pub screen_size: Size2D<Au>,

    /// A channel up to the constellation.
    pub constellation_chan: ConstellationChan,

    /// A channel up to the layout task.
    pub layout_chan: LayoutChan,

    /// Interface to the font cache task.
    pub font_cache_task: FontCacheTask,

    /// The CSS selector stylist.
    ///
    /// FIXME(#2604): Make this no longer an unsafe pointer once we have fast `RWArc`s.
    pub stylist: *const Stylist,

    /// The root node at which we're starting the layout.
    pub reflow_root: OpaqueNode,

    /// The URL.
    pub url: Url,

    /// The dirty rectangle, used during display list building.
    pub dirty: Rect<Au>,

    /// Starts at zero, and increased by one every time a layout completes.
    /// This can be used to easily check for invalid stale data.
    pub generation: uint,
}

pub struct LayoutContext<'a> {
    pub shared: &'a SharedLayoutContext,
    cached_local_layout_context: *mut LocalLayoutContext,
}

impl<'a> LayoutContext<'a> {
    pub fn new(shared_layout_context: &'a SharedLayoutContext) -> LayoutContext<'a> {

        let local_context = create_or_get_local_context(shared_layout_context);

        LayoutContext {
            shared: shared_layout_context,
            cached_local_layout_context: local_context,
        }
    }

    #[inline(always)]
    pub fn font_context<'a>(&'a self) -> &'a mut FontContext {
        unsafe {
            let cached_context = &mut *self.cached_local_layout_context;
            &mut cached_context.font_context
        }
    }

    #[inline(always)]
    pub fn applicable_declarations_cache<'a>(&'a self) -> &'a mut ApplicableDeclarationsCache {
        unsafe {
            let cached_context = &mut *self.cached_local_layout_context;
            &mut cached_context.applicable_declarations_cache
        }
    }

    #[inline(always)]
    pub fn style_sharing_candidate_cache<'a>(&'a self) -> &'a mut StyleSharingCandidateCache {
        unsafe {
            let cached_context = &mut *self.cached_local_layout_context;
            &mut cached_context.style_sharing_candidate_cache
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A safe wrapper for DOM nodes that prevents layout from mutating the DOM, from letting DOM nodes
//! escape, and from generally doing anything that it isn't supposed to. This is accomplished via
//! a simple whitelist of allowed operations, along with some lifetime magic to prevent nodes from
//! escaping.
//!
//! As a security wrapper is only as good as its whitelist, be careful when adding operations to
//! this list. The cardinal rules are:
//!
//! 1. Layout is not allowed to mutate the DOM.
//!
//! 2. Layout is not allowed to see anything with `LayoutDom` in the name, because it could hang
//!    onto these objects and cause use-after-free.
//!
//! When implementing wrapper functions, be careful that you do not touch the borrow flags, or you
//! will race and cause spurious thread failure. (Note that I do not believe these races are
//! exploitable, but they'll result in brokenness nonetheless.)
//!
//! Rules of the road for this file:
//!
//! * Do not call any methods on DOM nodes without checking to see whether they use borrow flags.
//!
//!   o Instead of `get_attr()`, use `.get_attr_val_for_layout()`.
//!
//!   o Instead of `html_element_in_html_document()`, use
//!     `html_element_in_html_document_for_layout()`.

#![allow(unsafe_code)]

use atomic_refcell::{AtomicRef, AtomicRefMut};
use data::{LayoutData, LayoutDataFlags, StyleAndLayoutData};
use script_layout_interface::wrapper_traits::{ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use script_layout_interface::wrapper_traits::GetLayoutData;
use style::computed_values::content::{self, ContentItem};
use style::dom::{NodeInfo, TNode};
use style::selector_parser::RestyleDamage;

pub trait LayoutNodeLayoutData {
    /// Similar to borrow_data*, but returns the full PersistentLayoutData rather
    /// than only the style::data::ElementData.
    fn borrow_layout_data(&self) -> Option<AtomicRef<LayoutData>>;
    fn mutate_layout_data(&self) -> Option<AtomicRefMut<LayoutData>>;
    fn flow_debug_id(self) -> usize;
}

impl<T: GetLayoutData> LayoutNodeLayoutData for T {
    fn borrow_layout_data(&self) -> Option<AtomicRef<LayoutData>> {
        self.get_raw_data().map(|d| d.layout_data.borrow())
    }

    fn mutate_layout_data(&self) -> Option<AtomicRefMut<LayoutData>> {
        self.get_raw_data().map(|d| d.layout_data.borrow_mut())
    }

    fn flow_debug_id(self) -> usize {
        self.borrow_layout_data().map_or(0, |d| d.flow_construction_result.debug_id())
    }
}

pub trait GetRawData {
    fn get_raw_data(&self) -> Option<&StyleAndLayoutData>;
}

impl<T: GetLayoutData> GetRawData for T {
    fn get_raw_data(&self) -> Option<&StyleAndLayoutData> {
        self.get_style_and_layout_data().map(|opaque| {
            let container = opaque.ptr.get() as *mut StyleAndLayoutData;
            unsafe { &*container }
        })
    }
}

pub trait ThreadSafeLayoutNodeHelpers {
    /// Returns the layout data flags for this node.
    fn flags(self) -> LayoutDataFlags;

    /// Adds the given flags to this node.
    fn insert_flags(self, new_flags: LayoutDataFlags);

    /// Removes the given flags from this node.
    fn remove_flags(self, flags: LayoutDataFlags);

    /// If this is a text node, generated content, or a form element, copies out
    /// its content. Otherwise, panics.
    ///
    /// FIXME(pcwalton): This might have too much copying and/or allocation. Profile this.
    fn text_content(&self) -> TextContent;

    /// The RestyleDamage from any restyling, or RestyleDamage::rebuild_and_reflow() if this
    /// is the first time layout is visiting this node. We implement this here, rather than
    /// with the rest of the wrapper layer, because we need layout code to determine whether
    /// layout has visited the node.
    fn restyle_damage(self) -> RestyleDamage;
}

impl<T: ThreadSafeLayoutNode> ThreadSafeLayoutNodeHelpers for T {
    fn flags(self) -> LayoutDataFlags {
            self.borrow_layout_data().as_ref().unwrap().flags
    }

    fn insert_flags(self, new_flags: LayoutDataFlags) {
        self.mutate_layout_data().unwrap().flags.insert(new_flags);
    }

    fn remove_flags(self, flags: LayoutDataFlags) {
        self.mutate_layout_data().unwrap().flags.remove(flags);
    }

    fn text_content(&self) -> TextContent {
        if self.get_pseudo_element_type().is_replaced_content() {
            let style = self.as_element().unwrap().resolved_style();

            return match style.as_ref().get_counters().content {
                content::T::Items(ref value) if !value.is_empty() => {
                    TextContent::GeneratedContent((*value).clone())
                }
                _ => TextContent::GeneratedContent(vec![]),
            };
        }

        return TextContent::Text(self.node_text_content());
    }

    fn restyle_damage(self) -> RestyleDamage {
        // We need the underlying node to potentially access the parent in the
        // case of text nodes. This is safe as long as we don't let the parent
        // escape and never access its descendants.
        let mut node = unsafe { self.unsafe_get() };

        // If this is a text node, use the parent element, since that's what
        // controls our style.
        if node.is_text_node() {
            node = node.parent_node().unwrap();
            debug_assert!(node.is_element());
        }

        let damage = {
            let data = node.get_raw_data().unwrap();

            if !data.layout_data.borrow().flags.contains(::data::LayoutDataFlags::HAS_BEEN_TRAVERSED) {
                // We're reflowing a node that was styled for the first time and
                // has never been visited by layout. Return rebuild_and_reflow,
                // because that's what the code expects.
                RestyleDamage::rebuild_and_reflow()
            } else {
                data.style_data.element_data.borrow().damage
            }
        };

        damage
    }

}

pub enum TextContent {
    Text(String),
    GeneratedContent(Vec<ContentItem>),
}

impl TextContent {
    pub fn is_empty(&self) -> bool {
        match *self {
            TextContent::Text(_) => false,
            TextContent::GeneratedContent(ref content) => content.is_empty(),
        }
    }
}
<commit_msg>Auto merge of #19176 - emilio:indentation-fixup, r=emilio<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A safe wrapper for DOM nodes that prevents layout from mutating the DOM, from letting DOM nodes
//! escape, and from generally doing anything that it isn't supposed to. This is accomplished via
//! a simple whitelist of allowed operations, along with some lifetime magic to prevent nodes from
//! escaping.
//!
//! As a security wrapper is only as good as its whitelist, be careful when adding operations to
//! this list. The cardinal rules are:
//!
//! 1. Layout is not allowed to mutate the DOM.
//!
//! 2. Layout is not allowed to see anything with `LayoutDom` in the name, because it could hang
//!    onto these objects and cause use-after-free.
//!
//! When implementing wrapper functions, be careful that you do not touch the borrow flags, or you
//! will race and cause spurious thread failure. (Note that I do not believe these races are
//! exploitable, but they'll result in brokenness nonetheless.)
//!
//! Rules of the road for this file:
//!
//! * Do not call any methods on DOM nodes without checking to see whether they use borrow flags.
//!
//!   o Instead of `get_attr()`, use `.get_attr_val_for_layout()`.
//!
//!   o Instead of `html_element_in_html_document()`, use
//!     `html_element_in_html_document_for_layout()`.

#![allow(unsafe_code)]

use atomic_refcell::{AtomicRef, AtomicRefMut};
use data::{LayoutData, LayoutDataFlags, StyleAndLayoutData};
use script_layout_interface::wrapper_traits::{ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use script_layout_interface::wrapper_traits::GetLayoutData;
use style::computed_values::content::{self, ContentItem};
use style::dom::{NodeInfo, TNode};
use style::selector_parser::RestyleDamage;

pub trait LayoutNodeLayoutData {
    /// Similar to borrow_data*, but returns the full PersistentLayoutData rather
    /// than only the style::data::ElementData.
    fn borrow_layout_data(&self) -> Option<AtomicRef<LayoutData>>;
    fn mutate_layout_data(&self) -> Option<AtomicRefMut<LayoutData>>;
    fn flow_debug_id(self) -> usize;
}

impl<T: GetLayoutData> LayoutNodeLayoutData for T {
    fn borrow_layout_data(&self) -> Option<AtomicRef<LayoutData>> {
        self.get_raw_data().map(|d| d.layout_data.borrow())
    }

    fn mutate_layout_data(&self) -> Option<AtomicRefMut<LayoutData>> {
        self.get_raw_data().map(|d| d.layout_data.borrow_mut())
    }

    fn flow_debug_id(self) -> usize {
        self.borrow_layout_data().map_or(0, |d| d.flow_construction_result.debug_id())
    }
}

pub trait GetRawData {
    fn get_raw_data(&self) -> Option<&StyleAndLayoutData>;
}

impl<T: GetLayoutData> GetRawData for T {
    fn get_raw_data(&self) -> Option<&StyleAndLayoutData> {
        self.get_style_and_layout_data().map(|opaque| {
            let container = opaque.ptr.get() as *mut StyleAndLayoutData;
            unsafe { &*container }
        })
    }
}

pub trait ThreadSafeLayoutNodeHelpers {
    /// Returns the layout data flags for this node.
    fn flags(self) -> LayoutDataFlags;

    /// Adds the given flags to this node.
    fn insert_flags(self, new_flags: LayoutDataFlags);

    /// Removes the given flags from this node.
    fn remove_flags(self, flags: LayoutDataFlags);

    /// If this is a text node, generated content, or a form element, copies out
    /// its content. Otherwise, panics.
    ///
    /// FIXME(pcwalton): This might have too much copying and/or allocation. Profile this.
    fn text_content(&self) -> TextContent;

    /// The RestyleDamage from any restyling, or RestyleDamage::rebuild_and_reflow() if this
    /// is the first time layout is visiting this node. We implement this here, rather than
    /// with the rest of the wrapper layer, because we need layout code to determine whether
    /// layout has visited the node.
    fn restyle_damage(self) -> RestyleDamage;
}

impl<T: ThreadSafeLayoutNode> ThreadSafeLayoutNodeHelpers for T {
    fn flags(self) -> LayoutDataFlags {
        self.borrow_layout_data().as_ref().unwrap().flags
    }

    fn insert_flags(self, new_flags: LayoutDataFlags) {
        self.mutate_layout_data().unwrap().flags.insert(new_flags);
    }

    fn remove_flags(self, flags: LayoutDataFlags) {
        self.mutate_layout_data().unwrap().flags.remove(flags);
    }

    fn text_content(&self) -> TextContent {
        if self.get_pseudo_element_type().is_replaced_content() {
            let style = self.as_element().unwrap().resolved_style();

            return match style.as_ref().get_counters().content {
                content::T::Items(ref value) if !value.is_empty() => {
                    TextContent::GeneratedContent((*value).clone())
                }
                _ => TextContent::GeneratedContent(vec![]),
            };
        }

        return TextContent::Text(self.node_text_content());
    }

    fn restyle_damage(self) -> RestyleDamage {
        // We need the underlying node to potentially access the parent in the
        // case of text nodes. This is safe as long as we don't let the parent
        // escape and never access its descendants.
        let mut node = unsafe { self.unsafe_get() };

        // If this is a text node, use the parent element, since that's what
        // controls our style.
        if node.is_text_node() {
            node = node.parent_node().unwrap();
            debug_assert!(node.is_element());
        }

        let damage = {
            let data = node.get_raw_data().unwrap();

            if !data.layout_data.borrow().flags.contains(::data::LayoutDataFlags::HAS_BEEN_TRAVERSED) {
                // We're reflowing a node that was styled for the first time and
                // has never been visited by layout. Return rebuild_and_reflow,
                // because that's what the code expects.
                RestyleDamage::rebuild_and_reflow()
            } else {
                data.style_data.element_data.borrow().damage
            }
        };

        damage
    }

}

pub enum TextContent {
    Text(String),
    GeneratedContent(Vec<ContentItem>),
}

impl TextContent {
    pub fn is_empty(&self) -> bool {
        match *self {
            TextContent::Text(_) => false,
            TextContent::GeneratedContent(ref content) => content.is_empty(),
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! The implementation of the DOM.
//!
//! The DOM is comprised of interfaces (defined by specifications using
//! [WebIDL](https://heycam.github.io/webidl/)) that are implemented as Rust
//! structs in submodules of this module. Its implementation is documented
//! below.
//!
//! A DOM object and its reflector
//! ==============================
//!
//! The implementation of an interface `Foo` in Servo's DOM involves two
//! related but distinct objects:
//!
//! * the **DOM object**: an instance of the Rust struct `dom::foo::Foo`
//!   (marked with the `#[dom_struct]` attribute) on the Rust heap;
//! * the **reflector**: a `JSObject` allocated by SpiderMonkey, that owns the
//!   DOM object.
//!
//! Memory management
//! =================
//!
//! Reflectors of DOM objects, and thus the DOM objects themselves, are managed
//! by the SpiderMonkey Garbage Collector. Thus, keeping alive a DOM object
//! is done through its reflector.
//!
//! For more information, see:
//!
//! * rooting pointers on the stack: the [`Root`](bindings/js/struct.Root.html)
//!   and [`JSRef`](bindings/js/struct.JSRef.html) smart pointers;
//! * tracing pointers in member fields: the [`JS`](bindings/js/struct.JS.html),
//!   [`MutNullableJS`](bindings/js/struct.MutNullableJS.html) and
//!   [`MutHeap`](bindings/js/struct.MutHeap.html) smart pointers and
//!   [the tracing implementation](bindings/trace/index.html);
//! * returning pointers from functions: the
//!   [`Temporary`](bindings/js/struct.Temporary.html) smart pointer;
//! * rooting pointers from across task boundaries or in channels: the
//!   [`Trusted`](bindings/refcounted/struct.Trusted.html) smart pointer;
//! * extracting pointers to DOM objects from their reflectors: the
//!   [`Unrooted`](bindings/js/struct.Unrooted.html) smart pointer.
//!
//! Inheritance
//! ===========
//!
//! Rust does not support struct inheritance, as would be used for the
//! object-oriented DOM APIs. To work around this issue, Servo stores an
//! instance of the superclass in the first field of its subclasses. (Note that
//! it is stored by value, rather than in a smart pointer such as `JS<T>`.)
//!
//! This implies that a pointer to an object can safely be cast to a pointer
//! to all its classes.
//!
//! This invariant is enforced by the lint in
//! `plugins::lints::inheritance_integrity`.
//!
//! Construction
//! ============
//!
//! DOM objects of type `T` in Servo have two constructors:
//!
//! * a `T::new_inherited` static method that returns a plain `T`, and
//! * a `T::new` static method that returns `Temporary<T>`.
//!
//! (The result of either method can be wrapped in `Result`, if that is
//! appropriate for the type in question.)
//!
//! The latter calls the former, boxes the result, and creates a reflector
//! corresponding to it by calling `dom::bindings::utils::reflect_dom_object`
//! (which yields ownership of the object to the SpiderMonkey Garbage Collector).
//! This is the API to use when creating a DOM object.
//!
//! The former should only be called by the latter, and by subclasses'
//! `new_inherited` methods.
//!
//! DOM object constructors in JavaScript correspond to a `T::Constructor`
//! static method. This method is always fallible.
//!
//! Destruction
//! ===========
//!
//! When the SpiderMonkey Garbage Collector discovers that the reflector of a
//! DOM object is garbage, it calls the reflector's finalization hook. This
//! function deletes the reflector's DOM object, calling its destructor in the
//! process.
//!
//! Mutability and aliasing
//! =======================
//!
//! Reflectors are JavaScript objects, and as such can be freely aliased. As
//! Rust does not allow mutable aliasing, mutable borrows of DOM objects are
//! not allowed. In particular, any mutable fields use `Cell` or `DOMRefCell`
//! to manage their mutability.
//!
//! `Reflector` and `Reflectable`
//! =============================
//!
//! Every DOM object has a `Reflector` as its first (transitive) member field.
//! This contains a `*mut JSObject` that points to its reflector.
//!
//! The `FooBinding::Wrap` function creates the reflector, stores a pointer to
//! the DOM object in the reflector, and initializes the pointer to the reflector
//! in the `Reflector` field.
//!
//! The `Reflectable` trait provides a `reflector()` method that returns the
//! DOM object's `Reflector`. It is implemented automatically for DOM structs
//! through the `#[dom_struct]` attribute.
//!
//! Implementing methods for a DOM object
//! =====================================
//!
//! In order to ensure that DOM objects are rooted when they are called, we
//! require that all methods are implemented for `JSRef<'a, Foo>`. This means
//! that all methods are defined on traits. Conventionally, those traits are
//! called
//!
//! * `dom::bindings::codegen::Bindings::FooBindings::FooMethods` for methods
//!   defined through IDL;
//! * `FooHelpers` for public methods;
//! * `PrivateFooHelpers` for private methods.
//!
//! Calling methods on a DOM object
//! ===============================
//!
//! To call a method on a DOM object, we require that the object is rooted, by
//! calling `.root()` on a `Temporary` or `JS` pointer. This constructs a
//! `Root` on the stack, which ensures the DOM object stays alive for the
//! duration of its lifetime. A `JSRef` on which to call the method can then be
//! obtained by calling the `r()` method on the `Root`.
//!
//! Accessing fields of a DOM object
//! ================================
//!
//! All fields of DOM objects are private; accessing them from outside their
//! module is done through explicit getter or setter methods.
//!
//! However, `JSRef<T>` dereferences to `&T`, so fields can be accessed on a
//! `JSRef<T>` directly within the module that defines the struct.
//!
//! Inheritance and casting
//! =======================
//!
//! For all DOM interfaces `Foo` in an inheritance chain, a
//! `dom::bindings::codegen::InheritTypes::FooCast` provides methods to cast
//! to other types in the inheritance chain. For example:
//!
//! ```ignore
//! # use script::dom::bindings::js::JSRef;
//! # use script::dom::bindings::codegen::InheritTypes::{NodeCast, HTMLElementCast};
//! # use script::dom::element::Element;
//! # use script::dom::node::Node;
//! # use script::dom::htmlelement::HTMLElement;
//! fn f(element: JSRef<Element>) {
//!     let base: JSRef<Node> = NodeCast::from_ref(element);
//!     let derived: Option<JSRef<HTMLElement>> = HTMLElementCast::to_ref(element);
//! }
//! ```
//!
//! Adding a new DOM interface
//! ==========================
//!
//! Adding a new interface `Foo` requires at least the following:
//!
//! * adding the new IDL file at `components/script/dom/webidls/Foo.webidl`;
//! * creating `components/script/dom/foo.rs`;
//! * listing `foo.rs` in components/script/dom/mod.rs`;
//! * defining the DOM struct `Foo` with a `#[dom_struct]` attribute, a
//!   superclass or `Reflector` member, and other members as appropriate;
//! * implementing the
//!   `dom::bindings::codegen::Bindings::FooBindings::FooMethods` trait for
//!   `JSRef<Foo>`.
//!
//! More information is available in the [bindings module](bindings/index.html).
//!
//! Accessing DOM objects from layout
//! =================================
//!
//! Layout code can access the DOM through the
//! [`LayoutJS`](bindings/js/struct.LayoutJS.html) smart pointer. This does not
//! keep the DOM object alive; we ensure that no DOM code (Garbage Collection
//! in particular) runs while the layout task is accessing the DOM.
//!
//! Methods accessible to layout are implemented on `LayoutJS<Foo>` using
//! `LayoutFooHelpers` traits.

#[macro_use]
pub mod macros;

pub mod bindings;

#[path="bindings/codegen/InterfaceTypes.rs"]
pub mod types;

pub mod activation;
pub mod attr;
pub mod blob;
pub mod browsercontext;
pub mod canvasgradient;
pub mod canvaspattern;
pub mod canvasrenderingcontext2d;
pub mod characterdata;
pub mod css;
pub mod cssstyledeclaration;
pub mod domrect;
pub mod domrectlist;
pub mod domstringmap;
pub mod comment;
pub mod console;
mod create;
pub mod customevent;
pub mod dedicatedworkerglobalscope;
pub mod document;
pub mod documentfragment;
pub mod documenttype;
pub mod domexception;
pub mod domimplementation;
pub mod domparser;
pub mod domtokenlist;
pub mod element;
pub mod errorevent;
pub mod event;
pub mod eventdispatcher;
pub mod eventtarget;
pub mod file;
pub mod formdata;
pub mod htmlanchorelement;
pub mod htmlappletelement;
pub mod htmlareaelement;
pub mod htmlaudioelement;
pub mod htmlbaseelement;
pub mod htmlbodyelement;
pub mod htmlbrelement;
pub mod htmlbuttonelement;
pub mod htmlcanvaselement;
pub mod htmlcollection;
pub mod htmldataelement;
pub mod htmldatalistelement;
pub mod htmldialogelement;
pub mod htmldirectoryelement;
pub mod htmldivelement;
pub mod htmldlistelement;
pub mod htmlelement;
pub mod htmlembedelement;
pub mod htmlfieldsetelement;
pub mod htmlfontelement;
pub mod htmlformelement;
pub mod htmlframeelement;
pub mod htmlframesetelement;
pub mod htmlheadelement;
pub mod htmlheadingelement;
pub mod htmlhrelement;
pub mod htmlhtmlelement;
pub mod htmliframeelement;
pub mod htmlimageelement;
pub mod htmlinputelement;
pub mod htmllabelelement;
pub mod htmllegendelement;
pub mod htmllielement;
pub mod htmllinkelement;
pub mod htmlmapelement;
pub mod htmlmediaelement;
pub mod htmlmetaelement;
pub mod htmlmeterelement;
pub mod htmlmodelement;
pub mod htmlobjectelement;
pub mod htmlolistelement;
pub mod htmloptgroupelement;
pub mod htmloptionelement;
pub mod htmloutputelement;
pub mod htmlparagraphelement;
pub mod htmlparamelement;
pub mod htmlpreelement;
pub mod htmlprogresselement;
pub mod htmlquoteelement;
pub mod htmlscriptelement;
pub mod htmlselectelement;
pub mod htmlspanelement;
pub mod htmlsourceelement;
pub mod htmlstyleelement;
pub mod htmltableelement;
pub mod htmltablecaptionelement;
pub mod htmltablecellelement;
pub mod htmltabledatacellelement;
pub mod htmltableheadercellelement;
pub mod htmltablecolelement;
pub mod htmltablerowelement;
pub mod htmltablesectionelement;
pub mod htmltemplateelement;
pub mod htmltextareaelement;
pub mod htmltimeelement;
pub mod htmltitleelement;
pub mod htmltrackelement;
pub mod htmlulistelement;
pub mod htmlvideoelement;
pub mod htmlunknownelement;
pub mod imagedata;
pub mod keyboardevent;
pub mod location;
pub mod messageevent;
pub mod mouseevent;
pub mod namednodemap;
pub mod navigator;
pub mod navigatorinfo;
pub mod node;
pub mod nodeiterator;
pub mod nodelist;
pub mod processinginstruction;
pub mod performance;
pub mod performancetiming;
pub mod progressevent;
pub mod range;
pub mod screen;
pub mod servohtmlparser;
pub mod storage;
pub mod storageevent;
pub mod text;
pub mod textdecoder;
pub mod textencoder;
pub mod treewalker;
pub mod uievent;
pub mod urlhelper;
pub mod urlsearchparams;
pub mod userscripts;
pub mod validitystate;
pub mod virtualmethods;
pub mod webglobject;
pub mod webglbuffer;
pub mod webglprogram;
pub mod webglrenderingcontext;
pub mod webglshader;
pub mod webgluniformlocation;
pub mod websocket;
pub mod window;
pub mod worker;
pub mod workerglobalscope;
pub mod workerlocation;
pub mod workernavigator;
pub mod xmlhttprequest;
pub mod xmlhttprequesteventtarget;
pub mod xmlhttprequestupload;

pub mod testbinding;
<commit_msg>Added CloseEvent DOM interface - lots of bugs (doesn't compile)<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! The implementation of the DOM.
//!
//! The DOM is comprised of interfaces (defined by specifications using
//! [WebIDL](https://heycam.github.io/webidl/)) that are implemented as Rust
//! structs in submodules of this module. Its implementation is documented
//! below.
//!
//! A DOM object and its reflector
//! ==============================
//!
//! The implementation of an interface `Foo` in Servo's DOM involves two
//! related but distinct objects:
//!
//! * the **DOM object**: an instance of the Rust struct `dom::foo::Foo`
//!   (marked with the `#[dom_struct]` attribute) on the Rust heap;
//! * the **reflector**: a `JSObject` allocated by SpiderMonkey, that owns the
//!   DOM object.
//!
//! Memory management
//! =================
//!
//! Reflectors of DOM objects, and thus the DOM objects themselves, are managed
//! by the SpiderMonkey Garbage Collector. Thus, keeping alive a DOM object
//! is done through its reflector.
//!
//! For more information, see:
//!
//! * rooting pointers on the stack: the [`Root`](bindings/js/struct.Root.html)
//!   and [`JSRef`](bindings/js/struct.JSRef.html) smart pointers;
//! * tracing pointers in member fields: the [`JS`](bindings/js/struct.JS.html),
//!   [`MutNullableJS`](bindings/js/struct.MutNullableJS.html) and
//!   [`MutHeap`](bindings/js/struct.MutHeap.html) smart pointers and
//!   [the tracing implementation](bindings/trace/index.html);
//! * returning pointers from functions: the
//!   [`Temporary`](bindings/js/struct.Temporary.html) smart pointer;
//! * rooting pointers from across task boundaries or in channels: the
//!   [`Trusted`](bindings/refcounted/struct.Trusted.html) smart pointer;
//! * extracting pointers to DOM objects from their reflectors: the
//!   [`Unrooted`](bindings/js/struct.Unrooted.html) smart pointer.
//!
//! Inheritance
//! ===========
//!
//! Rust does not support struct inheritance, as would be used for the
//! object-oriented DOM APIs. To work around this issue, Servo stores an
//! instance of the superclass in the first field of its subclasses. (Note that
//! it is stored by value, rather than in a smart pointer such as `JS<T>`.)
//!
//! This implies that a pointer to an object can safely be cast to a pointer
//! to all its classes.
//!
//! This invariant is enforced by the lint in
//! `plugins::lints::inheritance_integrity`.
//!
//! Construction
//! ============
//!
//! DOM objects of type `T` in Servo have two constructors:
//!
//! * a `T::new_inherited` static method that returns a plain `T`, and
//! * a `T::new` static method that returns `Temporary<T>`.
//!
//! (The result of either method can be wrapped in `Result`, if that is
//! appropriate for the type in question.)
//!
//! The latter calls the former, boxes the result, and creates a reflector
//! corresponding to it by calling `dom::bindings::utils::reflect_dom_object`
//! (which yields ownership of the object to the SpiderMonkey Garbage Collector).
//! This is the API to use when creating a DOM object.
//!
//! The former should only be called by the latter, and by subclasses'
//! `new_inherited` methods.
//!
//! DOM object constructors in JavaScript correspond to a `T::Constructor`
//! static method. This method is always fallible.
//!
//! Destruction
//! ===========
//!
//! When the SpiderMonkey Garbage Collector discovers that the reflector of a
//! DOM object is garbage, it calls the reflector's finalization hook. This
//! function deletes the reflector's DOM object, calling its destructor in the
//! process.
//!
//! Mutability and aliasing
//! =======================
//!
//! Reflectors are JavaScript objects, and as such can be freely aliased. As
//! Rust does not allow mutable aliasing, mutable borrows of DOM objects are
//! not allowed. In particular, any mutable fields use `Cell` or `DOMRefCell`
//! to manage their mutability.
//!
//! `Reflector` and `Reflectable`
//! =============================
//!
//! Every DOM object has a `Reflector` as its first (transitive) member field.
//! This contains a `*mut JSObject` that points to its reflector.
//!
//! The `FooBinding::Wrap` function creates the reflector, stores a pointer to
//! the DOM object in the reflector, and initializes the pointer to the reflector
//! in the `Reflector` field.
//!
//! The `Reflectable` trait provides a `reflector()` method that returns the
//! DOM object's `Reflector`. It is implemented automatically for DOM structs
//! through the `#[dom_struct]` attribute.
//!
//! Implementing methods for a DOM object
//! =====================================
//!
//! In order to ensure that DOM objects are rooted when they are called, we
//! require that all methods are implemented for `JSRef<'a, Foo>`. This means
//! that all methods are defined on traits. Conventionally, those traits are
//! called
//!
//! * `dom::bindings::codegen::Bindings::FooBindings::FooMethods` for methods
//!   defined through IDL;
//! * `FooHelpers` for public methods;
//! * `PrivateFooHelpers` for private methods.
//!
//! Calling methods on a DOM object
//! ===============================
//!
//! To call a method on a DOM object, we require that the object is rooted, by
//! calling `.root()` on a `Temporary` or `JS` pointer. This constructs a
//! `Root` on the stack, which ensures the DOM object stays alive for the
//! duration of its lifetime. A `JSRef` on which to call the method can then be
//! obtained by calling the `r()` method on the `Root`.
//!
//! Accessing fields of a DOM object
//! ================================
//!
//! All fields of DOM objects are private; accessing them from outside their
//! module is done through explicit getter or setter methods.
//!
//! However, `JSRef<T>` dereferences to `&T`, so fields can be accessed on a
//! `JSRef<T>` directly within the module that defines the struct.
//!
//! Inheritance and casting
//! =======================
//!
//! For all DOM interfaces `Foo` in an inheritance chain, a
//! `dom::bindings::codegen::InheritTypes::FooCast` provides methods to cast
//! to other types in the inheritance chain. For example:
//!
//! ```ignore
//! # use script::dom::bindings::js::JSRef;
//! # use script::dom::bindings::codegen::InheritTypes::{NodeCast, HTMLElementCast};
//! # use script::dom::element::Element;
//! # use script::dom::node::Node;
//! # use script::dom::htmlelement::HTMLElement;
//! fn f(element: JSRef<Element>) {
//!     let base: JSRef<Node> = NodeCast::from_ref(element);
//!     let derived: Option<JSRef<HTMLElement>> = HTMLElementCast::to_ref(element);
//! }
//! ```
//!
//! Adding a new DOM interface
//! ==========================
//!
//! Adding a new interface `Foo` requires at least the following:
//!
//! * adding the new IDL file at `components/script/dom/webidls/Foo.webidl`;
//! * creating `components/script/dom/foo.rs`;
//! * listing `foo.rs` in components/script/dom/mod.rs`;
//! * defining the DOM struct `Foo` with a `#[dom_struct]` attribute, a
//!   superclass or `Reflector` member, and other members as appropriate;
//! * implementing the
//!   `dom::bindings::codegen::Bindings::FooBindings::FooMethods` trait for
//!   `JSRef<Foo>`.
//!
//! More information is available in the [bindings module](bindings/index.html).
//!
//! Accessing DOM objects from layout
//! =================================
//!
//! Layout code can access the DOM through the
//! [`LayoutJS`](bindings/js/struct.LayoutJS.html) smart pointer. This does not
//! keep the DOM object alive; we ensure that no DOM code (Garbage Collection
//! in particular) runs while the layout task is accessing the DOM.
//!
//! Methods accessible to layout are implemented on `LayoutJS<Foo>` using
//! `LayoutFooHelpers` traits.

#[macro_use]
pub mod macros;

pub mod bindings;

#[path="bindings/codegen/InterfaceTypes.rs"]
pub mod types;

pub mod activation;
pub mod attr;
pub mod blob;
pub mod browsercontext;
pub mod canvasgradient;
pub mod canvaspattern;
pub mod canvasrenderingcontext2d;
pub mod characterdata;
pub mod css;
pub mod cssstyledeclaration;
pub mod domrect;
pub mod domrectlist;
pub mod domstringmap;
pub mod closeevent;
pub mod comment;
pub mod console;
mod create;
pub mod customevent;
pub mod dedicatedworkerglobalscope;
pub mod document;
pub mod documentfragment;
pub mod documenttype;
pub mod domexception;
pub mod domimplementation;
pub mod domparser;
pub mod domtokenlist;
pub mod element;
pub mod errorevent;
pub mod event;
pub mod eventdispatcher;
pub mod eventtarget;
pub mod file;
pub mod formdata;
pub mod htmlanchorelement;
pub mod htmlappletelement;
pub mod htmlareaelement;
pub mod htmlaudioelement;
pub mod htmlbaseelement;
pub mod htmlbodyelement;
pub mod htmlbrelement;
pub mod htmlbuttonelement;
pub mod htmlcanvaselement;
pub mod htmlcollection;
pub mod htmldataelement;
pub mod htmldatalistelement;
pub mod htmldialogelement;
pub mod htmldirectoryelement;
pub mod htmldivelement;
pub mod htmldlistelement;
pub mod htmlelement;
pub mod htmlembedelement;
pub mod htmlfieldsetelement;
pub mod htmlfontelement;
pub mod htmlformelement;
pub mod htmlframeelement;
pub mod htmlframesetelement;
pub mod htmlheadelement;
pub mod htmlheadingelement;
pub mod htmlhrelement;
pub mod htmlhtmlelement;
pub mod htmliframeelement;
pub mod htmlimageelement;
pub mod htmlinputelement;
pub mod htmllabelelement;
pub mod htmllegendelement;
pub mod htmllielement;
pub mod htmllinkelement;
pub mod htmlmapelement;
pub mod htmlmediaelement;
pub mod htmlmetaelement;
pub mod htmlmeterelement;
pub mod htmlmodelement;
pub mod htmlobjectelement;
pub mod htmlolistelement;
pub mod htmloptgroupelement;
pub mod htmloptionelement;
pub mod htmloutputelement;
pub mod htmlparagraphelement;
pub mod htmlparamelement;
pub mod htmlpreelement;
pub mod htmlprogresselement;
pub mod htmlquoteelement;
pub mod htmlscriptelement;
pub mod htmlselectelement;
pub mod htmlspanelement;
pub mod htmlsourceelement;
pub mod htmlstyleelement;
pub mod htmltableelement;
pub mod htmltablecaptionelement;
pub mod htmltablecellelement;
pub mod htmltabledatacellelement;
pub mod htmltableheadercellelement;
pub mod htmltablecolelement;
pub mod htmltablerowelement;
pub mod htmltablesectionelement;
pub mod htmltemplateelement;
pub mod htmltextareaelement;
pub mod htmltimeelement;
pub mod htmltitleelement;
pub mod htmltrackelement;
pub mod htmlulistelement;
pub mod htmlvideoelement;
pub mod htmlunknownelement;
pub mod imagedata;
pub mod keyboardevent;
pub mod location;
pub mod messageevent;
pub mod mouseevent;
pub mod namednodemap;
pub mod navigator;
pub mod navigatorinfo;
pub mod node;
pub mod nodeiterator;
pub mod nodelist;
pub mod processinginstruction;
pub mod performance;
pub mod performancetiming;
pub mod progressevent;
pub mod range;
pub mod screen;
pub mod servohtmlparser;
pub mod storage;
pub mod storageevent;
pub mod text;
pub mod textdecoder;
pub mod textencoder;
pub mod treewalker;
pub mod uievent;
pub mod urlhelper;
pub mod urlsearchparams;
pub mod userscripts;
pub mod validitystate;
pub mod virtualmethods;
pub mod webglobject;
pub mod webglbuffer;
pub mod webglprogram;
pub mod webglrenderingcontext;
pub mod webglshader;
pub mod webgluniformlocation;
pub mod websocket;
pub mod window;
pub mod worker;
pub mod workerglobalscope;
pub mod workerlocation;
pub mod workernavigator;
pub mod xmlhttprequest;
pub mod xmlhttprequesteventtarget;
pub mod xmlhttprequestupload;

pub mod testbinding;
<|endoftext|>


<commit_before>export poll_event;

export event, quit, quit_event, no_event;

type event_type = u8;

const noevent: u8 = 0u8;
const activeevent: u8 = 1u8;
const keydown: u8 = 2u8;
const keyup: u8 = 3u8;
const mousemotion: u8 = 4u8;
const mousebuttondown: u8 = 5u8;
const mousebuttonup: u8 = 6u8;
const joyaxismotion: u8 = 7u8;
const joyballmotion: u8 = 8u8;
const joyhatmotion: u8 = 9u8;
const joybuttondown: u8 = 10u8;
const joybuttonup: u8 = 11u8;
const quit: u8 = 12u8;
const syswmevent: u8 = 13u8;
const event_reserveda: u8 = 14u8;
const event_reservedb: u8 = 15u8;
const videoresize: u8 = 16u8;
const videoexpose: u8 = 17u8;
const event_reserved2: u8 = 18u8;
const event_reserved3: u8 = 19u8;
const event_reserved4: u8 = 20u8;
const event_reserved5: u8 = 21u8;
const event_reserved6: u8 = 22u8;
const event_reserved7: u8 = 23u8;
const event_userevent: u8 = 24u8;

type raw_event = {
    type_: event_type,
    // FIXME: Not sure exactly how big this needs to be
    event: (u64, u64, u64, u64, u64, u64, u64, u64)
};

enum event {
    quit_event(*quit_event_),
    no_event
}

type quit_event_ = {
    type_: event_type
};

fn null_event() -> raw_event {
    {
        type_: 0u8,
        event: (0u64, 0u64, 0u64, 0u64, 0u64, 0u64, 0u64, 0u64)
    }
}

fn log_event(e: raw_event) {
    let name = if e.type_ == noevent { "none" }
    else if e.type_ == activeevent { "active" }
    else if e.type_ == keydown { "keydown" }
    else if e.type_ == keyup { "keyup" }
    else if e.type_ == mousemotion { "mousemotion" }
    else if e.type_ == mousebuttondown { "mousebuttondown" }
    else if e.type_ == mousebuttonup { "mousebuttonup" }
    else if e.type_ == quit { "quit" }
    else if e.type_ == syswmevent { "syswmevent" }
    else if e.type_ == videoresize { "videoresize" }
    else if e.type_ == videoexpose { "videoexpose" }
    else { "other" };
    #debug("event: %s", name);
}

fn poll_event(f: fn(event)) unsafe {
    let raw_event = null_event();
    let result = SDL::SDL_PollEvent(ptr::addr_of(raw_event));
    if result as int == 0 {
        let event_ptr = ptr::addr_of(raw_event.event);
        log_event(raw_event);
        if (raw_event.type_ == quit) {
            f(quit_event(unsafe::reinterpret_cast(event_ptr)));
        } else {
            f(no_event);
        }
    } else {
        f(no_event);
    }
}

native mod SDL {
    fn SDL_PollEvent(event: *raw_event) -> c::c_int;
}
<commit_msg>quit_event doesn't need a param<commit_after>export poll_event;

export event, quit_event, no_event;

type event_type = u8;

const noevent: u8 = 0u8;
const activeevent: u8 = 1u8;
const keydown: u8 = 2u8;
const keyup: u8 = 3u8;
const mousemotion: u8 = 4u8;
const mousebuttondown: u8 = 5u8;
const mousebuttonup: u8 = 6u8;
const joyaxismotion: u8 = 7u8;
const joyballmotion: u8 = 8u8;
const joyhatmotion: u8 = 9u8;
const joybuttondown: u8 = 10u8;
const joybuttonup: u8 = 11u8;
const quit: u8 = 12u8;
const syswmevent: u8 = 13u8;
const event_reserveda: u8 = 14u8;
const event_reservedb: u8 = 15u8;
const videoresize: u8 = 16u8;
const videoexpose: u8 = 17u8;
const event_reserved2: u8 = 18u8;
const event_reserved3: u8 = 19u8;
const event_reserved4: u8 = 20u8;
const event_reserved5: u8 = 21u8;
const event_reserved6: u8 = 22u8;
const event_reserved7: u8 = 23u8;
const event_userevent: u8 = 24u8;

type raw_event = {
    type_: event_type,
    // FIXME: Not sure exactly how big this needs to be
    event: (u64, u64, u64, u64, u64, u64, u64, u64)
};

enum event {
    quit_event,
    no_event
}

type quit_event_ = {
    type_: event_type
};

fn null_event() -> raw_event {
    {
        type_: 0u8,
        event: (0u64, 0u64, 0u64, 0u64, 0u64, 0u64, 0u64, 0u64)
    }
}

fn log_event(e: raw_event) {
    let name = if e.type_ == noevent { "none" }
    else if e.type_ == activeevent { "active" }
    else if e.type_ == keydown { "keydown" }
    else if e.type_ == keyup { "keyup" }
    else if e.type_ == mousemotion { "mousemotion" }
    else if e.type_ == mousebuttondown { "mousebuttondown" }
    else if e.type_ == mousebuttonup { "mousebuttonup" }
    else if e.type_ == quit { "quit" }
    else if e.type_ == syswmevent { "syswmevent" }
    else if e.type_ == videoresize { "videoresize" }
    else if e.type_ == videoexpose { "videoexpose" }
    else { "other" };
    #debug("event: %s", name);
}

fn poll_event(f: fn(event)) unsafe {
    let raw_event = null_event();
    let result = SDL::SDL_PollEvent(ptr::addr_of(raw_event));
    if result as int == 0 {
        let event_ptr = ptr::addr_of(raw_event.event);
        log_event(raw_event);
        if (raw_event.type_ == quit) {
            f(quit_event);
        } else {
            f(no_event);
        }
    } else {
        f(no_event);
    }
}

native mod SDL {
    fn SDL_PollEvent(event: *raw_event) -> c::c_int;
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate eve;

use test::Bencher;
use std::collections::BTreeMap;

use eve::map::*;

#[bench]
fn bench_insert_map_3(b: &mut Bencher) {
    b.iter(|| {
        let mut map = Map::new(3);
        for i in (0..1000000) {
            map.insert(i, 1);
        }
    });
}

#[bench]
fn bench_insert_map_1(b: &mut Bencher) {
    b.iter(|| {
        let mut map = Map::new(1);
        for i in (0..1000000) {
            map.insert(i, 1);
        }
    });
}

#[bench]
fn bench_insert_btree(b: &mut Bencher) {
    b.iter(|| {
        let mut map = BTreeMap::new();
        for i in (0..1000000) {
            map.insert(i, 1);
        }
    });
}

#[allow(dead_code)]
fn main() {
    let mut map = Map::new(1);
    for i in (0..10) {
        map.insert(i, 1);
        println!("{:?}", map);
    }

    let mut map = Map::new(3);
    for i in (0..10) {
        map.insert(i, 1);
        println!("{:?}", map);
    }
}<commit_msg>Improve benchmarks<commit_after>#![feature(test)]

extern crate test;
extern crate eve;

use test::Bencher;
use std::collections::BTreeMap;
use std::io::prelude::*;
use std::fs::File;

use eve::map::*;

#[bench]
fn bench_insert_int_map_3(b: &mut Bencher) {
    b.iter(|| {
        let mut map = Map::new(3);
        for i in (0i64..1000000) {
            map.insert(i * 25214903917, 1);
        }
    });
}

#[bench]
fn bench_insert_int_map_1(b: &mut Bencher) {
    b.iter(|| {
        let mut map = Map::new(1);
        for i in (0i64..1000000) {
            map.insert(i * 25214903917, 1);
        }
    });
}

#[bench]
fn bench_insert_int_btree(b: &mut Bencher) {
    b.iter(|| {
        let mut map = BTreeMap::new();
        for i in (0i64..1000000) {
            map.insert(i * 25214903917, 1);
        }
    });
}

fn words() -> Vec<String> {
    let mut contents = String::new();
    File::open("/usr/share/dict/words").unwrap().read_to_string(&mut contents).unwrap();
    contents.lines().map(|word| word.to_owned()).collect()
}

#[bench]
fn bench_insert_string_map_3(b: &mut Bencher) {
    let words = words();
    b.iter(|| {
        let mut map = Map::new(3);
        for word in words.iter() {
            map.insert(word.clone(), 1);
        }
    });
}

#[bench]
fn bench_insert_string_map_1(b: &mut Bencher) {
    let words = words();
    b.iter(|| {
        let mut map = Map::new(1);
        for word in words.iter() {
            map.insert(word.clone(), 1);
        }
    });
}

#[bench]
fn bench_insert_string_btree(b: &mut Bencher) {
    let words = words();
    b.iter(|| {
        let mut map = BTreeMap::new();
        for word in words.iter() {
            map.insert(word.clone(), 1);
        }
    });
}

#[allow(dead_code)]
fn main() {
    let mut map = Map::new(1);
    for i in (0..10) {
        map.insert(i, 1);
        println!("{:?}", map);
    }

    let mut map = Map::new(3);
    for i in (0..10) {
        map.insert(i, 1);
        println!("{:?}", map);
    }
}<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;

#[derive(Debug)]
enum Direction {
    North,
    East,
    West,
    South,
}

#[derive(Debug)]
struct State {
    x: isize,
    y: isize,
    direction: Direction
}

fn parse(instruction: &str) -> (char, u32) {
    let mut chars = instruction.chars();
    let dir = chars.next().unwrap();
    let length = chars.collect::<String>().parse::<u32>().unwrap();
    (dir, length)
}

fn go(state: State, turn: char, length: u32) -> State {
    use Direction::*;
    let length: isize = length as isize;
    let new_dir = if turn == 'R' {
        match state.direction {
            North => East,
            East => South,
            South => West,
            West => North,
        }
    } else {
        match state.direction {
            North => West,
            East => North,
            South => East,
            West => South,
        }
    };
    match new_dir {
        North => State{x: state.x, y: state.y + length, direction: new_dir },
        East =>  State{x: state.x + length, y: state.y, direction: new_dir },
        South => State{x: state.x, y: state.y - length, direction: new_dir },
        West => State{x: state.x - length, y: state.y, direction: new_dir },
    }
}

fn part1(instructions: &str) -> isize {
    let mut bunnies = State{x: 0, y: 0, direction: Direction::North};
    let instructions: Vec<&str> = instructions.split(", ").collect();
    for instruction in instructions {
        let (turn, n) = parse(instruction);
        bunnies = go(bunnies, turn, n);
    }
    bunnies.x.abs() + bunnies.y.abs()
}

fn main() {
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        println!("{:?}", part1(&line));
    }
}
<commit_msg>[day01] update with part2<commit_after>use std::io;
use std::io::prelude::*;
use std::collections::HashSet;

#[derive(Debug)]
enum Direction {
    North,
    East,
    West,
    South,
}

#[derive(Debug)]
struct State {
    x: isize,
    y: isize,
    direction: Direction,
    visited: HashSet<(isize, isize)>,
    crossed: Vec<(isize, isize)>,
}

impl Direction {
    fn turn(&self, dir: char) -> Direction {
        use Direction::*;
        let left_right = |left, right| if dir == 'L' { left } else { right };
        match self {
            &North => left_right(West, East),
            &East => left_right(North, South),
            &South => left_right(East, West),
            &West => left_right(South, North),
        }
    }
}

impl State {
    fn new() -> State {
        State {
            x: 0,
            y: 0,
            direction: Direction::North,
            visited: HashSet::new(),
            crossed: Vec::new(),
        }
    }

    fn move_to(&mut self, turn: char, length: u32) {
        use Direction::*;
        self.direction = self.direction.turn(turn);
        for _ in 0..length {
            match self.direction {
                North => self.y += 1,
                East => self.x += 1,
                South => self.y -= 1,
                West => self.x -= 1,
            }
            if !self.visited.insert((self.x, self.y)) {
                self.crossed.push((self.x, self.y));
            }
        }
    }
}

fn parse(instruction: &str) -> (char, u32) {
    let mut chars = instruction.chars();
    let dir = chars.next().unwrap();
    let length = chars.collect::<String>().parse::<u32>().unwrap();
    (dir, length)
}

fn main() {
    let stdin = io::stdin();
    let mut position = State::new();
    // input only contains one line
    let line = stdin.lock().lines().next().unwrap().unwrap();
    let instructions: Vec<&str> = line.split(", ").collect();
    for instruction in instructions {
        let (turn, n) = parse(instruction);
        position.move_to(turn, n);
    }
    let part1 = position.x.abs() + position.y.abs();
    println!("part 1: {:?}", part1);

    let &(x, y) = position.crossed.first().unwrap();
    println!("part 2: {:?}", x.abs() + y.abs());
}
<|endoftext|>


<commit_before>fn generate_table () {
    let pi: f64 = 3.1415926536897932384626;
    let k1: f64 = 0.6072529350088812561694; // 1/k
    let num_bits: uint = 32;
    //let num_elms: uint = num_bits;
    let mul: uint = 1<<(num_bits-2);

    println!("Cordic sin in rust");
    println!("num bits {}", num_bits);
    println!("mul {}", mul);
    println!("1<<(num_bits-2) {}", ((1i << (num_bits-2)) as f64));
    println!("pi is {}", pi);
    println!("k1 is {}", k1);

    println!("let cordic_tab = [");

    let shift: f64 = 2.0;
    for ii in range(0, num_bits) {
        let ipow: f64 = 1f64/shift.powi(ii as i32);
        let cur: f64 = ipow.atan() * (mul as f64);

        if ii % 4 == 0 && ii > 0 {
            println!("");
        }
        if ii == 0 {
            print!("{:0.8f}f64, ", cur);
        } else {
            print!("{:0.8f}, ", cur);
        }
    }

    println!("];");
}

fn sin(theta: f64) {

    let num_bits: uint = 32;
    let mut d: int;
    let z: int = theta as int;
    let cordic_tab = [
        843314856.53262615f64, 497837829.38176435, 263043836.58692065, 133525158.66814968,
        67021686.89696868, 33543515.72887244, 16775850.86663180, 8388437.33958306,
        4194282.66686198, 2097149.33333944, 1048575.66666686, 524287.95833334,
        262143.99479167, 131071.99934896, 65535.99991862, 32767.99998983,
        16383.99999873, 8191.99999984, 4095.99999998, 2048.00000000,
        1024.00000000, 512.00000000, 256.00000000, 128.00000000,
        64.00000000, 32.00000000, 16.00000000, 8.00000000,
        4.00000000, 2.00000000, 1.00000000, 0.50000000];

    for ii in range(0, num_bits) {
        if z >= 0 {
            d = 0;
        } else {
            d = -1;
        }
        println!("{}", d);
    }

}
fn main() {
    generate_table();

    sin(0.5);
}
<commit_msg>build up state of sin function<commit_after>fn generate_table () {
    let pi: f64 = 3.1415926536897932384626;
    let k1: f64 = 0.6072529350088812561694; // 1/k
    let num_bits: uint = 32;
    //let num_elms: uint = num_bits;
    let mul: uint = 1<<(num_bits-2);

    println!("Cordic sin in rust");
    println!("num bits {}", num_bits);
    println!("mul {}", mul);
    println!("1<<(num_bits-2) {}", ((1i << (num_bits-2)) as f64));
    println!("pi is {}", pi);
    println!("k1 is {}", k1);

    println!("let cordic_tab = [");

    let shift: f64 = 2.0;
    for ii in range(0, num_bits) {
        let ipow: f64 = 1f64/shift.powi(ii as i32);
        let cur: f64 = ipow.atan() * (mul as f64);

        if ii % 4 == 0 && ii > 0 {
            println!("");
        }
        if ii == 0 {
            print!("{:0.8f}f64, ", cur);
        } else {
            print!("{:0.8f}, ", cur);
        }
    }

    println!("];");
}

fn sin(theta: f64) {

    let num_bits: uint = 32;

    let k1: f64 = 0.6072529350088812561694; // 1/k
    let mul: uint = 1<<(num_bits-2);
    let mut x: f64 = (mul as f64) * k1;
    let mut y: f64 = 0.0;
    let mut z: f64 = theta;

    let mut d: int;

    let z: int = theta as int;
    let cordic_tab = [
        843314856.53262615f64, 497837829.38176435, 263043836.58692065, 133525158.66814968,
        67021686.89696868, 33543515.72887244, 16775850.86663180, 8388437.33958306,
        4194282.66686198, 2097149.33333944, 1048575.66666686, 524287.95833334,
        262143.99479167, 131071.99934896, 65535.99991862, 32767.99998983,
        16383.99999873, 8191.99999984, 4095.99999998, 2048.00000000,
        1024.00000000, 512.00000000, 256.00000000, 128.00000000,
        64.00000000, 32.00000000, 16.00000000, 8.00000000,
        4.00000000, 2.00000000, 1.00000000, 0.50000000];

    for ii in range(0, num_bits) {
        if z >= 0 {
            d = 0;
        } else {
            d = -1;
        }

        /*
        tx = x - (((y>>k) ^ d) - d);
        ty = y + (((x>>k) ^ d) - d);
        tz = z - ((cordic_ctab[k] ^ d) - d);
        x = tx; y = ty; z = tz;
        */

        println!("{}", d);
    }

}
fn main() {
    generate_table();

    sin(0.5);
}
<|endoftext|>


<commit_before>/**
use the taylor series to caculate tan^-1 (x) where |x| <= 1, x >= 0
**/
fn taylor_atan (x: f64) -> f64 {
    let mut a: f64 = 0.0;
    let mut s: f64 = 1.0;
    let mut xpow: f64;

    // by definition
    if x == 0.0 {
        return 0.0;
    }

    // this is well known, and the taylor series we are using explictly assumes |x| < 1
    if x == 1.0 {
        return std::f64::consts::FRAC_PI_4;
    }

    for ii in range(1i, 60) {
        if ii % 2 == 0 {
            continue;
        }
        xpow = 1.0;
        for _ in range(0i, ii) {
            xpow *= x;
        }
        a += s * xpow / (ii as f64);
        s = -1.0*s;
    }

    return a;
}

fn generate_table () {

    let pi: f64 = std::f64::consts::PI;
    let k1: f64 = 0.6072529350088812561694; // 1/k
    let num_bits: uint = 32;
    let mul: uint = 1<<(num_bits-2);

    println!("Cordic sin in rust");
    println!("num bits {}", num_bits);
    println!("mul {}", mul);
    println!("1<<(num_bits-2) {}", ((1i << (num_bits-2)) as f64));
    println!("pi is {}", pi);
    println!("k1 is {}", k1);

    println!("let cordic_tab = [");

    let shift: f64 = 2.0;
    for ii in range(0, num_bits) {
        let ipow: f64 = 1f64/shift.powi(ii as i32);
        let cur: f64 = taylor_atan(ipow) * (mul as f64);

        if ii % 4 == 0 && ii > 0 {
            println!("");
        }
        if ii == 0 {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        } else {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        }
    }

    println!("];");
}

fn sin(theta: f64) -> f64 {

    let num_bits: uint = 32;

    let k1: f64 = 0.6072529350088812561694; // 1/k
    let mul: f64 = (1i << (num_bits-2)) as f64;
    let cordic_k1: f64 = k1 * mul;
    let mut x: int = cordic_k1.floor() as int; //0x26DD3B6A;
    let mut y: int = 0;
    let mut z: int = (mul * theta).floor() as int;
    let mut tx: int;
    let mut ty: int;
    let mut tz: int;

    let mut d: int;

    // this table is generated by generate_table()
    let cordic_tab = [
        0x3243f6a8, 0x1dac6705, 0xfadbafc, 0x7f56ea6,
        0x3feab76, 0x1ffd55b, 0xfffaaa, 0x7fff55,
        0x3fffea, 0x1ffffd, 0xfffff, 0x7ffff,
        0x3ffff, 0x1ffff, 0xffff, 0x7fff,
        0x3fff, 0x1fff, 0xfff, 0x7ff,
        0x3ff, 0x1ff, 0xff, 0x7f,
        0x3f, 0x1f, 0xf, 0x8,
        0x4, 0x2, 0x1, 0x0, ];

    for k in range(0, num_bits) {
        if z >= 0 {
            d = 0;
        } else {
            d = -1;
        }

        tx = x - (((y>>k) ^ d) - d);
        ty = y + (((x>>k) ^ d) - d);
        tz = z - ((cordic_tab[k] ^ d) - d);
        x = tx; y = ty; z = tz;
    }

    let s: f64 = (y as f64)/(mul as f64);

    return s;

}

fn main() {
    generate_table();

    let frac_pi_2: f64 = std::f64::consts::FRAC_PI_2; //pi/2.0;

    for ii in range(0i, 50) {
        let cur: f64 = ii as f64;
        let theta: f64 = cur/50.0 * frac_pi_2;
        let s: f64 = sin(theta);
            println!("sin({}) ~= {}", theta, s);
    }
}
<commit_msg>explicit type<commit_after>/**
use the taylor series to caculate tan^-1 (x) where |x| <= 1, x >= 0
**/
fn taylor_atan (x: f64) -> f64 {
    let mut a: f64 = 0.0;
    let mut s: f64 = 1.0;
    let mut xpow: f64;

    // by definition
    if x == 0.0 {
        return 0.0;
    }

    // this is well known, and the taylor series we are using explictly assumes |x| < 1
    if x == 1.0 {
        return std::f64::consts::FRAC_PI_4;
    }

    for ii in range(1i, 60) {
        if ii % 2 == 0 {
            continue;
        }
        xpow = 1.0;
        for _ in range(0i, ii) {
            xpow *= x;
        }
        a += s * xpow / (ii as f64);
        s = -1.0*s;
    }

    return a;
}

fn generate_table () {

    let pi: f64 = std::f64::consts::PI;
    let k1: f64 = 0.6072529350088812561694; // 1/k
    let num_bits: uint = 32;
    let mul: uint = 1<<(num_bits-2);

    println!("Cordic sin in rust");
    println!("num bits {}", num_bits);
    println!("mul {}", mul);
    println!("1<<(num_bits-2) {}", ((1i << (num_bits-2)) as f64));
    println!("pi is {}", pi);
    println!("k1 is {}", k1);

    println!("let cordic_tab = [");

    let shift: f64 = 2.0;
    for ii in range(0, num_bits) {
        let ipow: f64 = 1f64/shift.powi(ii as i32);
        let cur: f64 = taylor_atan(ipow) * (mul as f64);

        if ii % 4 == 0 && ii > 0 {
            println!("");
        }
        if ii == 0 {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        } else {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        }
    }

    println!("];");
}

fn sin(theta: f64) -> f64 {

    let num_bits: uint = 32;

    let k1: f64 = 0.6072529350088812561694; // 1/k
    let mul: f64 = (1i << (num_bits-2)) as f64;
    let cordic_k1: f64 = k1 * mul;
    let mut x: i64 = cordic_k1.floor() as i64; //0x26DD3B6A;
    let mut y: i64 = 0;
    let mut z: i64 = (mul * theta).floor() as i64;
    let mut tx: i64;
    let mut ty: i64;
    let mut tz: i64;

    let mut d: i64;

    // this table is generated by generate_table()
    let cordic_tab = [
        0x3243f6a8, 0x1dac6705, 0xfadbafc, 0x7f56ea6,
        0x3feab76, 0x1ffd55b, 0xfffaaa, 0x7fff55,
        0x3fffea, 0x1ffffd, 0xfffff, 0x7ffff,
        0x3ffff, 0x1ffff, 0xffff, 0x7fff,
        0x3fff, 0x1fff, 0xfff, 0x7ff,
        0x3ff, 0x1ff, 0xff, 0x7f,
        0x3f, 0x1f, 0xf, 0x8,
        0x4, 0x2, 0x1, 0x0, ];

    for k in range(0, num_bits) {
        if z >= 0 {
            d = 0;
        } else {
            d = -1;
        }

        tx = x - (((y>>k) ^ d) - d);
        ty = y + (((x>>k) ^ d) - d);
        tz = z - ((cordic_tab[k] ^ d) - d);
        x = tx; y = ty; z = tz;
    }

    let s: f64 = (y as f64)/(mul as f64);

    return s;

}

fn main() {
    generate_table();

    let frac_pi_2: f64 = std::f64::consts::FRAC_PI_2; //pi/2.0;

    for ii in range(0i, 50) {
        let cur: f64 = ii as f64;
        let theta: f64 = cur/50.0 * frac_pi_2;
        let s: f64 = sin(theta);
            println!("sin({}) ~= {}", theta, s);
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate ratel;

use test::Bencher;

static SOURCE: &'static str = r#"

'use strict';

/**
 * Extract red color out of a color integer:
 *
 * 0x00DEAD -> 0x00
 *
 * @param  {Number} color
 * @return {Number}
 */
function red( color )
{
    let foo = 3.14;
    return color >> 16;
}

/**
 * Extract green out of a color integer:
 *
 * 0x00DEAD -> 0xDE
 *
 * @param  {Number} color
 * @return {Number}
 */
function green( color )
{
    return ( color >> 8 ) & 0xFF;
}

/**
 * Extract blue color out of a color integer:
 *
 * 0x00DEAD -> 0xAD
 *
 * @param  {Number} color
 * @return {Number}
 */
function blue( color )
{
    return color & 0xFF;
}

/**
 * Converts an integer containing a color such as 0x00DEAD to a hex
 * string, such as '#00DEAD';
 *
 * @param  {Number} int
 * @return {String}
 */
function intToHex( int )
{
    const mask = '#000000';

    const hex = int.toString( 16 );

    return mask.substring( 0, 7 - hex.length ) + hex;
}

/**
 * Converts a hex string containing a color such as '#00DEAD' to
 * an integer, such as 0x00DEAD;
 *
 * @param  {Number} num
 * @return {String}
 */
function hexToInt( hex )
{
    return parseInt( hex.substring( 1 ), 16 );
}

module.exports = {
    red,
    green,
    blue,
    intToHex,
    hexToInt,
};

"#;

#[bench]
fn parse_to_ast(b: &mut Bencher) {
    b.bytes = SOURCE.len() as u64;

    b.iter(|| {
        let _module = ratel::parser::parse(SOURCE).expect("Must parse");
    });
}

#[bench]
fn tokenize(b: &mut Bencher) {
    b.bytes = SOURCE.len() as u64;

    b.iter(|| {
        let mut lexer = ratel::lexer::Lexer::new(SOURCE);

        while lexer.get_token() != ratel::lexer::Token::EndOfProgram {

        }
    });
}

// #[bench]
// fn parse_to_ast_and_transform_es5(b: &mut Bencher) {
//     b.bytes = SOURCE.len() as u64;

//     b.iter(|| {
//         let mut ast = ratel::parser::parse(SOURCE.to_owned()).expect("Must parse");

//         let settings = ratel::transformer::Settings::target_es5();

//         ratel::transformer::transform(&mut ast, settings);

//         ast
//     });
// }

// #[bench]
// fn codegen_from_ast(b: &mut Bencher) {
//     let mut ast = ratel::parser::parse(SOURCE.to_owned()).expect("Must parse");

//     let settings = ratel::transformer::Settings::target_es5();

//     ratel::transformer::transform(&mut ast, settings);

//     let output = ratel::codegen::generate_code(&ast, true);

//     b.bytes = output.len() as u64;

//     b.iter(|| {
//         ratel::codegen::generate_code(&ast, true)
//     });
// }
<commit_msg>Restored codegen benchmark<commit_after>#![feature(test)]

extern crate test;
extern crate ratel;

use test::Bencher;

static SOURCE: &'static str = r#"

'use strict';

/**
 * Extract red color out of a color integer:
 *
 * 0x00DEAD -> 0x00
 *
 * @param  {Number} color
 * @return {Number}
 */
function red( color )
{
    let foo = 3.14;
    return color >> 16;
}

/**
 * Extract green out of a color integer:
 *
 * 0x00DEAD -> 0xDE
 *
 * @param  {Number} color
 * @return {Number}
 */
function green( color )
{
    return ( color >> 8 ) & 0xFF;
}

/**
 * Extract blue color out of a color integer:
 *
 * 0x00DEAD -> 0xAD
 *
 * @param  {Number} color
 * @return {Number}
 */
function blue( color )
{
    return color & 0xFF;
}

/**
 * Converts an integer containing a color such as 0x00DEAD to a hex
 * string, such as '#00DEAD';
 *
 * @param  {Number} int
 * @return {String}
 */
function intToHex( int )
{
    const mask = '#000000';

    const hex = int.toString( 16 );

    return mask.substring( 0, 7 - hex.length ) + hex;
}

/**
 * Converts a hex string containing a color such as '#00DEAD' to
 * an integer, such as 0x00DEAD;
 *
 * @param  {Number} num
 * @return {String}
 */
function hexToInt( hex )
{
    return parseInt( hex.substring( 1 ), 16 );
}

module.exports = {
    red,
    green,
    blue,
    intToHex,
    hexToInt,
};

"#;

#[bench]
fn parse_to_ast(b: &mut Bencher) {
    b.bytes = SOURCE.len() as u64;

    b.iter(|| {
        let _module = ratel::parser::parse(SOURCE).expect("Must parse");
    });
}

#[bench]
fn tokenize(b: &mut Bencher) {
    b.bytes = SOURCE.len() as u64;

    b.iter(|| {
        let mut lexer = ratel::lexer::Lexer::new(SOURCE);

        while lexer.get_token() != ratel::lexer::Token::EndOfProgram {

        }
    });
}

// #[bench]
// fn parse_to_ast_and_transform_es5(b: &mut Bencher) {
//     b.bytes = SOURCE.len() as u64;

//     b.iter(|| {
//         let mut ast = ratel::parser::parse(SOURCE.to_owned()).expect("Must parse");

//         let settings = ratel::transformer::Settings::target_es5();

//         ratel::transformer::transform(&mut ast, settings);

//         ast
//     });
// }

#[bench]
fn codegen_from_ast(b: &mut Bencher) {
    let module = ratel::parser::parse(SOURCE).expect("Must parse");
    let output = ratel::codegen::codegen(&module, true);

    b.bytes = output.len() as u64;

    b.iter(|| {
        ratel::codegen::codegen(&module, true)
    });
}
<|endoftext|>