<commit_before>#![crate_id = "memcached#0.1"]
#![crate_type = "lib"]
extern crate libc;

use std::ptr;
use std::mem::size_of;
use std::c_str::CString;
use libc::{
  c_char,
  c_uint,
  size_t,
  malloc,
  free,
  c_void
};
use native::{
  memcached_create,
  memcached_set,
  memcached_get,
  memcached_st,
  memcached_return_t,
  memcached_server_add,
};

pub mod native;

pub struct Client {
  cl: *mut memcached_st
}

pub struct Server<'a> {
  host: &'a str,
  port: uint,
}

impl Client {
  pub fn new() -> Client {
    Client{ cl: unsafe { memcached_create(ptr::mut_null()) } }
  }

  pub fn add_server(&self, server: &Server) {
    unsafe { memcached_server_add(self.cl, server.host.to_c_str().unwrap(), server.port as u16) };
  }

  pub fn set(&self, key: &str, value: &str, expire: int) {
    let key_c = key.to_c_str();
    let value_c = value.to_c_str();
    unsafe {
      memcached_set(self.cl, key_c.clone().unwrap(), key_c.len() as u64, value_c.clone().unwrap(), value_c.len() as u64, expire as i64, 0);
    }
  }

  pub fn get(&self, key: &str) -> CString {
    let key_c = key.to_c_str();
    unsafe {
      let value_length = malloc(size_of::<size_t>() as size_t) as *mut size_t;
      let error = malloc(size_of::<memcached_return_t>() as size_t) as *mut memcached_return_t;
      let flags = malloc(size_of::<c_uint>() as size_t) as *mut c_uint;
      let value = memcached_get(self.cl, key_c.clone().unwrap(), key_c.len() as u64, value_length, flags, error);
      let c_str = CString::new(value as *c_char, false);
      free(value_length as *mut c_void);
      free(error as *mut c_void);
      free(flags as *mut c_void);
      c_str
    }
  }
}

#[test]
fn test() {
  let cache = Client::new();
  let server = &Server { host: "127.0.0.1", port: 11211 };
  cache.add_server(server);
  cache.set("hoge", "fuga", 10);
  assert!(cache.get("hoge").as_str().unwrap() == "fuga");
}
<commit_msg>Add Server::new()<commit_after>#![crate_id = "memcached#0.1"]
#![crate_type = "lib"]
extern crate libc;

use std::ptr;
use std::mem::size_of;
use std::c_str::CString;
use libc::{
  c_char,
  c_uint,
  size_t,
  malloc,
  free,
  c_void
};
use native::{
  memcached_create,
  memcached_set,
  memcached_get,
  memcached_st,
  memcached_return_t,
  memcached_server_add,
};

pub mod native;

pub struct Client {
  cl: *mut memcached_st
}

pub struct Server<'a> {
  host: &'a str,
  port: uint,
}

impl<'a> Server<'a> {
  pub fn new<'a>(host: &'a str, port: uint) -> Server<'a> {
    Server { host: host, port: port }
  }
}

impl Client {
  pub fn new() -> Client {
    Client{ cl: unsafe { memcached_create(ptr::mut_null()) } }
  }

  pub fn add_server(&self, server: &Server) {
    unsafe { memcached_server_add(self.cl, server.host.to_c_str().unwrap(), server.port as u16) };
  }

  pub fn set(&self, key: &str, value: &str, expire: int) {
    let key_c = key.to_c_str();
    let value_c = value.to_c_str();
    unsafe {
      memcached_set(self.cl, key_c.clone().unwrap(), key_c.len() as u64, value_c.clone().unwrap(), value_c.len() as u64, expire as i64, 0);
    }
  }

  pub fn get(&self, key: &str) -> CString {
    let key_c = key.to_c_str();
    unsafe {
      let value_length = malloc(size_of::<size_t>() as size_t) as *mut size_t;
      let error = malloc(size_of::<memcached_return_t>() as size_t) as *mut memcached_return_t;
      let flags = malloc(size_of::<c_uint>() as size_t) as *mut c_uint;
      let value = memcached_get(self.cl, key_c.clone().unwrap(), key_c.len() as u64, value_length, flags, error);
      let c_str = CString::new(value as *c_char, false);
      free(value_length as *mut c_void);
      free(error as *mut c_void);
      free(flags as *mut c_void);
      c_str
    }
  }
}

#[test]
fn test() {
  let cache = Client::new();
  let server = Server::new("127.0.0.1", 11211);
  cache.add_server(&server);
  cache.set("hoge", "fuga", 10);
  assert!(cache.get("hoge").as_str().unwrap() == "fuga");
}
<|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/. */

use dom::bindings::trace::JSTraceable;
use js::jsapi::{JSTracer};

use std::cell;
use std::cell::RefCell;
use std::mem;

/// A mutable field in DOM for large sized value.
/// This has a special method to return the pointer of itself
/// for used in layout task.
/// This simply wraps `RefCell<T>` to add the special method.
pub struct DOMRefCell<T> {
    base: RefCell<T>,
}

pub type Ref<'a, T> = cell::Ref<'a, T>;
pub type RefMut<'a, T> = cell::RefMut<'a, T>;

impl<T> DOMRefCell<T> {
    #[inline(always)]
    pub fn new(value: T) -> DOMRefCell<T> {
        DOMRefCell {
            base: RefCell::new(value),
        }
    }

    #[inline(always)]
    pub fn unwrap(self) -> T {
        self.base.unwrap()
    }

    #[inline(always)]
    pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
        self.base.try_borrow()
    }

    #[inline(always)]
    pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
        self.base.borrow()
    }

    #[inline(always)]
    pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
        self.base.try_borrow_mut()
    }

    #[inline(always)]
    pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
        self.base.borrow_mut()
    }

    /// This returns the pointer which refers T in `RefCell<T>` directly.
    pub unsafe fn borrow_for_layout<'a>(&'a self) -> &'a T {
        let val = mem::transmute::<&RefCell<T>, &T>(&self.base);
        val
    }
}

impl<T: JSTraceable> JSTraceable for DOMRefCell<T> {
    fn trace(&self, trc: *mut JSTracer) {
        (*self).base.borrow().trace(trc)
    }
}
<commit_msg>Customize RefCell instead of wrapping it<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/. */

use dom::bindings::trace::JSTraceable;
use js::jsapi::{JSTracer};

use std::cell::{Cell, UnsafeCell};
use std::kinds::marker;

/// A mutable field in the DOM.
///
/// This extends the API of `core::cell::RefCell` to allow unsafe access in
/// certain situations.
pub struct DOMRefCell<T> {
    value: UnsafeCell<T>,
    borrow: Cell<BorrowFlag>,
    nocopy: marker::NoCopy,
    nosync: marker::NoSync,
}

// Functionality specific to Servo's `DOMRefCell` type
// ===================================================

impl<T> DOMRefCell<T> {
    /// Return a reference to the contents.
    ///
    /// For use in the layout task only.
    pub unsafe fn borrow_for_layout<'a>(&'a self) -> &'a T {
        &*self.value.get()
    }
}

impl<T: JSTraceable> JSTraceable for DOMRefCell<T> {
    fn trace(&self, trc: *mut JSTracer) {
        (*self).borrow().trace(trc)
    }
}

// Functionality duplicated with `core::cell::RefCell`
// ===================================================
//
// This can shrink once rust-lang/rust#18131 is fixed.

// Values [1, MAX-1] represent the number of `Ref` active
// (will not outgrow its range since `uint` is the size of the address space)
type BorrowFlag = uint;
static UNUSED: BorrowFlag = 0;
static WRITING: BorrowFlag = -1;

impl<T> DOMRefCell<T> {
    pub fn new(value: T) -> DOMRefCell<T> {
        DOMRefCell {
            value: UnsafeCell::new(value),
            borrow: Cell::new(UNUSED),
            nocopy: marker::NoCopy,
            nosync: marker::NoSync,
        }
    }

    pub fn unwrap(self) -> T {
        debug_assert!(self.borrow.get() == UNUSED);
        unsafe{self.value.unwrap()}
    }

    pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
        match self.borrow.get() {
            WRITING => None,
            borrow => {
                self.borrow.set(borrow + 1);
                Some(Ref { _parent: self })
            }
        }
    }

    pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
        match self.try_borrow() {
            Some(ptr) => ptr,
            None => fail!("DOMRefCell<T> already mutably borrowed")
        }
    }

    pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
        match self.borrow.get() {
            UNUSED => {
                self.borrow.set(WRITING);
                Some(RefMut { _parent: self })
            },
            _ => None
        }
    }

    pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
        match self.try_borrow_mut() {
            Some(ptr) => ptr,
            None => fail!("DOMRefCell<T> already borrowed")
        }
    }
}

pub struct Ref<'b, T:'b> {
    _parent: &'b DOMRefCell<T>
}

#[unsafe_destructor]
impl<'b, T> Drop for Ref<'b, T> {
    fn drop(&mut self) {
        let borrow = self._parent.borrow.get();
        debug_assert!(borrow != WRITING && borrow != UNUSED);
        self._parent.borrow.set(borrow - 1);
    }
}

impl<'b, T> Deref<T> for Ref<'b, T> {
    #[inline]
    fn deref<'a>(&'a self) -> &'a T {
        unsafe { &*self._parent.value.get() }
    }
}

pub struct RefMut<'b, T:'b> {
    _parent: &'b DOMRefCell<T>
}

#[unsafe_destructor]
impl<'b, T> Drop for RefMut<'b, T> {
    fn drop(&mut self) {
        let borrow = self._parent.borrow.get();
        debug_assert!(borrow == WRITING);
        self._parent.borrow.set(UNUSED);
    }
}

impl<'b, T> Deref<T> for RefMut<'b, T> {
    #[inline]
    fn deref<'a>(&'a self) -> &'a T {
        unsafe { &*self._parent.value.get() }
    }
}

impl<'b, T> DerefMut<T> for RefMut<'b, T> {
    #[inline]
    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { &mut *self._parent.value.get() }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// 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.

//! Encapsulate running the `hab-sup` executable for tests.

use std::collections::HashSet;
use std::env;
use std::net::TcpListener;
use std::path::{Path, PathBuf};
use std::process::{Child, Command, Stdio};
use std::string::ToString;
use std::sync::Mutex;
use std::thread;
use std::time::Duration;

use hcore::url::DEPOT_URL_ENVVAR;
use rand;
use rand::distributions::{IndependentSample, Range};

use super::test_butterfly;

lazy_static! {
    /// Keep track of all TCP ports currently being used by TestSup
    /// instances. Allows us to run tests in parallel without fear of
    /// port conflicts between them.
    static ref CLAIMED_PORTS: Mutex<HashSet<u16>> = {
        Mutex::new(HashSet::new())
    };
}

pub struct TestSup {
    pub hab_root: PathBuf,
    pub origin_name: String,
    pub package_name: String,
    pub service_group: String,
    pub http_port: u16,
    pub butterfly_port: u16,
    pub butterfly_client: test_butterfly::Client,
    pub cmd: Command,
    pub process: Option<Child>,
}

/// Return a free TCP port number. We test to see that the system has
/// not already bound the port, while also tracking which ports are
/// being used by other test supervisors that may be running alongside
/// this one.
///
/// Once you receive a port number from this function, you can be
/// reasonably sure that you're the only one that will be using
/// it. There could be a race condition if the machine the tests are
/// running on just happens to claim the same port number for
/// something between the time we check and the time the TestSup
/// claims it. If that happens to you, you should probably buy lottery
/// tickets, though.
///
/// This function will recursively call itself with a decremented
/// value for `tries` if it happens to pick a port that's already in
/// use. Once all tries are used up, it panics! Yay!
fn unclaimed_port(tries: u16) -> u16 {
    if tries == 0 {
        panic!("Couldn't find an unclaimed port for the test supervisor!")
    }
    let p = random_port();
    match TcpListener::bind(format!("127.0.0.1:{}", p)) {
        Ok(_listener) => {
            // The system hasn't bound it. Now we make sure none of
            // our other tests have bound it.
            let mut ports = CLAIMED_PORTS.lock().unwrap();
            if ports.contains(&p) {
                // Oops, another test is using it, try again
                thread::sleep(Duration::from_millis(500));
                unclaimed_port(tries - 1)
            } else {
                // Nobody was using it. Return the port; the TcpListener
                // that is currently bound to the port will be dropped,
                // thus freeing the port for our use.
                ports.insert(p);
                p
            }
        }
        Err(_) => {
            // port already in use, try again
            unclaimed_port(tries - 1)
        }
    }
}

/// Return a random unprivileged, unregistered TCP port number.
fn random_port() -> u16 {
    // IANA port registrations go to 49151
    let between = Range::new(49152, ::std::u16::MAX);
    let mut rng = rand::thread_rng();
    between.ind_sample(&mut rng)
}

/// Find an executable relative to the current integration testing
/// executable.
///
/// Thus if the current executable is
///
///    /home/me/habitat/target/debug/deps/compilation-ccaf2f45c24e3840
///
/// and we look for `hab-sup`, we'll find it at
///
///    /home/me/habitat/target/debug/hab-sup
///
fn find_exe<B>(binary_name: B) -> PathBuf
where
    B: AsRef<Path>,
{
    let exe_root = env::current_exe()
        .unwrap()
        .parent()  // deps
        .unwrap()
        .parent()  // debug
        .unwrap()
        .to_path_buf();
    let bin = exe_root.join(binary_name.as_ref());
    assert!(
        bin.exists(),
        format!(
            "Expected to find a {:?} executable at {:?}",
            binary_name.as_ref(),
            bin
        )
    );
    bin
}

/// Return whether or not the tests are being run with the `--nocapture` flag meaning we want to
/// see more output.
fn nocapture() -> bool {
    env::args().any(|arg| arg == "--nocapture")
}

impl TestSup {
    /// Create a new `TestSup` that will listen on randomly-selected
    /// ports for both gossip and HTTP requests so tests run in
    /// parallel don't step on each other.
    ///
    /// See also `new`.
    pub fn new_with_random_ports<R, O, P, S>(
        fs_root: R,
        origin: O,
        pkg_name: P,
        service_group: S,
    ) -> TestSup
    where
        R: AsRef<Path>,
        O: ToString,
        P: ToString,
        S: ToString,
    {
        // We'll give 10 tries to find a free port number
        let http_port = unclaimed_port(10);
        let butterfly_port = unclaimed_port(10);

        TestSup::new(
            fs_root,
            origin,
            pkg_name,
            service_group,
            http_port,
            butterfly_port,
        )
    }

    /// Bundle up a Habitat supervisor process along with an
    /// associated Butterfly client for injecting new configuration
    /// values. The supervisor executable is the one that has been
    /// compiled for the current `cargo test` invocation.
    ///
    /// The supervisor is configured to run a single package for a
    /// test. This package is assumed to have already been installed
    /// relative to `fs_root` (i.e., the `FS_ROOT` environment
    /// variable, which in our tests will be a randomly-named
    /// temporary directory that this supervisor will view as `/`.).
    ///
    /// A Butterfly client is also created for interacting with this
    /// supervisor and package. It is properly configured according to
    /// the value provided for `butterfly_port`. To use it, see the
    /// `apply_config` function.
    ///
    /// (No HTTP interaction with the supervisor is currently called
    /// for, so we don't have a HTTP client.)
    pub fn new<R, O, P, S>(
        fs_root: R,
        origin: O,
        pkg_name: P,
        service_group: S,
        http_port: u16,
        butterfly_port: u16,
    ) -> TestSup
    where
        R: AsRef<Path>,
        O: ToString,
        P: ToString,
        S: ToString,
    {
        let sup_exe = find_exe("hab-sup");
        let launcher_exe = find_exe("hab-launch");

        let mut cmd = Command::new(&launcher_exe);
        let listen_host = "0.0.0.0";

        let origin = origin.to_string();
        let pkg_name = pkg_name.to_string();
        let service_group = service_group.to_string();

        cmd.env(
            "TESTING_FS_ROOT",
            fs_root.as_ref().to_string_lossy().as_ref(),
        ).env("HAB_SUP_BINARY", &sup_exe)
            .env(DEPOT_URL_ENVVAR, "http://hab.sup.test/v1/depot")
            .arg("start")
            .arg("--listen-gossip")
            .arg(format!("{}:{}", listen_host, butterfly_port))
            .arg("--listen-http")
            .arg(format!("{}:{}", listen_host, http_port))
            .arg(format!("{}/{}", origin, pkg_name))
            .stdin(Stdio::null());
        if !nocapture() {
            cmd.stdout(Stdio::null());
            cmd.stderr(Stdio::null());
        }

        let bc = test_butterfly::Client::new(&pkg_name, &service_group, butterfly_port);

        TestSup {
            hab_root: fs_root.as_ref().to_path_buf(),
            origin_name: origin,
            package_name: pkg_name,
            service_group: service_group.to_string(),
            http_port: http_port,
            butterfly_port: butterfly_port,
            butterfly_client: bc,
            cmd: cmd,
            process: None,
        }
    }

    /// Spawn a process actually running the supervisor.
    pub fn start(&mut self) {
        let child = self.cmd.spawn().expect("Couldn't start the supervisor!");
        self.process = Some(child);
    }

    /// The equivalent of performing `hab apply` with the given
    /// configuration.
    pub fn apply_config<T>(&mut self, toml_config: T)
    where
        T: ToString,
    {
        self.butterfly_client.apply(toml_config.to_string())
    }
}

// We kill the supervisor so you don't have to! We also free up the
// ports used by this supervisor so other tests can use them.
impl Drop for TestSup {
    fn drop(&mut self) {
        let mut ports = CLAIMED_PORTS.lock().unwrap();
        ports.remove(&self.http_port);
        ports.remove(&self.butterfly_port);
        self.process
            .take()
            .expect("No process to kill!")
            .kill()
            .expect("Tried to kill supervisor!");
    }
}
<commit_msg>[sup/test] Add better nocapture support in tests.<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// 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.

//! Encapsulate running the `hab-sup` executable for tests.

use std::collections::HashSet;
use std::env;
use std::net::TcpListener;
use std::path::{Path, PathBuf};
use std::process::{Child, Command, Stdio};
use std::string::ToString;
use std::sync::Mutex;
use std::thread;
use std::time::Duration;

use hcore::url::DEPOT_URL_ENVVAR;
use rand;
use rand::distributions::{IndependentSample, Range};

use super::test_butterfly;

lazy_static! {
    /// Keep track of all TCP ports currently being used by TestSup
    /// instances. Allows us to run tests in parallel without fear of
    /// port conflicts between them.
    static ref CLAIMED_PORTS: Mutex<HashSet<u16>> = {
        Mutex::new(HashSet::new())
    };
}

pub struct TestSup {
    pub hab_root: PathBuf,
    pub origin_name: String,
    pub package_name: String,
    pub service_group: String,
    pub http_port: u16,
    pub butterfly_port: u16,
    pub butterfly_client: test_butterfly::Client,
    pub cmd: Command,
    pub process: Option<Child>,
}

/// Return a free TCP port number. We test to see that the system has
/// not already bound the port, while also tracking which ports are
/// being used by other test supervisors that may be running alongside
/// this one.
///
/// Once you receive a port number from this function, you can be
/// reasonably sure that you're the only one that will be using
/// it. There could be a race condition if the machine the tests are
/// running on just happens to claim the same port number for
/// something between the time we check and the time the TestSup
/// claims it. If that happens to you, you should probably buy lottery
/// tickets, though.
///
/// This function will recursively call itself with a decremented
/// value for `tries` if it happens to pick a port that's already in
/// use. Once all tries are used up, it panics! Yay!
fn unclaimed_port(tries: u16) -> u16 {
    if tries == 0 {
        panic!("Couldn't find an unclaimed port for the test supervisor!")
    }
    let p = random_port();
    match TcpListener::bind(format!("127.0.0.1:{}", p)) {
        Ok(_listener) => {
            // The system hasn't bound it. Now we make sure none of
            // our other tests have bound it.
            let mut ports = CLAIMED_PORTS.lock().unwrap();
            if ports.contains(&p) {
                // Oops, another test is using it, try again
                thread::sleep(Duration::from_millis(500));
                unclaimed_port(tries - 1)
            } else {
                // Nobody was using it. Return the port; the TcpListener
                // that is currently bound to the port will be dropped,
                // thus freeing the port for our use.
                ports.insert(p);
                p
            }
        }
        Err(_) => {
            // port already in use, try again
            unclaimed_port(tries - 1)
        }
    }
}

/// Return a random unprivileged, unregistered TCP port number.
fn random_port() -> u16 {
    // IANA port registrations go to 49151
    let between = Range::new(49152, ::std::u16::MAX);
    let mut rng = rand::thread_rng();
    between.ind_sample(&mut rng)
}

/// Find an executable relative to the current integration testing
/// executable.
///
/// Thus if the current executable is
///
///    /home/me/habitat/target/debug/deps/compilation-ccaf2f45c24e3840
///
/// and we look for `hab-sup`, we'll find it at
///
///    /home/me/habitat/target/debug/hab-sup
///
fn find_exe<B>(binary_name: B) -> PathBuf
where
    B: AsRef<Path>,
{
    let exe_root = env::current_exe()
        .unwrap()
        .parent()  // deps
        .unwrap()
        .parent()  // debug
        .unwrap()
        .to_path_buf();
    let bin = exe_root.join(binary_name.as_ref());
    assert!(
        bin.exists(),
        format!(
            "Expected to find a {:?} executable at {:?}",
            binary_name.as_ref(),
            bin
        )
    );
    bin
}

/// Return whether or not the tests are being run with the `--nocapture` flag meaning we want to
/// see more output.
fn nocapture_set() -> bool {
    if env::args().any(|arg| arg == "--nocapture") {
        return true;
    } else {
        match env::var("RUST_TEST_NOCAPTURE") {
            Ok(val) => &val != "0",
            Err(_) => false,
        }
    }
}

impl TestSup {
    /// Create a new `TestSup` that will listen on randomly-selected
    /// ports for both gossip and HTTP requests so tests run in
    /// parallel don't step on each other.
    ///
    /// See also `new`.
    pub fn new_with_random_ports<R, O, P, S>(
        fs_root: R,
        origin: O,
        pkg_name: P,
        service_group: S,
    ) -> TestSup
    where
        R: AsRef<Path>,
        O: ToString,
        P: ToString,
        S: ToString,
    {
        // We'll give 10 tries to find a free port number
        let http_port = unclaimed_port(10);
        let butterfly_port = unclaimed_port(10);

        TestSup::new(
            fs_root,
            origin,
            pkg_name,
            service_group,
            http_port,
            butterfly_port,
        )
    }

    /// Bundle up a Habitat supervisor process along with an
    /// associated Butterfly client for injecting new configuration
    /// values. The supervisor executable is the one that has been
    /// compiled for the current `cargo test` invocation.
    ///
    /// The supervisor is configured to run a single package for a
    /// test. This package is assumed to have already been installed
    /// relative to `fs_root` (i.e., the `FS_ROOT` environment
    /// variable, which in our tests will be a randomly-named
    /// temporary directory that this supervisor will view as `/`.).
    ///
    /// A Butterfly client is also created for interacting with this
    /// supervisor and package. It is properly configured according to
    /// the value provided for `butterfly_port`. To use it, see the
    /// `apply_config` function.
    ///
    /// (No HTTP interaction with the supervisor is currently called
    /// for, so we don't have a HTTP client.)
    pub fn new<R, O, P, S>(
        fs_root: R,
        origin: O,
        pkg_name: P,
        service_group: S,
        http_port: u16,
        butterfly_port: u16,
    ) -> TestSup
    where
        R: AsRef<Path>,
        O: ToString,
        P: ToString,
        S: ToString,
    {
        let sup_exe = find_exe("hab-sup");
        let launcher_exe = find_exe("hab-launch");

        let mut cmd = Command::new(&launcher_exe);
        let listen_host = "0.0.0.0";

        let origin = origin.to_string();
        let pkg_name = pkg_name.to_string();
        let service_group = service_group.to_string();

        cmd.env(
            "TESTING_FS_ROOT",
            fs_root.as_ref().to_string_lossy().as_ref(),
        ).env("HAB_SUP_BINARY", &sup_exe)
            .env(DEPOT_URL_ENVVAR, "http://hab.sup.test/v1/depot")
            .arg("start")
            .arg("--listen-gossip")
            .arg(format!("{}:{}", listen_host, butterfly_port))
            .arg("--listen-http")
            .arg(format!("{}:{}", listen_host, http_port))
            .arg(format!("{}/{}", origin, pkg_name))
            .stdin(Stdio::null());
        if !nocapture_set() {
            cmd.stdout(Stdio::null());
            cmd.stderr(Stdio::null());
        }

        let bc = test_butterfly::Client::new(&pkg_name, &service_group, butterfly_port);

        TestSup {
            hab_root: fs_root.as_ref().to_path_buf(),
            origin_name: origin,
            package_name: pkg_name,
            service_group: service_group.to_string(),
            http_port: http_port,
            butterfly_port: butterfly_port,
            butterfly_client: bc,
            cmd: cmd,
            process: None,
        }
    }

    /// Spawn a process actually running the supervisor.
    pub fn start(&mut self) {
        let child = self.cmd.spawn().expect("Couldn't start the supervisor!");
        self.process = Some(child);
    }

    /// The equivalent of performing `hab apply` with the given
    /// configuration.
    pub fn apply_config<T>(&mut self, toml_config: T)
    where
        T: ToString,
    {
        self.butterfly_client.apply(toml_config.to_string())
    }
}

// We kill the supervisor so you don't have to! We also free up the
// ports used by this supervisor so other tests can use them.
impl Drop for TestSup {
    fn drop(&mut self) {
        let mut ports = CLAIMED_PORTS.lock().unwrap();
        ports.remove(&self.http_port);
        ports.remove(&self.butterfly_port);
        self.process
            .take()
            .expect("No process to kill!")
            .kill()
            .expect("Tried to kill supervisor!");
    }
}
<|endoftext|>


<commit_before>use nalgebra::{Point2, Point3, Scalar};
use num::{Float, Unsigned};
use std::ops::Range;

use super::generate::{Conjoint, Indexed, Textured};
use super::primitive::{MapPrimitiveInto, Quad};

pub trait Cube: Iterator + Sized {
    type Point;

    fn point(&self, index: usize) -> Self::Point;

    fn face(&self, index: usize) -> Quad<Self::Point> {
        self.indexed_face(index).map_points_into(|index| self.point(index))
    }

    fn indexed_face(&self, index: usize) -> Quad<usize> {
        match index {
            0 => Quad::new(5, 7, 3, 1),
            1 => Quad::new(6, 7, 5, 4),
            2 => Quad::new(3, 7, 6, 2),
            3 => Quad::new(0, 1, 3, 2),
            4 => Quad::new(4, 5, 1, 0),
            5 => Quad::new(0, 2, 6, 4),
            _ => panic!(),
        }
    }

    fn textured_face(&self, _: usize) -> Quad<Point2<f32>> {
        Quad::new(Point2::new(0.0, 1.0),
                  Point2::new(1.0, 1.0),
                  Point2::new(1.0, 0.0),
                  Point2::new(0.0, 0.0))
    }
}

impl<T, C> Conjoint<T> for C
    where C: Cube<Point = T>
{
    fn conjoint_point(&self, index: usize) -> T {
        self.point(index)
    }

    fn conjoint_point_count(&self) -> usize {
        8
    }
}

impl<C> Indexed<Quad<usize>> for C
    where C: Cube
{
    fn indexed_polygon(&self, index: usize) -> Quad<usize> {
        self.indexed_face(index)
    }

    fn indexed_polygon_count(&self) -> usize {
        6
    }
}

impl<C> Textured<Quad<Point2<f32>>> for C
    where C: Cube
{
    fn textured_polygon(&self, index: usize) -> Quad<Point2<f32>> {
        self.textured_face(index)
    }

    fn textured_polygon_count(&self) -> usize {
        6
    }
}

#[derive(Clone)]
pub struct RCube<T>
    where T: Float + Scalar
{
    faces: Range<usize>,
    low: T,
    high: T,
}

impl<T> RCube<T>
    where T: Float + Scalar
{
    fn new(low: T, high: T) -> Self {
        RCube {
            faces: 0..6,
            low: low,
            high: high,
        }
    }

    pub fn with_unit_radius() -> Self {
        RCube::new(-T::one(), T::one())
    }

    pub fn with_unit_width() -> Self {
        let half = T::one() / (T::one() + T::one());
        RCube::new(-half, half)
    }
}

impl<T> Cube for RCube<T>
    where T: Float + Scalar
{
    type Point = Point3<T>;

    fn point(&self, index: usize) -> Self::Point {
        point(index, self.low, self.high)
    }
}

impl<T> Iterator for RCube<T>
    where T: Float + Scalar
{
    type Item = Quad<<Self as Cube>::Point>;

    fn next(&mut self) -> Option<Self::Item> {
        self.faces.next().map(|index| self.face(index))
    }
}

#[derive(Clone)]
pub struct NCube<T>
    where T: Unsigned + Scalar
{
    faces: Range<usize>,
    low: T,
    high: T,
}

impl<T> NCube<T>
    where T: Unsigned + Scalar
{
    fn new(low: T, high: T) -> Self {
        NCube {
            faces: 0..6,
            low: low,
            high: high,
        }
    }

    pub fn with_unit_radius() -> Self {
        NCube::new(T::zero(), T::one() + T::one())
    }

    pub fn with_unit_width() -> Self {
        NCube::new(T::zero(), T::one())
    }
}

impl<T> Cube for NCube<T>
    where T: Unsigned + Scalar
{
    type Point = Point3<T>;

    fn point(&self, index: usize) -> Self::Point {
        point(index, self.low, self.high)
    }
}

impl<T> Iterator for NCube<T>
    where T: Unsigned + Scalar
{
    type Item = Quad<<Self as Cube>::Point>;

    fn next(&mut self) -> Option<Self::Item> {
        self.faces.next().map(|index| self.face(index))
    }
}

fn point<T>(index: usize, low: T, high: T) -> Point3<T>
    where T: Scalar
{
    let x = if index & 0b100 == 0b100 { high } else { low };
    let y = if index & 0b010 == 0b010 { high } else { low };
    let z = if index & 0b001 == 0b001 { high } else { low };
    Point3::new(x, y, z)
}
<commit_msg>Align texture coordinate generation for cubes.<commit_after>use nalgebra::{Point2, Point3, Scalar};
use num::{Float, Unsigned};
use std::ops::Range;

use super::generate::{Conjoint, Indexed, Textured};
use super::primitive::{MapPrimitiveInto, Quad};

pub trait Cube: Iterator + Sized {
    type Point;

    fn point(&self, index: usize) -> Self::Point;

    fn face(&self, index: usize) -> Quad<Self::Point> {
        self.indexed_face(index).map_points_into(|index| self.point(index))
    }

    fn indexed_face(&self, index: usize) -> Quad<usize> {
        match index {
            0 => Quad::new(5, 7, 3, 1), // front
            1 => Quad::new(6, 7, 5, 4), // right
            2 => Quad::new(3, 7, 6, 2), // top
            3 => Quad::new(0, 1, 3, 2), // left
            4 => Quad::new(4, 5, 1, 0), // bottom
            5 => Quad::new(0, 2, 6, 4), // back
            _ => panic!(),
        }
    }

    fn textured_face(&self, index: usize) -> Quad<Point2<f32>> {
        let uu = Point2::new(1.0, 1.0);
        let ul = Point2::new(1.0, 0.0);
        let ll = Point2::new(0.0, 0.0);
        let lu = Point2::new(0.0, 1.0);
        match index {
            0 => Quad::new(uu, ul, ll, lu), // front
            1 => Quad::new(ul, ll, lu, uu), // right
            2 => Quad::new(lu, uu, ul, ll), // top
            3 => Quad::new(lu, uu, ul, ll), // left
            4 => Quad::new(uu, ul, ll, lu), // bottom
            5 => Quad::new(uu, ul, ll, lu), // back
            _ => panic!(),
        }
    }
}

impl<T, C> Conjoint<T> for C
    where C: Cube<Point = T>
{
    fn conjoint_point(&self, index: usize) -> T {
        self.point(index)
    }

    fn conjoint_point_count(&self) -> usize {
        8
    }
}

impl<C> Indexed<Quad<usize>> for C
    where C: Cube
{
    fn indexed_polygon(&self, index: usize) -> Quad<usize> {
        self.indexed_face(index)
    }

    fn indexed_polygon_count(&self) -> usize {
        6
    }
}

impl<C> Textured<Quad<Point2<f32>>> for C
    where C: Cube
{
    fn textured_polygon(&self, index: usize) -> Quad<Point2<f32>> {
        self.textured_face(index)
    }

    fn textured_polygon_count(&self) -> usize {
        6
    }
}

#[derive(Clone)]
pub struct RCube<T>
    where T: Float + Scalar
{
    faces: Range<usize>,
    low: T,
    high: T,
}

impl<T> RCube<T>
    where T: Float + Scalar
{
    fn new(low: T, high: T) -> Self {
        RCube {
            faces: 0..6,
            low: low,
            high: high,
        }
    }

    pub fn with_unit_radius() -> Self {
        RCube::new(-T::one(), T::one())
    }

    pub fn with_unit_width() -> Self {
        let half = T::one() / (T::one() + T::one());
        RCube::new(-half, half)
    }
}

impl<T> Cube for RCube<T>
    where T: Float + Scalar
{
    type Point = Point3<T>;

    fn point(&self, index: usize) -> Self::Point {
        point(index, self.low, self.high)
    }
}

impl<T> Iterator for RCube<T>
    where T: Float + Scalar
{
    type Item = Quad<<Self as Cube>::Point>;

    fn next(&mut self) -> Option<Self::Item> {
        self.faces.next().map(|index| self.face(index))
    }
}

#[derive(Clone)]
pub struct NCube<T>
    where T: Unsigned + Scalar
{
    faces: Range<usize>,
    low: T,
    high: T,
}

impl<T> NCube<T>
    where T: Unsigned + Scalar
{
    fn new(low: T, high: T) -> Self {
        NCube {
            faces: 0..6,
            low: low,
            high: high,
        }
    }

    pub fn with_unit_radius() -> Self {
        NCube::new(T::zero(), T::one() + T::one())
    }

    pub fn with_unit_width() -> Self {
        NCube::new(T::zero(), T::one())
    }
}

impl<T> Cube for NCube<T>
    where T: Unsigned + Scalar
{
    type Point = Point3<T>;

    fn point(&self, index: usize) -> Self::Point {
        point(index, self.low, self.high)
    }
}

impl<T> Iterator for NCube<T>
    where T: Unsigned + Scalar
{
    type Item = Quad<<Self as Cube>::Point>;

    fn next(&mut self) -> Option<Self::Item> {
        self.faces.next().map(|index| self.face(index))
    }
}

fn point<T>(index: usize, low: T, high: T) -> Point3<T>
    where T: Scalar
{
    let x = if index & 0b100 == 0b100 { high } else { low };
    let y = if index & 0b010 == 0b010 { high } else { low };
    let z = if index & 0b001 == 0b001 { high } else { low };
    Point3::new(x, y, z)
}
<|endoftext|>


<commit_before>use std::iter::Rev;
use core::slice::Iter;
use std::collections::hash_map::{HashMap, Entries, Entry};
use std::collections::HashSet;

use util::{OptionBorrowExt, IntoOwned, IteratorClonedPairwiseExt};

pub const NS_XMLNS_PREFIX: &'static str = "xmlns";
pub const NS_XMLNS_URI: &'static str    = "http://www.w3.org/2000/xmlns/";
pub const NS_XML_PREFIX: &'static str   = "xml";
pub const NS_XML_URI: &'static str      = "http://www.w3.org/XML/1998/namespace";
pub const NS_EMPTY_URI: &'static str    = "";

/// Denotes something which contains namespace URI mappings.
///
/// A URI mapping is a pair of type `(Option<&str>, &str)`, where the first item
/// is a namespace prefix (`None` meaning default prefix) and the second item
/// is a URI mapped to this prefix.
pub trait NamespaceIterable<'a, I: Iterator<(Option<&'a str>, &'a str)>> {
    fn uri_mappings(&'a self) -> I;
}

/// Namespace is a map from prefixes to namespace URIs.
///
/// `None` prefix means no prefix (i.e. default namespace).
#[deriving(PartialEq, Clone)]
pub struct Namespace(pub HashMap<Option<String>, String>);

impl Namespace {
    /// Returns an empty namespace.
    #[inline]
    pub fn empty() -> Namespace { Namespace(HashMap::with_capacity(3)) }

    /// Checks whether this namespace is empty.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    /// Checks whether this namespace is essentially empty, that is, it does not contain
    /// anything but the default mappings.
    pub fn is_essentially_empty(&self) -> bool {
        // a shortcut for a namespace which is definitely not empty
        if self.0.len() > 3 { return false; }

        self.0.iter().all(|(k, v)| match (k.borrow_internals(), v[]) {
            (None,                  NS_EMPTY_URI) => true,
            (Some(NS_XMLNS_PREFIX), NS_XMLNS_URI) => true,
            (Some(NS_XML_PREFIX),   NS_XML_URI)   => true,
            _ => false
        })
    }

    /// Puts a mapping into this namespace.
    ///
    /// This method does not override an already existing mapping.
    ///
    /// Returns a boolean flag indicating whether the map already contained
    /// the given prefix.
    ///
    /// # Parameters
    /// * `prefix` --- namespace prefix (`None` means default namespace);
    /// * `uri`    --- namespace URI.
    ///
    /// # Return value
    /// `true` if `prefix` has been inserted successfully; `false` if the `prefix`
    /// was already present in the namespace.
    pub fn put<S1, S2>(&mut self, prefix: Option<S1>, uri: S2) -> bool
            where S1: IntoOwned<String>, S2: IntoOwned<String> {
        match self.0.entry(prefix.map(|v| v.into_owned())) {
            Entry::Occupied(_) => false,
            Entry::Vacant(ve) => {
                ve.set(uri.into_owned());
                true
            }
        }
    }

    /// Puts a mapping into this namespace forcefully.
    ///
    /// This method, as opposed to `put()`, does replace an already existing mapping.
    ///
    /// Returns previous URI which was assigned to the given prefix, if it is present.
    ///
    /// # Parameters
    /// * `prefix` --- namespace prefix (`None` means default namespace);
    /// * `uri`    --- namespace URI.
    ///
    /// # Return value
    /// `Some(uri)` with `uri` being a previous URI assigned to the `prefix`, or
    /// `None` if such prefix was not present in the namespace before.
    pub fn force_put<S1, S2>(&mut self, prefix: Option<S1>, uri: S2) -> Option<String>
            where S1: IntoOwned<String>, S2: IntoOwned<String> {
        self.0.insert(prefix.map(|v| v.into_owned()), uri.into_owned())
    }

    /// Queries the namespace for the given prefix.
    ///
    /// # Parameters
    /// * `prefix` --- namespace prefix (`None` means default namespace).
    ///
    /// # Return value
    /// Namespace URI corresponding to the given prefix, if it is present.
    pub fn get<'a>(&'a self, prefix: &Option<String>) -> Option<&'a str> {
        self.0.get(prefix).map(|s| &**s)
    }
}

/// An iterator over mappings from prefixes to URIs in a namespace.
///
/// This is a separate structure because `map()` operation on iterators uses an unboxed
/// closure type which can't be named.
pub struct NamespaceMappings<'a> {
    entries: Entries<'a, Option<String>, String>
}

impl<'a> Iterator<(Option<&'a str>, &'a str)> for NamespaceMappings<'a> {
    fn next(&mut self) -> Option<(Option<&'a str>, &'a str)> {
        self.entries.next().map(|(prefix, uri)| {
            (prefix.as_ref().map(|p| p.as_slice()), uri.as_slice())
        })
    }
}

impl<'a> NamespaceIterable<'a, NamespaceMappings<'a>> for Namespace {
    fn uri_mappings(&'a self) -> NamespaceMappings<'a> {
        NamespaceMappings { entries: self.0.iter() }
    }
}

/// Namespace stack is a sequence of namespaces.
///
/// Namespace stack is used to represent cumulative namespace consisting of
/// combined namespaces from nested elements.
#[deriving(Clone, PartialEq)]
pub struct NamespaceStack(pub Vec<Namespace>);

impl NamespaceStack {
    /// Returns an empty namespace stack.
    #[inline]
    pub fn empty() -> NamespaceStack { NamespaceStack(Vec::with_capacity(2)) }

    /// Returns a namespace stack with default items in it.
    ///
    /// Default items are the following:
    ///
    /// * `xml` → `http://www.w3.org/XML/1998/namespace`;
    /// * `xmlns` → `http://www.w3.org/2000/xmlns/`.
    #[inline]
    pub fn default() -> NamespaceStack {
        let mut nst = NamespaceStack::empty();
        nst.push_empty();
        // xml namespace
        nst.put(Some(NS_XML_PREFIX.to_string()), NS_XML_URI.to_string());
        // xmlns namespace
        nst.put(Some(NS_XMLNS_PREFIX.to_string()), NS_XMLNS_URI.to_string());
        // empty namespace
        nst.put(None, NS_EMPTY_URI.to_string());
        nst
    }

    /// Adds an empty namespace to the top of this stack.
    #[inline]
    pub fn push_empty(&mut self) {
        self.0.push(Namespace::empty());
    }

    /// Removes a namespace at the top of the stack.
    ///
    /// Fails if the stack is empty.
    #[inline]
    pub fn pop(&mut self) -> Namespace {
        self.0.pop().unwrap()
    }

    /// Returns a namespace at the top of the stack, leaving the stack intact.
    ///
    /// Fails if the stack is empty.
    #[inline]
    pub fn peek<'a>(&'a mut self) -> &'a mut Namespace {
        self.0.last_mut().unwrap()
    }

    /// Puts a mapping into the topmost namespace in this stack.
    ///
    /// This method does not override a mapping in the topmost namespace if it is
    /// already present, however, it does not depend on other namespaces in the stack,
    /// so it is possible to put a mapping which is present in lower namespaces.
    ///
    /// Returns a boolean flag indicating whether the topmost namespace
    /// already contained the given prefix.
    ///
    /// # Parameters
    /// * `prefix` --- namespace prefix (`None` means default namespace);
    /// * `uri`    --- namespace URI.
    ///
    /// # Return value
    /// `true` if `prefix` has been inserted successfully; `false` if the `prefix`
    /// was already present in the namespace.
    #[inline]
    pub fn put(&mut self, prefix: Option<String>, uri: String) -> bool {
        self.0.last_mut().unwrap().put(prefix, uri)
    }

    /// Performs a search for the given prefix in the whole stack.
    ///
    /// This method walks the stack from top to bottom, querying each namespace
    /// in order for the given prefix. If none of the namespaces contains the prefix,
    /// `None` is returned.
    ///
    /// # Parameters
    /// * `prefix` --- namespace prefix (`None` means default namespace)
    #[inline]
    pub fn get<'a>(&'a self, prefix: &Option<String>) -> Option<&'a str> {
        for ns in self.0.iter().rev() {
            match ns.get(prefix) {
                None => {},
                r => return r,
            }
        }
        None
    }

    /// Combines this stack of namespaces into a single namespace.
    ///
    /// Namespaces are combined in left-to-right order, that is, rightmost namespace
    /// elements take priority over leftmost ones.
    pub fn squash(&self) -> Namespace {
        let mut result = HashMap::new();
        for ns in self.0.iter() {
            result.extend(ns.0.iter().cloned_pairwise());
        }
        Namespace(result)
    }
}

/// An iterator over mappings from prefixes to URIs in a namespace stack.
pub struct NamespaceStackMappings<'a> {
    namespaces: Rev<Iter<'a, Namespace>>,
    current_namespace: Option<NamespaceMappings<'a>>,
    used_keys: HashSet<Option<&'a str>>
}

impl<'a> NamespaceStackMappings<'a> {
    fn to_next_namespace(&mut self) -> bool {
        self.current_namespace = self.namespaces.next().map(|ns| ns.uri_mappings());
        self.current_namespace.is_some()
    }
}

impl<'a> Iterator<(Option<&'a str>, &'a str)> for NamespaceStackMappings<'a> {
    fn next(&mut self) -> Option<(Option<&'a str>, &'a str)> {
        // If there is no current namespace and no next namespace, we're finished
        if self.current_namespace.is_none() && !self.to_next_namespace() {
            return None;
        }
        let next_item = self.current_namespace.as_mut().unwrap().next();

        match next_item {
            // There is an element in the current namespace
            Some((k, v)) => if self.used_keys.contains(&k) {
                // If the current key is used, go to the next one
                self.next()
            } else {
                // Otherwise insert the current key to the set of used keys and
                // return the mapping
                self.used_keys.insert(k);
                Some((k, v))
            },
            // Current namespace is exhausted
            None => if self.to_next_namespace() {
                // If there is next namespace, continue from it
                self.next()
            } else {
                // No next namespace, exiting
                None
            }
        }
    }
}

impl<'a> NamespaceIterable<'a, NamespaceStackMappings<'a>> for NamespaceStack {
    fn uri_mappings(&'a self) -> NamespaceStackMappings<'a> {
        NamespaceStackMappings {
            namespaces: self.0.iter().rev(),
            current_namespace: None,
            used_keys: HashSet::new()
        }
    }
}
<commit_msg>Fix rename hash_map::Entries -> hash_map::Iter<commit_after>use std::iter::Rev;
use core::slice::Iter;
use std::collections::hash_map::{HashMap, Entry};
use std::collections::hash_map::Iter as Entries;
use std::collections::HashSet;

use util::{OptionBorrowExt, IntoOwned, IteratorClonedPairwiseExt};

pub const NS_XMLNS_PREFIX: &'static str = "xmlns";
pub const NS_XMLNS_URI: &'static str    = "http://www.w3.org/2000/xmlns/";
pub const NS_XML_PREFIX: &'static str   = "xml";
pub const NS_XML_URI: &'static str      = "http://www.w3.org/XML/1998/namespace";
pub const NS_EMPTY_URI: &'static str    = "";

/// Denotes something which contains namespace URI mappings.
///
/// A URI mapping is a pair of type `(Option<&str>, &str)`, where the first item
/// is a namespace prefix (`None` meaning default prefix) and the second item
/// is a URI mapped to this prefix.
pub trait NamespaceIterable<'a, I: Iterator<(Option<&'a str>, &'a str)>> {
    fn uri_mappings(&'a self) -> I;
}

/// Namespace is a map from prefixes to namespace URIs.
///
/// `None` prefix means no prefix (i.e. default namespace).
#[deriving(PartialEq, Clone)]
pub struct Namespace(pub HashMap<Option<String>, String>);

impl Namespace {
    /// Returns an empty namespace.
    #[inline]
    pub fn empty() -> Namespace { Namespace(HashMap::with_capacity(3)) }

    /// Checks whether this namespace is empty.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    /// Checks whether this namespace is essentially empty, that is, it does not contain
    /// anything but the default mappings.
    pub fn is_essentially_empty(&self) -> bool {
        // a shortcut for a namespace which is definitely not empty
        if self.0.len() > 3 { return false; }

        self.0.iter().all(|(k, v)| match (k.borrow_internals(), v[]) {
            (None,                  NS_EMPTY_URI) => true,
            (Some(NS_XMLNS_PREFIX), NS_XMLNS_URI) => true,
            (Some(NS_XML_PREFIX),   NS_XML_URI)   => true,
            _ => false
        })
    }

    /// Puts a mapping into this namespace.
    ///
    /// This method does not override an already existing mapping.
    ///
    /// Returns a boolean flag indicating whether the map already contained
    /// the given prefix.
    ///
    /// # Parameters
    /// * `prefix` --- namespace prefix (`None` means default namespace);
    /// * `uri`    --- namespace URI.
    ///
    /// # Return value
    /// `true` if `prefix` has been inserted successfully; `false` if the `prefix`
    /// was already present in the namespace.
    pub fn put<S1, S2>(&mut self, prefix: Option<S1>, uri: S2) -> bool
            where S1: IntoOwned<String>, S2: IntoOwned<String> {
        match self.0.entry(prefix.map(|v| v.into_owned())) {
            Entry::Occupied(_) => false,
            Entry::Vacant(ve) => {
                ve.set(uri.into_owned());
                true
            }
        }
    }

    /// Puts a mapping into this namespace forcefully.
    ///
    /// This method, as opposed to `put()`, does replace an already existing mapping.
    ///
    /// Returns previous URI which was assigned to the given prefix, if it is present.
    ///
    /// # Parameters
    /// * `prefix` --- namespace prefix (`None` means default namespace);
    /// * `uri`    --- namespace URI.
    ///
    /// # Return value
    /// `Some(uri)` with `uri` being a previous URI assigned to the `prefix`, or
    /// `None` if such prefix was not present in the namespace before.
    pub fn force_put<S1, S2>(&mut self, prefix: Option<S1>, uri: S2) -> Option<String>
            where S1: IntoOwned<String>, S2: IntoOwned<String> {
        self.0.insert(prefix.map(|v| v.into_owned()), uri.into_owned())
    }

    /// Queries the namespace for the given prefix.
    ///
    /// # Parameters
    /// * `prefix` --- namespace prefix (`None` means default namespace).
    ///
    /// # Return value
    /// Namespace URI corresponding to the given prefix, if it is present.
    pub fn get<'a>(&'a self, prefix: &Option<String>) -> Option<&'a str> {
        self.0.get(prefix).map(|s| &**s)
    }
}

/// An iterator over mappings from prefixes to URIs in a namespace.
///
/// This is a separate structure because `map()` operation on iterators uses an unboxed
/// closure type which can't be named.
pub struct NamespaceMappings<'a> {
    entries: Entries<'a, Option<String>, String>
}

impl<'a> Iterator<(Option<&'a str>, &'a str)> for NamespaceMappings<'a> {
    fn next(&mut self) -> Option<(Option<&'a str>, &'a str)> {
        self.entries.next().map(|(prefix, uri)| {
            (prefix.as_ref().map(|p| p.as_slice()), uri.as_slice())
        })
    }
}

impl<'a> NamespaceIterable<'a, NamespaceMappings<'a>> for Namespace {
    fn uri_mappings(&'a self) -> NamespaceMappings<'a> {
        NamespaceMappings { entries: self.0.iter() }
    }
}

/// Namespace stack is a sequence of namespaces.
///
/// Namespace stack is used to represent cumulative namespace consisting of
/// combined namespaces from nested elements.
#[deriving(Clone, PartialEq)]
pub struct NamespaceStack(pub Vec<Namespace>);

impl NamespaceStack {
    /// Returns an empty namespace stack.
    #[inline]
    pub fn empty() -> NamespaceStack { NamespaceStack(Vec::with_capacity(2)) }

    /// Returns a namespace stack with default items in it.
    ///
    /// Default items are the following:
    ///
    /// * `xml` → `http://www.w3.org/XML/1998/namespace`;
    /// * `xmlns` → `http://www.w3.org/2000/xmlns/`.
    #[inline]
    pub fn default() -> NamespaceStack {
        let mut nst = NamespaceStack::empty();
        nst.push_empty();
        // xml namespace
        nst.put(Some(NS_XML_PREFIX.to_string()), NS_XML_URI.to_string());
        // xmlns namespace
        nst.put(Some(NS_XMLNS_PREFIX.to_string()), NS_XMLNS_URI.to_string());
        // empty namespace
        nst.put(None, NS_EMPTY_URI.to_string());
        nst
    }

    /// Adds an empty namespace to the top of this stack.
    #[inline]
    pub fn push_empty(&mut self) {
        self.0.push(Namespace::empty());
    }

    /// Removes a namespace at the top of the stack.
    ///
    /// Fails if the stack is empty.
    #[inline]
    pub fn pop(&mut self) -> Namespace {
        self.0.pop().unwrap()
    }

    /// Returns a namespace at the top of the stack, leaving the stack intact.
    ///
    /// Fails if the stack is empty.
    #[inline]
    pub fn peek<'a>(&'a mut self) -> &'a mut Namespace {
        self.0.last_mut().unwrap()
    }

    /// Puts a mapping into the topmost namespace in this stack.
    ///
    /// This method does not override a mapping in the topmost namespace if it is
    /// already present, however, it does not depend on other namespaces in the stack,
    /// so it is possible to put a mapping which is present in lower namespaces.
    ///
    /// Returns a boolean flag indicating whether the topmost namespace
    /// already contained the given prefix.
    ///
    /// # Parameters
    /// * `prefix` --- namespace prefix (`None` means default namespace);
    /// * `uri`    --- namespace URI.
    ///
    /// # Return value
    /// `true` if `prefix` has been inserted successfully; `false` if the `prefix`
    /// was already present in the namespace.
    #[inline]
    pub fn put(&mut self, prefix: Option<String>, uri: String) -> bool {
        self.0.last_mut().unwrap().put(prefix, uri)
    }

    /// Performs a search for the given prefix in the whole stack.
    ///
    /// This method walks the stack from top to bottom, querying each namespace
    /// in order for the given prefix. If none of the namespaces contains the prefix,
    /// `None` is returned.
    ///
    /// # Parameters
    /// * `prefix` --- namespace prefix (`None` means default namespace)
    #[inline]
    pub fn get<'a>(&'a self, prefix: &Option<String>) -> Option<&'a str> {
        for ns in self.0.iter().rev() {
            match ns.get(prefix) {
                None => {},
                r => return r,
            }
        }
        None
    }

    /// Combines this stack of namespaces into a single namespace.
    ///
    /// Namespaces are combined in left-to-right order, that is, rightmost namespace
    /// elements take priority over leftmost ones.
    pub fn squash(&self) -> Namespace {
        let mut result = HashMap::new();
        for ns in self.0.iter() {
            result.extend(ns.0.iter().cloned_pairwise());
        }
        Namespace(result)
    }
}

/// An iterator over mappings from prefixes to URIs in a namespace stack.
pub struct NamespaceStackMappings<'a> {
    namespaces: Rev<Iter<'a, Namespace>>,
    current_namespace: Option<NamespaceMappings<'a>>,
    used_keys: HashSet<Option<&'a str>>
}

impl<'a> NamespaceStackMappings<'a> {
    fn to_next_namespace(&mut self) -> bool {
        self.current_namespace = self.namespaces.next().map(|ns| ns.uri_mappings());
        self.current_namespace.is_some()
    }
}

impl<'a> Iterator<(Option<&'a str>, &'a str)> for NamespaceStackMappings<'a> {
    fn next(&mut self) -> Option<(Option<&'a str>, &'a str)> {
        // If there is no current namespace and no next namespace, we're finished
        if self.current_namespace.is_none() && !self.to_next_namespace() {
            return None;
        }
        let next_item = self.current_namespace.as_mut().unwrap().next();

        match next_item {
            // There is an element in the current namespace
            Some((k, v)) => if self.used_keys.contains(&k) {
                // If the current key is used, go to the next one
                self.next()
            } else {
                // Otherwise insert the current key to the set of used keys and
                // return the mapping
                self.used_keys.insert(k);
                Some((k, v))
            },
            // Current namespace is exhausted
            None => if self.to_next_namespace() {
                // If there is next namespace, continue from it
                self.next()
            } else {
                // No next namespace, exiting
                None
            }
        }
    }
}

impl<'a> NamespaceIterable<'a, NamespaceStackMappings<'a>> for NamespaceStack {
    fn uri_mappings(&'a self) -> NamespaceStackMappings<'a> {
        NamespaceStackMappings {
            namespaces: self.0.iter().rev(),
            current_namespace: None,
            used_keys: HashSet::new()
        }
    }
}
<|endoftext|>


<commit_before>use alloc::allocator::{Alloc, Layout};
use alloc::heap::Heap;
use core::{cmp, slice};

use super::FONT;
use super::primitive::{fast_set32, fast_set64, fast_copy};

/// A display
pub struct Display {
    pub width: usize,
    pub height: usize,
    pub onscreen: &'static mut [u32],
    pub offscreen: &'static mut [u32],
}

impl Display {
    pub fn new(width: usize, height: usize, onscreen: usize) -> Display {
        let size = width * height;
        let offscreen = unsafe { Heap.alloc(Layout::from_size_align_unchecked(size * 4, 4096)).unwrap() };
        unsafe { fast_set64(offscreen as *mut u64, 0, size/2) };
        Display {
            width: width,
            height: height,
            onscreen: unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) },
            offscreen: unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) }
        }
    }

    /// Draw a rectangle
    pub fn rect(&mut self, x: usize, y: usize, w: usize, h: usize, color: u32) {
        let start_y = cmp::min(self.height, y);
        let end_y = cmp::min(self.height, y + h);

        let start_x = cmp::min(self.width, x);
        let len = cmp::min(self.width, x + w) - start_x;

        let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;

        let stride = self.width * 4;

        let offset = y * stride + start_x * 4;
        offscreen_ptr += offset;

        let mut rows = end_y - start_y;
        while rows > 0 {
            unsafe {
                fast_set32(offscreen_ptr as *mut u32, color, len);
            }
            offscreen_ptr += stride;
            rows -= 1;
        }
    }

    /// Invert a rectangle
    pub fn invert(&mut self, x: usize, y: usize, w: usize, h: usize) {
        let start_y = cmp::min(self.height, y);
        let end_y = cmp::min(self.height, y + h);

        let start_x = cmp::min(self.width, x);
        let len = cmp::min(self.width, x + w) - start_x;

        let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;

        let stride = self.width * 4;

        let offset = y * stride + start_x * 4;
        offscreen_ptr += offset;

        let mut rows = end_y - start_y;
        while rows > 0 {
            let mut row_ptr = offscreen_ptr;
            let mut cols = len;
            while cols > 0 {
                unsafe {
                    let color = *(row_ptr as *mut u32);
                    *(row_ptr as *mut u32) = !color;
                }
                row_ptr += 4;
                cols -= 1;
            }
            offscreen_ptr += stride;
            rows -= 1;
        }
    }

    /// Draw a character
    pub fn char(&mut self, x: usize, y: usize, character: char, color: u32) {
        if x + 8 <= self.width && y + 16 <= self.height {
            let mut dst = self.offscreen.as_mut_ptr() as usize + (y * self.width + x) * 4;

            let font_i = 16 * (character as usize);
            if font_i + 16 <= FONT.len() {
                for row in 0..16 {
                    let row_data = FONT[font_i + row];
                    for col in 0..8 {
                        if (row_data >> (7 - col)) & 1 == 1 {
                            unsafe { *((dst + col * 4) as *mut u32)  = color; }
                        }
                    }
                    dst += self.width * 4;
                }
            }
        }
    }

    // Scroll the screen
    pub fn scroll(&mut self, lines: usize) {
        let offset = cmp::min(self.height, lines) * self.width;
        let size = self.offscreen.len() - offset;
        unsafe {
            let to = self.offscreen.as_mut_ptr();
            let from = to.offset(offset as isize);
            fast_copy(to as *mut u8, from as *const u8, size * 4);
        }
    }

    /// Copy from offscreen to onscreen
    pub fn sync(&mut self, x: usize, y: usize, w: usize, h: usize) {
        let start_y = cmp::min(self.height, y);
        let end_y = cmp::min(self.height, y + h);

        let start_x = cmp::min(self.width, x);
        let len = (cmp::min(self.width, x + w) - start_x) * 4;

        let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;
        let mut onscreen_ptr = self.onscreen.as_mut_ptr() as usize;

        let stride = self.width * 4;

        let offset = y * stride + start_x * 4;
        offscreen_ptr += offset;
        onscreen_ptr += offset;

        let mut rows = end_y - start_y;
        while rows > 0 {
            unsafe {
                fast_copy(onscreen_ptr as *mut u8, offscreen_ptr as *const u8, len);
            }
            offscreen_ptr += stride;
            onscreen_ptr += stride;
            rows -= 1;
        }
    }
}

impl Drop for Display {
    fn drop(&mut self) {
        unsafe { Heap.dealloc(self.offscreen.as_mut_ptr() as *mut u8, Layout::from_size_align_unchecked(self.offscreen.len() * 4, 4096)) };
    }
}
<commit_msg>Fix compilation error for graphical_debug<commit_after>use alloc::allocator::{Alloc, Layout};
use alloc::heap::Heap;
use core::{cmp, slice};
use core::ptr::NonNull;

use super::FONT;
use super::primitive::{fast_set32, fast_set64, fast_copy};

/// A display
pub struct Display {
    pub width: usize,
    pub height: usize,
    pub onscreen: &'static mut [u32],
    pub offscreen: &'static mut [u32],
}

impl Display {
    pub fn new(width: usize, height: usize, onscreen: usize) -> Display {
        let size = width * height;
        let offscreen = unsafe { Heap.alloc(Layout::from_size_align_unchecked(size * 4, 4096)).unwrap().as_ptr() };
        unsafe { fast_set64(offscreen as *mut u64, 0, size/2) };
        Display {
            width: width,
            height: height,
            onscreen: unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) },
            offscreen: unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) }
        }
    }

    /// Draw a rectangle
    pub fn rect(&mut self, x: usize, y: usize, w: usize, h: usize, color: u32) {
        let start_y = cmp::min(self.height, y);
        let end_y = cmp::min(self.height, y + h);

        let start_x = cmp::min(self.width, x);
        let len = cmp::min(self.width, x + w) - start_x;

        let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;

        let stride = self.width * 4;

        let offset = y * stride + start_x * 4;
        offscreen_ptr += offset;

        let mut rows = end_y - start_y;
        while rows > 0 {
            unsafe {
                fast_set32(offscreen_ptr as *mut u32, color, len);
            }
            offscreen_ptr += stride;
            rows -= 1;
        }
    }

    /// Invert a rectangle
    pub fn invert(&mut self, x: usize, y: usize, w: usize, h: usize) {
        let start_y = cmp::min(self.height, y);
        let end_y = cmp::min(self.height, y + h);

        let start_x = cmp::min(self.width, x);
        let len = cmp::min(self.width, x + w) - start_x;

        let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;

        let stride = self.width * 4;

        let offset = y * stride + start_x * 4;
        offscreen_ptr += offset;

        let mut rows = end_y - start_y;
        while rows > 0 {
            let mut row_ptr = offscreen_ptr;
            let mut cols = len;
            while cols > 0 {
                unsafe {
                    let color = *(row_ptr as *mut u32);
                    *(row_ptr as *mut u32) = !color;
                }
                row_ptr += 4;
                cols -= 1;
            }
            offscreen_ptr += stride;
            rows -= 1;
        }
    }

    /// Draw a character
    pub fn char(&mut self, x: usize, y: usize, character: char, color: u32) {
        if x + 8 <= self.width && y + 16 <= self.height {
            let mut dst = self.offscreen.as_mut_ptr() as usize + (y * self.width + x) * 4;

            let font_i = 16 * (character as usize);
            if font_i + 16 <= FONT.len() {
                for row in 0..16 {
                    let row_data = FONT[font_i + row];
                    for col in 0..8 {
                        if (row_data >> (7 - col)) & 1 == 1 {
                            unsafe { *((dst + col * 4) as *mut u32)  = color; }
                        }
                    }
                    dst += self.width * 4;
                }
            }
        }
    }

    // Scroll the screen
    pub fn scroll(&mut self, lines: usize) {
        let offset = cmp::min(self.height, lines) * self.width;
        let size = self.offscreen.len() - offset;
        unsafe {
            let to = self.offscreen.as_mut_ptr();
            let from = to.offset(offset as isize);
            fast_copy(to as *mut u8, from as *const u8, size * 4);
        }
    }

    /// Copy from offscreen to onscreen
    pub fn sync(&mut self, x: usize, y: usize, w: usize, h: usize) {
        let start_y = cmp::min(self.height, y);
        let end_y = cmp::min(self.height, y + h);

        let start_x = cmp::min(self.width, x);
        let len = (cmp::min(self.width, x + w) - start_x) * 4;

        let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;
        let mut onscreen_ptr = self.onscreen.as_mut_ptr() as usize;

        let stride = self.width * 4;

        let offset = y * stride + start_x * 4;
        offscreen_ptr += offset;
        onscreen_ptr += offset;

        let mut rows = end_y - start_y;
        while rows > 0 {
            unsafe {
                fast_copy(onscreen_ptr as *mut u8, offscreen_ptr as *const u8, len);
            }
            offscreen_ptr += stride;
            onscreen_ptr += stride;
            rows -= 1;
        }
    }
}

impl Drop for Display {
    fn drop(&mut self) {
        unsafe { Heap.dealloc(NonNull::new(self.offscreen.as_mut_ptr()).unwrap().as_opaque(), Layout::from_size_align_unchecked(self.offscreen.len() * 4, 4096)) };
    }
}
<|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/. */

use servo_util::namespace;
use dom::attr::Attr;
use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, CommentCast};
use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, CharacterDataCast};
use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast;
use dom::bindings::js::JS;
use dom::characterdata::CharacterData;
use dom::comment::Comment;
use dom::documenttype::DocumentType;
use dom::element::Element;
use dom::node::NodeIterator;
use dom::node::{DoctypeNodeTypeId, DocumentFragmentNodeTypeId, CommentNodeTypeId};
use dom::node::{DocumentNodeTypeId, ElementNodeTypeId, ProcessingInstructionNodeTypeId};
use dom::node::{TextNodeTypeId, NodeHelpers};
use dom::processinginstruction::ProcessingInstruction;
use dom::text::Text;

pub fn serialize(iterator: &mut NodeIterator) -> ~str {
    let mut html = ~"";
    let mut open_elements: ~[~str] = ~[];

    for node in *iterator {
        while open_elements.len() > iterator.depth {
            html.push_str(~"</" + open_elements.pop() + ">");
        }
        html.push_str(
            match node.type_id() {
                ElementNodeTypeId(..) => {
                    let elem: JS<Element> = ElementCast::to(&node);
                    serialize_elem(&elem, &mut open_elements)
                }
                CommentNodeTypeId => {
                    let comment: JS<Comment> = CommentCast::to(&node);
                    serialize_comment(&comment)
                }
                TextNodeTypeId => {
                    let text: JS<Text> = TextCast::to(&node);
                    serialize_text(&text)
                }
                DoctypeNodeTypeId => {
                    let doctype: JS<DocumentType> = DocumentTypeCast::to(&node);
                    serialize_doctype(&doctype)
                }
                ProcessingInstructionNodeTypeId => {
                    let processing_instruction: JS<ProcessingInstruction> = ProcessingInstructionCast::to(&node);
                    serialize_processing_instruction(&processing_instruction)
                }
                DocumentFragmentNodeTypeId => {
                    ~""
                }
                DocumentNodeTypeId => {
                    fail!("It shouldn't be possible to serialize a document node")
                }
            }
        );
    }
    while open_elements.len() > 0 {
        html.push_str(~"</" + open_elements.pop() + ">");
    }
    html
}

fn serialize_comment(comment: &JS<Comment>) -> ~str {
    ~"<!--" + comment.get().characterdata.data + "-->"
}

fn serialize_text(text: &JS<Text>) -> ~str {
    match text.get().characterdata.node.parent_node {
        Some(ref parent) if parent.is_element() => {
            let elem: JS<Element> = ElementCast::to(parent);
            match elem.get().tag_name.as_slice() {
                "style" | "script" | "xmp" | "iframe" |
                "noembed" | "noframes" | "plaintext" |
                "noscript" if elem.get().namespace == namespace::HTML => {
                    text.get().characterdata.data.clone()
                },
                _ => escape(text.get().characterdata.data, false)
            }
        }
        _ => escape(text.get().characterdata.data, false)
    }
}

fn serialize_processing_instruction(processing_instruction: &JS<ProcessingInstruction>) -> ~str {
    ~"<?" + processing_instruction.get().target + " " + processing_instruction.get().characterdata.data + "?>"
}

fn serialize_doctype(doctype: &JS<DocumentType>) -> ~str {
    ~"<!DOCTYPE" + doctype.get().name + ">"
}

fn serialize_elem(elem: &JS<Element>, open_elements: &mut ~[~str]) -> ~str {
    let mut rv = ~"<" + elem.get().tag_name;
    for attr in elem.get().attrs.iter() {
        rv.push_str(serialize_attr(attr));
    };
    rv.push_str(">");
    match elem.get().tag_name.as_slice() {
        "pre" | "listing" | "textarea" if elem.get().namespace == namespace::HTML => {
            match elem.get().node.first_child {
                Some(ref child) if child.is_text() => {
                    let text: JS<CharacterData> = CharacterDataCast::to(child);
                    if text.get().data[0] == 0x0A as u8 {
                        rv.push_str("\x0A");
                    }
                },
                _ => {}
            }
        },
        _ => {}
    }
    if !elem.get().is_void() {
        open_elements.push(elem.get().tag_name.clone());
    }
    rv
}

fn serialize_attr(attr: &JS<Attr>) -> ~str {
    let attr_name = if attr.get().namespace == namespace::XML {
        ~"xml:" + attr.get().local_name.clone()
    } else if attr.get().namespace == namespace::XMLNS &&
        attr.get().local_name.as_slice() == "xmlns" {
        ~"xmlns"
    } else if attr.get().namespace == namespace::XMLNS {
        ~"xmlns:" + attr.get().local_name.clone()
    } else if attr.get().namespace == namespace::XLink {
        ~"xlink:" + attr.get().local_name.clone()
    } else {
        attr.get().name.clone()
    };
    ~" " + attr_name + "=\"" + escape(attr.get().value, true) + "\""
}

fn escape(string: &str, attr_mode: bool) -> ~str {
    let replaced = string.replace("&", "&").replace("\xA0", " ");
    match attr_mode {
        true => {
            replaced.replace("\"", """)
        },
        false => {
            replaced.replace("<", "<").replace(">", ">")
        }
    }
}
<commit_msg>Add empty text check for first child of pre in innerHTML.(fixes #1743)<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/. */

use servo_util::namespace;
use dom::attr::Attr;
use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, CommentCast};
use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, CharacterDataCast};
use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast;
use dom::bindings::js::JS;
use dom::characterdata::CharacterData;
use dom::comment::Comment;
use dom::documenttype::DocumentType;
use dom::element::Element;
use dom::node::NodeIterator;
use dom::node::{DoctypeNodeTypeId, DocumentFragmentNodeTypeId, CommentNodeTypeId};
use dom::node::{DocumentNodeTypeId, ElementNodeTypeId, ProcessingInstructionNodeTypeId};
use dom::node::{TextNodeTypeId, NodeHelpers};
use dom::processinginstruction::ProcessingInstruction;
use dom::text::Text;

pub fn serialize(iterator: &mut NodeIterator) -> ~str {
    let mut html = ~"";
    let mut open_elements: ~[~str] = ~[];

    for node in *iterator {
        while open_elements.len() > iterator.depth {
            html.push_str(~"</" + open_elements.pop() + ">");
        }
        html.push_str(
            match node.type_id() {
                ElementNodeTypeId(..) => {
                    let elem: JS<Element> = ElementCast::to(&node);
                    serialize_elem(&elem, &mut open_elements)
                }
                CommentNodeTypeId => {
                    let comment: JS<Comment> = CommentCast::to(&node);
                    serialize_comment(&comment)
                }
                TextNodeTypeId => {
                    let text: JS<Text> = TextCast::to(&node);
                    serialize_text(&text)
                }
                DoctypeNodeTypeId => {
                    let doctype: JS<DocumentType> = DocumentTypeCast::to(&node);
                    serialize_doctype(&doctype)
                }
                ProcessingInstructionNodeTypeId => {
                    let processing_instruction: JS<ProcessingInstruction> = ProcessingInstructionCast::to(&node);
                    serialize_processing_instruction(&processing_instruction)
                }
                DocumentFragmentNodeTypeId => {
                    ~""
                }
                DocumentNodeTypeId => {
                    fail!("It shouldn't be possible to serialize a document node")
                }
            }
        );
    }
    while open_elements.len() > 0 {
        html.push_str(~"</" + open_elements.pop() + ">");
    }
    html
}

fn serialize_comment(comment: &JS<Comment>) -> ~str {
    ~"<!--" + comment.get().characterdata.data + "-->"
}

fn serialize_text(text: &JS<Text>) -> ~str {
    match text.get().characterdata.node.parent_node {
        Some(ref parent) if parent.is_element() => {
            let elem: JS<Element> = ElementCast::to(parent);
            match elem.get().tag_name.as_slice() {
                "style" | "script" | "xmp" | "iframe" |
                "noembed" | "noframes" | "plaintext" |
                "noscript" if elem.get().namespace == namespace::HTML => {
                    text.get().characterdata.data.clone()
                },
                _ => escape(text.get().characterdata.data, false)
            }
        }
        _ => escape(text.get().characterdata.data, false)
    }
}

fn serialize_processing_instruction(processing_instruction: &JS<ProcessingInstruction>) -> ~str {
    ~"<?" + processing_instruction.get().target + " " + processing_instruction.get().characterdata.data + "?>"
}

fn serialize_doctype(doctype: &JS<DocumentType>) -> ~str {
    ~"<!DOCTYPE" + doctype.get().name + ">"
}

fn serialize_elem(elem: &JS<Element>, open_elements: &mut ~[~str]) -> ~str {
    let mut rv = ~"<" + elem.get().tag_name;
    for attr in elem.get().attrs.iter() {
        rv.push_str(serialize_attr(attr));
    };
    rv.push_str(">");
    match elem.get().tag_name.as_slice() {
        "pre" | "listing" | "textarea" if elem.get().namespace == namespace::HTML => {
            match elem.get().node.first_child {
                Some(ref child) if child.is_text() => {
                    let text: JS<CharacterData> = CharacterDataCast::to(child);
                    if text.get().data.len() > 0 && text.get().data[0] == 0x0A as u8 {
                        rv.push_str("\x0A");
                    }
                },
                _ => {}
            }
        },
        _ => {}
    }
    if !elem.get().is_void() {
        open_elements.push(elem.get().tag_name.clone());
    }
    rv
}

fn serialize_attr(attr: &JS<Attr>) -> ~str {
    let attr_name = if attr.get().namespace == namespace::XML {
        ~"xml:" + attr.get().local_name.clone()
    } else if attr.get().namespace == namespace::XMLNS &&
        attr.get().local_name.as_slice() == "xmlns" {
        ~"xmlns"
    } else if attr.get().namespace == namespace::XMLNS {
        ~"xmlns:" + attr.get().local_name.clone()
    } else if attr.get().namespace == namespace::XLink {
        ~"xlink:" + attr.get().local_name.clone()
    } else {
        attr.get().name.clone()
    };
    ~" " + attr_name + "=\"" + escape(attr.get().value, true) + "\""
}

fn escape(string: &str, attr_mode: bool) -> ~str {
    let replaced = string.replace("&", "&").replace("\xA0", " ");
    match attr_mode {
        true => {
            replaced.replace("\"", """)
        },
        false => {
            replaced.replace("<", "<").replace(">", ">")
        }
    }
}
<|endoftext|>


<commit_before>// run-pass

// rust-lang/rust#64655: with panic=unwind, a panic from a subroutine
// should still run desstructors as it unwindws the stack. However,
// bugs with how the nounwind LLVM attribute was applied led to this
// simple case being mishandled *if* you had optimization *and* fat
// LTO turned on.

// This test is the closest thing to a "regression test" we can do
// without actually spawning subprocesses and comparing stderr
// results.
//
// This test takes the code from the above issue and adapts it to
// better fit our test infrastructure:
//
// * Instead of relying on println! to observe whether the destructor
//   is run, we instead run the code in a spawned thread and
//   communicate the destructor's operation via a synchronous atomic
//   in static memory.
//
// * To keep the output from confusing a casual user, we override the
//   panic hook to be a no-op (rather than printing a message to
//   stderr).
//
// (pnkfelix has confirmed by hand that these additions do not mask
// the underlying bug.)

// LTO settings cannot be combined with -C prefer-dynamic
// no-prefer-dynamic

// The revisions combine each lto setting with each optimization
// setting; pnkfelix observed three differing behaviors at opt-levels
// 0/1/2+3 for this test, so it seems prudent to be thorough.

// revisions: no0 no1 no2 no3 thin0 thin1 thin2 thin3 fat0 fat1 fat2  fat3

//[no0]compile-flags: -C opt-level=0 -C lto=no
//[no1]compile-flags: -C opt-level=1 -C lto=no
//[no2]compile-flags: -C opt-level=2 -C lto=no
//[no3]compile-flags: -C opt-level=3 -C lto=no
//[thin0]compile-flags: -C opt-level=0 -C lto=thin
//[thin1]compile-flags: -C opt-level=1 -C lto=thin
//[thin2]compile-flags: -C opt-level=2 -C lto=thin
//[thin3]compile-flags: -C opt-level=3 -C lto=thin
//[fat0]compile-flags: -C opt-level=0 -C lto=fat
//[fat1]compile-flags: -C opt-level=1 -C lto=fat
//[fat2]compile-flags: -C opt-level=2 -C lto=fat
//[fat3]compile-flags: -C opt-level=3 -C lto=fat

fn main() {
    use std::sync::atomic::{AtomicUsize, Ordering};

    static SHARED: AtomicUsize = AtomicUsize::new(0);

    assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 0);

    let old_hook = std::panic::take_hook();

    std::panic::set_hook(Box::new(|_| { } )); // no-op on panic.

    let handle = std::thread::spawn(|| {
        struct Droppable;
        impl Drop for Droppable {
            fn drop(&mut self) {
                SHARED.fetch_add(1, Ordering::SeqCst);
            }
        }

        let _guard = Droppable;
        None::<()>.expect("???");
    });

    let wait = handle.join();

    // reinstate handler to ease observation of assertion failures.
    std::panic::set_hook(old_hook);

    assert!(wait.is_err());

    assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 1);
}

<commit_msg>fix typo<commit_after>// run-pass

// rust-lang/rust#64655: with panic=unwind, a panic from a subroutine
// should still run desstructors as it unwinds the stack. However,
// bugs with how the nounwind LLVM attribute was applied led to this
// simple case being mishandled *if* you had optimization *and* fat
// LTO turned on.

// This test is the closest thing to a "regression test" we can do
// without actually spawning subprocesses and comparing stderr
// results.
//
// This test takes the code from the above issue and adapts it to
// better fit our test infrastructure:
//
// * Instead of relying on println! to observe whether the destructor
//   is run, we instead run the code in a spawned thread and
//   communicate the destructor's operation via a synchronous atomic
//   in static memory.
//
// * To keep the output from confusing a casual user, we override the
//   panic hook to be a no-op (rather than printing a message to
//   stderr).
//
// (pnkfelix has confirmed by hand that these additions do not mask
// the underlying bug.)

// LTO settings cannot be combined with -C prefer-dynamic
// no-prefer-dynamic

// The revisions combine each lto setting with each optimization
// setting; pnkfelix observed three differing behaviors at opt-levels
// 0/1/2+3 for this test, so it seems prudent to be thorough.

// revisions: no0 no1 no2 no3 thin0 thin1 thin2 thin3 fat0 fat1 fat2  fat3

//[no0]compile-flags: -C opt-level=0 -C lto=no
//[no1]compile-flags: -C opt-level=1 -C lto=no
//[no2]compile-flags: -C opt-level=2 -C lto=no
//[no3]compile-flags: -C opt-level=3 -C lto=no
//[thin0]compile-flags: -C opt-level=0 -C lto=thin
//[thin1]compile-flags: -C opt-level=1 -C lto=thin
//[thin2]compile-flags: -C opt-level=2 -C lto=thin
//[thin3]compile-flags: -C opt-level=3 -C lto=thin
//[fat0]compile-flags: -C opt-level=0 -C lto=fat
//[fat1]compile-flags: -C opt-level=1 -C lto=fat
//[fat2]compile-flags: -C opt-level=2 -C lto=fat
//[fat3]compile-flags: -C opt-level=3 -C lto=fat

fn main() {
    use std::sync::atomic::{AtomicUsize, Ordering};

    static SHARED: AtomicUsize = AtomicUsize::new(0);

    assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 0);

    let old_hook = std::panic::take_hook();

    std::panic::set_hook(Box::new(|_| { } )); // no-op on panic.

    let handle = std::thread::spawn(|| {
        struct Droppable;
        impl Drop for Droppable {
            fn drop(&mut self) {
                SHARED.fetch_add(1, Ordering::SeqCst);
            }
        }

        let _guard = Droppable;
        None::<()>.expect("???");
    });

    let wait = handle.join();

    // reinstate handler to ease observation of assertion failures.
    std::panic::set_hook(old_hook);

    assert!(wait.is_err());

    assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 1);
}

<|endoftext|>


<commit_before>use std::io;

use fc_util::ratelimiter::RateLimiter;

// This struct represents the strongly typed equivalent of the json body for TokenBucket
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct TokenBucket {
    pub size: u64,
    pub refill_time: u64,
}

impl Default for TokenBucket {
    fn default() -> Self {
        TokenBucket {
            size: 0,
            refill_time: 0,
        }
    }
}

// This struct represents the strongly typed equivalent of the json body for RateLimiter
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub struct RateLimiterDescription {
    pub bandwidth: TokenBucket,
    pub ops: TokenBucket,
}

// TryFrom trait is sadly marked unstable, so make our own
impl RateLimiterDescription {
    fn into_implementation(&self) -> io::Result<RateLimiter> {
        RateLimiter::new(
            self.bandwidth.size,
            self.bandwidth.refill_time,
            self.ops.size,
            self.ops.refill_time,
        )
    }
}

pub fn description_into_implementation(
    rate_limiter_description: Option<&RateLimiterDescription>,
) -> io::Result<Option<RateLimiter>> {
    match rate_limiter_description {
        Some(rld) => Ok(Some(rld.into_implementation()?)),
        None => Ok(None),
    }
}

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

    #[test]
    fn test_token_bucket_derives() {
        let tb = TokenBucket {
            size: 0,
            refill_time: 0,
        };
        let tbc = tb.clone();
        // test clone and partial eq
        assert_eq!(tb, tbc);
    }

    #[test]
    fn test_rate_limiter_default() {
        let l = RateLimiterDescription::default();
        assert_eq!(l.bandwidth.size, 0);
        assert_eq!(l.bandwidth.refill_time, 0);
        assert_eq!(l.ops.size, 0);
        assert_eq!(l.ops.refill_time, 0);
    }

    #[test]
    fn test_rate_limiter_into_impl() {
        RateLimiterDescription::default()
            .into_implementation()
            .unwrap();
    }
}
<commit_msg>rename TokenBucket in api_server crate to TokenBucketDescription<commit_after>use std::io;

use fc_util::ratelimiter::RateLimiter;

// This struct represents the strongly typed equivalent of the json body for TokenBucket
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct TokenBucketDescription {
    pub size: u64,
    pub refill_time: u64,
}

impl Default for TokenBucketDescription {
    fn default() -> Self {
        TokenBucketDescription {
            size: 0,
            refill_time: 0,
        }
    }
}

// This struct represents the strongly typed equivalent of the json body for RateLimiter
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub struct RateLimiterDescription {
    pub bandwidth: TokenBucketDescription,
    pub ops: TokenBucketDescription,
}

// TryFrom trait is sadly marked unstable, so make our own
impl RateLimiterDescription {
    fn into_implementation(&self) -> io::Result<RateLimiter> {
        RateLimiter::new(
            self.bandwidth.size,
            self.bandwidth.refill_time,
            self.ops.size,
            self.ops.refill_time,
        )
    }
}

pub fn description_into_implementation(
    rate_limiter_description: Option<&RateLimiterDescription>,
) -> io::Result<Option<RateLimiter>> {
    match rate_limiter_description {
        Some(rld) => Ok(Some(rld.into_implementation()?)),
        None => Ok(None),
    }
}

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

    #[test]
    fn test_token_bucket_derives() {
        let tb = TokenBucketDescription {
            size: 0,
            refill_time: 0,
        };
        let tbc = tb.clone();
        // test clone and partial eq
        assert_eq!(tb, tbc);
    }

    #[test]
    fn test_rate_limiter_default() {
        let l = RateLimiterDescription::default();
        assert_eq!(l.bandwidth.size, 0);
        assert_eq!(l.bandwidth.refill_time, 0);
        assert_eq!(l.ops.size, 0);
        assert_eq!(l.ops.refill_time, 0);
    }

    #[test]
    fn test_rate_limiter_into_impl() {
        RateLimiterDescription::default()
            .into_implementation()
            .unwrap();
    }
}
<|endoftext|>


<commit_before><commit_msg>Only run rainbow highlighting test on 64-bit Unix<commit_after><|endoftext|>