<commit_before>//! # generator
//!
//! Rust generator library
//!

#![feature(fnbox)]
#![feature(rustc_private)]
#![feature(rt)]
#![feature(box_raw)]
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]

#[macro_use]
extern crate log;
extern crate libc;
extern crate context;

pub mod env;
pub use env::ContextStack;

use context::Stack;
use context::Context as RegContext;
use std::rt::unwind::try;
use std::rt::util::min_stack;
use std::boxed::FnBox;
use std::any::Any;
use std::mem;
use std::ptr;

/// generator context
pub struct Context {
    /// generator regs context
    regs: RegContext,
    /// generator execution stack
    stack: Stack,
    /// passed in para for send
    para: *mut Any,
    /// this is just a buffer for the return value
    ret:  *mut Any,
    /// track generator ref, yield will -1, send will +1
    _ref: u32,
    /// priave flag that control the execution flow
    _flag: bool,
}

impl Context {
    /// return a default generator context
    pub fn new() -> Context {
        Context {
            regs: RegContext::empty(),
            stack: Stack::new(min_stack()),
            para: unsafe { mem::transmute(&0 as &Any) },
            ret: unsafe { mem::transmute(&0 as &Any) },
            _ref: 0,
            _flag: false,
        }
    }

    /// empty context used for the normal thread
    pub fn empty() -> Context {
        Context {
            regs: RegContext::empty(),
            stack: unsafe { Stack::dummy_stack() },
            para: unsafe { mem::transmute(&0 as &Any) },
            ret: unsafe { mem::transmute(&0 as &Any) },
            _ref: 0,
            _flag: false,
        }
    }

    /// save current generator context
    #[inline(always)]
    pub fn save(&mut self) {
        self._ref -= 1;
        self._flag = true;
        RegContext::save(&mut self.regs);
    }

    /// generator involke flag, save it along with context
    #[inline]
    pub fn get_flag(&mut self)-> &'static mut bool {
        unsafe {mem::transmute(&mut self._flag)}
    }

    /// get current generator send para
    #[inline]
    pub fn get_para<T>(&self) -> Option<T> where T: Any {
        let para = unsafe { &mut *self.para };
        let val = para.downcast_mut::<Option<T>>().unwrap();
        // simple consume the value
        mem::replace(val, None)
    }

    /// set current generator return value
    #[inline]
    pub fn set_ret<T>(&mut self, v: T) where T: Any {
        let ret = unsafe { &mut *self.ret };
        // add type check and panic with message
        let val = ret.downcast_mut::<Option<T>>().unwrap();
        mem::replace(val, Some(v));
    }
}

/// generator trait
pub trait Generator<A> {
    /// Output type
    type Output;

    /// send interface
    fn send(&mut self, para: A) -> Self::Output;

    /// is finished
    fn is_done(&self) -> bool;
}

/// FnGenerator
pub struct FnGenerator<A, T> {
    context: Context,
    // save the input
    para: Option<A>,
    // save the output
    ret: Option<T>,
    // boxed functor
    f: Option<Box<FnBox()->T>>
}

impl<A, T> FnGenerator<A, T> {
    fn resume_gen(&mut self) {
        let env = ContextStack::current();
        let cur = &mut env.top().regs;
        let ctx = &mut self.context as *mut Context;
        let to = unsafe {&mut (*ctx).regs};
        // save current generator context on stack
        env.push(ctx);
        // switch context
        RegContext::swap(cur, to);
    }

    #[inline]
    fn is_started(&self) -> bool {
        // when the f is consumed we think it's running
        self.f.is_none()
    }

    fn send_impl(&mut self, para: Option<A>) -> Option<T> {
        if self.is_started() && self.context._ref != 0 {
            return None;
        }

        // every time we call the function, increase the ref count
        // yiled will decrease it and return will not
        self.context._ref += 1;
        self.resume_gen();

        // this is the passed in value of the send primitive
        // the yield part would read out this value in the next round
        // use the replace is would drop the old value
        mem::replace(&mut self.para, para);

        self.ret.take()
    }
}

impl<A: Any, T: Any> Generator<A> for FnGenerator<A, T> {
    type Output = T;

    fn send(&mut self, para: A) -> T {
        let ret = self.send_impl(Some(para));
        ret.unwrap()
    }

    fn is_done(&self) -> bool {
       self.is_started() && self.context._ref != 0
    }
}

impl<A: Any, T: Any> Iterator for FnGenerator<A, T> {
    type Item = T;
    // The 'Iterator' trait only requires the 'next' method to be defined. The
    // return type is 'Option<T>', 'None' is returned when the 'Iterator' is
    // over, otherwise the next value is returned wrapped in 'Some'
    fn next(&mut self) -> Option<T> {
        self.send_impl(None)
    }
}

/// switch back to parent context
pub fn yield_now() {
    let env = ContextStack::current();
    let ctx = env.top();
    let sp = ctx.stack.start();
    // judge if this is root context
    if sp != ptr::null() {
        env.pop();
        let ctx = env.top();
        RegContext::load(&ctx.regs);
    }
}

#[allow(unused_variables)]
extern "C" fn gen_init(arg: usize, f: *mut libc::c_void) {
    let func: Box<Box<FnBox()>> = unsafe {
        Box::from_raw(f as *mut Box<FnBox()>)
    };

    if let Err(cause) = unsafe { try(move|| func()) } {
        error!("Panicked inside: {:?}", cause.downcast::<&str>());
    }

    yield_now();
}

/// create generator
pub fn make_gen<A: Any, T: Any>(p: Option<A>, f: Box<FnBox()->T>) -> Box<FnGenerator<A, T>> {
    let mut g = Box::new(FnGenerator {
       para: p, ret: None, f: Some(f),
       context: Context::new()
    });

    g.context.para = &mut g.para as &mut Any;
    g.context.ret = &mut g.ret as &mut Any;

    unsafe {
        let ptr = Box::into_raw(g);

        //let start = Box::new(||{g.ret = Some((g.f.take().unwrap())())});
        let start = Box::new(move||{
            let mut g = Box::from_raw(ptr);
            g.ret = Some((g.f.take().unwrap())());
            // don't free the box here
            Box::into_raw(g);
        });

        let stk = &mut (*ptr).context.stack;
        let reg = &mut (*ptr).context.regs;
        reg.init_with(gen_init, ptr as usize, start, stk);
        Box::from_raw(ptr)
    }
}

#[macro_export]
macro_rules! generator {
    // `(func, <type>)`
    // func: the expression for unsafe async function which contains yiled
    // para: default send para type to the generator
    ($func:expr, <$para:ty>) => (
        generator::make_gen::<$para, _>(None, Box::new(move|| unsafe{$func}))
    );

    // `(func, para)`
    // func: the expression for unsafe async function which contains yiled
    // para: default send para to the generator
    ($func:expr, $para:expr) => (
        generator::make_gen(Some($para), Box::new(move|| unsafe{$func}))
    );

    ($func:expr) => (generator!($func, ()));
}

#[macro_export]
macro_rules! _yield {
    // `(para)`
    // val: the value that need to be yield
    // and got the send para from context
    ($val:expr) => (
        {
            let context = generator::ContextStack::current().top();
            let _no_use = context.get_flag();
            context.save();
            if *_no_use {
                *_no_use = false;
                // set the return value
                context.set_ret($val);
                // don't use the return instruction
                generator::yield_now();
                // will never come here, but for type check
                return $val;
            }
            context.get_para().unwrap()
        }
    );

    () => (_yield!(()));
}

/// yield without get the passed in para
#[macro_export]
macro_rules! _yield_ {
    // `(para)`
    // val: the value that need to be yield
    // and got the send para from context
    ($val:expr) => (
        {
            let context = generator::ContextStack::current().top();
            let _no_use = context.get_flag();
            context.save();
            if *_no_use {
                *_no_use = false;
                context.set_ret($val);
                // don't use the return instruction
                generator::yield_now();
                // context.load();
                return $val;
            }
        }
    );

    () => (_yield_!(()));
}

<commit_msg>reduce _yield macro<commit_after>//! # generator
//!
//! Rust generator library
//!

#![feature(fnbox)]
#![feature(rustc_private)]
#![feature(rt)]
#![feature(box_raw)]
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]

#[macro_use]
extern crate log;
extern crate libc;
extern crate context;

pub mod env;
pub use env::ContextStack;

use context::Stack;
use context::Context as RegContext;
use std::rt::unwind::try;
use std::rt::util::min_stack;
use std::boxed::FnBox;
use std::any::Any;
use std::mem;
use std::ptr;

/// generator context
pub struct Context {
    /// generator regs context
    regs: RegContext,
    /// generator execution stack
    stack: Stack,
    /// passed in para for send
    para: *mut Any,
    /// this is just a buffer for the return value
    ret:  *mut Any,
    /// track generator ref, yield will -1, send will +1
    _ref: u32,
    /// priave flag that control the execution flow
    _flag: bool,
}

impl Context {
    /// return a default generator context
    pub fn new() -> Context {
        Context {
            regs: RegContext::empty(),
            stack: Stack::new(min_stack()),
            para: unsafe { mem::transmute(&0 as &Any) },
            ret: unsafe { mem::transmute(&0 as &Any) },
            _ref: 0,
            _flag: false,
        }
    }

    /// empty context used for the normal thread
    pub fn empty() -> Context {
        Context {
            regs: RegContext::empty(),
            stack: unsafe { Stack::dummy_stack() },
            para: unsafe { mem::transmute(&0 as &Any) },
            ret: unsafe { mem::transmute(&0 as &Any) },
            _ref: 0,
            _flag: false,
        }
    }

    /// save current generator context
    #[inline(always)]
    pub fn save(&mut self) {
        self._ref -= 1;
        self._flag = true;
        RegContext::save(&mut self.regs);
    }

    /// generator involke flag, save it along with context
    #[inline]
    pub fn get_flag(&mut self)-> &'static mut bool {
        unsafe {mem::transmute(&mut self._flag)}
    }

    /// get current generator send para
    #[inline]
    pub fn get_para<T>(&self) -> Option<T> where T: Any {
        let para = unsafe { &mut *self.para };
        let val = para.downcast_mut::<Option<T>>().unwrap();
        // simple consume the value
        mem::replace(val, None)
    }

    /// set current generator return value
    #[inline]
    pub fn set_ret<T>(&mut self, v: T) where T: Any {
        let ret = unsafe { &mut *self.ret };
        // add type check and panic with message
        let val = ret.downcast_mut::<Option<T>>().unwrap();
        mem::replace(val, Some(v));
    }
}

/// generator trait
pub trait Generator<A> {
    /// Output type
    type Output;

    /// send interface
    fn send(&mut self, para: A) -> Self::Output;

    /// is finished
    fn is_done(&self) -> bool;
}

/// FnGenerator
pub struct FnGenerator<A, T> {
    context: Context,
    // save the input
    para: Option<A>,
    // save the output
    ret: Option<T>,
    // boxed functor
    f: Option<Box<FnBox()->T>>
}

impl<A, T> FnGenerator<A, T> {
    fn resume_gen(&mut self) {
        let env = ContextStack::current();
        let cur = &mut env.top().regs;
        let ctx = &mut self.context as *mut Context;
        let to = unsafe {&mut (*ctx).regs};
        // save current generator context on stack
        env.push(ctx);
        // switch context
        RegContext::swap(cur, to);
    }

    #[inline]
    fn is_started(&self) -> bool {
        // when the f is consumed we think it's running
        self.f.is_none()
    }

    fn send_impl(&mut self, para: Option<A>) -> Option<T> {
        if self.is_started() && self.context._ref != 0 {
            return None;
        }

        // every time we call the function, increase the ref count
        // yiled will decrease it and return will not
        self.context._ref += 1;
        self.resume_gen();

        // this is the passed in value of the send primitive
        // the yield part would read out this value in the next round
        // use the replace is would drop the old value
        mem::replace(&mut self.para, para);

        self.ret.take()
    }
}

impl<A: Any, T: Any> Generator<A> for FnGenerator<A, T> {
    type Output = T;

    fn send(&mut self, para: A) -> T {
        let ret = self.send_impl(Some(para));
        ret.unwrap()
    }

    fn is_done(&self) -> bool {
       self.is_started() && self.context._ref != 0
    }
}

impl<A: Any, T: Any> Iterator for FnGenerator<A, T> {
    type Item = T;
    // The 'Iterator' trait only requires the 'next' method to be defined. The
    // return type is 'Option<T>', 'None' is returned when the 'Iterator' is
    // over, otherwise the next value is returned wrapped in 'Some'
    fn next(&mut self) -> Option<T> {
        self.send_impl(None)
    }
}

/// switch back to parent context
pub fn yield_now() {
    let env = ContextStack::current();
    let ctx = env.top();
    let sp = ctx.stack.start();
    // judge if this is root context
    if sp != ptr::null() {
        env.pop();
        let ctx = env.top();
        RegContext::load(&ctx.regs);
    }
}

#[allow(unused_variables)]
extern "C" fn gen_init(arg: usize, f: *mut libc::c_void) {
    let func: Box<Box<FnBox()>> = unsafe {
        Box::from_raw(f as *mut Box<FnBox()>)
    };

    if let Err(cause) = unsafe { try(move|| func()) } {
        error!("Panicked inside: {:?}", cause.downcast::<&str>());
    }

    yield_now();
}

/// create generator
pub fn make_gen<A: Any, T: Any>(p: Option<A>, f: Box<FnBox()->T>) -> Box<FnGenerator<A, T>> {
    let mut g = Box::new(FnGenerator {
       para: p, ret: None, f: Some(f),
       context: Context::new()
    });

    g.context.para = &mut g.para as &mut Any;
    g.context.ret = &mut g.ret as &mut Any;

    unsafe {
        let ptr = Box::into_raw(g);

        //let start = Box::new(||{g.ret = Some((g.f.take().unwrap())())});
        let start = Box::new(move||{
            let mut g = Box::from_raw(ptr);
            g.ret = Some((g.f.take().unwrap())());
            // don't free the box here
            Box::into_raw(g);
        });

        let stk = &mut (*ptr).context.stack;
        let reg = &mut (*ptr).context.regs;
        reg.init_with(gen_init, ptr as usize, start, stk);
        Box::from_raw(ptr)
    }
}

#[macro_export]
macro_rules! generator {
    // `(func, <type>)`
    // func: the expression for unsafe async function which contains yiled
    // para: default send para type to the generator
    ($func:expr, <$para:ty>) => (
        generator::make_gen::<$para, _>(None, Box::new(move|| unsafe{$func}))
    );

    // `(func, para)`
    // func: the expression for unsafe async function which contains yiled
    // para: default send para to the generator
    ($func:expr, $para:expr) => (
        generator::make_gen(Some($para), Box::new(move|| unsafe{$func}))
    );

    ($func:expr) => (generator!($func, ()));
}

#[macro_export]
macro_rules! _yield {
    // `(para)`
    // val: the value that need to be yield
    // and got the send para from context
    ($val:expr) => ({
        _yield_!($val);
        generator::ContextStack::current().top().get_para().unwrap()
    });

    () => (_yield!(()));
}

/// yield without get the passed in para
#[macro_export]
macro_rules! _yield_ {
    // `(para)`
    // val: the value that need to be yield
    // and got the send para from context
    ($val:expr) => ({
        let context = generator::ContextStack::current().top();
        let _no_use = context.get_flag();
        context.save();
        if *_no_use {
            *_no_use = false;
            context.set_ret($val);
            // don't use the return instruction
            generator::yield_now();
            // context.load();
            return $val;
        }
    });

    () => (_yield_!(()));
}

<|endoftext|>


<commit_before>//! `sled` is a high-performance embedded database with
//! an API that is similar to a `BTreeMap<[u8], [u8]>`,
//! but with several additional capabilities for
//! assisting creators of stateful systems.
//!
//! It is fully thread-safe, and all operations are
//! atomic. Multiple `Tree`s are supported with the
//! [`Db::open_tree`](struct.Db.html#method.open_tree) method.
//!
//! ACID transactions involving reads and writes to
//! multiple items are supported with the
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! method. Transactions may also operate over
//! multiple `Tree`s (see
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! docs for more info).
//!
//! Users may also subscribe to updates on individual
//! `Tree`s by using the
//! [`Tree::watch_prefix`](struct.Tree.html#method.watch_prefix)
//! method, which returns a blocking `Iterator` over
//! updates to keys that begin with the provided
//! prefix. You may supply an empty prefix to subscribe
//! to everything.
//!
//! [Merge operators](https://github.com/spacejam/sled/wiki/merge-operators)
//! (aka read-modify-write operators) are supported. A
//! merge operator is a function that specifies
//! how new data can be merged into an existing value
//! without requiring both a read and a write.
//! Using the
//! [`Tree::merge`](struct.Tree.html#method.merge)
//! method, you may "push" data to a `Tree` value
//! and have the provided merge operator combine
//! it with the existing value, if there was one.
//! They are set on a per-`Tree` basis, and essentially
//! allow any sort of data structure to be built
//! using merges as an atomic high-level operation.
//!
//! `sled` is built by experienced database engineers
//! who think users should spend less time tuning and
//! working against high-friction APIs. Expect
//! significant ergonomic and performance improvements
//! over time. Most surprises are bugs, so please
//! [let us know](mailto:t@jujit.su?subject=sled%20sucks!!!) if something
//! is high friction.
//!
//! # Examples
//!
//! ```
//! let t = sled::open("my_db").unwrap();
//!
//! // insert and get
//! t.insert(b"yo!", b"v1");
//! assert_eq!(&t.get(b"yo!").unwrap().unwrap(), b"v1");
//!
//! // Atomic compare-and-swap.
//! t.compare_and_swap(
//!     b"yo!",      // key
//!     Some(b"v1"), // old value, None for not present
//!     Some(b"v2"), // new value, None for delete
//! )
//! .unwrap();
//!
//! // Iterates over key-value pairs, starting at the given key.
//! let scan_key: &[u8] = b"a non-present key before yo!";
//! let mut iter = t.range(scan_key..);
//! assert_eq!(&iter.next().unwrap().unwrap().0, b"yo!");
//! assert_eq!(iter.next(), None);
//!
//! t.remove(b"yo!");
//! assert_eq!(t.get(b"yo!"), Ok(None));
//! ```
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/spacejam/sled/master/art/tree_face_anti-transphobia.png"
)]
#![cfg_attr(test, deny(warnings))]
#![deny(
    missing_docs,
    future_incompatible,
    nonstandard_style,
    rust_2018_idioms,
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unsafe_code,
    unused_qualifications
)]
#![deny(
    // over time, consider enabling the following commented-out lints:
    // clippy::missing_const_for_fn,
    // clippy::missing_docs_in_private_items,
    // clippy::module_name_repetitions,
    // clippy::multiple_crate_versions,
    // clippy::unimplemented,
    // clippy::wildcard_enum_match_arm,
    // clippy::else_if_without_else,
    // clippy::float_arithmetic,
    // clippy::indexing_slicing,
    clippy::cast_lossless,
    clippy::cast_possible_truncation,
    clippy::cast_possible_wrap,
    clippy::cast_precision_loss,
    clippy::cast_sign_loss,
    clippy::checked_conversions,
    clippy::decimal_literal_representation,
    clippy::doc_markdown,
    clippy::empty_enum,
    clippy::expl_impl_clone_on_copy,
    clippy::explicit_into_iter_loop,
    clippy::explicit_iter_loop,
    clippy::fallible_impl_from,
    clippy::filter_map,
    clippy::filter_map_next,
    clippy::find_map,
    clippy::get_unwrap,
    clippy::if_not_else,
    clippy::inline_always,
    clippy::invalid_upcast_comparisons,
    clippy::items_after_statements,
    clippy::map_flatten,
    clippy::match_same_arms,
    clippy::maybe_infinite_iter,
    clippy::mem_forget,
    clippy::multiple_inherent_impl,
    clippy::mut_mut,
    clippy::needless_borrow,
    clippy::needless_continue,
    clippy::needless_pass_by_value,
    clippy::non_ascii_literal,
    clippy::option_map_unwrap_or,
    clippy::option_map_unwrap_or_else,
    clippy::path_buf_push_overwrite,
    clippy::print_stdout,
    clippy::pub_enum_variant_names,
    clippy::redundant_closure_for_method_calls,
    clippy::replace_consts,
    clippy::result_map_unwrap_or_else,
    clippy::shadow_reuse,
    clippy::shadow_same,
    clippy::shadow_unrelated,
    clippy::single_match_else,
    clippy::string_add,
    clippy::string_add_assign,
    clippy::type_repetition_in_bounds,
    clippy::unicode_not_nfc,
    clippy::unseparated_literal_suffix,
    clippy::used_underscore_binding,
    clippy::wildcard_dependencies,
    clippy::wrong_pub_self_convention,
)]
#![recursion_limit = "128"]

#[cfg(feature = "failpoints")]
use fail::fail_point;

macro_rules! maybe_fail {
    ($e:expr) => {
        #[cfg(feature = "failpoints")]
        fail_point!($e, |_| Err(Error::FailPoint));
    };
}

macro_rules! once {
    ($args:block) => {
        static E: AtomicBool = AtomicBool::new(false);
        if !E.compare_and_swap(false, true, Relaxed) {
            // only execute this once
            $args;
        }
    };
}

mod batch;
mod binary_search;
mod config;
mod context;
mod db;
mod dll;
mod fastlock;
mod histogram;
mod iter;
mod ivec;
mod lazy;
mod lru;
mod meta;
mod metrics;
mod node;
mod oneshot;
mod pagecache;
mod prefix;
mod result;
mod serialization;
mod stack;
mod subscription;
mod sys_limits;
mod transaction;
mod tree;
mod vecset;

#[cfg(not(any(windows, target_os = "linux", target_os = "macos")))]
mod threadpool {
    use super::OneShot;

    /// Just execute a task without involving threads.
    pub fn spawn<F, R>(work: F) -> OneShot<R>
    where
        F: FnOnce() -> R + Send + 'static,
        R: Send + 'static,
    {
        let (promise_filler, promise) = OneShot::pair();
        let task = move || {
            let result = (work)();
            promise_filler.fill(result);
        };

        (task)();
        return promise;
    }
}

#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
mod threadpool;

#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
mod flusher;

#[cfg(feature = "event_log")]
/// The event log helps debug concurrency issues.
pub mod event_log;

#[cfg(feature = "measure_allocs")]
mod measure_allocs;

#[cfg(feature = "measure_allocs")]
#[global_allocator]
static ALLOCATOR: measure_allocs::TrackingAllocator =
    measure_allocs::TrackingAllocator;

const DEFAULT_TREE_ID: &[u8] = b"__sled__default";

/// hidden re-export of items for testing purposes
#[doc(hidden)]
pub use {
    self::{
        config::RunningConfig,
        lazy::Lazy,
        pagecache::{
            constants::{
                MAX_MSG_HEADER_LEN, MAX_SPACE_AMPLIFICATION,
                MINIMUM_ITEMS_PER_SEGMENT, SEG_HEADER_LEN,
            },
            DiskPtr, Log, LogKind, LogOffset, LogRead, Lsn, PageCache, PageId,
            SegmentMode,
        },
    },
    crossbeam_epoch::{pin, Atomic, Guard, Owned, Shared},
};

pub use self::{
    batch::Batch,
    config::Config,
    db::{open, Db},
    iter::Iter,
    ivec::IVec,
    result::{Error, Result},
    subscription::{Event, Subscriber},
    transaction::{
        abort, ConflictableTransactionError, ConflictableTransactionResult,
        TransactionError, TransactionResult, Transactional, TransactionalTree,
    },
    tree::{CompareAndSwapError, CompareAndSwapResult, Tree},
};

use {
    self::{
        binary_search::binary_search_lub,
        context::Context,
        histogram::Histogram,
        lru::Lru,
        meta::Meta,
        metrics::{clock, Measure, M},
        node::{Data, Node},
        oneshot::{OneShot, OneShotFiller},
        result::CasResult,
        serialization::Serialize,
        subscription::Subscriptions,
        tree::TreeInner,
        vecset::VecSet,
    },
    crossbeam_utils::{Backoff, CachePadded},
    log::{debug, error, trace, warn},
    pagecache::RecoveryGuard,
    parking_lot::{Condvar, Mutex, RwLock},
    std::{
        collections::BTreeMap,
        convert::TryFrom,
        fmt::{self, Debug},
        io::{Read, Write},
        sync::{
            atomic::{
                AtomicBool, AtomicI64 as AtomicLsn, AtomicU64, AtomicUsize,
                Ordering::{Acquire, Relaxed, Release, SeqCst},
            },
            Arc,
        },
    },
};

fn crc32(buf: &[u8]) -> u32 {
    let mut hasher = crc32fast::Hasher::new();
    hasher.update(buf);
    hasher.finalize()
}

#[cfg(any(test, feature = "lock_free_delays"))]
mod debug_delay;

#[cfg(any(test, feature = "lock_free_delays"))]
use debug_delay::debug_delay;

/// This function is useful for inducing random jitter into our atomic
/// operations, shaking out more possible interleavings quickly. It gets
/// fully eliminated by the compiler in non-test code.
#[cfg(not(any(test, feature = "lock_free_delays")))]
const fn debug_delay() {}

/// Link denotes a tree node or its modification fragment such as
/// key addition or removal.
#[derive(Clone, Debug, PartialEq)]
pub enum Link {
    /// A new value is set for a given key
    Set(IVec, IVec),
    /// The associated value is removed for a given key
    Del(IVec),
    /// A child of this Index node is marked as mergable
    ParentMergeIntention(PageId),
    /// The merging child has been completely merged into its left sibling
    ParentMergeConfirm,
    /// A Node is marked for being merged into its left sibling
    ChildMergeCap,
}

/// A fast map that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastMap8<K, V> = std::collections::HashMap<
    K,
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// A fast set that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastSet8<V> = std::collections::HashSet<
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// Allows arbitrary logic to be injected into mere operations of the
/// `PageCache`.
pub type MergeOperator = fn(
    key: &[u8],
    last_value: Option<&[u8]>,
    new_merge: &[u8],
) -> Option<Vec<u8>>;

fn is_sorted<T: PartialOrd>(xs: &[T]) -> bool {
    xs.windows(2).all(|pair| pair[0] <= pair[1])
}
<commit_msg>Export Serialize for testing<commit_after>//! `sled` is a high-performance embedded database with
//! an API that is similar to a `BTreeMap<[u8], [u8]>`,
//! but with several additional capabilities for
//! assisting creators of stateful systems.
//!
//! It is fully thread-safe, and all operations are
//! atomic. Multiple `Tree`s are supported with the
//! [`Db::open_tree`](struct.Db.html#method.open_tree) method.
//!
//! ACID transactions involving reads and writes to
//! multiple items are supported with the
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! method. Transactions may also operate over
//! multiple `Tree`s (see
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! docs for more info).
//!
//! Users may also subscribe to updates on individual
//! `Tree`s by using the
//! [`Tree::watch_prefix`](struct.Tree.html#method.watch_prefix)
//! method, which returns a blocking `Iterator` over
//! updates to keys that begin with the provided
//! prefix. You may supply an empty prefix to subscribe
//! to everything.
//!
//! [Merge operators](https://github.com/spacejam/sled/wiki/merge-operators)
//! (aka read-modify-write operators) are supported. A
//! merge operator is a function that specifies
//! how new data can be merged into an existing value
//! without requiring both a read and a write.
//! Using the
//! [`Tree::merge`](struct.Tree.html#method.merge)
//! method, you may "push" data to a `Tree` value
//! and have the provided merge operator combine
//! it with the existing value, if there was one.
//! They are set on a per-`Tree` basis, and essentially
//! allow any sort of data structure to be built
//! using merges as an atomic high-level operation.
//!
//! `sled` is built by experienced database engineers
//! who think users should spend less time tuning and
//! working against high-friction APIs. Expect
//! significant ergonomic and performance improvements
//! over time. Most surprises are bugs, so please
//! [let us know](mailto:t@jujit.su?subject=sled%20sucks!!!) if something
//! is high friction.
//!
//! # Examples
//!
//! ```
//! let t = sled::open("my_db").unwrap();
//!
//! // insert and get
//! t.insert(b"yo!", b"v1");
//! assert_eq!(&t.get(b"yo!").unwrap().unwrap(), b"v1");
//!
//! // Atomic compare-and-swap.
//! t.compare_and_swap(
//!     b"yo!",      // key
//!     Some(b"v1"), // old value, None for not present
//!     Some(b"v2"), // new value, None for delete
//! )
//! .unwrap();
//!
//! // Iterates over key-value pairs, starting at the given key.
//! let scan_key: &[u8] = b"a non-present key before yo!";
//! let mut iter = t.range(scan_key..);
//! assert_eq!(&iter.next().unwrap().unwrap().0, b"yo!");
//! assert_eq!(iter.next(), None);
//!
//! t.remove(b"yo!");
//! assert_eq!(t.get(b"yo!"), Ok(None));
//! ```
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/spacejam/sled/master/art/tree_face_anti-transphobia.png"
)]
#![cfg_attr(test, deny(warnings))]
#![deny(
    missing_docs,
    future_incompatible,
    nonstandard_style,
    rust_2018_idioms,
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unsafe_code,
    unused_qualifications
)]
#![deny(
    // over time, consider enabling the following commented-out lints:
    // clippy::missing_const_for_fn,
    // clippy::missing_docs_in_private_items,
    // clippy::module_name_repetitions,
    // clippy::multiple_crate_versions,
    // clippy::unimplemented,
    // clippy::wildcard_enum_match_arm,
    // clippy::else_if_without_else,
    // clippy::float_arithmetic,
    // clippy::indexing_slicing,
    clippy::cast_lossless,
    clippy::cast_possible_truncation,
    clippy::cast_possible_wrap,
    clippy::cast_precision_loss,
    clippy::cast_sign_loss,
    clippy::checked_conversions,
    clippy::decimal_literal_representation,
    clippy::doc_markdown,
    clippy::empty_enum,
    clippy::expl_impl_clone_on_copy,
    clippy::explicit_into_iter_loop,
    clippy::explicit_iter_loop,
    clippy::fallible_impl_from,
    clippy::filter_map,
    clippy::filter_map_next,
    clippy::find_map,
    clippy::get_unwrap,
    clippy::if_not_else,
    clippy::inline_always,
    clippy::invalid_upcast_comparisons,
    clippy::items_after_statements,
    clippy::map_flatten,
    clippy::match_same_arms,
    clippy::maybe_infinite_iter,
    clippy::mem_forget,
    clippy::multiple_inherent_impl,
    clippy::mut_mut,
    clippy::needless_borrow,
    clippy::needless_continue,
    clippy::needless_pass_by_value,
    clippy::non_ascii_literal,
    clippy::option_map_unwrap_or,
    clippy::option_map_unwrap_or_else,
    clippy::path_buf_push_overwrite,
    clippy::print_stdout,
    clippy::pub_enum_variant_names,
    clippy::redundant_closure_for_method_calls,
    clippy::replace_consts,
    clippy::result_map_unwrap_or_else,
    clippy::shadow_reuse,
    clippy::shadow_same,
    clippy::shadow_unrelated,
    clippy::single_match_else,
    clippy::string_add,
    clippy::string_add_assign,
    clippy::type_repetition_in_bounds,
    clippy::unicode_not_nfc,
    clippy::unseparated_literal_suffix,
    clippy::used_underscore_binding,
    clippy::wildcard_dependencies,
    clippy::wrong_pub_self_convention,
)]
#![recursion_limit = "128"]

#[cfg(feature = "failpoints")]
use fail::fail_point;

macro_rules! maybe_fail {
    ($e:expr) => {
        #[cfg(feature = "failpoints")]
        fail_point!($e, |_| Err(Error::FailPoint));
    };
}

macro_rules! once {
    ($args:block) => {
        static E: AtomicBool = AtomicBool::new(false);
        if !E.compare_and_swap(false, true, Relaxed) {
            // only execute this once
            $args;
        }
    };
}

mod batch;
mod binary_search;
mod config;
mod context;
mod db;
mod dll;
mod fastlock;
mod histogram;
mod iter;
mod ivec;
mod lazy;
mod lru;
mod meta;
mod metrics;
mod node;
mod oneshot;
mod pagecache;
mod prefix;
mod result;
mod serialization;
mod stack;
mod subscription;
mod sys_limits;
mod transaction;
mod tree;
mod vecset;

#[cfg(not(any(windows, target_os = "linux", target_os = "macos")))]
mod threadpool {
    use super::OneShot;

    /// Just execute a task without involving threads.
    pub fn spawn<F, R>(work: F) -> OneShot<R>
    where
        F: FnOnce() -> R + Send + 'static,
        R: Send + 'static,
    {
        let (promise_filler, promise) = OneShot::pair();
        let task = move || {
            let result = (work)();
            promise_filler.fill(result);
        };

        (task)();
        return promise;
    }
}

#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
mod threadpool;

#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
mod flusher;

#[cfg(feature = "event_log")]
/// The event log helps debug concurrency issues.
pub mod event_log;

#[cfg(feature = "measure_allocs")]
mod measure_allocs;

#[cfg(feature = "measure_allocs")]
#[global_allocator]
static ALLOCATOR: measure_allocs::TrackingAllocator =
    measure_allocs::TrackingAllocator;

const DEFAULT_TREE_ID: &[u8] = b"__sled__default";

/// hidden re-export of items for testing purposes
#[doc(hidden)]
pub use {
    self::{
        config::RunningConfig,
        lazy::Lazy,
        pagecache::{
            constants::{
                MAX_MSG_HEADER_LEN, MAX_SPACE_AMPLIFICATION,
                MINIMUM_ITEMS_PER_SEGMENT, SEG_HEADER_LEN,
            },
            DiskPtr, Log, LogKind, LogOffset, LogRead, Lsn, PageCache, PageId,
            SegmentMode,
        },
        serialization::Serialize,
    },
    crossbeam_epoch::{pin, Atomic, Guard, Owned, Shared},
};

pub use self::{
    batch::Batch,
    config::Config,
    db::{open, Db},
    iter::Iter,
    ivec::IVec,
    result::{Error, Result},
    subscription::{Event, Subscriber},
    transaction::{
        abort, ConflictableTransactionError, ConflictableTransactionResult,
        TransactionError, TransactionResult, Transactional, TransactionalTree,
    },
    tree::{CompareAndSwapError, CompareAndSwapResult, Tree},
};

use {
    self::{
        binary_search::binary_search_lub,
        context::Context,
        histogram::Histogram,
        lru::Lru,
        meta::Meta,
        metrics::{clock, Measure, M},
        node::{Data, Node},
        oneshot::{OneShot, OneShotFiller},
        result::CasResult,
        subscription::Subscriptions,
        tree::TreeInner,
        vecset::VecSet,
    },
    crossbeam_utils::{Backoff, CachePadded},
    log::{debug, error, trace, warn},
    pagecache::RecoveryGuard,
    parking_lot::{Condvar, Mutex, RwLock},
    std::{
        collections::BTreeMap,
        convert::TryFrom,
        fmt::{self, Debug},
        io::{Read, Write},
        sync::{
            atomic::{
                AtomicBool, AtomicI64 as AtomicLsn, AtomicU64, AtomicUsize,
                Ordering::{Acquire, Relaxed, Release, SeqCst},
            },
            Arc,
        },
    },
};

fn crc32(buf: &[u8]) -> u32 {
    let mut hasher = crc32fast::Hasher::new();
    hasher.update(buf);
    hasher.finalize()
}

#[cfg(any(test, feature = "lock_free_delays"))]
mod debug_delay;

#[cfg(any(test, feature = "lock_free_delays"))]
use debug_delay::debug_delay;

/// This function is useful for inducing random jitter into our atomic
/// operations, shaking out more possible interleavings quickly. It gets
/// fully eliminated by the compiler in non-test code.
#[cfg(not(any(test, feature = "lock_free_delays")))]
const fn debug_delay() {}

/// Link denotes a tree node or its modification fragment such as
/// key addition or removal.
#[derive(Clone, Debug, PartialEq)]
pub enum Link {
    /// A new value is set for a given key
    Set(IVec, IVec),
    /// The associated value is removed for a given key
    Del(IVec),
    /// A child of this Index node is marked as mergable
    ParentMergeIntention(PageId),
    /// The merging child has been completely merged into its left sibling
    ParentMergeConfirm,
    /// A Node is marked for being merged into its left sibling
    ChildMergeCap,
}

/// A fast map that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastMap8<K, V> = std::collections::HashMap<
    K,
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// A fast set that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastSet8<V> = std::collections::HashSet<
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// Allows arbitrary logic to be injected into mere operations of the
/// `PageCache`.
pub type MergeOperator = fn(
    key: &[u8],
    last_value: Option<&[u8]>,
    new_merge: &[u8],
) -> Option<Vec<u8>>;

fn is_sorted<T: PartialOrd>(xs: &[T]) -> bool {
    xs.windows(2).all(|pair| pair[0] <= pair[1])
}
<|endoftext|>


<commit_before>#![crate_id = "logger"]
#![license = "MIT"]

//! Request logging middleware for Iron

extern crate iron;
extern crate time;

use iron::{Ingot, Alloy, Request, Response};
use iron::ingot::{Status, Continue};

use time::precise_time_ns;

#[deriving(Clone)]
pub struct Logger {
    entry_time: u64
}

impl Logger {
    pub fn new() -> Logger {
        Logger { entry_time: 0u64 }
    }
}

impl<Rq: Request, Rs: Response> Ingot<Rq, Rs> for Logger {
    fn enter(&mut self, _req: &mut Rq, _res: &mut Rs, _alloy: &mut Alloy) -> Status {
        self.entry_time = precise_time_ns();
        Continue
    }
    fn exit(&mut self, req: &mut Rq, res: &mut Rs, _al: &mut Alloy) -> Status {
        let response_time_ms = (precise_time_ns() - self.entry_time) as f64 / 1000000.0;
        println!("Request body: {}\nMethod: {}\nURI: {}\nStatus: {}\nResponse time: {} ms\n",
                 req.body(), req.method(), req.uri(), res.status(), response_time_ms);
        Continue
    }
}
<commit_msg>(feat) Implemented single-line logging format with colored response codes.<commit_after>#![crate_id = "logger"]
#![license = "MIT"]

//! Request logging middleware for Iron

extern crate iron;
extern crate time;

use iron::{Ingot, Alloy, Request, Response};
use iron::ingot::{Status, Continue};

use time::precise_time_ns;

use std::io::stdio::println;

#[deriving(Clone)]
pub struct Logger {
    entry_time: u64
}

impl Logger {
    pub fn new() -> Logger {
        Logger { entry_time: 0u64 }
    }
}

enum Color {
    Red,
    Yellow,
    Green,
    Blue
}

fn colorize(string: String, color: Color) -> String {
    let color_str = match color {
        Red => "\x1B[31m",
        Yellow => "\x1B[33m",
        Green => "\x1B[32m",
        Blue => "\x1B[34m"
    };
    color_str.to_string().append(string.as_slice()).append("\x1B[39m")
}

impl<Rq: Request, Rs: Response> Ingot<Rq, Rs> for Logger {
    fn enter(&mut self, _req: &mut Rq, _res: &mut Rs, _alloy: &mut Alloy) -> Status {
        self.entry_time = precise_time_ns();
        Continue
    }
    fn exit(&mut self, req: &mut Rq, res: &mut Rs, _al: &mut Alloy) -> Status {
        let status = res.status();
        let status_color = match status.code() {
            _n @ 200..299 => Green, // Success
            _n @ 300..399 => Yellow, // Redirection
            _n @ 400..599 => Red, // Error
            _ => Blue // Information
        };
        let response_time_ms = (precise_time_ns() - self.entry_time) as f64 / 1000000.0;

        let mut output = String::new();
        output.push_str(format!("\x1B[1m{}\x1B[0m {} \x1B[1m->\x1B[0m ",
                                req.method(), req.uri()).as_slice());
        output.push_str(colorize(format!("{}", status), status_color).as_slice());
        output.push_str(format!(" ({} ms)", response_time_ms).as_slice());
        println(output.as_slice());

        Continue
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Write};
use std::path::Path;
use std::process;

const NOSYMLINK: &str = "
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When building `cxx` from a git clone, git's symlink support needs
to be enabled on platforms that have it off by default (Windows).
Either use:

   $ git config --global core.symlinks true

prior to cloning, or else use:

   $ git clone -c core.symlinks=true ...

for the clone.

Symlinks are only required for local development, not for building
`cxx` as a (possibly transitive) dependency from crates.io.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
";

fn main() {
    if !Path::new("src/syntax/mod.rs").exists() {
        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
        process::exit(1);
    }
}
<commit_msg>Display usable clone command on symlink error<commit_after>use std::io::{self, Write};
use std::path::Path;
use std::process;

const NOSYMLINK: &str = "
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When building `cxx` from a git clone, git's symlink support needs
to be enabled on platforms that have it off by default (Windows).
Either use:

   $ git config --global core.symlinks true

prior to cloning, or else use:

   $ git clone -c core.symlinks=true https://github.com/dtolnay/cxx

for the clone.

Symlinks are only required for local development, not for building
`cxx` as a (possibly transitive) dependency from crates.io.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
";

fn main() {
    if !Path::new("src/syntax/mod.rs").exists() {
        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
        process::exit(1);
    }
}
<|endoftext|>


<commit_before>#![feature(alloc, core, old_io)]

extern crate xml;

pub use builder::build;
pub use dom::{Document, Element, RcNode, RcElement};

pub use xml::EventReader;
pub use xml::attribute::OwnedAttribute;
pub use xml::common::Error as ParserError;
pub use xml::common::XmlVersion;
pub use xml::name::OwnedName;
pub use xml::namespace::Namespace;
pub use xml::reader::config::ParserConfig;
pub use xml::reader::events::XmlEvent;

mod builder;
mod dom;
mod error;
<commit_msg>Redefine exports.<commit_after>#![feature(alloc, core, old_io)]

extern crate xml;

pub use builder::build;
pub use dom::{
    Document,
    Element, ElementIterator, RcElement, WeakElement,
    Text, TextIterator,
    Node, RcNode,
};
pub use error::BuildError;

pub use xml::EventReader;
pub use xml::attribute::OwnedAttribute;
pub use xml::common::Error as ParserError;
pub use xml::common::XmlVersion;
pub use xml::name::OwnedName;
pub use xml::namespace::Namespace;
pub use xml::reader::config::ParserConfig;
pub use xml::reader::events::XmlEvent;

mod builder;
mod dom;
mod error;
<|endoftext|>


<commit_before>#![cfg_attr(feature = "unstable", plugin(serde_macros))]
#![cfg_attr(feature = "unstable", feature(plugin, custom_derive, custom_attribute))]
#![doc(html_root_url="https://arcnmx.github.io/ocf-rs")]

#[cfg(feature = "unstable")]
include!("lib.rs");

#[cfg(feature = "syntex")]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
<commit_msg>Fail to compile if no stability feature is provided<commit_after>#![cfg_attr(feature = "unstable", plugin(serde_macros))]
#![cfg_attr(feature = "unstable", feature(plugin, custom_derive, custom_attribute))]
#![doc(html_root_url="https://arcnmx.github.io/ocf-rs")]

#[cfg(feature = "unstable")]
include!("lib.rs");

#[cfg(feature = "syntex")]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));

#[cfg(not(any(feature = "unstable", feature = "syntex")))]
error_expected_unstable_or_stable_feature!();
<|endoftext|>


<commit_before>//! This crate defines voxel data types and interfaces for interacting with voxels.

#![deny(missing_docs)]
#![deny(warnings)]

extern crate cgmath;
extern crate collision;
#[macro_use]
extern crate log;
extern crate serde;
#[macro_use]
extern crate serde_derive;

pub mod bounds;
pub mod brush;
pub mod field;
pub mod mosaic;
pub mod tree;

pub mod impls;

/// The interface provided by Voxels.
pub trait T<Material> {
  /// Apply a brush to this voxel.
  fn brush<Mosaic>(
    this: &mut Self,
    bounds: &bounds::T,
    brush: &mut brush::T<Mosaic>,
  ) where Mosaic: mosaic::T<Material>;
}
<commit_msg>Fix testing<commit_after>//! This crate defines voxel data types and interfaces for interacting with voxels.

#![deny(missing_docs)]
#![deny(warnings)]

#![cfg_attr(test, feature(test))]

extern crate cgmath;
extern crate collision;
#[macro_use]
extern crate log;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[cfg(test)]
extern crate test;

pub mod bounds;
pub mod brush;
pub mod field;
pub mod mosaic;
pub mod tree;

pub mod impls;

/// The interface provided by Voxels.
pub trait T<Material> {
  /// Apply a brush to this voxel.
  fn brush<Mosaic>(
    this: &mut Self,
    bounds: &bounds::T,
    brush: &mut brush::T<Mosaic>,
  ) where Mosaic: mosaic::T<Material>;
}
<|endoftext|>


<commit_before>use atom::*;
use error::*;

pub fn add(v: &Vec<Value>) -> Result<Value> {
    assert!(v.len() >= 2);
    v.iter().fold(Ok(0.into()), |acc, x| acc.and_then(|a| a.add(x)))
}

pub fn sub(v: &Vec<Value>) -> Result<Value> {
    assert!(v.len() == 2);
    v[0].sub(&v[1])
}
pub fn mul(v: &Vec<Value>) -> Result<Value> {
    assert!(v.len() >= 2);
    v.iter().fold(Ok(1.into()), |acc, x| acc.and_then(|a| a.mul(x)))
}

pub fn div(v: &Vec<Value>) -> Result<Value> {
    assert!(v.len() >= 2);
    v[0].div(&v[1])
}

pub fn modulus(v: &Vec<Value>) -> Result<Value> {
    assert!(v.len() == 2);
    v[0].modulus(&v[1])
}
<commit_msg>Use &[Value] in ops instead of &Vec<Value><commit_after>use atom::*;
use error::*;

pub fn add(v: &[Value]) -> Result<Value> {
    assert!(v.len() >= 2);
    v.iter().fold(Ok(0.into()), |acc, x| acc.and_then(|a| a.add(x)))
}

pub fn sub(v: &[Value]) -> Result<Value> {
    assert!(v.len() == 2);
    v[0].sub(&v[1])
}
pub fn mul(v: &[Value]) -> Result<Value> {
    assert!(v.len() >= 2);
    v.iter().fold(Ok(1.into()), |acc, x| acc.and_then(|a| a.mul(x)))
}

pub fn div(v: &[Value]) -> Result<Value> {
    assert!(v.len() >= 2);
    v[0].div(&v[1])
}

pub fn modulus(v: &[Value]) -> Result<Value> {
    assert!(v.len() == 2);
    v[0].modulus(&v[1])
}
<|endoftext|>


<commit_before>use ONE_MINUS_EPSILON;

const PCG32_DEFAULT_STATE: u64 = 0x853c49e6748fea9b;
const PCG32_DEFAULT_STREAM: u64 = 0xda3e39cb94b95bdb;
const PCG32_MULT: u64 = 0x5851f42d4c957f2d;

#[derive(Copy, Clone)]
pub struct RNG {
    state: u64,
    inc: u64,
}

impl RNG {
    pub fn new() -> RNG {
        RNG {
            state: PCG32_DEFAULT_STATE,
            inc: PCG32_DEFAULT_STREAM,
        }
    }

    pub fn uniform_u32(&mut self) -> u32 {
        let oldstate = self.state;
        self.state = oldstate * PCG32_MULT + self.inc;
        let xorshifted = (((oldstate >> 18) ^ oldstate) >> 27) as u32;
        let rot = (oldstate >> 59) as u32;

        (xorshifted >> rot) | (xorshifted << ((!rot + 1) & 31))
    }

    pub fn uniform_u32_bounded(&mut self, b: u32) -> u32 {
        let threshold = (!b + 1) & b;
        loop {
            let r = self.uniform_u32();
            if r >= threshold {
                return r % b;
            }
        }
    }

    pub fn uniform_f32(&mut self) -> f32 {
        (self.uniform_u32() as f32 * 2.3283064365386963e-10).min(ONE_MINUS_EPSILON)
    }

    pub fn set_sequence(&mut self, seed: u64) {
        self.state = 0;
        self.inc = (seed << 1) | 1;
        let _ = self.uniform_u32();
        self.state += PCG32_DEFAULT_STATE;
        let _ = self.uniform_u32();
    }
}

impl Default for RNG {
    fn default() -> RNG {
        RNG::new()
    }
}
<commit_msg>Use Wrapping<> so it doesn't blow-up in debug mode<commit_after>use std::num::Wrapping;

use ONE_MINUS_EPSILON;

const PCG32_DEFAULT_STATE: Wrapping<u64> = Wrapping(0x853c49e6748fea9b);
const PCG32_DEFAULT_STREAM: Wrapping<u64> = Wrapping(0xda3e39cb94b95bdb);
const PCG32_MULT: Wrapping<u64> = Wrapping(0x5851f42d4c957f2d);

#[derive(Copy, Clone)]
pub struct RNG {
    state: Wrapping<u64>,
    inc: Wrapping<u64>,
}

impl RNG {
    pub fn new() -> RNG {
        RNG {
            state: PCG32_DEFAULT_STATE,
            inc: PCG32_DEFAULT_STREAM,
        }
    }

    pub fn uniform_u32(&mut self) -> u32 {
        let oldstate = self.state;
        self.state = oldstate * PCG32_MULT + self.inc;
        let xorshifted = Wrapping((((oldstate >> 18) ^ oldstate) >> 27).0 as u32);
        let rot = (oldstate >> 59).0 as u32;

        ((xorshifted.0 >> rot) | (xorshifted.0 << ((!Wrapping(rot) + Wrapping(1)).0 & 31)))
    }

    pub fn uniform_u32_bounded(&mut self, b: u32) -> u32 {
        let threshold = (!b + 1) & b;
        loop {
            let r = self.uniform_u32();
            if r >= threshold {
                return r % b;
            }
        }
    }

    pub fn uniform_f32(&mut self) -> f32 {
        (self.uniform_u32() as f32 * 2.3283064365386963e-10).min(ONE_MINUS_EPSILON)
    }

    pub fn set_sequence(&mut self, seed: u64) {
        self.state = Wrapping(0);
        self.inc = Wrapping((seed << 1) | 1);
        let _ = self.uniform_u32();
        self.state += PCG32_DEFAULT_STATE;
        let _ = self.uniform_u32();
    }
}

impl Default for RNG {
    fn default() -> RNG {
        RNG::new()
    }
}
<|endoftext|>


<commit_before>use crate::common::*;
use crate::d2s;
use crate::d2s_intrinsics::*;
use crate::parse::Error;
#[cfg(feature = "no-panic")]
use no_panic::no_panic;

const DOUBLE_EXPONENT_BIAS: usize = 1023;

fn floor_log2(value: u64) -> u32 {
    63_u32.wrapping_sub(value.leading_zeros())
}

#[cfg_attr(feature = "no-panic", no_panic)]
pub fn s2d(buffer: &[u8]) -> Result<f64, Error> {
    let len = buffer.len();
    if len == 0 {
        return Err(Error::InputTooShort);
    }

    let mut m10digits = 0;
    let mut e10digits = 0;
    let mut dot_index = len;
    let mut e_index = len;
    let mut m10 = 0u64;
    let mut e10 = 0i32;
    let mut signed_m = false;
    let mut signed_e = false;

    let mut i = 0;
    if unsafe { *buffer.get_unchecked(0) } == b'-' {
        signed_m = true;
        i += 1;
    }

    while let Some(c) = buffer.get(i).copied() {
        if c == b'.' {
            if dot_index != len {
                return Err(Error::MalformedInput);
            }
            dot_index = i;
            i += 1;
            continue;
        }
        if c < b'0' || c > b'9' {
            break;
        }
        if m10digits >= 17 {
            return Err(Error::InputTooLong);
        }
        m10 = 10 * m10 + (c - b'0') as u64;
        if m10 != 0 {
            m10digits += 1;
        }
        i += 1;
    }

    if let Some(b'e') | Some(b'E') = buffer.get(i) {
        e_index = i;
        i += 1;
        match buffer.get(i) {
            Some(b'-') => {
                signed_e = true;
                i += 1;
            }
            Some(b'+') => i += 1,
            _ => {}
        }
        while let Some(c) = buffer.get(i).copied() {
            if c < b'0' || c > b'9' {
                return Err(Error::MalformedInput);
            }
            if e10digits > 3 {
                // TODO: Be more lenient. Return +/-Infinity or +/-0 instead.
                return Err(Error::InputTooLong);
            }
            e10 = 10 * e10 + (c - b'0') as i32;
            if e10 != 0 {
                e10digits += 1;
            }
            i += 1;
        }
    }

    if i < len {
        return Err(Error::MalformedInput);
    }
    if signed_e {
        e10 = -e10;
    }
    e10 -= if dot_index < e_index {
        (e_index - dot_index - 1) as i32
    } else {
        0
    };
    if m10 == 0 {
        return Ok(if signed_m { -0.0 } else { 0.0 });
    }

    if m10digits + e10 <= -324 || m10 == 0 {
        // Number is less than 1e-324, which should be rounded down to 0; return
        // +/-0.0.
        let ieee = (signed_m as u64) << (d2s::DOUBLE_EXPONENT_BITS + d2s::DOUBLE_MANTISSA_BITS);
        return Ok(f64::from_bits(ieee));
    }
    if m10digits + e10 >= 310 {
        // Number is larger than 1e+309, which should be rounded to +/-Infinity.
        let ieee = ((signed_m as u64) << (d2s::DOUBLE_EXPONENT_BITS + d2s::DOUBLE_MANTISSA_BITS))
            | (0x7ff_u64 << d2s::DOUBLE_MANTISSA_BITS);
        return Ok(f64::from_bits(ieee));
    }

    // Convert to binary float m2 * 2^e2, while retaining information about
    // whether the conversion was exact (trailing_zeros).
    let e2: i32;
    let m2: u64;
    let mut trailing_zeros: bool;
    if e10 >= 0 {
        // The length of m * 10^e in bits is:
        //   log2(m10 * 10^e10) = log2(m10) + e10 log2(10) = log2(m10) + e10 + e10 * log2(5)
        //
        // We want to compute the DOUBLE_MANTISSA_BITS + 1 top-most bits (+1 for
        // the implicit leading one in IEEE format). We therefore choose a
        // binary output exponent of
        //   log2(m10 * 10^e10) - (DOUBLE_MANTISSA_BITS + 1).
        //
        // We use floor(log2(5^e10)) so that we get at least this many bits; better to
        // have an additional bit than to not have enough bits.
        e2 = floor_log2(m10)
            .wrapping_add(e10 as u32)
            .wrapping_add(log2_pow5(e10) as u32)
            .wrapping_sub(d2s::DOUBLE_MANTISSA_BITS + 1) as i32;

        // We now compute [m10 * 10^e10 / 2^e2] = [m10 * 5^e10 / 2^(e2-e10)].
        // To that end, we use the DOUBLE_POW5_SPLIT table.
        let j = e2
            .wrapping_sub(e10)
            .wrapping_sub(ceil_log2_pow5(e10))
            .wrapping_add(d2s::DOUBLE_POW5_BITCOUNT);
        debug_assert!(j >= 0);
        debug_assert!(e10 < d2s::DOUBLE_POW5_SPLIT.len() as i32);
        m2 = mul_shift_64(
            m10,
            unsafe { d2s::DOUBLE_POW5_SPLIT.get_unchecked(e10 as usize) },
            j as u32,
        );

        // We also compute if the result is exact, i.e.,
        //   [m10 * 10^e10 / 2^e2] == m10 * 10^e10 / 2^e2.
        // This can only be the case if 2^e2 divides m10 * 10^e10, which in turn
        // requires that the largest power of 2 that divides m10 + e10 is
        // greater than e2. If e2 is less than e10, then the result must be
        // exact. Otherwise we use the existing multiple_of_power_of_2 function.
        trailing_zeros = e2 < e10 || e2 - e10 < 64 && multiple_of_power_of_2(m10, (e2 - e10) as u32);
    } else {
        e2 = floor_log2(m10)
            .wrapping_add(e10 as u32)
            .wrapping_sub(ceil_log2_pow5(-e10) as u32)
            .wrapping_sub(d2s::DOUBLE_MANTISSA_BITS + 1) as i32;
        let j = e2
            .wrapping_sub(e10)
            .wrapping_add(ceil_log2_pow5(-e10))
            .wrapping_sub(1)
            .wrapping_add(d2s::DOUBLE_POW5_INV_BITCOUNT);
        debug_assert!(-e10 < d2s::DOUBLE_POW5_INV_SPLIT.len() as i32);
        m2 = mul_shift_64(
            m10,
            unsafe { d2s::DOUBLE_POW5_INV_SPLIT.get_unchecked(-e10 as usize) },
            j as u32,
        );
        trailing_zeros = multiple_of_power_of_5(m10, -e10 as u32);
    }

    // Compute the final IEEE exponent.
    let mut ieee_e2 = i32::max(0, e2 + DOUBLE_EXPONENT_BIAS as i32 + floor_log2(m2) as i32) as u32;

    if ieee_e2 > 0x7fe {
        // Final IEEE exponent is larger than the maximum representable; return +/-Infinity.
        let ieee = ((signed_m as u64) << (d2s::DOUBLE_EXPONENT_BITS + d2s::DOUBLE_MANTISSA_BITS))
            | (0x7ff_u64 << d2s::DOUBLE_MANTISSA_BITS);
        return Ok(f64::from_bits(ieee));
    }

    // We need to figure out how much we need to shift m2. The tricky part is that we need to take
    // the final IEEE exponent into account, so we need to reverse the bias and also special-case
    // the value 0.
    let shift = if ieee_e2 == 0 { 1 } else { ieee_e2 as i32 }
        .wrapping_sub(e2)
        .wrapping_sub(DOUBLE_EXPONENT_BIAS as i32)
        .wrapping_sub(d2s::DOUBLE_MANTISSA_BITS as i32);
    debug_assert!(shift >= 0);

    // We need to round up if the exact value is more than 0.5 above the value we computed. That's
    // equivalent to checking if the last removed bit was 1 and either the value was not just
    // trailing zeros or the result would otherwise be odd.
    //
    // We need to update trailing_zeros given that we have the exact output exponent ieee_e2 now.
    trailing_zeros &= (m2 & ((1_u64 << (shift - 1)) - 1)) == 0;
    let last_removed_bit = (m2 >> (shift - 1)) & 1;
    let round_up = last_removed_bit != 0 && (!trailing_zeros || ((m2 >> shift) & 1) != 0);

    let mut ieee_m2 = (m2 >> shift).wrapping_add(round_up as u64);
    if ieee_m2 == (1_u64 << (d2s::DOUBLE_MANTISSA_BITS + 1)) {
        // Due to how the IEEE represents +/-Infinity, we don't need to check for overflow here.
        ieee_e2 += 1;
    }
    ieee_m2 &= (1_u64 << d2s::DOUBLE_MANTISSA_BITS) - 1;
    let ieee = ((((signed_m as u64) << d2s::DOUBLE_EXPONENT_BITS) | ieee_e2 as u64)
        << d2s::DOUBLE_MANTISSA_BITS)
        | ieee_m2;
    Ok(f64::from_bits(ieee))
}
<commit_msg>Format with rustfmt 2020-04-21<commit_after>use crate::common::*;
use crate::d2s;
use crate::d2s_intrinsics::*;
use crate::parse::Error;
#[cfg(feature = "no-panic")]
use no_panic::no_panic;

const DOUBLE_EXPONENT_BIAS: usize = 1023;

fn floor_log2(value: u64) -> u32 {
    63_u32.wrapping_sub(value.leading_zeros())
}

#[cfg_attr(feature = "no-panic", no_panic)]
pub fn s2d(buffer: &[u8]) -> Result<f64, Error> {
    let len = buffer.len();
    if len == 0 {
        return Err(Error::InputTooShort);
    }

    let mut m10digits = 0;
    let mut e10digits = 0;
    let mut dot_index = len;
    let mut e_index = len;
    let mut m10 = 0u64;
    let mut e10 = 0i32;
    let mut signed_m = false;
    let mut signed_e = false;

    let mut i = 0;
    if unsafe { *buffer.get_unchecked(0) } == b'-' {
        signed_m = true;
        i += 1;
    }

    while let Some(c) = buffer.get(i).copied() {
        if c == b'.' {
            if dot_index != len {
                return Err(Error::MalformedInput);
            }
            dot_index = i;
            i += 1;
            continue;
        }
        if c < b'0' || c > b'9' {
            break;
        }
        if m10digits >= 17 {
            return Err(Error::InputTooLong);
        }
        m10 = 10 * m10 + (c - b'0') as u64;
        if m10 != 0 {
            m10digits += 1;
        }
        i += 1;
    }

    if let Some(b'e') | Some(b'E') = buffer.get(i) {
        e_index = i;
        i += 1;
        match buffer.get(i) {
            Some(b'-') => {
                signed_e = true;
                i += 1;
            }
            Some(b'+') => i += 1,
            _ => {}
        }
        while let Some(c) = buffer.get(i).copied() {
            if c < b'0' || c > b'9' {
                return Err(Error::MalformedInput);
            }
            if e10digits > 3 {
                // TODO: Be more lenient. Return +/-Infinity or +/-0 instead.
                return Err(Error::InputTooLong);
            }
            e10 = 10 * e10 + (c - b'0') as i32;
            if e10 != 0 {
                e10digits += 1;
            }
            i += 1;
        }
    }

    if i < len {
        return Err(Error::MalformedInput);
    }
    if signed_e {
        e10 = -e10;
    }
    e10 -= if dot_index < e_index {
        (e_index - dot_index - 1) as i32
    } else {
        0
    };
    if m10 == 0 {
        return Ok(if signed_m { -0.0 } else { 0.0 });
    }

    if m10digits + e10 <= -324 || m10 == 0 {
        // Number is less than 1e-324, which should be rounded down to 0; return
        // +/-0.0.
        let ieee = (signed_m as u64) << (d2s::DOUBLE_EXPONENT_BITS + d2s::DOUBLE_MANTISSA_BITS);
        return Ok(f64::from_bits(ieee));
    }
    if m10digits + e10 >= 310 {
        // Number is larger than 1e+309, which should be rounded to +/-Infinity.
        let ieee = ((signed_m as u64) << (d2s::DOUBLE_EXPONENT_BITS + d2s::DOUBLE_MANTISSA_BITS))
            | (0x7ff_u64 << d2s::DOUBLE_MANTISSA_BITS);
        return Ok(f64::from_bits(ieee));
    }

    // Convert to binary float m2 * 2^e2, while retaining information about
    // whether the conversion was exact (trailing_zeros).
    let e2: i32;
    let m2: u64;
    let mut trailing_zeros: bool;
    if e10 >= 0 {
        // The length of m * 10^e in bits is:
        //   log2(m10 * 10^e10) = log2(m10) + e10 log2(10) = log2(m10) + e10 + e10 * log2(5)
        //
        // We want to compute the DOUBLE_MANTISSA_BITS + 1 top-most bits (+1 for
        // the implicit leading one in IEEE format). We therefore choose a
        // binary output exponent of
        //   log2(m10 * 10^e10) - (DOUBLE_MANTISSA_BITS + 1).
        //
        // We use floor(log2(5^e10)) so that we get at least this many bits; better to
        // have an additional bit than to not have enough bits.
        e2 = floor_log2(m10)
            .wrapping_add(e10 as u32)
            .wrapping_add(log2_pow5(e10) as u32)
            .wrapping_sub(d2s::DOUBLE_MANTISSA_BITS + 1) as i32;

        // We now compute [m10 * 10^e10 / 2^e2] = [m10 * 5^e10 / 2^(e2-e10)].
        // To that end, we use the DOUBLE_POW5_SPLIT table.
        let j = e2
            .wrapping_sub(e10)
            .wrapping_sub(ceil_log2_pow5(e10))
            .wrapping_add(d2s::DOUBLE_POW5_BITCOUNT);
        debug_assert!(j >= 0);
        debug_assert!(e10 < d2s::DOUBLE_POW5_SPLIT.len() as i32);
        m2 = mul_shift_64(
            m10,
            unsafe { d2s::DOUBLE_POW5_SPLIT.get_unchecked(e10 as usize) },
            j as u32,
        );

        // We also compute if the result is exact, i.e.,
        //   [m10 * 10^e10 / 2^e2] == m10 * 10^e10 / 2^e2.
        // This can only be the case if 2^e2 divides m10 * 10^e10, which in turn
        // requires that the largest power of 2 that divides m10 + e10 is
        // greater than e2. If e2 is less than e10, then the result must be
        // exact. Otherwise we use the existing multiple_of_power_of_2 function.
        trailing_zeros =
            e2 < e10 || e2 - e10 < 64 && multiple_of_power_of_2(m10, (e2 - e10) as u32);
    } else {
        e2 = floor_log2(m10)
            .wrapping_add(e10 as u32)
            .wrapping_sub(ceil_log2_pow5(-e10) as u32)
            .wrapping_sub(d2s::DOUBLE_MANTISSA_BITS + 1) as i32;
        let j = e2
            .wrapping_sub(e10)
            .wrapping_add(ceil_log2_pow5(-e10))
            .wrapping_sub(1)
            .wrapping_add(d2s::DOUBLE_POW5_INV_BITCOUNT);
        debug_assert!(-e10 < d2s::DOUBLE_POW5_INV_SPLIT.len() as i32);
        m2 = mul_shift_64(
            m10,
            unsafe { d2s::DOUBLE_POW5_INV_SPLIT.get_unchecked(-e10 as usize) },
            j as u32,
        );
        trailing_zeros = multiple_of_power_of_5(m10, -e10 as u32);
    }

    // Compute the final IEEE exponent.
    let mut ieee_e2 = i32::max(0, e2 + DOUBLE_EXPONENT_BIAS as i32 + floor_log2(m2) as i32) as u32;

    if ieee_e2 > 0x7fe {
        // Final IEEE exponent is larger than the maximum representable; return +/-Infinity.
        let ieee = ((signed_m as u64) << (d2s::DOUBLE_EXPONENT_BITS + d2s::DOUBLE_MANTISSA_BITS))
            | (0x7ff_u64 << d2s::DOUBLE_MANTISSA_BITS);
        return Ok(f64::from_bits(ieee));
    }

    // We need to figure out how much we need to shift m2. The tricky part is that we need to take
    // the final IEEE exponent into account, so we need to reverse the bias and also special-case
    // the value 0.
    let shift = if ieee_e2 == 0 { 1 } else { ieee_e2 as i32 }
        .wrapping_sub(e2)
        .wrapping_sub(DOUBLE_EXPONENT_BIAS as i32)
        .wrapping_sub(d2s::DOUBLE_MANTISSA_BITS as i32);
    debug_assert!(shift >= 0);

    // We need to round up if the exact value is more than 0.5 above the value we computed. That's
    // equivalent to checking if the last removed bit was 1 and either the value was not just
    // trailing zeros or the result would otherwise be odd.
    //
    // We need to update trailing_zeros given that we have the exact output exponent ieee_e2 now.
    trailing_zeros &= (m2 & ((1_u64 << (shift - 1)) - 1)) == 0;
    let last_removed_bit = (m2 >> (shift - 1)) & 1;
    let round_up = last_removed_bit != 0 && (!trailing_zeros || ((m2 >> shift) & 1) != 0);

    let mut ieee_m2 = (m2 >> shift).wrapping_add(round_up as u64);
    if ieee_m2 == (1_u64 << (d2s::DOUBLE_MANTISSA_BITS + 1)) {
        // Due to how the IEEE represents +/-Infinity, we don't need to check for overflow here.
        ieee_e2 += 1;
    }
    ieee_m2 &= (1_u64 << d2s::DOUBLE_MANTISSA_BITS) - 1;
    let ieee = ((((signed_m as u64) << d2s::DOUBLE_EXPONENT_BITS) | ieee_e2 as u64)
        << d2s::DOUBLE_MANTISSA_BITS)
        | ieee_m2;
    Ok(f64::from_bits(ieee))
}
<|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 GPU based renderer for the web.

It serves as an experimental render backend for [Servo](https://servo.org/),
but it can also be used as such in a standalone application.

# External dependencies
WebRender currently depends on [FreeType](https://www.freetype.org/)

# Api Structure
The main entry point to WebRender is the `webrender::Renderer`.

By calling `Renderer::new(...)` you get a `Renderer`, as well as a `RenderApiSender`.
Your `Renderer` is responsible to render the previously processed frames onto the screen.

By calling `yourRenderApiSender.create_api()`, you'll get a `RenderApi` instance,
which is responsible for managing resources and documents. A worker thread is used internally
to untie the workload from the application thread and therefore be able to make better use of
multicore systems.

## Frame

What is referred to as a `frame`, is the current geometry on the screen.
A new Frame is created by calling [`set_display_list()`][newframe] on the `RenderApi`.
When the geometry is processed, the application will be informed via a `RenderNotifier`,
a callback which you employ with [set_render_notifier][notifier] on the `Renderer`
More information about [stacking contexts][stacking_contexts].

`set_display_list()` also needs to be supplied with `BuiltDisplayList`s.
These are obtained by finalizing a `DisplayListBuilder`. These are used to draw your geometry.
But it doesn't only contain trivial geometry, it can also store another StackingContext, as
they're nestable.

[stacking_contexts]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
[newframe]: ../webrender_api/struct.RenderApi.html#method.set_display_list
[notifier]: renderer/struct.Renderer.html#method.set_render_notifier
*/

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate thread_profiler;

mod border;
mod clip_scroll_node;
mod clip_scroll_tree;
mod debug_colors;
mod debug_font_data;
mod debug_render;
#[cfg(feature = "debugger")]
mod debug_server;
mod device;
mod ellipse;
mod frame;
mod frame_builder;
mod freelist;
mod geometry;
mod glyph_cache;
mod glyph_rasterizer;
mod gpu_cache;
mod internal_types;
mod mask_cache;
mod prim_store;
mod print_tree;
mod profiler;
mod record;
mod render_backend;
mod render_task;
mod renderer;
mod resource_cache;
mod scene;
mod spring;
mod texture_allocator;
mod texture_cache;
mod tiling;
mod util;

mod shader_source {
    include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
}

pub use record::{ApiRecordingReceiver, BinaryRecorder, WEBRENDER_RECORDING_HEADER};

mod platform {
    #[cfg(target_os="macos")]
    pub use platform::macos::font;
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub use platform::unix::font;
    #[cfg(target_os = "windows")]
    pub use platform::windows::font;

    #[cfg(target_os="macos")]
    pub mod macos {
        pub mod font;
    }
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub mod unix {
        pub mod font;
    }
    #[cfg(target_os = "windows")]
    pub mod windows {
        pub mod font;
    }
}

#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

#[cfg(all(unix, not(target_os="macos")))]
extern crate freetype;

#[cfg(target_os = "windows")]
extern crate dwrote;

extern crate app_units;
extern crate bincode;
extern crate euclid;
extern crate fxhash;
extern crate gleam;
extern crate num_traits;
//extern crate notify;
extern crate time;
pub extern crate webrender_api;
extern crate byteorder;
extern crate rayon;
extern crate plane_split;
#[cfg(feature = "debugger")]
extern crate ws;
#[cfg(feature = "debugger")]
extern crate serde_json;
#[cfg(feature = "debugger")]
#[macro_use]
extern crate serde_derive;

#[cfg(any(target_os="macos", target_os="windows"))]
extern crate gamma_lut;

pub use renderer::{ExternalImage, ExternalImageSource, ExternalImageHandler};
pub use renderer::{GraphicsApi, GraphicsApiInfo, ReadPixelsFormat, Renderer, RendererOptions};
pub use renderer::{CpuProfile, GpuProfile, DebugFlags};
pub use renderer::{MAX_VERTEX_TEXTURE_WIDTH, PROFILER_DBG, RENDER_TARGET_DBG, TEXTURE_CACHE_DBG};

pub use webrender_api as api;

#[doc(hidden)]
pub use device::build_shader_strings;
<commit_msg>Auto merge of #1617 - glennw:wr-fix-mod, r=larsbergstrom<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 GPU based renderer for the web.

It serves as an experimental render backend for [Servo](https://servo.org/),
but it can also be used as such in a standalone application.

# External dependencies
WebRender currently depends on [FreeType](https://www.freetype.org/)

# Api Structure
The main entry point to WebRender is the `webrender::Renderer`.

By calling `Renderer::new(...)` you get a `Renderer`, as well as a `RenderApiSender`.
Your `Renderer` is responsible to render the previously processed frames onto the screen.

By calling `yourRenderApiSender.create_api()`, you'll get a `RenderApi` instance,
which is responsible for managing resources and documents. A worker thread is used internally
to untie the workload from the application thread and therefore be able to make better use of
multicore systems.

## Frame

What is referred to as a `frame`, is the current geometry on the screen.
A new Frame is created by calling [`set_display_list()`][newframe] on the `RenderApi`.
When the geometry is processed, the application will be informed via a `RenderNotifier`,
a callback which you employ with [set_render_notifier][notifier] on the `Renderer`
More information about [stacking contexts][stacking_contexts].

`set_display_list()` also needs to be supplied with `BuiltDisplayList`s.
These are obtained by finalizing a `DisplayListBuilder`. These are used to draw your geometry.
But it doesn't only contain trivial geometry, it can also store another StackingContext, as
they're nestable.

[stacking_contexts]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
[newframe]: ../webrender_api/struct.RenderApi.html#method.set_display_list
[notifier]: renderer/struct.Renderer.html#method.set_render_notifier
*/

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate thread_profiler;

mod border;
mod clip_scroll_node;
mod clip_scroll_tree;
mod debug_colors;
mod debug_font_data;
mod debug_render;
#[cfg(feature = "debugger")]
mod debug_server;
mod device;
mod ellipse;
mod frame;
mod frame_builder;
mod freelist;
mod geometry;
mod glyph_cache;
mod glyph_rasterizer;
mod gpu_cache;
mod internal_types;
mod mask_cache;
mod prim_store;
mod print_tree;
mod profiler;
mod record;
mod render_backend;
mod render_task;
mod renderer;
mod resource_cache;
mod scene;
mod spring;
mod texture_allocator;
mod texture_cache;
mod tiling;
mod util;

mod shader_source {
    include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
}

pub use record::{ApiRecordingReceiver, BinaryRecorder, WEBRENDER_RECORDING_HEADER};

mod platform {
    #[cfg(target_os="macos")]
    pub use platform::macos::font;
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub use platform::unix::font;
    #[cfg(target_os = "windows")]
    pub use platform::windows::font;

    #[cfg(target_os="macos")]
    pub mod macos {
        pub mod font;
    }
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub mod unix {
        pub mod font;
    }
    #[cfg(target_os = "windows")]
    pub mod windows {
        pub mod font;
    }
}

#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

#[cfg(all(unix, not(target_os="macos")))]
extern crate freetype;

#[cfg(target_os = "windows")]
extern crate dwrote;

extern crate app_units;
extern crate bincode;
extern crate euclid;
extern crate fxhash;
extern crate gleam;
extern crate num_traits;
//extern crate notify;
extern crate time;
pub extern crate webrender_api;
extern crate byteorder;
extern crate rayon;
extern crate plane_split;
#[cfg(feature = "debugger")]
extern crate ws;
#[cfg(feature = "debugger")]
extern crate serde_json;
#[cfg(feature = "debugger")]
#[macro_use]
extern crate serde_derive;

#[cfg(any(target_os="macos", target_os="windows"))]
extern crate gamma_lut;

pub use renderer::{ExternalImage, ExternalImageSource, ExternalImageHandler};
pub use renderer::{GraphicsApi, GraphicsApiInfo, ReadPixelsFormat, Renderer, RendererOptions};
pub use renderer::{CpuProfile, GpuProfile, DebugFlags, RendererKind};
pub use renderer::{MAX_VERTEX_TEXTURE_WIDTH, PROFILER_DBG, RENDER_TARGET_DBG, TEXTURE_CACHE_DBG};

pub use webrender_api as api;

#[doc(hidden)]
pub use device::build_shader_strings;
<|endoftext|>


<commit_before>use super::Spec;

use std::cmp::PartialEq;
use std::fmt::Debug;

impl<'s, T> Spec<'s, Vec<T>>
    where T: Debug + PartialEq
{
    pub fn has_length(&self, expected: usize) {
        let length = self.subject.len();
        if length != expected {
            panic!(format!("expected vec with length of <{:?}> but was <{:?}>",
                           expected,
                           length));
        }
    }

    pub fn contains(&self, expected_value: &T) {
        if !self.subject.contains(expected_value) {
            Self::panic_unmatched(expected_value, self.subject);
        }
    }

    pub fn mapped_contains<F, M: 's>(&self, mapping_function: F, expected_value: &M)
        where M: Debug + PartialEq,
              F: Fn(&'s T) -> &M
    {
        let mapped_vec: Vec<&M> = self.subject.iter().map(mapping_function).collect();
        if !mapped_vec.contains(&expected_value) {
            Self::panic_unmatched(expected_value, mapped_vec);
        }
    }

    fn panic_unmatched<E: Debug, A: Debug>(expected: E, actual: A) {
        panic!(format!("expected vec to contain <{:?}> but contains <{:?}>",
                       expected,
                       actual));
    }
}
<commit_msg>Allow for length matching on vec without the held type implementing debug or partialeq<commit_after>use super::Spec;

use std::cmp::PartialEq;
use std::fmt::Debug;

impl<'s, T> Spec<'s, Vec<T>> {
    pub fn has_length(&self, expected: usize) {
        let length = self.subject.len();
        if length != expected {
            panic!(format!("expected vec with length of <{:?}> but was <{:?}>",
                           expected,
                           length));
        }
    }
}

impl<'s, T> Spec<'s, Vec<T>>
    where T: Debug + PartialEq
{
    pub fn contains(&self, expected_value: &T) {
        if !self.subject.contains(expected_value) {
            Self::panic_unmatched(expected_value, self.subject);
        }
    }

    pub fn mapped_contains<F, M: 's>(&self, mapping_function: F, expected_value: &M)
        where M: Debug + PartialEq,
              F: Fn(&'s T) -> &M
    {
        let mapped_vec: Vec<&M> = self.subject.iter().map(mapping_function).collect();
        if !mapped_vec.contains(&expected_value) {
            Self::panic_unmatched(expected_value, mapped_vec);
        }
    }

    fn panic_unmatched<E: Debug, A: Debug>(expected: E, actual: A) {
        panic!(format!("expected vec to contain <{:?}> but contains <{:?}>",
                       expected,
                       actual));
    }
}
<|endoftext|>


<commit_before>use types::*;

use nom::{be_i8, be_u8, be_i16, be_u16, be_i32, be_u32, be_i64, be_u64, be_f32, be_f64};

/* FIXME: we convert to a Some so that nom can happily handle some _ case which would otherwise fail as we're exhaustive */
named!(pub parse_value<AMQPValue>,                 switch!(map!(parse_type, |t| Some(t)),
    Some(AMQPType::Boolean)        => map!(call!(parse_boolean),          |b| AMQPValue::Boolean(b))        |
    Some(AMQPType::ShortShortInt)  => map!(call!(parse_short_short_int),  |i| AMQPValue::ShortShortInt(i))  |
    Some(AMQPType::ShortShortUInt) => map!(call!(parse_short_short_uint), |u| AMQPValue::ShortShortUInt(u)) |
    Some(AMQPType::ShortInt)       => map!(call!(parse_short_int),        |i| AMQPValue::ShortInt(i))       |
    Some(AMQPType::ShortUInt)      => map!(call!(parse_short_uint),       |u| AMQPValue::ShortUInt(u))      |
    Some(AMQPType::LongInt)        => map!(call!(parse_long_int),         |i| AMQPValue::LongInt(i))        |
    Some(AMQPType::LongUInt)       => map!(call!(parse_long_uint),        |u| AMQPValue::LongUInt(u))       |
    Some(AMQPType::LongLongInt)    => map!(call!(parse_long_long_int),    |i| AMQPValue::LongLongInt(i))    |
    Some(AMQPType::LongLongUInt)   => map!(call!(parse_long_long_uint),   |u| AMQPValue::LongLongUInt(u))   |
    Some(AMQPType::Float)          => map!(call!(parse_float),            |f| AMQPValue::Float(f))          |
    Some(AMQPType::Double)         => map!(call!(parse_double),           |d| AMQPValue::Double(d))         |
    Some(AMQPType::DecimalValue)   => map!(call!(parse_decimal_value),    |d| AMQPValue::DecimalValue(d))   |
    Some(AMQPType::ShortString)    => map!(call!(parse_short_string),     |s| AMQPValue::ShortString(s))    |
    Some(AMQPType::LongString)     => map!(call!(parse_long_string),      |s| AMQPValue::LongString(s))     |
    Some(AMQPType::FieldArray)     => map!(call!(parse_field_array),      |a| AMQPValue::FieldArray(a))     |
    Some(AMQPType::Timestamp)      => map!(call!(parse_timestamp),        |t| AMQPValue::Timestamp(t))      |
    Some(AMQPType::FieldTable)     => map!(call!(parse_field_table),      |t| AMQPValue::FieldTable(t))     |
    Some(AMQPType::Void)           => value!(AMQPValue::Void)
));

named!(pub parse_type<AMQPType>,                   map_opt!(be_u8, |t| AMQPType::from_id(t as char)));

named!(pub parse_boolean<Boolean>,                 map!(be_u8, |b| b != 0));
named!(pub parse_short_short_int<ShortShortInt>,   call!(be_i8));
named!(pub parse_short_short_uint<ShortShortUInt>, call!(be_u8));
named!(pub parse_short_int<ShortInt>,              call!(be_i16));
named!(pub parse_short_uint<ShortUInt>,            call!(be_u16));
named!(pub parse_long_int<LongInt>,                call!(be_i32));
named!(pub parse_long_uint<LongUInt>,              call!(be_u32));
named!(pub parse_long_long_int<LongLongInt>,       call!(be_i64));
named!(pub parse_long_long_uint<LongLongUInt>,     call!(be_u64));
named!(pub parse_float<Float>,                     call!(be_f32));
named!(pub parse_double<Double>,                   call!(be_f64));
named!(pub parse_decimal_value<DecimalValue>,      do_parse!(scale: parse_short_short_uint >> value: parse_long_uint >> (DecimalValue { scale: scale, value: value, })));
named!(pub parse_short_string<ShortString>,        do_parse!(length: parse_short_short_uint >> s: take_str!(length) >> (s.to_string())));
named!(pub parse_long_string<LongString>,          do_parse!(length: parse_long_uint >> s: take_str!(length) >> (s.to_string())));
named!(pub parse_field_array<FieldArray>,          do_parse!(length: parse_long_int >> array: count!(parse_value, length as usize) >> (array)));
named!(pub parse_timestamp<Timestamp>,             call!(parse_long_long_uint));
named!(pub parse_field_table<FieldTable>,          do_parse!(length: parse_long_uint >> table: flat_map!(take!(length as usize), fold_many0!(complete!(pair!(parse_short_string, parse_value)), FieldTable::new(), |mut acc: FieldTable, (key, value)| {
    acc.insert(key, value);
    acc
})) >> (table)));

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

    use nom::IResult;

    const EMPTY: &'static [u8] = b"";

    #[test]
    fn test_parse_boolean() {
        assert_eq!(parse_boolean(&[0]), IResult::Done(EMPTY, false));
        assert_eq!(parse_boolean(&[1]), IResult::Done(EMPTY, true));
    }

    #[test]
    fn test_parse_short_short_uint() {
        assert_eq!(parse_short_short_uint(&[0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_short_uint(&[255]), IResult::Done(EMPTY, 255));
    }

    #[test]
    fn test_parse_short_short_int() {
        assert_eq!(parse_short_short_int(&[0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_short_int(&[255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_short_uint() {
        assert_eq!(parse_short_uint(&[0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_uint(&[255, 255]), IResult::Done(EMPTY, 65535));
    }

    #[test]
    fn test_parse_short_int() {
        assert_eq!(parse_short_int(&[0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_int(&[255, 255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_long_uint() {
        assert_eq!(parse_long_uint(&[0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_uint(&[255, 255, 255, 255]), IResult::Done(EMPTY, 4294967295));
    }

    #[test]
    fn test_parse_long_int() {
        assert_eq!(parse_long_int(&[0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_int(&[255, 255, 255, 255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_long_long_uint() {
        assert_eq!(parse_long_long_uint(&[0,   0,   0,   0,   0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_long_uint(&[255, 255, 255, 255, 255, 255, 255, 255]), IResult::Done(EMPTY, 18446744073709551615));
    }

    #[test]
    fn test_parse_long_long_int() {
        assert_eq!(parse_long_long_int(&[0,   0,   0,   0,   0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_long_int(&[255, 255, 255, 255, 255, 255, 255, 255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_float() {
        assert_eq!(parse_float(&[0,  0,  0,  0]),  IResult::Done(EMPTY, 0.));
        assert_eq!(parse_float(&[42, 42, 42, 42]), IResult::Done(EMPTY, 0.00000000000015113662));
    }

    #[test]
    fn test_parse_double() {
        assert_eq!(parse_double(&[0,  0,  0,  0,  0,  0,  0,  0]),  IResult::Done(EMPTY, 0.));
        assert_eq!(parse_double(&[42, 42, 42, 42, 42, 42, 42, 42]), IResult::Done(EMPTY, 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014260258159703532));
    }

    #[test]
    fn test_parse_decimal_value() {
        assert_eq!(parse_decimal_value(&[0,   0,   0,   0,   0]),   IResult::Done(EMPTY, DecimalValue { scale: 0,   value: 0          }));
        assert_eq!(parse_decimal_value(&[255, 255, 255, 255, 255]), IResult::Done(EMPTY, DecimalValue { scale: 255, value: 4294967295 }));
    }

    #[test]
    fn test_parse_short_string() {
        assert_eq!(parse_short_string(&[0]),                     IResult::Done(EMPTY, ShortString::new()));
        assert_eq!(parse_short_string(&[4, 116, 101, 115, 116]), IResult::Done(EMPTY, "test".to_string()));
    }

    #[test]
    fn test_parse_long_string() {
        assert_eq!(parse_long_string(&[0, 0, 0, 0]),                     IResult::Done(EMPTY, LongString::new()));
        assert_eq!(parse_long_string(&[0, 0, 0, 4, 116, 101, 115, 116]), IResult::Done(EMPTY, "test".to_string()));
    }

    #[test]
    fn test_parse_field_array() {
        assert_eq!(parse_field_array(&[0, 0, 0, 0]), IResult::Done(EMPTY, FieldArray::new()));
    }

    #[test]
    fn test_parse_timestamp() {
        assert_eq!(parse_timestamp(&[0,   0,   0,   0,   0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_timestamp(&[255, 255, 255, 255, 255, 255, 255, 255]), IResult::Done(EMPTY, 18446744073709551615));
    }

    #[test]
    fn test_parse_field_table() {
        assert_eq!(parse_field_table(&[0, 0, 0, 0]), IResult::Done(EMPTY, FieldTable::new()));
    }
}
<commit_msg>types: add more complex parsing tests<commit_after>use types::*;

use nom::{be_i8, be_u8, be_i16, be_u16, be_i32, be_u32, be_i64, be_u64, be_f32, be_f64};

/* FIXME: we convert to a Some so that nom can happily handle some _ case which would otherwise fail as we're exhaustive */
named!(pub parse_value<AMQPValue>,                 switch!(map!(parse_type, |t| Some(t)),
    Some(AMQPType::Boolean)        => map!(call!(parse_boolean),          |b| AMQPValue::Boolean(b))        |
    Some(AMQPType::ShortShortInt)  => map!(call!(parse_short_short_int),  |i| AMQPValue::ShortShortInt(i))  |
    Some(AMQPType::ShortShortUInt) => map!(call!(parse_short_short_uint), |u| AMQPValue::ShortShortUInt(u)) |
    Some(AMQPType::ShortInt)       => map!(call!(parse_short_int),        |i| AMQPValue::ShortInt(i))       |
    Some(AMQPType::ShortUInt)      => map!(call!(parse_short_uint),       |u| AMQPValue::ShortUInt(u))      |
    Some(AMQPType::LongInt)        => map!(call!(parse_long_int),         |i| AMQPValue::LongInt(i))        |
    Some(AMQPType::LongUInt)       => map!(call!(parse_long_uint),        |u| AMQPValue::LongUInt(u))       |
    Some(AMQPType::LongLongInt)    => map!(call!(parse_long_long_int),    |i| AMQPValue::LongLongInt(i))    |
    Some(AMQPType::LongLongUInt)   => map!(call!(parse_long_long_uint),   |u| AMQPValue::LongLongUInt(u))   |
    Some(AMQPType::Float)          => map!(call!(parse_float),            |f| AMQPValue::Float(f))          |
    Some(AMQPType::Double)         => map!(call!(parse_double),           |d| AMQPValue::Double(d))         |
    Some(AMQPType::DecimalValue)   => map!(call!(parse_decimal_value),    |d| AMQPValue::DecimalValue(d))   |
    Some(AMQPType::ShortString)    => map!(call!(parse_short_string),     |s| AMQPValue::ShortString(s))    |
    Some(AMQPType::LongString)     => map!(call!(parse_long_string),      |s| AMQPValue::LongString(s))     |
    Some(AMQPType::FieldArray)     => map!(call!(parse_field_array),      |a| AMQPValue::FieldArray(a))     |
    Some(AMQPType::Timestamp)      => map!(call!(parse_timestamp),        |t| AMQPValue::Timestamp(t))      |
    Some(AMQPType::FieldTable)     => map!(call!(parse_field_table),      |t| AMQPValue::FieldTable(t))     |
    Some(AMQPType::Void)           => value!(AMQPValue::Void)
));

named!(pub parse_type<AMQPType>,                   map_opt!(be_u8, |t| AMQPType::from_id(t as char)));

named!(pub parse_boolean<Boolean>,                 map!(be_u8, |b| b != 0));
named!(pub parse_short_short_int<ShortShortInt>,   call!(be_i8));
named!(pub parse_short_short_uint<ShortShortUInt>, call!(be_u8));
named!(pub parse_short_int<ShortInt>,              call!(be_i16));
named!(pub parse_short_uint<ShortUInt>,            call!(be_u16));
named!(pub parse_long_int<LongInt>,                call!(be_i32));
named!(pub parse_long_uint<LongUInt>,              call!(be_u32));
named!(pub parse_long_long_int<LongLongInt>,       call!(be_i64));
named!(pub parse_long_long_uint<LongLongUInt>,     call!(be_u64));
named!(pub parse_float<Float>,                     call!(be_f32));
named!(pub parse_double<Double>,                   call!(be_f64));
named!(pub parse_decimal_value<DecimalValue>,      do_parse!(scale: parse_short_short_uint >> value: parse_long_uint >> (DecimalValue { scale: scale, value: value, })));
named!(pub parse_short_string<ShortString>,        do_parse!(length: parse_short_short_uint >> s: take_str!(length) >> (s.to_string())));
named!(pub parse_long_string<LongString>,          do_parse!(length: parse_long_uint >> s: take_str!(length) >> (s.to_string())));
named!(pub parse_field_array<FieldArray>,          do_parse!(length: parse_long_int >> array: count!(parse_value, length as usize) >> (array)));
named!(pub parse_timestamp<Timestamp>,             call!(parse_long_long_uint));
named!(pub parse_field_table<FieldTable>,          do_parse!(length: parse_long_uint >> table: flat_map!(take!(length as usize), fold_many0!(complete!(pair!(parse_short_string, parse_value)), FieldTable::new(), |mut acc: FieldTable, (key, value)| {
    acc.insert(key, value);
    acc
})) >> (table)));

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

    use nom::IResult;

    const EMPTY: &'static [u8] = b"";

    #[test]
    fn test_parse_boolean() {
        assert_eq!(parse_boolean(&[0]), IResult::Done(EMPTY, false));
        assert_eq!(parse_boolean(&[1]), IResult::Done(EMPTY, true));
    }

    #[test]
    fn test_parse_short_short_uint() {
        assert_eq!(parse_short_short_uint(&[0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_short_uint(&[255]), IResult::Done(EMPTY, 255));
    }

    #[test]
    fn test_parse_short_short_int() {
        assert_eq!(parse_short_short_int(&[0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_short_int(&[255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_short_uint() {
        assert_eq!(parse_short_uint(&[0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_uint(&[255, 255]), IResult::Done(EMPTY, 65535));
    }

    #[test]
    fn test_parse_short_int() {
        assert_eq!(parse_short_int(&[0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_int(&[255, 255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_long_uint() {
        assert_eq!(parse_long_uint(&[0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_uint(&[255, 255, 255, 255]), IResult::Done(EMPTY, 4294967295));
    }

    #[test]
    fn test_parse_long_int() {
        assert_eq!(parse_long_int(&[0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_int(&[255, 255, 255, 255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_long_long_uint() {
        assert_eq!(parse_long_long_uint(&[0,   0,   0,   0,   0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_long_uint(&[255, 255, 255, 255, 255, 255, 255, 255]), IResult::Done(EMPTY, 18446744073709551615));
    }

    #[test]
    fn test_parse_long_long_int() {
        assert_eq!(parse_long_long_int(&[0,   0,   0,   0,   0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_long_int(&[255, 255, 255, 255, 255, 255, 255, 255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_float() {
        assert_eq!(parse_float(&[0,  0,  0,  0]),  IResult::Done(EMPTY, 0.));
        assert_eq!(parse_float(&[42, 42, 42, 42]), IResult::Done(EMPTY, 0.00000000000015113662));
    }

    #[test]
    fn test_parse_double() {
        assert_eq!(parse_double(&[0,  0,  0,  0,  0,  0,  0,  0]),  IResult::Done(EMPTY, 0.));
        assert_eq!(parse_double(&[42, 42, 42, 42, 42, 42, 42, 42]), IResult::Done(EMPTY, 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014260258159703532));
    }

    #[test]
    fn test_parse_decimal_value() {
        assert_eq!(parse_decimal_value(&[0,   0,   0,   0,   0]),   IResult::Done(EMPTY, DecimalValue { scale: 0,   value: 0          }));
        assert_eq!(parse_decimal_value(&[255, 255, 255, 255, 255]), IResult::Done(EMPTY, DecimalValue { scale: 255, value: 4294967295 }));
    }

    #[test]
    fn test_parse_short_string() {
        assert_eq!(parse_short_string(&[0]),                     IResult::Done(EMPTY, ShortString::new()));
        assert_eq!(parse_short_string(&[4, 116, 101, 115, 116]), IResult::Done(EMPTY, "test".to_string()));
    }

    #[test]
    fn test_parse_long_string() {
        assert_eq!(parse_long_string(&[0, 0, 0, 0]),                     IResult::Done(EMPTY, LongString::new()));
        assert_eq!(parse_long_string(&[0, 0, 0, 4, 116, 101, 115, 116]), IResult::Done(EMPTY, "test".to_string()));
    }

    #[test]
    fn test_parse_field_array() {
        assert_eq!(parse_field_array(&[0, 0, 0, 0]),                                 IResult::Done(EMPTY, FieldArray::new()));
        assert_eq!(parse_field_array(&[0, 0, 0, 2, 115, 4, 116, 101, 115, 116, 86]), IResult::Done(EMPTY, vec![AMQPValue::ShortString("test".to_string()), AMQPValue::Void]));
    }

    #[test]
    fn test_parse_timestamp() {
        assert_eq!(parse_timestamp(&[0,   0,   0,   0,   0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_timestamp(&[255, 255, 255, 255, 255, 255, 255, 255]), IResult::Done(EMPTY, 18446744073709551615));
    }

    #[test]
    fn test_parse_field_table() {
        let mut table = FieldTable::new();
        table.insert("test".to_string(), AMQPValue::ShortString("test".to_string()));
        table.insert("tt".to_string(),   AMQPValue::Void);
        assert_eq!(parse_field_table(&[0, 0, 0, 0]),                                                                      IResult::Done(EMPTY, FieldTable::new()));
        assert_eq!(parse_field_table(&[0, 0, 0, 15, 4, 116, 101, 115, 116, 115, 4, 116, 101, 115, 116, 2, 116, 116, 86]), IResult::Done(EMPTY, table));
    }
}
<|endoftext|>