<commit_before>use iron::{Handler, Response, Request, IronResult, Url, Error};
use typemap::Assoc;
use trie::Trie;

/// Exposes the original, unmodified path to be stored in `Request::extensions`.
pub struct OriginalUrl;
impl Assoc<Url> for OriginalUrl {}

/// `Mount` is a simple mounting middleware.
///
/// Mounting allows you to install a handler on a route and have it receive requests as if they
/// are relative to that route. For example, a handler mounted on `/foo/` will receive
/// requests like `/foo/bar` as if they are just `/bar`. Iron's mounting middleware allows
/// you to specify multiple mountings using one middleware instance. Requests that pass through
/// the mounting middleware are passed along to the mounted handler that best matches the request's
/// path. `Request::url` is modified so that requests appear to be relative to the mounted handler's route.
///
/// Mounted handlers may also access the *original* URL by requesting the `OriginalUrl` key
/// from `Request::extensions`.
pub struct Mount {
    inner: Trie<String, Match>
}

struct Match {
    handler: Box<Handler + Send + Sync>,
    length: uint
}

/// The error returned by `Mount` when a request doesn't match any mounted handlers.
#[deriving(Show)]
pub struct NoMatch;

impl Error for NoMatch {
    fn name(&self) -> &'static str { "No Match" }
}

impl Mount {
    /// Creates a new instance of `Mount`.
    pub fn new() -> Mount {
        Mount {
            inner: Trie::new()
        }
    }

    /// Mounts a given `Handler` onto a route.
    ///
    /// This method may be called multiple times with different routes.
    /// For a given request, the *most specific* handler will be selected.
    ///
    /// Existing handlers on the same route will be overwritten.
    pub fn mount<H: Handler>(&mut self, route: &str, handler: H) -> &mut Mount {
        // Parse the route into a list of strings. The unwrap is safe because strs are UTF-8.
        let key: Vec<String> = Path::new(route).str_components().map(|s| s.unwrap().to_string()).collect();

        // Insert a match struct into the trie.
        self.inner.insert(key.as_slice(), Match {
            handler: box handler as Box<Handler + Send + Sync>,
            length: key.len()
        });
        self
    }
}

impl Handler for Mount {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        // Find the matching handler.
        let matched = {
            // Extract the request path.
            let path = req.url.path.as_slice();

            // If present, remove the trailing empty string (which represents a trailing slash).
            // If it isn't removed the path will never match anything, because
            // Path::str_components ignores trailing slashes and will never create routes
            // ending in "".
            let key = match path.last() {
                Some(s) if s.is_empty() => path.slice_to(path.len() - 1),
                _ => path
            };

            // Search the Trie for the nearest most specific match.
            match self.inner.find_ancestor(key) {
                Some(matched) => matched,
                None => return Err(NoMatch.erase())
            }
        };

        // We have a match, so fire off the child.
        // If another mount middleware hasn't already, insert the unmodified url
        // into the extensions as the "original url".
        let is_outer_mount = !req.extensions.contains::<OriginalUrl, Url>();
        if is_outer_mount {
            req.extensions.insert::<OriginalUrl, Url>(req.url.clone());
        }

        // Remove the prefix from the request's path before passing it to the mounted handler.
        // If the prefix is entirely removed and no trailing slash was present, the new path
        // will be the empty list. For the purposes of redirection, conveying that the path
        // did not include a trailing slash is more important than providing a non-empty list.
        req.url.path = req.url.path.as_slice().slice_from(matched.length).to_vec();

        let res = matched.handler.call(req);

        // Reverse the URL munging, for future middleware.
        req.url = match req.extensions.find::<OriginalUrl, Url>() {
            Some(original) => original.clone(),
            None => fail!("OriginalUrl unexpectedly removed from req.extensions.")
        };

        // If this mount middleware is the outermost mount middleware,
        // remove the original url from the extensions map to prevent leakage.
        if is_outer_mount {
            req.extensions.remove::<OriginalUrl, Url>();
        }

        res
    }
}

<commit_msg>(fix) fail! to panic!<commit_after>use iron::{Handler, Response, Request, IronResult, Url, Error};
use typemap::Assoc;
use trie::Trie;

/// Exposes the original, unmodified path to be stored in `Request::extensions`.
pub struct OriginalUrl;
impl Assoc<Url> for OriginalUrl {}

/// `Mount` is a simple mounting middleware.
///
/// Mounting allows you to install a handler on a route and have it receive requests as if they
/// are relative to that route. For example, a handler mounted on `/foo/` will receive
/// requests like `/foo/bar` as if they are just `/bar`. Iron's mounting middleware allows
/// you to specify multiple mountings using one middleware instance. Requests that pass through
/// the mounting middleware are passed along to the mounted handler that best matches the request's
/// path. `Request::url` is modified so that requests appear to be relative to the mounted handler's route.
///
/// Mounted handlers may also access the *original* URL by requesting the `OriginalUrl` key
/// from `Request::extensions`.
pub struct Mount {
    inner: Trie<String, Match>
}

struct Match {
    handler: Box<Handler + Send + Sync>,
    length: uint
}

/// The error returned by `Mount` when a request doesn't match any mounted handlers.
#[deriving(Show)]
pub struct NoMatch;

impl Error for NoMatch {
    fn name(&self) -> &'static str { "No Match" }
}

impl Mount {
    /// Creates a new instance of `Mount`.
    pub fn new() -> Mount {
        Mount {
            inner: Trie::new()
        }
    }

    /// Mounts a given `Handler` onto a route.
    ///
    /// This method may be called multiple times with different routes.
    /// For a given request, the *most specific* handler will be selected.
    ///
    /// Existing handlers on the same route will be overwritten.
    pub fn mount<H: Handler>(&mut self, route: &str, handler: H) -> &mut Mount {
        // Parse the route into a list of strings. The unwrap is safe because strs are UTF-8.
        let key: Vec<String> = Path::new(route).str_components().map(|s| s.unwrap().to_string()).collect();

        // Insert a match struct into the trie.
        self.inner.insert(key.as_slice(), Match {
            handler: box handler as Box<Handler + Send + Sync>,
            length: key.len()
        });
        self
    }
}

impl Handler for Mount {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        // Find the matching handler.
        let matched = {
            // Extract the request path.
            let path = req.url.path.as_slice();

            // If present, remove the trailing empty string (which represents a trailing slash).
            // If it isn't removed the path will never match anything, because
            // Path::str_components ignores trailing slashes and will never create routes
            // ending in "".
            let key = match path.last() {
                Some(s) if s.is_empty() => path.slice_to(path.len() - 1),
                _ => path
            };

            // Search the Trie for the nearest most specific match.
            match self.inner.find_ancestor(key) {
                Some(matched) => matched,
                None => return Err(NoMatch.erase())
            }
        };

        // We have a match, so fire off the child.
        // If another mount middleware hasn't already, insert the unmodified url
        // into the extensions as the "original url".
        let is_outer_mount = !req.extensions.contains::<OriginalUrl, Url>();
        if is_outer_mount {
            req.extensions.insert::<OriginalUrl, Url>(req.url.clone());
        }

        // Remove the prefix from the request's path before passing it to the mounted handler.
        // If the prefix is entirely removed and no trailing slash was present, the new path
        // will be the empty list. For the purposes of redirection, conveying that the path
        // did not include a trailing slash is more important than providing a non-empty list.
        req.url.path = req.url.path.as_slice().slice_from(matched.length).to_vec();

        let res = matched.handler.call(req);

        // Reverse the URL munging, for future middleware.
        req.url = match req.extensions.find::<OriginalUrl, Url>() {
            Some(original) => original.clone(),
            None => panic!("OriginalUrl unexpectedly removed from req.extensions.")
        };

        // If this mount middleware is the outermost mount middleware,
        // remove the original url from the extensions map to prevent leakage.
        if is_outer_mount {
            req.extensions.remove::<OriginalUrl, Url>();
        }

        res
    }
}

<|endoftext|>


<commit_before>//! Allocating pages of memory from the OS and carving them into individual
//! allocations.

use std::{cmp, mem, ptr};
use std::marker::PhantomData;
use bit_vec::BitVec;
use traits::{IntoHeap, Tracer};
use heap::Heap;
use marking::MarkingTracer;
use ptr::{Pointer, UntypedPointer};

/// Non-inlined function that serves as an entry point to marking. This is used
/// for marking root set entries.
unsafe fn mark_entry_point<'h, T: IntoHeap<'h>>(addr: UntypedPointer, tracer: &mut MarkingTracer) {
    let addr = addr.as_typed_ptr::<T::In>();

    if Heap::get_mark_bit::<T>(addr) {
        // If the mark bit is set, then this object is gray in the classic
        // tri-color sense: seen but we just popped it off the mark stack and
        // have't finished enumerating its outgoing edges.
        T::trace(addr.as_ref(), tracer);
    } else {
        // If the mark bit is not set, then this object is white in the classic
        // tri-color sense: freshly discovered to be live, and we now need to
        // set its mark bit and then process its edges or push it onto the mark
        // stack for later edge processing.
        tracer.visit::<T>(addr);
    }
}

pub fn heap_type_id<'h, T: IntoHeap<'h>>() -> usize {
    mark_entry_point::<T> as *const () as usize
}

pub(crate) const PAGE_SIZE: usize = 0x1000;

/// We rely on all bits to the right of this bit being 0 in addresses of
/// TypedPage instances.
pub(crate) const PAGE_ALIGN: usize = 0x1000;

fn is_aligned(ptr: *const ()) -> bool {
    ptr as usize & (PAGE_ALIGN - 1) == 0
}

pub struct PageHeader {
    pub heap: *mut Heap,
    mark_bits: BitVec,
    allocated_bits: BitVec,
    mark_fn: unsafe fn(UntypedPointer, &mut MarkingTracer),
    sweep_fn: unsafe fn(&mut PageHeader),
    freelist: *mut (),
}

impl PageHeader {
    pub fn find(ptr: UntypedPointer) -> *mut PageHeader {
        let header_addr = ptr.as_usize() & !(PAGE_ALIGN - 1);
        header_addr as *mut PageHeader
    }

    pub fn clear_mark_bits(&mut self) {
        self.mark_bits.clear();
    }

    /// True if nothing on this page is allocated.
    pub fn is_empty(&self) -> bool {
        self.allocated_bits.none()
    }

    pub unsafe fn mark(&self, ptr: UntypedPointer, tracer: &mut MarkingTracer) {
        (self.mark_fn)(ptr, tracer);
    }

    pub unsafe fn sweep(&mut self) {
        (self.sweep_fn)(self);
    }

    pub fn type_id(&self) -> usize {
        self.mark_fn as usize
    }

    pub fn downcast_mut<'h, T: IntoHeap<'h>>(&mut self) -> Option<&mut TypedPage<T::In>> {
        if heap_type_id::<T>() == self.type_id() {
            let ptr = self as *mut PageHeader as *mut TypedPage<T::In>;
            Some(unsafe { &mut *ptr })
        } else {
            None
        }
    }
}

pub struct TypedPage<U> {
    pub header: PageHeader,
    pub allocations: PhantomData<U>,
}

/// Returns the smallest multiple of `k` that is at least `n`.
///
/// Panics if the answer is too big to fit in a `usize`.
fn round_up(n: usize, k: usize) -> usize {
    let a = n / k * k;
    if a == n {
        n
    } else {
        n + k
    }
}

impl<U> TypedPage<U> {
    /// The actual size of an allocation can't be smaller than the size of a
    /// pointer, due to the way we store the freelist by stealing a pointer
    /// from the allocation itself.
    fn allocation_size() -> usize {
        cmp::max(mem::size_of::<U>(), mem::size_of::<*mut U>())
    }

    fn allocation_align() -> usize {
        cmp::max(mem::align_of::<U>(), mem::align_of::<*mut U>())
    }

    /// Offset, in bytes, of the first allocation from the start of the page.
    pub(crate) fn first_allocation_offset() -> usize {
        round_up(mem::size_of::<PageHeader>(), Self::allocation_align())
    }

    /// Number of allocations that fit in a page.
    pub fn capacity() -> usize {
        (PAGE_SIZE - Self::first_allocation_offset()) / Self::allocation_size()
    }

    fn first_object_addr(&self) -> usize {
        (self as *const Self as usize) + Self::first_allocation_offset()
    }

    unsafe fn init(&mut self) {
        let mut addr = self.first_object_addr();
        for _ in 0..Self::capacity() {
            self.add_to_free_list(addr as *mut U);

            // This can't use `ptr = ptr.offset(1)` because if U is smaller
            // than a pointer, allocations are padded to pointer size.
            // `.offset(1)` doesn't know about the padding and therefore
            // wouldn't advance to the next allocation.
            addr += Self::allocation_size();
        }
    }

    /// Return the page containing the object `ptr` points to.
    pub fn find(ptr: Pointer<U>) -> *mut TypedPage<U> {
        let ptr: usize = ptr.into();
        let page_addr = ptr & !(PAGE_ALIGN - 1);
        page_addr as *mut TypedPage<U>
    }

    unsafe fn add_to_free_list(&mut self, p: *mut U) {
        let listp = p as *mut *mut ();
        *listp = self.header.freelist;
        assert_eq!(*listp, self.header.freelist);
        self.header.freelist = p as *mut ();
    }

    unsafe fn allocation_index(&self, ptr: Pointer<U>) -> usize {
        let base = self.first_object_addr();

        // Check that ptr is in range.
        assert!(ptr.as_void() >= base as _);
        assert!(ptr.as_void() < (base + (Self::capacity() * Self::allocation_size())) as _);

        let index = (ptr.as_usize() - base as usize) / Self::allocation_size();
        assert_eq!(
            (base + index * Self::allocation_size()) as *const (),
            ptr.as_void()
        );
        index
    }

    pub unsafe fn get_mark_bit(&mut self, ptr: Pointer<U>) -> bool {
        let index = self.allocation_index(ptr);
        self.header.mark_bits[index]
    }

    pub unsafe fn set_mark_bit(&mut self, ptr: Pointer<U>) {
        let index = self.allocation_index(ptr);
        self.header.mark_bits.set(index, true);
    }

    pub unsafe fn try_alloc(&mut self) -> Option<Pointer<U>> {
        let p = self.header.freelist;
        if p.is_null() {
            None
        } else {
            let listp = p as *mut *mut ();
            self.header.freelist = *listp;
            let ap = Pointer::new(p as *mut U);
            let index = self.allocation_index(ap);
            assert!(!self.header.allocated_bits[index]);
            self.header.allocated_bits.set(index, true);
            Some(ap)
        }
    }

    unsafe fn sweep(&mut self) {
        let mut addr = self.first_object_addr();
        for i in 0..Self::capacity() {
            if self.header.allocated_bits[i] && !self.header.mark_bits[i] {
                ptr::drop_in_place(addr as *mut U);
                self.header.allocated_bits.set(i, false);
                self.add_to_free_list(addr as *mut U);
            }
            addr += Self::allocation_size();
        }
    }
}

unsafe fn sweep_entry_point<'h, T: IntoHeap<'h>>(header: &mut PageHeader) {
    header.downcast_mut::<T>().unwrap().sweep();
}

pub struct PageBox(*mut PageHeader);

impl PageBox {
    pub fn new<'h, T: IntoHeap<'h>>(heap: *mut Heap) -> PageBox {
        assert!(
            mem::size_of::<TypedPage<T::In>>() <= TypedPage::<T::In>::first_allocation_offset()
        );
        assert!(
            TypedPage::<T::In>::first_allocation_offset() +
                TypedPage::<T::In>::capacity() * TypedPage::<T::In>::allocation_size() <=
                PAGE_SIZE
        );
        let raw_page: *mut () = {
            let mut vec: Vec<u8> = Vec::with_capacity(PAGE_SIZE);
            let page = vec.as_mut_ptr() as *mut ();

            // Rust makes no guarantee whatsoever that this will work.
            // If it doesn't, panic.
            assert!(is_aligned(page));

            mem::forget(vec);
            page
        };

        let page: *mut TypedPage<T::In> = raw_page as *mut TypedPage<T::In>;
        let capacity = TypedPage::<T::In>::capacity();
        unsafe {
            ptr::write(
                page,
                TypedPage {
                    header: PageHeader {
                        heap: heap,
                        mark_bits: BitVec::from_elem(capacity, false),
                        allocated_bits: BitVec::from_elem(capacity, false),
                        mark_fn: mark_entry_point::<T>,
                        sweep_fn: sweep_entry_point::<T>,
                        freelist: ptr::null_mut(),
                    },
                    allocations: PhantomData,
                },
            );
            TypedPage::init(&mut *page);
            PageBox(&mut (*page).header as *mut PageHeader)
        }
    }
}

impl ::std::ops::Deref for PageBox {
    type Target = PageHeader;
    fn deref(&self) -> &PageHeader {
        unsafe { &*self.0 }
    }
}

impl ::std::ops::DerefMut for PageBox {
    fn deref_mut(&mut self) -> &mut PageHeader {
        unsafe { &mut *self.0 }
    }
}

impl Drop for PageBox {
    fn drop(&mut self) {
        unsafe {
            assert!((*self.0).is_empty());

            ptr::drop_in_place(self.0);

            // Deallocate the memory.
            Vec::from_raw_parts(self.0 as *mut u8, 0, PAGE_SIZE);
        }
    }
}
<commit_msg>Document safety rule for `TypedPage::try_alloc`.<commit_after>//! Allocating pages of memory from the OS and carving them into individual
//! allocations.

use std::{cmp, mem, ptr};
use std::marker::PhantomData;
use bit_vec::BitVec;
use traits::{IntoHeap, Tracer};
use heap::Heap;
use marking::MarkingTracer;
use ptr::{Pointer, UntypedPointer};

/// Non-inlined function that serves as an entry point to marking. This is used
/// for marking root set entries.
unsafe fn mark_entry_point<'h, T: IntoHeap<'h>>(addr: UntypedPointer, tracer: &mut MarkingTracer) {
    let addr = addr.as_typed_ptr::<T::In>();

    if Heap::get_mark_bit::<T>(addr) {
        // If the mark bit is set, then this object is gray in the classic
        // tri-color sense: seen but we just popped it off the mark stack and
        // have't finished enumerating its outgoing edges.
        T::trace(addr.as_ref(), tracer);
    } else {
        // If the mark bit is not set, then this object is white in the classic
        // tri-color sense: freshly discovered to be live, and we now need to
        // set its mark bit and then process its edges or push it onto the mark
        // stack for later edge processing.
        tracer.visit::<T>(addr);
    }
}

pub fn heap_type_id<'h, T: IntoHeap<'h>>() -> usize {
    mark_entry_point::<T> as *const () as usize
}

pub(crate) const PAGE_SIZE: usize = 0x1000;

/// We rely on all bits to the right of this bit being 0 in addresses of
/// TypedPage instances.
pub(crate) const PAGE_ALIGN: usize = 0x1000;

fn is_aligned(ptr: *const ()) -> bool {
    ptr as usize & (PAGE_ALIGN - 1) == 0
}

pub struct PageHeader {
    pub heap: *mut Heap,
    mark_bits: BitVec,
    allocated_bits: BitVec,
    mark_fn: unsafe fn(UntypedPointer, &mut MarkingTracer),
    sweep_fn: unsafe fn(&mut PageHeader),
    freelist: *mut (),
}

impl PageHeader {
    pub fn find(ptr: UntypedPointer) -> *mut PageHeader {
        let header_addr = ptr.as_usize() & !(PAGE_ALIGN - 1);
        header_addr as *mut PageHeader
    }

    pub fn clear_mark_bits(&mut self) {
        self.mark_bits.clear();
    }

    /// True if nothing on this page is allocated.
    pub fn is_empty(&self) -> bool {
        self.allocated_bits.none()
    }

    pub unsafe fn mark(&self, ptr: UntypedPointer, tracer: &mut MarkingTracer) {
        (self.mark_fn)(ptr, tracer);
    }

    pub unsafe fn sweep(&mut self) {
        (self.sweep_fn)(self);
    }

    pub fn type_id(&self) -> usize {
        self.mark_fn as usize
    }

    pub fn downcast_mut<'h, T: IntoHeap<'h>>(&mut self) -> Option<&mut TypedPage<T::In>> {
        if heap_type_id::<T>() == self.type_id() {
            let ptr = self as *mut PageHeader as *mut TypedPage<T::In>;
            Some(unsafe { &mut *ptr })
        } else {
            None
        }
    }
}

pub struct TypedPage<U> {
    pub header: PageHeader,
    pub allocations: PhantomData<U>,
}

/// Returns the smallest multiple of `k` that is at least `n`.
///
/// Panics if the answer is too big to fit in a `usize`.
fn round_up(n: usize, k: usize) -> usize {
    let a = n / k * k;
    if a == n {
        n
    } else {
        n + k
    }
}

impl<U> TypedPage<U> {
    /// The actual size of an allocation can't be smaller than the size of a
    /// pointer, due to the way we store the freelist by stealing a pointer
    /// from the allocation itself.
    fn allocation_size() -> usize {
        cmp::max(mem::size_of::<U>(), mem::size_of::<*mut U>())
    }

    fn allocation_align() -> usize {
        cmp::max(mem::align_of::<U>(), mem::align_of::<*mut U>())
    }

    /// Offset, in bytes, of the first allocation from the start of the page.
    pub(crate) fn first_allocation_offset() -> usize {
        round_up(mem::size_of::<PageHeader>(), Self::allocation_align())
    }

    /// Number of allocations that fit in a page.
    pub fn capacity() -> usize {
        (PAGE_SIZE - Self::first_allocation_offset()) / Self::allocation_size()
    }

    fn first_object_addr(&self) -> usize {
        (self as *const Self as usize) + Self::first_allocation_offset()
    }

    unsafe fn init(&mut self) {
        let mut addr = self.first_object_addr();
        for _ in 0..Self::capacity() {
            self.add_to_free_list(addr as *mut U);

            // This can't use `ptr = ptr.offset(1)` because if U is smaller
            // than a pointer, allocations are padded to pointer size.
            // `.offset(1)` doesn't know about the padding and therefore
            // wouldn't advance to the next allocation.
            addr += Self::allocation_size();
        }
    }

    /// Return the page containing the object `ptr` points to.
    pub fn find(ptr: Pointer<U>) -> *mut TypedPage<U> {
        let ptr: usize = ptr.into();
        let page_addr = ptr & !(PAGE_ALIGN - 1);
        page_addr as *mut TypedPage<U>
    }

    unsafe fn add_to_free_list(&mut self, p: *mut U) {
        let listp = p as *mut *mut ();
        *listp = self.header.freelist;
        assert_eq!(*listp, self.header.freelist);
        self.header.freelist = p as *mut ();
    }

    unsafe fn allocation_index(&self, ptr: Pointer<U>) -> usize {
        let base = self.first_object_addr();

        // Check that ptr is in range.
        assert!(ptr.as_void() >= base as _);
        assert!(ptr.as_void() < (base + (Self::capacity() * Self::allocation_size())) as _);

        let index = (ptr.as_usize() - base as usize) / Self::allocation_size();
        assert_eq!(
            (base + index * Self::allocation_size()) as *const (),
            ptr.as_void()
        );
        index
    }

    pub unsafe fn get_mark_bit(&mut self, ptr: Pointer<U>) -> bool {
        let index = self.allocation_index(ptr);
        self.header.mark_bits[index]
    }

    pub unsafe fn set_mark_bit(&mut self, ptr: Pointer<U>) {
        let index = self.allocation_index(ptr);
        self.header.mark_bits.set(index, true);
    }

    /// Allocate a `U`-sized-and-aligned region of uninitialized memory
    /// from this page.
    ///
    /// # Safety
    ///
    /// This is safe unless GC is happening.
    pub unsafe fn try_alloc(&mut self) -> Option<Pointer<U>> {
        let p = self.header.freelist;
        if p.is_null() {
            None
        } else {
            let listp = p as *mut *mut ();
            self.header.freelist = *listp;
            let ap = Pointer::new(p as *mut U);
            let index = self.allocation_index(ap);
            assert!(!self.header.allocated_bits[index]);
            self.header.allocated_bits.set(index, true);
            Some(ap)
        }
    }

    unsafe fn sweep(&mut self) {
        let mut addr = self.first_object_addr();
        for i in 0..Self::capacity() {
            if self.header.allocated_bits[i] && !self.header.mark_bits[i] {
                ptr::drop_in_place(addr as *mut U);
                self.header.allocated_bits.set(i, false);
                self.add_to_free_list(addr as *mut U);
            }
            addr += Self::allocation_size();
        }
    }
}

unsafe fn sweep_entry_point<'h, T: IntoHeap<'h>>(header: &mut PageHeader) {
    header.downcast_mut::<T>().unwrap().sweep();
}

pub struct PageBox(*mut PageHeader);

impl PageBox {
    pub fn new<'h, T: IntoHeap<'h>>(heap: *mut Heap) -> PageBox {
        assert!(
            mem::size_of::<TypedPage<T::In>>() <= TypedPage::<T::In>::first_allocation_offset()
        );
        assert!(
            TypedPage::<T::In>::first_allocation_offset() +
                TypedPage::<T::In>::capacity() * TypedPage::<T::In>::allocation_size() <=
                PAGE_SIZE
        );
        let raw_page: *mut () = {
            let mut vec: Vec<u8> = Vec::with_capacity(PAGE_SIZE);
            let page = vec.as_mut_ptr() as *mut ();

            // Rust makes no guarantee whatsoever that this will work.
            // If it doesn't, panic.
            assert!(is_aligned(page));

            mem::forget(vec);
            page
        };

        let page: *mut TypedPage<T::In> = raw_page as *mut TypedPage<T::In>;
        let capacity = TypedPage::<T::In>::capacity();
        unsafe {
            ptr::write(
                page,
                TypedPage {
                    header: PageHeader {
                        heap: heap,
                        mark_bits: BitVec::from_elem(capacity, false),
                        allocated_bits: BitVec::from_elem(capacity, false),
                        mark_fn: mark_entry_point::<T>,
                        sweep_fn: sweep_entry_point::<T>,
                        freelist: ptr::null_mut(),
                    },
                    allocations: PhantomData,
                },
            );
            TypedPage::init(&mut *page);
            PageBox(&mut (*page).header as *mut PageHeader)
        }
    }
}

impl ::std::ops::Deref for PageBox {
    type Target = PageHeader;
    fn deref(&self) -> &PageHeader {
        unsafe { &*self.0 }
    }
}

impl ::std::ops::DerefMut for PageBox {
    fn deref_mut(&mut self) -> &mut PageHeader {
        unsafe { &mut *self.0 }
    }
}

impl Drop for PageBox {
    fn drop(&mut self) {
        unsafe {
            assert!((*self.0).is_empty());

            ptr::drop_in_place(self.0);

            // Deallocate the memory.
            Vec::from_raw_parts(self.0 as *mut u8, 0, PAGE_SIZE);
        }
    }
}
<|endoftext|>


<commit_before>//! Functions for deserializing datatypes used by the protocol
use errors::Result;
use u128;

use std::io::Read;

use byteorder::{BigEndian, ReadBytesExt};

/// Read a single bool from the Reader
pub fn read_bool<R: Read>(reader: &mut R) -> Result<bool> {
    let byte = read_u8(reader)?;
    match byte {
        0 => Ok(false),
        1 => Ok(true),
        _ => bail!("Bool had invalid value {}", byte),
    }
}

/* Many of these functions obviously just duplicate functions from byteorder.
 * I keep them here to keep everything nicely organized, and also to make
 * things easier in the clientbound packet event macros.
 *
 * Also it ensures that if the MC modern protocol is changed, we can simply
 * change these functions without breaking anything. */

/// Read a single i8 from the Reader
pub fn read_i8<R: Read>(reader: &mut R) -> Result<i8> {
    Ok(reader.read_i8()?)
}

/// Read a single u8 from the Reader
pub fn read_u8<R: Read>(reader: &mut R) -> Result<u8> {
    Ok(reader.read_u8()?)
}

/// Read a single i16 from the Reader
pub fn read_i16<R: Read>(reader: &mut R) -> Result<i16> {
    Ok(reader.read_i16::<BigEndian>()?)
}

/// Read a single u16 from the Reader
pub fn read_u16<R: Read>(reader: &mut R) -> Result<u16> {
    Ok(reader.read_u16::<BigEndian>()?)
}

/// Read a single i32 from the Reader
pub fn read_i32<R: Read>(reader: &mut R) -> Result<i32> {
    Ok(reader.read_i32::<BigEndian>()?)
}

/// Read a single i64 from the Reader
pub fn read_i64<R: Read>(reader: &mut R) -> Result<i64> {
    Ok(reader.read_i64::<BigEndian>()?)
}

/// Read a single u64 from the Reader
pub fn read_u64<R: Read>(reader: &mut R) -> Result<u64> {
    Ok(reader.read_u64::<BigEndian>()?)
}

/// Read a single f32 from the Reader
pub fn read_f32<R: Read>(reader: &mut R) -> Result<f32> {
    Ok(reader.read_f32::<BigEndian>()?)
}

/// Read a single f64 from the Reader
pub fn read_f64<R: Read>(reader: &mut R) -> Result<f64> {
    Ok(reader.read_f64::<BigEndian>()?)
}

/// Read a length-prefixed utf-8 String from the Reader
#[allow(non_snake_case)]
pub fn read_String<R: Read>(reader: &mut R) -> Result<String> {
    let length = read_varint(reader)? as usize;

    if length > (1 << 16) {
        bail!("read_string refusing to read string due to its length");
    }

    let mut ret = String::with_capacity(length);
    let read = reader.take(length as u64).read_to_string(&mut ret)?;

    if read != length {
        bail!("read_String expected a string with length {} but was only able to read {} bytes", length, read);
    }

    Ok(ret)
}

/// Read a Minecraft-style varint, which currently fits into a i32
pub fn read_varint<R: Read>(reader: &mut R) -> Result<i32> {
    let mut radix: u64 = 128;
    let msb: u8 = 0b10000000; /* Only the MSB set */

    /* First we read the varint as an unsigned int */
    let mut buf = reader.read_u8()?;
    let mut res = (buf & (!msb)) as u64;

    let mut i: usize = 0;
    while (buf & msb) != 0 {
        if i >= 5 {
            bail!("VarInt is too long");
        }

        i += 1;
        buf = reader.read_u8()?;
        res += ((buf & (!msb)) as u64) * radix;
        radix <<= 7;
    }

    /* Now we convert it to signed */
    if res >= 4294967296 {
        bail!("Received too large varint");
    }

    if res > 2147483647 {
        return Ok((4294967296 - res) as i32 * -1);
    } else {
        return Ok(res as i32);
    }
}

/// Read length-prefixed bytearray where the length is given as a varint
pub fn read_prefixed_bytearray<R: Read>(reader: &mut R) -> Result<Vec<u8>> {
    let length = read_varint(reader)?;
    let mut tmp = vec![0; length as usize];
    reader.read_exact(&mut tmp)?;
    Ok(tmp)
}

/// Read length-prefixed varint array where the length is given as a varint
pub fn read_prefixed_varintarray<R: Read>(reader: &mut R) -> Result<Vec<i32>> {
    let length = read_varint(reader)?;
    let mut tmp = Vec::with_capacity(length as usize);
    for _ in 0..length {
        tmp.push(read_varint(reader)?);
    }
    Ok(tmp)
}

/// Read a uuid encoded as 16 bytes
pub fn read_uuid<R: Read>(reader: &mut R) -> Result<u128> {
    let a = read_u64(reader)?;
    let b = read_u64(reader)?;
    Ok(u128(a, b))
}

/// Read a uuid encoded as a string
///
/// Either with or without dashes.
pub fn read_uuid_str<R: Read>(reader: &mut R) -> Result<u128> {
    /* If it's without dashes, then it'll be 32 characters long, else it'll
     * be 36 characters long, so we read 32 characters first and see if it
     * contains any dahes */

    let tmp = read_String(reader)?.replace("-", "");

    let a = match u64::from_str_radix(&tmp[..16], 16) {
        Ok(x) => x,
        Err(_) => bail!("Invalid hex in first half of uuid_str"),
    };
    let b = match u64::from_str_radix(&tmp[16..], 16) {
        Ok(x) => x,
        Err(_) => bail!("Invalid hex in second half of uuid_str"),
    };
    Ok(u128(a, b))
}

/// Read a bytearray to the end of the reader
pub fn read_bytearray_to_end<R: Read>(reader: &mut R) -> Result<Vec<u8>> {
    let mut tmp = Vec::new();
    reader.read_to_end(&mut tmp)?;
    Ok(tmp)
}

/// Alias for read_bytearray_to_end
pub fn read_bytearray<R: Read>(reader: &mut R) -> Result<Vec<u8>> {
    read_bytearray_to_end(reader)
}

/// Read a position as described on wiki.vg, i.e. x/y/z given as an u64
pub fn read_position<R: Read>(reader: &mut R) -> Result<(i32, i32, i32)> {
    let val = read_u64(reader)?;
    let mut x = (val >> 38) as i32;
    let mut y = ((val >> 26) & 0xfff) as i32;
    let mut z = (val & 0x3ffffff) as i32;
    if x >= 1 << 25 {
        x -= 1 << 26;
    }
    if y >= 1 << 11 {
        y -= 1 << 12;
    }
    if z >= 2 << 25 {
        z -= 1 << 26;
    }
    Ok((x, y, z))
}
<commit_msg>read_uuid_str: Chain error instead of throwing it away<commit_after>//! Functions for deserializing datatypes used by the protocol
use errors::{Result, ResultExt};
use u128;

use std::io::Read;

use byteorder::{BigEndian, ReadBytesExt};

/// Read a single bool from the Reader
pub fn read_bool<R: Read>(reader: &mut R) -> Result<bool> {
    let byte = read_u8(reader)?;
    match byte {
        0 => Ok(false),
        1 => Ok(true),
        _ => bail!("Bool had invalid value {}", byte),
    }
}

/* Many of these functions obviously just duplicate functions from byteorder.
 * I keep them here to keep everything nicely organized, and also to make
 * things easier in the clientbound packet event macros.
 *
 * Also it ensures that if the MC modern protocol is changed, we can simply
 * change these functions without breaking anything. */

/// Read a single i8 from the Reader
pub fn read_i8<R: Read>(reader: &mut R) -> Result<i8> {
    Ok(reader.read_i8()?)
}

/// Read a single u8 from the Reader
pub fn read_u8<R: Read>(reader: &mut R) -> Result<u8> {
    Ok(reader.read_u8()?)
}

/// Read a single i16 from the Reader
pub fn read_i16<R: Read>(reader: &mut R) -> Result<i16> {
    Ok(reader.read_i16::<BigEndian>()?)
}

/// Read a single u16 from the Reader
pub fn read_u16<R: Read>(reader: &mut R) -> Result<u16> {
    Ok(reader.read_u16::<BigEndian>()?)
}

/// Read a single i32 from the Reader
pub fn read_i32<R: Read>(reader: &mut R) -> Result<i32> {
    Ok(reader.read_i32::<BigEndian>()?)
}

/// Read a single i64 from the Reader
pub fn read_i64<R: Read>(reader: &mut R) -> Result<i64> {
    Ok(reader.read_i64::<BigEndian>()?)
}

/// Read a single u64 from the Reader
pub fn read_u64<R: Read>(reader: &mut R) -> Result<u64> {
    Ok(reader.read_u64::<BigEndian>()?)
}

/// Read a single f32 from the Reader
pub fn read_f32<R: Read>(reader: &mut R) -> Result<f32> {
    Ok(reader.read_f32::<BigEndian>()?)
}

/// Read a single f64 from the Reader
pub fn read_f64<R: Read>(reader: &mut R) -> Result<f64> {
    Ok(reader.read_f64::<BigEndian>()?)
}

/// Read a length-prefixed utf-8 String from the Reader
#[allow(non_snake_case)]
pub fn read_String<R: Read>(reader: &mut R) -> Result<String> {
    let length = read_varint(reader)? as usize;

    if length > (1 << 16) {
        bail!("read_string refusing to read string due to its length");
    }

    let mut ret = String::with_capacity(length);
    let read = reader.take(length as u64).read_to_string(&mut ret)?;

    if read != length {
        bail!("read_String expected a string with length {} but was only able to read {} bytes", length, read);
    }

    Ok(ret)
}

/// Read a Minecraft-style varint, which currently fits into a i32
pub fn read_varint<R: Read>(reader: &mut R) -> Result<i32> {
    let mut radix: u64 = 128;
    let msb: u8 = 0b10000000; /* Only the MSB set */

    /* First we read the varint as an unsigned int */
    let mut buf = reader.read_u8()?;
    let mut res = (buf & (!msb)) as u64;

    let mut i: usize = 0;
    while (buf & msb) != 0 {
        if i >= 5 {
            bail!("VarInt is too long");
        }

        i += 1;
        buf = reader.read_u8()?;
        res += ((buf & (!msb)) as u64) * radix;
        radix <<= 7;
    }

    /* Now we convert it to signed */
    if res >= 4294967296 {
        bail!("Received too large varint");
    }

    if res > 2147483647 {
        return Ok((4294967296 - res) as i32 * -1);
    } else {
        return Ok(res as i32);
    }
}

/// Read length-prefixed bytearray where the length is given as a varint
pub fn read_prefixed_bytearray<R: Read>(reader: &mut R) -> Result<Vec<u8>> {
    let length = read_varint(reader)?;
    let mut tmp = vec![0; length as usize];
    reader.read_exact(&mut tmp)?;
    Ok(tmp)
}

/// Read length-prefixed varint array where the length is given as a varint
pub fn read_prefixed_varintarray<R: Read>(reader: &mut R) -> Result<Vec<i32>> {
    let length = read_varint(reader)?;
    let mut tmp = Vec::with_capacity(length as usize);
    for _ in 0..length {
        tmp.push(read_varint(reader)?);
    }
    Ok(tmp)
}

/// Read a uuid encoded as 16 bytes
pub fn read_uuid<R: Read>(reader: &mut R) -> Result<u128> {
    let a = read_u64(reader)?;
    let b = read_u64(reader)?;
    Ok(u128(a, b))
}

/// Read a uuid encoded as a string
///
/// Either with or without dashes.
pub fn read_uuid_str<R: Read>(reader: &mut R) -> Result<u128> {
    let tmp = read_String(reader)?.replace("-", "");
    let a = u64::from_str_radix(&tmp[..16], 16).chain_err(|| "Invalid hex in first half of uuid_str")?;
    let b = u64::from_str_radix(&tmp[16..], 16).chain_err(|| "Invalid hex in second half of uuid_str")?;
    Ok(u128(a, b))
}

/// Read a bytearray to the end of the reader
pub fn read_bytearray_to_end<R: Read>(reader: &mut R) -> Result<Vec<u8>> {
    let mut tmp = Vec::new();
    reader.read_to_end(&mut tmp)?;
    Ok(tmp)
}

/// Alias for read_bytearray_to_end
pub fn read_bytearray<R: Read>(reader: &mut R) -> Result<Vec<u8>> {
    read_bytearray_to_end(reader)
}

/// Read a position as described on wiki.vg, i.e. x/y/z given as an u64
pub fn read_position<R: Read>(reader: &mut R) -> Result<(i32, i32, i32)> {
    let val = read_u64(reader)?;
    let mut x = (val >> 38) as i32;
    let mut y = ((val >> 26) & 0xfff) as i32;
    let mut z = (val & 0x3ffffff) as i32;
    if x >= 1 << 25 {
        x -= 1 << 26;
    }
    if y >= 1 << 11 {
        y -= 1 << 12;
    }
    if z >= 2 << 25 {
        z -= 1 << 26;
    }
    Ok((x, y, z))
}
<|endoftext|>


<commit_before>use super::config::{Config, Capture};
use std::collections::BTreeMap;
use std::io::{BufRead, Write};

#[derive(Debug, Clone, Copy)]
pub enum OutputFormat {
    LittleEndian,
    BigEndian,
    HexList,
}

struct Replacement {
    // Line for purposes of printing errors.
    line: usize,
    // Left shift amount
    shift: i32,
    // Segment to add the value to.
    add_segment: usize,
    // The index in the add_segment to add the value.
    index: usize,
    // The tag to retrieve the position to add.
    tag: String,
    // The segment for which we are retrieving the position from the tag.
    pos_segment: usize,
    // The offset we add after retrieving the value from the tag.
    pos_offset: isize,
}

pub struct Parser<'a> {
    config: &'a Config,
    segments: Vec<Vec<u64>>,
    tags: BTreeMap<String, Vec<usize>>,
    replacements: Vec<Replacement>,
}

fn shift_left_or_right(a: u64, shift: i32) -> u64 {
    if shift < 0 {
        a >> (-shift)
    } else {
        a << shift
    }
}

impl<'a> Parser<'a> {
    pub fn new(config: &'a Config) -> Self {
        Parser {
            config: config,
            segments: {
                let mut v = Vec::new();
                for _ in 0..config.segment_widths.len() {
                    v.push(Vec::new());
                }
                v
            },
            tags: BTreeMap::new(),
            replacements: Vec::new(),
        }
    }

    pub fn link(&mut self) {
        // Iterate through every replacement.
        for r in &self.replacements {
            // Get the tag offset vector corresponding to the replacement.
            let tag = self.tags.get(&r.tag).unwrap_or_else(|| {
                panic!("Error: Tag \"{}\" used on line {} never defined.",
                       r.tag,
                       r.line);
            });
            self.segments[r.add_segment][r.index] +=
                shift_left_or_right((tag[r.pos_segment] as isize + r.pos_offset) as u64, r.shift);
        }
    }

    pub fn parse<B>(&mut self, bufread: B)
        where B: BufRead
    {
        for (index, line) in bufread.lines().enumerate() {
            let line = line.unwrap_or_else(|e| panic!("Error: Failed to read from buffer: {}", e));

            // Remove everything after the first #, which denotes a comment.
            let line = line.splitn(2, '#').next().unwrap();

            if self.config.split_whitespace {
                for word in line.split_whitespace() {
                    self.parse_segment(word, index + 1);
                }
            } else {
                self.parse_segment(line, index + 1);
            }
        }
    }

    pub fn output<W>(&self, format: OutputFormat, segment: usize, w: &mut W)
        where W: Write
    {
        use byteorder::{ByteOrder, LittleEndian, BigEndian};
        match format {
            OutputFormat::LittleEndian => {
                // Allocate enough bytes to store a u64
                let mut bytes = [0; 8];
                let width = self.config.segment_widths[segment];
                for val in &self.segments[segment] {
                    LittleEndian::write_u64(&mut bytes, *val);
                    w.write_all(&bytes[0..width]).unwrap_or_else(|e| {
                        panic!("Error: Writing to output file for segment {} failed: {}",
                               segment,
                               e);
                    });
                }
            }
            OutputFormat::BigEndian => {
                // Allocate enough bytes to store a u64
                let mut bytes = [0; 8];
                let width = self.config.segment_widths[segment];
                for val in &self.segments[segment] {
                    BigEndian::write_u64(&mut bytes, *val);
                    w.write_all(&bytes[0..width]).unwrap_or_else(|e| {
                        panic!("Error: Writing to output file for segment {} failed: {}",
                               segment,
                               e);
                    });
                }
            }
            OutputFormat::HexList => {
                use std::iter::FromIterator;
                // Allocate enough bytes to store a u64
                let mut bytes = [0u8; 8];
                let width = self.config.segment_widths[segment];
                for val in &self.segments[segment] {
                    BigEndian::write_u64(&mut bytes, *val);
                    w.write_all((String::from_iter(bytes[(8 - width)..8]
                                .iter()
                                .map(|&b| format!("{:02X}", b))) +
                                    "\n")
                            .as_bytes())
                        .unwrap_or_else(|e| {
                            panic!("Error: Writing to output file for segment {} failed: {}",
                                   segment,
                                   e);
                        });
                }
            }
        }
    }

    pub fn parse_segment(&mut self, segment: &str, line: usize) {
        if segment.is_empty() {
            return;
        }
        if self.attempt_tag_create(segment) {
            return;
        }
        if self.attempt_rules(segment, line) {
            return;
        }
        panic!("Error: Unrecognized symbol \"{}\" on line {}.",
               segment,
               line);
    }

    fn attempt_tag_create(&mut self, segment: &str) -> bool {
        if let Some(caps) = self.config.tag_create.regex.as_ref().unwrap().captures(segment) {
            self.tags.insert(caps.at(1).unwrap().to_string(),
                             self.segments
                                 .iter()
                                 .map(|v| v.len())
                                 .collect());
            true
        } else {
            false
        }
    }

    fn attempt_rules(&mut self, segment: &str, line: usize) -> bool {
        let config = &self.config;
        for rule in &config.rules {
            if let Some(caps) = rule.regex.as_ref().unwrap().captures(segment) {
                let mut segvals = rule.segment_values.clone();
                for self_reference in &rule.self_references {
                    segvals[self_reference.add_segment][self_reference.add_index] +=
                        if self_reference.shift < 0 {
                            (self.segments[self_reference.from_segment].len() as u64) >>
                            ((-self_reference.shift) as u32)
                        } else {
                            (self.segments[self_reference.from_segment].len() as u64) <<
                            (self_reference.shift as u32)
                        };
                }
                for (index, capture) in rule.captures.iter().enumerate() {
                    use std::mem::transmute;
                    let cap_string = caps.at(index + 1).unwrap();
                    match *capture {
                        Capture::Tag { ref feedbacks } => {
                            for feedback in feedbacks {
                                self.replacements.push(Replacement {
                                    line: line,
                                    shift: feedback.shift,
                                    add_segment: feedback.add_segment,
                                    index: self.segments[feedback.add_segment].len() +
                                           feedback.add_index,
                                    tag: String::from(cap_string),
                                    pos_segment: feedback.from_segment,
                                    pos_offset: if feedback.relative {
                                        feedback.offset -
                                        self.segments[feedback.from_segment].len() as isize
                                    } else {
                                        feedback.offset
                                    },
                                });
                            }
                        }
                        Capture::Str { add_segment } => {
                            for c in cap_string.chars() {
                                self.segments[add_segment].push(c as u64);
                            }
                        }
                        Capture::Num { ref feedbacks, ref base } => {
                            let pval = i64::from_str_radix(cap_string, *base).unwrap_or_else(|e| {
                                panic!("Error: Failed to parse captured string \"{}\" from \
                                        \"{}\": {}",
                                       cap_string,
                                       segment,
                                       e);
                            });
                            let val: u64 = unsafe { transmute(pval) };

                            for feedback in feedbacks {
                                let mut shiftval = shift_left_or_right(val, feedback.shift);
                                if feedback.negate {
                                    shiftval = !shiftval + 1;
                                }
                                if feedback.fill {
                                    let baseval = segvals[feedback.segment][feedback.index];
                                    let fill_amount = shiftval as isize + feedback.fill_offset;
                                    if fill_amount.is_negative() {
                                        panic!("Error: Got a negative fill amount!");
                                    } else if feedback.align {
                                        while self.segments[feedback.segment].len() <
                                              fill_amount as usize {
                                            self.segments[feedback.segment].push(baseval);
                                        }
                                    } else {
                                        for _ in 0..fill_amount {
                                            self.segments[feedback.segment].push(baseval);
                                        }
                                    }
                                    segvals[feedback.segment].pop();
                                } else {
                                    segvals[feedback.segment][index] += shiftval;
                                }
                            }
                        }
                    }
                }
                for (segvec, segment) in segvals.iter_mut().zip(self.segments.iter_mut()) {
                    segment.append(segvec);
                }
                return true;
            }
        }
        false
    }
}
<commit_msg>fix issue with indexing (used wrong index)<commit_after>use super::config::{Config, Capture};
use std::collections::BTreeMap;
use std::io::{BufRead, Write};

#[derive(Debug, Clone, Copy)]
pub enum OutputFormat {
    LittleEndian,
    BigEndian,
    HexList,
}

struct Replacement {
    // Line for purposes of printing errors.
    line: usize,
    // Left shift amount
    shift: i32,
    // Segment to add the value to.
    add_segment: usize,
    // The index in the add_segment to add the value.
    index: usize,
    // The tag to retrieve the position to add.
    tag: String,
    // The segment for which we are retrieving the position from the tag.
    pos_segment: usize,
    // The offset we add after retrieving the value from the tag.
    pos_offset: isize,
}

pub struct Parser<'a> {
    config: &'a Config,
    segments: Vec<Vec<u64>>,
    tags: BTreeMap<String, Vec<usize>>,
    replacements: Vec<Replacement>,
}

fn shift_left_or_right(a: u64, shift: i32) -> u64 {
    if shift < 0 {
        a >> (-shift)
    } else {
        a << shift
    }
}

impl<'a> Parser<'a> {
    pub fn new(config: &'a Config) -> Self {
        Parser {
            config: config,
            segments: {
                let mut v = Vec::new();
                for _ in 0..config.segment_widths.len() {
                    v.push(Vec::new());
                }
                v
            },
            tags: BTreeMap::new(),
            replacements: Vec::new(),
        }
    }

    pub fn link(&mut self) {
        // Iterate through every replacement.
        for r in &self.replacements {
            // Get the tag offset vector corresponding to the replacement.
            let tag = self.tags.get(&r.tag).unwrap_or_else(|| {
                panic!("Error: Tag \"{}\" used on line {} never defined.",
                       r.tag,
                       r.line);
            });
            self.segments[r.add_segment][r.index] +=
                shift_left_or_right((tag[r.pos_segment] as isize + r.pos_offset) as u64, r.shift);
        }
    }

    pub fn parse<B>(&mut self, bufread: B)
        where B: BufRead
    {
        for (index, line) in bufread.lines().enumerate() {
            let line = line.unwrap_or_else(|e| panic!("Error: Failed to read from buffer: {}", e));

            // Remove everything after the first #, which denotes a comment.
            let line = line.splitn(2, '#').next().unwrap();

            if self.config.split_whitespace {
                for word in line.split_whitespace() {
                    self.parse_segment(word, index + 1);
                }
            } else {
                self.parse_segment(line, index + 1);
            }
        }
    }

    pub fn output<W>(&self, format: OutputFormat, segment: usize, w: &mut W)
        where W: Write
    {
        use byteorder::{ByteOrder, LittleEndian, BigEndian};
        match format {
            OutputFormat::LittleEndian => {
                // Allocate enough bytes to store a u64
                let mut bytes = [0; 8];
                let width = self.config.segment_widths[segment];
                for val in &self.segments[segment] {
                    LittleEndian::write_u64(&mut bytes, *val);
                    w.write_all(&bytes[0..width]).unwrap_or_else(|e| {
                        panic!("Error: Writing to output file for segment {} failed: {}",
                               segment,
                               e);
                    });
                }
            }
            OutputFormat::BigEndian => {
                // Allocate enough bytes to store a u64
                let mut bytes = [0; 8];
                let width = self.config.segment_widths[segment];
                for val in &self.segments[segment] {
                    BigEndian::write_u64(&mut bytes, *val);
                    w.write_all(&bytes[0..width]).unwrap_or_else(|e| {
                        panic!("Error: Writing to output file for segment {} failed: {}",
                               segment,
                               e);
                    });
                }
            }
            OutputFormat::HexList => {
                use std::iter::FromIterator;
                // Allocate enough bytes to store a u64
                let mut bytes = [0u8; 8];
                let width = self.config.segment_widths[segment];
                for val in &self.segments[segment] {
                    BigEndian::write_u64(&mut bytes, *val);
                    w.write_all((String::from_iter(bytes[(8 - width)..8]
                                .iter()
                                .map(|&b| format!("{:02X}", b))) +
                                    "\n")
                            .as_bytes())
                        .unwrap_or_else(|e| {
                            panic!("Error: Writing to output file for segment {} failed: {}",
                                   segment,
                                   e);
                        });
                }
            }
        }
    }

    pub fn parse_segment(&mut self, segment: &str, line: usize) {
        if segment.is_empty() {
            return;
        }
        if self.attempt_tag_create(segment) {
            return;
        }
        if self.attempt_rules(segment, line) {
            return;
        }
        panic!("Error: Unrecognized symbol \"{}\" on line {}.",
               segment,
               line);
    }

    fn attempt_tag_create(&mut self, segment: &str) -> bool {
        if let Some(caps) = self.config.tag_create.regex.as_ref().unwrap().captures(segment) {
            self.tags.insert(caps.at(1).unwrap().to_string(),
                             self.segments
                                 .iter()
                                 .map(|v| v.len())
                                 .collect());
            true
        } else {
            false
        }
    }

    fn attempt_rules(&mut self, segment: &str, line: usize) -> bool {
        let config = &self.config;
        for rule in &config.rules {
            if let Some(caps) = rule.regex.as_ref().unwrap().captures(segment) {
                let mut segvals = rule.segment_values.clone();
                for self_reference in &rule.self_references {
                    segvals[self_reference.add_segment][self_reference.add_index] +=
                        if self_reference.shift < 0 {
                            (self.segments[self_reference.from_segment].len() as u64) >>
                            ((-self_reference.shift) as u32)
                        } else {
                            (self.segments[self_reference.from_segment].len() as u64) <<
                            (self_reference.shift as u32)
                        };
                }
                for (index, capture) in rule.captures.iter().enumerate() {
                    use std::mem::transmute;
                    let cap_string = caps.at(index + 1).unwrap();
                    match *capture {
                        Capture::Tag { ref feedbacks } => {
                            for feedback in feedbacks {
                                self.replacements.push(Replacement {
                                    line: line,
                                    shift: feedback.shift,
                                    add_segment: feedback.add_segment,
                                    index: self.segments[feedback.add_segment].len() +
                                           feedback.add_index,
                                    tag: String::from(cap_string),
                                    pos_segment: feedback.from_segment,
                                    pos_offset: if feedback.relative {
                                        feedback.offset -
                                        self.segments[feedback.from_segment].len() as isize
                                    } else {
                                        feedback.offset
                                    },
                                });
                            }
                        }
                        Capture::Str { add_segment } => {
                            for c in cap_string.chars() {
                                self.segments[add_segment].push(c as u64);
                            }
                        }
                        Capture::Num { ref feedbacks, ref base } => {
                            let pval = i64::from_str_radix(cap_string, *base).unwrap_or_else(|e| {
                                panic!("Error: Failed to parse captured string \"{}\" from \
                                        \"{}\": {}",
                                       cap_string,
                                       segment,
                                       e);
                            });
                            let val: u64 = unsafe { transmute(pval) };

                            for feedback in feedbacks {
                                let mut shiftval = shift_left_or_right(val, feedback.shift);
                                if feedback.negate {
                                    shiftval = !shiftval + 1;
                                }
                                if feedback.fill {
                                    let baseval = segvals[feedback.segment][feedback.index];
                                    let fill_amount = shiftval as isize + feedback.fill_offset;
                                    if fill_amount.is_negative() {
                                        panic!("Error: Got a negative fill amount!");
                                    } else if feedback.align {
                                        while self.segments[feedback.segment].len() <
                                              fill_amount as usize {
                                            self.segments[feedback.segment].push(baseval);
                                        }
                                    } else {
                                        for _ in 0..fill_amount {
                                            self.segments[feedback.segment].push(baseval);
                                        }
                                    }
                                    segvals[feedback.segment].pop();
                                } else {
                                    segvals[feedback.segment][feedback.index] += shiftval;
                                }
                            }
                        }
                    }
                }
                for (segvec, segment) in segvals.iter_mut().zip(self.segments.iter_mut()) {
                    segment.append(segvec);
                }
                return true;
            }
        }
        false
    }
}
<|endoftext|>


<commit_before>/// The sure stream.
///
/// The sure stream represents a linearization of a SureTree.  By keeping
/// representations as iterators across SureNodes instead of keeping an
/// entire tree in memory, we can process larger filesystem trees, using
/// temporary space on the hard disk instead of using memory.
use crate::{suretree::AttMap, Error, Result};
use flate2::{read::GzDecoder, write::GzEncoder, Compression};
use std::{
    fs::File,
    io::{self, BufRead, BufReader, BufWriter, Read, Write},
    path::{Path, PathBuf},
};
use weave::NamingConvention;

mod compare;
pub mod fs;
mod fullpath;
mod hashes;

pub use compare::compare_trees;
pub use fullpath::into_tracker;
pub use hashes::{HashCombiner, HashUpdater, Source};

#[derive(Clone, Debug)]
pub enum SureNode {
    Enter { name: String, atts: AttMap },
    Leave,
    File { name: String, atts: AttMap },
    Sep,
}

impl SureNode {
    pub fn is_enter(&self) -> bool {
        matches!(self, SureNode::Enter { .. })
    }

    pub fn is_reg_file(&self) -> bool {
        match self {
            SureNode::File { atts, .. } => atts["kind"] == "file",
            _ => false,
        }
    }

    pub fn is_file(&self) -> bool {
        matches!(self, SureNode::File { .. })
    }

    pub fn is_leave(&self) -> bool {
        matches!(self, SureNode::Leave)
    }

    pub fn is_sep(&self) -> bool {
        matches!(self, SureNode::Sep)
    }

    pub fn needs_hash(&self) -> bool {
        match self {
            SureNode::File { atts, .. } => atts["kind"] == "file" && !atts.contains_key("sha1"),
            _ => false,
        }
    }

    pub fn size(&self) -> u64 {
        match self {
            SureNode::File { atts, .. } => {
                atts.get("size").map(|x| x.parse().unwrap()).unwrap_or(0)
            }
            _ => 0,
        }
    }

    /// Get the name of this node.  Panics if the node type does not have
    /// an associated name.
    pub fn name(&self) -> &str {
        match self {
            SureNode::File { ref name, .. } => name,
            SureNode::Enter { ref name, .. } => name,
            _ => panic!("Node does not have a name"),
        }
    }

    /// Safely get the name of this node.
    pub fn get_name(&self) -> Option<&str> {
        match self {
            SureNode::File { ref name, .. } => Some(name),
            SureNode::Enter { ref name, .. } => Some(name),
            _ => None,
        }
    }

    /// Get a nice representation of the kind of this node.  Returns "???"
    /// if the kind isn't meaningful.
    pub fn kind(&self) -> &str {
        self.atts()
            .map(|a| a.get("kind").map(|k| &k[..]).unwrap_or("???"))
            .unwrap_or("???")
    }

    /// Access the nodes attributes.
    pub fn atts(&self) -> Option<&AttMap> {
        match self {
            SureNode::File { ref atts, .. } => Some(atts),
            SureNode::Enter { ref atts, .. } => Some(atts),
            _ => None,
        }
    }

    /// Access the nodes attributes mutably.
    pub fn atts_mut(&mut self) -> Option<&mut AttMap> {
        match self {
            SureNode::File { ref mut atts, .. } => Some(atts),
            SureNode::Enter { ref mut atts, .. } => Some(atts),
            _ => None,
        }
    }
}

// TODO: These might be possible to make more generic, but it gets messy,
// as it might just be best to assume failure.

/// Write a sure iterator to a standard gzipped file of the given name.
pub fn save<P, I>(name: P, nodes: I) -> Result<()>
where
    P: AsRef<Path>,
    I: Iterator<Item = Result<SureNode>>,
{
    let wr = File::create(name)?;
    let wr = GzEncoder::new(wr, Compression::default());
    save_to(wr, nodes)
}

/// Write a sure iterator to a new temp file with a given naming
/// convention.  Returns the name of the file, if it could be created.  The
/// data will not be written compressed.
pub fn save_naming<I, N>(naming: &N, nodes: I) -> Result<PathBuf>
where
    N: NamingConvention,
    I: Iterator<Item = Result<SureNode>>,
{
    let (tmp_name, mut tmp_file) = naming.temp_file()?;
    save_to(&mut tmp_file, nodes)?;
    Ok(tmp_name)
}

/// Save a sure tree to the given writer.
pub fn save_to<W, I>(wr: W, nodes: I) -> Result<()>
where
    W: Write,
    I: Iterator<Item = Result<SureNode>>,
{
    let mut wr = BufWriter::new(wr);

    writeln!(&mut wr, "asure-2.0")?;
    writeln!(&mut wr, "-----")?;

    for node in nodes {
        match node? {
            SureNode::Enter { name, atts } => header(&mut wr, 'd', &name, &atts)?,
            SureNode::File { name, atts } => header(&mut wr, 'f', &name, &atts)?,
            SureNode::Sep => writeln!(&mut wr, "-")?,
            SureNode::Leave => writeln!(&mut wr, "u")?,
        }
    }
    Ok(())
}

/// For pushed based writing, we can also write using a NodeWriter.
pub struct NodeWriter<W: Write> {
    writer: BufWriter<W>,
}

impl<W: Write> NodeWriter<W> {
    pub fn new(writer: W) -> Result<NodeWriter<W>> {
        let mut wr = BufWriter::new(writer);
        writeln!(&mut wr, "asure-2.0")?;
        writeln!(&mut wr, "-----")?;

        Ok(NodeWriter { writer: wr })
    }

    pub fn write_node(&mut self, node: &SureNode) -> Result<()> {
        match node {
            SureNode::Enter { name, atts } => header(&mut self.writer, 'd', &name, &atts)?,
            SureNode::File { name, atts } => header(&mut self.writer, 'f', &name, &atts)?,
            SureNode::Sep => writeln!(&mut self.writer, "-")?,
            SureNode::Leave => writeln!(&mut self.writer, "u")?,
        }
        Ok(())
    }
}

fn header<W: Write>(out: &mut W, kind: char, name: &str, atts: &AttMap) -> Result<()> {
    write!(out, "{}{} [", kind, name)?;

    for (k, v) in atts {
        write!(out, "{} {} ", k, v)?;
    }
    writeln!(out, "]")?;
    Ok(())
}

/// Load and iterate a sure tree from a standard gzip compressed surefile.
pub fn load<P: AsRef<Path>>(name: P) -> Result<ReadIterator<GzDecoder<File>>> {
    let rd = File::open(name)?;
    let rd = GzDecoder::new(rd);
    load_from(rd)
}

/// Load a surenode sequence from the given reader.
pub fn load_from<R: Read>(rd: R) -> Result<ReadIterator<R>> {
    let rd = BufReader::new(rd);
    let mut lines = rd.split('\n' as u8);

    fixed(&mut lines, b"asure-2.0")?;
    fixed(&mut lines, b"-----")?;

    Ok(ReadIterator {
        lines: lines,
        depth: 0,
        done: false,
    })
}

fn fixed<I>(inp: &mut I, exp: &[u8]) -> Result<()>
where
    I: Iterator<Item = io::Result<Vec<u8>>>,
{
    match inp.next() {
        Some(Ok(ref text)) if &text[..] == exp => Ok(()),
        Some(Ok(ref text)) => Err(Error::UnexpectedLine(
            String::from_utf8_lossy(text).into_owned(),
            String::from_utf8_lossy(exp).into_owned(),
        )),
        Some(Err(e)) => Err(Error::SureFileError(e)),
        None => Err(Error::SureFileEof),
    }
}

pub struct ReadIterator<R> {
    lines: io::Split<BufReader<R>>,
    depth: usize,
    done: bool,
}

impl<R: Read> Iterator for ReadIterator<R> {
    type Item = Result<SureNode>;

    fn next(&mut self) -> Option<Result<SureNode>> {
        if self.done {
            return None;
        }

        let line = match self.get_line() {
            Ok(line) => line,
            Err(e) => return Some(Err(e)),
        };

        match line[0] {
            b'd' => {
                let (dname, datts) = decode_entity(&line[1..]);
                self.depth += 1;
                Some(Ok(SureNode::Enter {
                    name: dname,
                    atts: datts,
                }))
            }
            b'f' => {
                let (fname, fatts) = decode_entity(&line[1..]);
                Some(Ok(SureNode::File {
                    name: fname,
                    atts: fatts,
                }))
            }
            b'-' => Some(Ok(SureNode::Sep)),
            b'u' => {
                self.depth -= 1;
                if self.depth == 0 {
                    self.done = true;
                }
                Some(Ok(SureNode::Leave))
            }
            ch => Some(Err(Error::InvalidSurefileChar(ch as char))),
        }
    }
}

impl<R: Read> ReadIterator<R> {
    fn get_line(&mut self) -> Result<Vec<u8>> {
        match self.lines.next() {
            None => return Err(Error::TruncatedSurefile),
            Some(l) => Ok(l?),
        }
    }
}

// TODO: This should return Result to handle errors.
pub(crate) fn decode_entity(text: &[u8]) -> (String, AttMap) {
    let (name, mut text) = get_delim(text, b' ');
    assert!(text[0] == b'[');
    text = &text[1..];

    let mut atts = AttMap::new();
    while text[0] != b']' {
        let (key, t2) = get_delim(text, b' ');
        let (value, t2) = get_delim(t2, b' ');
        text = t2;

        atts.insert(key, value);
    }

    (name, atts)
}

fn get_delim(text: &[u8], delim: u8) -> (String, &[u8]) {
    let mut it = text.iter();
    let space = it.position(|&s| s == delim).unwrap();
    (
        String::from_utf8(text[..space].to_owned()).unwrap(),
        &text[space + 1..],
    )
}
<commit_msg>clippy: Use a byte literal<commit_after>/// The sure stream.
///
/// The sure stream represents a linearization of a SureTree.  By keeping
/// representations as iterators across SureNodes instead of keeping an
/// entire tree in memory, we can process larger filesystem trees, using
/// temporary space on the hard disk instead of using memory.
use crate::{suretree::AttMap, Error, Result};
use flate2::{read::GzDecoder, write::GzEncoder, Compression};
use std::{
    fs::File,
    io::{self, BufRead, BufReader, BufWriter, Read, Write},
    path::{Path, PathBuf},
};
use weave::NamingConvention;

mod compare;
pub mod fs;
mod fullpath;
mod hashes;

pub use compare::compare_trees;
pub use fullpath::into_tracker;
pub use hashes::{HashCombiner, HashUpdater, Source};

#[derive(Clone, Debug)]
pub enum SureNode {
    Enter { name: String, atts: AttMap },
    Leave,
    File { name: String, atts: AttMap },
    Sep,
}

impl SureNode {
    pub fn is_enter(&self) -> bool {
        matches!(self, SureNode::Enter { .. })
    }

    pub fn is_reg_file(&self) -> bool {
        match self {
            SureNode::File { atts, .. } => atts["kind"] == "file",
            _ => false,
        }
    }

    pub fn is_file(&self) -> bool {
        matches!(self, SureNode::File { .. })
    }

    pub fn is_leave(&self) -> bool {
        matches!(self, SureNode::Leave)
    }

    pub fn is_sep(&self) -> bool {
        matches!(self, SureNode::Sep)
    }

    pub fn needs_hash(&self) -> bool {
        match self {
            SureNode::File { atts, .. } => atts["kind"] == "file" && !atts.contains_key("sha1"),
            _ => false,
        }
    }

    pub fn size(&self) -> u64 {
        match self {
            SureNode::File { atts, .. } => {
                atts.get("size").map(|x| x.parse().unwrap()).unwrap_or(0)
            }
            _ => 0,
        }
    }

    /// Get the name of this node.  Panics if the node type does not have
    /// an associated name.
    pub fn name(&self) -> &str {
        match self {
            SureNode::File { ref name, .. } => name,
            SureNode::Enter { ref name, .. } => name,
            _ => panic!("Node does not have a name"),
        }
    }

    /// Safely get the name of this node.
    pub fn get_name(&self) -> Option<&str> {
        match self {
            SureNode::File { ref name, .. } => Some(name),
            SureNode::Enter { ref name, .. } => Some(name),
            _ => None,
        }
    }

    /// Get a nice representation of the kind of this node.  Returns "???"
    /// if the kind isn't meaningful.
    pub fn kind(&self) -> &str {
        self.atts()
            .map(|a| a.get("kind").map(|k| &k[..]).unwrap_or("???"))
            .unwrap_or("???")
    }

    /// Access the nodes attributes.
    pub fn atts(&self) -> Option<&AttMap> {
        match self {
            SureNode::File { ref atts, .. } => Some(atts),
            SureNode::Enter { ref atts, .. } => Some(atts),
            _ => None,
        }
    }

    /// Access the nodes attributes mutably.
    pub fn atts_mut(&mut self) -> Option<&mut AttMap> {
        match self {
            SureNode::File { ref mut atts, .. } => Some(atts),
            SureNode::Enter { ref mut atts, .. } => Some(atts),
            _ => None,
        }
    }
}

// TODO: These might be possible to make more generic, but it gets messy,
// as it might just be best to assume failure.

/// Write a sure iterator to a standard gzipped file of the given name.
pub fn save<P, I>(name: P, nodes: I) -> Result<()>
where
    P: AsRef<Path>,
    I: Iterator<Item = Result<SureNode>>,
{
    let wr = File::create(name)?;
    let wr = GzEncoder::new(wr, Compression::default());
    save_to(wr, nodes)
}

/// Write a sure iterator to a new temp file with a given naming
/// convention.  Returns the name of the file, if it could be created.  The
/// data will not be written compressed.
pub fn save_naming<I, N>(naming: &N, nodes: I) -> Result<PathBuf>
where
    N: NamingConvention,
    I: Iterator<Item = Result<SureNode>>,
{
    let (tmp_name, mut tmp_file) = naming.temp_file()?;
    save_to(&mut tmp_file, nodes)?;
    Ok(tmp_name)
}

/// Save a sure tree to the given writer.
pub fn save_to<W, I>(wr: W, nodes: I) -> Result<()>
where
    W: Write,
    I: Iterator<Item = Result<SureNode>>,
{
    let mut wr = BufWriter::new(wr);

    writeln!(&mut wr, "asure-2.0")?;
    writeln!(&mut wr, "-----")?;

    for node in nodes {
        match node? {
            SureNode::Enter { name, atts } => header(&mut wr, 'd', &name, &atts)?,
            SureNode::File { name, atts } => header(&mut wr, 'f', &name, &atts)?,
            SureNode::Sep => writeln!(&mut wr, "-")?,
            SureNode::Leave => writeln!(&mut wr, "u")?,
        }
    }
    Ok(())
}

/// For pushed based writing, we can also write using a NodeWriter.
pub struct NodeWriter<W: Write> {
    writer: BufWriter<W>,
}

impl<W: Write> NodeWriter<W> {
    pub fn new(writer: W) -> Result<NodeWriter<W>> {
        let mut wr = BufWriter::new(writer);
        writeln!(&mut wr, "asure-2.0")?;
        writeln!(&mut wr, "-----")?;

        Ok(NodeWriter { writer: wr })
    }

    pub fn write_node(&mut self, node: &SureNode) -> Result<()> {
        match node {
            SureNode::Enter { name, atts } => header(&mut self.writer, 'd', &name, &atts)?,
            SureNode::File { name, atts } => header(&mut self.writer, 'f', &name, &atts)?,
            SureNode::Sep => writeln!(&mut self.writer, "-")?,
            SureNode::Leave => writeln!(&mut self.writer, "u")?,
        }
        Ok(())
    }
}

fn header<W: Write>(out: &mut W, kind: char, name: &str, atts: &AttMap) -> Result<()> {
    write!(out, "{}{} [", kind, name)?;

    for (k, v) in atts {
        write!(out, "{} {} ", k, v)?;
    }
    writeln!(out, "]")?;
    Ok(())
}

/// Load and iterate a sure tree from a standard gzip compressed surefile.
pub fn load<P: AsRef<Path>>(name: P) -> Result<ReadIterator<GzDecoder<File>>> {
    let rd = File::open(name)?;
    let rd = GzDecoder::new(rd);
    load_from(rd)
}

/// Load a surenode sequence from the given reader.
pub fn load_from<R: Read>(rd: R) -> Result<ReadIterator<R>> {
    let rd = BufReader::new(rd);
    let mut lines = rd.split(b'\n');

    fixed(&mut lines, b"asure-2.0")?;
    fixed(&mut lines, b"-----")?;

    Ok(ReadIterator {
        lines: lines,
        depth: 0,
        done: false,
    })
}

fn fixed<I>(inp: &mut I, exp: &[u8]) -> Result<()>
where
    I: Iterator<Item = io::Result<Vec<u8>>>,
{
    match inp.next() {
        Some(Ok(ref text)) if &text[..] == exp => Ok(()),
        Some(Ok(ref text)) => Err(Error::UnexpectedLine(
            String::from_utf8_lossy(text).into_owned(),
            String::from_utf8_lossy(exp).into_owned(),
        )),
        Some(Err(e)) => Err(Error::SureFileError(e)),
        None => Err(Error::SureFileEof),
    }
}

pub struct ReadIterator<R> {
    lines: io::Split<BufReader<R>>,
    depth: usize,
    done: bool,
}

impl<R: Read> Iterator for ReadIterator<R> {
    type Item = Result<SureNode>;

    fn next(&mut self) -> Option<Result<SureNode>> {
        if self.done {
            return None;
        }

        let line = match self.get_line() {
            Ok(line) => line,
            Err(e) => return Some(Err(e)),
        };

        match line[0] {
            b'd' => {
                let (dname, datts) = decode_entity(&line[1..]);
                self.depth += 1;
                Some(Ok(SureNode::Enter {
                    name: dname,
                    atts: datts,
                }))
            }
            b'f' => {
                let (fname, fatts) = decode_entity(&line[1..]);
                Some(Ok(SureNode::File {
                    name: fname,
                    atts: fatts,
                }))
            }
            b'-' => Some(Ok(SureNode::Sep)),
            b'u' => {
                self.depth -= 1;
                if self.depth == 0 {
                    self.done = true;
                }
                Some(Ok(SureNode::Leave))
            }
            ch => Some(Err(Error::InvalidSurefileChar(ch as char))),
        }
    }
}

impl<R: Read> ReadIterator<R> {
    fn get_line(&mut self) -> Result<Vec<u8>> {
        match self.lines.next() {
            None => return Err(Error::TruncatedSurefile),
            Some(l) => Ok(l?),
        }
    }
}

// TODO: This should return Result to handle errors.
pub(crate) fn decode_entity(text: &[u8]) -> (String, AttMap) {
    let (name, mut text) = get_delim(text, b' ');
    assert!(text[0] == b'[');
    text = &text[1..];

    let mut atts = AttMap::new();
    while text[0] != b']' {
        let (key, t2) = get_delim(text, b' ');
        let (value, t2) = get_delim(t2, b' ');
        text = t2;

        atts.insert(key, value);
    }

    (name, atts)
}

fn get_delim(text: &[u8], delim: u8) -> (String, &[u8]) {
    let mut it = text.iter();
    let space = it.position(|&s| s == delim).unwrap();
    (
        String::from_utf8(text[..space].to_owned()).unwrap(),
        &text[space + 1..],
    )
}
<|endoftext|>


<commit_before>pub use self::core::OnceCell;

#[allow(unsafe_code)]
mod core {
    use std::cell::UnsafeCell;

    /// A mutable memory location that can be set only once.
    pub struct OnceCell<T>(UnsafeCell<Option<T>>);

    impl<T> OnceCell<T> {
        /// Creates a new `OnceCell` that may already be initialized.
        ///
        /// # Example
        ///
        /// ```
        /// use mitochondria::OnceCell;
        ///
        /// let c = OnceCell::new(Some("Hello vesicle!".to_owned()));
        /// ```
        #[inline]
        pub fn new(value: Option<T>) -> Self {
            OnceCell(UnsafeCell::new(value))
        }

        /// Calls a function to try to initialize this cell.
        ///
        /// If the cell was already-initialized, the function is *not* called.
        /// Otherwise, if the function returns `Ok(value)`, the cell is
        /// initialized with `value`.
        ///
        /// This method returns `None` if the cell could not be initialized,
        /// or `Some(&value)` otherwise.
        ///
        /// # Examples
        ///
        /// ```
        /// use mitochondria::OnceCell;
        ///
        /// let c = OnceCell::new(None);
        ///
        /// assert_eq!(c.try_init_once(|| Err(())), None);
        ///
        /// let greeting: &str = c.try_init_once(|| {
        ///     Ok("Hello ribosome!".to_owned())
        /// }).unwrap();
        /// ```
        ///
        /// ```
        /// use mitochondria::OnceCell;
        ///
        /// let c = OnceCell::new(Some("Hello reticulum!".to_owned()));
        ///
        /// // Calls to `try_init_once` on initialized cells are ignored.
        /// assert_eq!(c.try_init_once(|| Ok("Goodbye!".to_owned())).unwrap(),
        ///            "Hello reticulum!");
        /// ```
        #[allow(unsafe_code)]
        #[inline]
        pub fn try_init_once<F>(&self, f: F) -> Option<&T>
            where F: FnOnce() -> Result<T, ()>
        {
            if self.borrow().is_none() {
                if let Ok(value) = f() {
                    // f() may have initialised the value already.
                    if self.borrow().is_none() {
                        unsafe { *self.0.get() = Some(value); }
                    }
                }
            }
            self.borrow()
        }

        /// Borrows the contained value, if initialized.
        ///
        /// # Examples
        ///
        /// ```
        /// use mitochondria::OnceCell;
        ///
        /// let c = OnceCell::new(None);
        ///
        /// assert!(c.borrow().is_none());
        ///
        /// let greeting = c.init_once(|| "Hello nucleus!".to_owned());
        /// assert_eq!(c.borrow(), Some(greeting));
        /// ```
        #[inline]
        pub fn borrow(&self) -> Option<&T> {
            unsafe { (*self.0.get()).as_ref() }
        }
    }
}

impl<T> OnceCell<T> {
    /// Calls a function to initialize this cell and borrows its value.
    ///
    /// If the cell was already-initialized, the function is *not* called and
    /// the returned value is the one that was already there.
    ///
    /// # Examples
    ///
    /// ```
    /// use mitochondria::OnceCell;
    ///
    /// let c = OnceCell::new(None);
    ///
    /// let greeting: &str = c.init_once(|| "Hello ribosome!".to_owned());
    /// ```
    ///
    /// ```
    /// use mitochondria::OnceCell;
    ///
    /// let c = OnceCell::new(Some("Hello reticulum!".to_owned()));
    ///
    /// // Calls to `init_once` on initialized cells are ignored.
    /// assert_eq!(c.init_once(|| "Goodbye!".to_owned()),
    ///            "Hello reticulum!");
    /// ```
    #[inline]
    pub fn init_once<F>(&self, f: F) -> &T where F: FnOnce() -> T {
        self.try_init_once(|| Ok(f())).unwrap()
    }
}

#[cfg(test)]
mod tests {
    use OnceCell;

    #[test]
    fn reentrancy() {
        let c = OnceCell::new(None);

        let value = *c.init_once(|| {
            c.init_once(|| "ribosome");
            "nucleolus"
        });

        assert_eq!(value, "ribosome");
    }
}
<commit_msg>Implement Send, Clone, Debug and Default for OnceCell<commit_after>pub use self::core::OnceCell;

use std::fmt;

#[allow(unsafe_code)]
mod core {
    use std::cell::UnsafeCell;

    /// A mutable memory location that can be set only once.
    pub struct OnceCell<T>(UnsafeCell<Option<T>>);

    unsafe impl<T> Send for OnceCell<T> where T: Send {}

    impl<T> OnceCell<T> {
        /// Creates a new `OnceCell` that may already be initialized.
        ///
        /// # Example
        ///
        /// ```
        /// use mitochondria::OnceCell;
        ///
        /// let c = OnceCell::new(Some("Hello vesicle!".to_owned()));
        /// ```
        #[inline]
        pub fn new(value: Option<T>) -> Self {
            OnceCell(UnsafeCell::new(value))
        }

        /// Calls a function to try to initialize this cell.
        ///
        /// If the cell was already-initialized, the function is *not* called.
        /// Otherwise, if the function returns `Ok(value)`, the cell is
        /// initialized with `value`.
        ///
        /// This method returns `None` if the cell could not be initialized,
        /// or `Some(&value)` otherwise.
        ///
        /// # Examples
        ///
        /// ```
        /// use mitochondria::OnceCell;
        ///
        /// let c = OnceCell::new(None);
        ///
        /// assert_eq!(c.try_init_once(|| Err(())), None);
        ///
        /// let greeting: &str = c.try_init_once(|| {
        ///     Ok("Hello ribosome!".to_owned())
        /// }).unwrap();
        /// ```
        ///
        /// ```
        /// use mitochondria::OnceCell;
        ///
        /// let c = OnceCell::new(Some("Hello reticulum!".to_owned()));
        ///
        /// // Calls to `try_init_once` on initialized cells are ignored.
        /// assert_eq!(c.try_init_once(|| Ok("Goodbye!".to_owned())).unwrap(),
        ///            "Hello reticulum!");
        /// ```
        #[allow(unsafe_code)]
        #[inline]
        pub fn try_init_once<F>(&self, f: F) -> Option<&T>
            where F: FnOnce() -> Result<T, ()>
        {
            if self.borrow().is_none() {
                if let Ok(value) = f() {
                    // f() may have initialised the value already.
                    if self.borrow().is_none() {
                        unsafe { *self.0.get() = Some(value); }
                    }
                }
            }
            self.borrow()
        }

        /// Borrows the contained value, if initialized.
        ///
        /// # Examples
        ///
        /// ```
        /// use mitochondria::OnceCell;
        ///
        /// let c = OnceCell::new(None);
        ///
        /// assert!(c.borrow().is_none());
        ///
        /// let greeting = c.init_once(|| "Hello nucleus!".to_owned());
        /// assert_eq!(c.borrow(), Some(greeting));
        /// ```
        #[inline]
        pub fn borrow(&self) -> Option<&T> {
            unsafe { (*self.0.get()).as_ref() }
        }
    }
}

impl<T> OnceCell<T> {
    /// Calls a function to initialize this cell and borrows its value.
    ///
    /// If the cell was already-initialized, the function is *not* called and
    /// the returned value is the one that was already there.
    ///
    /// # Examples
    ///
    /// ```
    /// use mitochondria::OnceCell;
    ///
    /// let c = OnceCell::new(None);
    ///
    /// let greeting: &str = c.init_once(|| "Hello ribosome!".to_owned());
    /// ```
    ///
    /// ```
    /// use mitochondria::OnceCell;
    ///
    /// let c = OnceCell::new(Some("Hello reticulum!".to_owned()));
    ///
    /// // Calls to `init_once` on initialized cells are ignored.
    /// assert_eq!(c.init_once(|| "Goodbye!".to_owned()),
    ///            "Hello reticulum!");
    /// ```
    #[inline]
    pub fn init_once<F>(&self, f: F) -> &T where F: FnOnce() -> T {
        self.try_init_once(|| Ok(f())).unwrap()
    }
}

impl<T: Clone> Clone for OnceCell<T> {
    #[inline]
    fn clone(&self) -> Self {
        OnceCell::new(self.borrow().cloned())
    }
}

impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("OnceCell").field(&self.borrow()).finish()
    }
}

impl<T: Default> Default for OnceCell<T> {
    #[inline]
    fn default() -> Self {
        OnceCell::new(Default::default())
    }
}

#[cfg(test)]
mod tests {
    use OnceCell;

    #[test]
    fn reentrancy() {
        let c = OnceCell::new(None);

        let value = *c.init_once(|| {
            c.init_once(|| "ribosome");
            "nucleolus"
        });

        assert_eq!(value, "ribosome");
    }
}
<|endoftext|>


<commit_before>
use std::ops::{Index, IndexMut};
use std::str::FromStr;

use error::{NcclError, ErrorKind};
use token::{TokenKind, Token};

// top level key that contains everything is __top_level__
#[derive(Clone, Debug, PartialEq)]
pub struct Pair {
    pub key: String,
    pub value: Vec<Pair>
}

impl Pair {
    pub fn new(key: &str) -> Self {
        Pair {
            key: key.to_owned(),
            value: vec![]
        }
    }

    pub fn pretty_print(&self) {
        self.pp_rec(0);
    }

    fn pp_rec(&self, indent: u32) {
        for _ in 0..indent {
            print!("    ");
        }
        println!("{}", self.key);
        for value in self.value.iter() {
            value.pp_rec(indent + 1);
        }
    }

    pub fn add(&mut self, value: &str) {
        self.value.push(Pair::new(value));
    }

    pub fn add_slice(&mut self, path: &[String]) {
        let mut s = self.traverse_path(&path[0..path.len() - 1]);
        if !s.has_key(&path[path.len() - 1]) {
            s.add(&path[path.len() - 1]);
        }
    }

    pub fn traverse_path(&mut self, path: &[String]) -> &mut Pair {
        if path.len() == 0 {
            self
        } else {
            if !self.has_key(&path[0]) {
                self.add(&path[0]);
            }
            self.get(&path[0]).unwrap().traverse_path(&path[1..path.len()])
        }
    }

    pub fn add_pair(&mut self, pair: Pair) {
        if !self.keys().contains(&pair.key) {
            self.value.push(pair);
        } else {
            self[&pair.key].value = pair.value;
        }
    }

    pub fn has_key(&self, key: &str) -> bool {
        for item in self.value.iter() {
            if &item.key == key {
                return true;
            }
        }

        return false;
    }

    pub fn get(&mut self, value: &str) -> Result<&mut Pair, NcclError> {
        let value = value.to_owned();

        if self.value.is_empty() {
            return Err(NcclError::new(ErrorKind::KeyNotFound, &format!("Pair does not have key: {}", value), 0));
        } else {
            for item in self.value.iter_mut() {
                if item.key == value {
                    return Ok(item);
                }
            }
        }

        Err(NcclError::new(ErrorKind::KeyNotFound, &format!("Could not find key: {}", value), 0))
    }

    pub fn get_ref(&self, value: &str) -> Result<&Pair, NcclError> {
        let value_owned = value.to_owned();

        if self.value.is_empty() {
            return Ok(self);
        } else {
            for item in self.value.iter() {
                if item.key == value_owned {
                    return Ok(item);
                }
            }
        }

        Err(NcclError::new(ErrorKind::KeyNotFound, "Cound not find key", 0))
    }

    pub fn value(&self) -> Result<String, NcclError>  {
        if self.value.len() == 1 {
            Ok(self.value[0].key.clone())
        } else if self.value.len() > 1 {
            Err(NcclError::new(ErrorKind::NoValue, "Key has multiple values", 0))
        } else {
            Err(NcclError::new(ErrorKind::NoValue, "Key does not have value", 0))
        }
    }

    pub fn value_as<T>(&self) -> Result<T, NcclError> where T: FromStr {
        match self.value() {
            Ok(value) => match value.parse::<T>() {
                Ok(ok) => Ok(ok),
                Err(_) => Err(NcclError::new(ErrorKind::ParseError, "Could not parse value", 0))
            },
            Err(err) => Err(err)
        }
    }

    pub fn keys(&self) -> Vec<String> {
        self.value.clone().into_iter().map(|x| x.key).collect()
    }

    pub fn keys_as<T: FromStr>(&self) -> Result<Vec<T>, NcclError> {
        // XXX this is gross
        match self.keys().iter().map(|s| s.parse::<T>()).collect::<Result<Vec<T>, _>>() {
            Ok(ok) => Ok(ok),
            Err(_) => Err(NcclError::new(ErrorKind::FromStrError, "Could not parse keys", 0))
        }
    }

    pub fn as_tokens(&self) -> Vec<Token> {
        self.as_tokens_rec(0)
    }

    fn as_tokens_rec(&self, indent: u32) -> Vec<Token> {
        let mut tokens: Vec<Token> = vec![];
        tokens.push(Token::new(TokenKind::Value, self.key.clone(), 0));
        tokens.push(Token::new(TokenKind::Newline, "\n".into(), 0));
        for value in self.value.iter() {
            for _ in 0..indent {
                tokens.push(Token::new(TokenKind::Indent, "".into(), 0));
            }
            tokens.append(&mut value.as_tokens_rec(indent + 1));
            tokens.push(Token::new(TokenKind::Newline, "\n".into(), 0));
        }
        tokens
    }
}

impl<'a> Index<&'a str> for Pair {
    type Output = Pair;
    fn index(&self, i: &str) -> &Pair {
        self.get_ref(i).unwrap()
    }
}

impl<'a> IndexMut<&'a str> for Pair {
    fn index_mut(&mut self, i: &str) -> &mut Pair {
        self.get(i).unwrap()
    }
}

<commit_msg>value returns option instead<commit_after>
use std::ops::{Index, IndexMut};
use std::str::FromStr;

use error::{NcclError, ErrorKind};
use token::{TokenKind, Token};

// top level key that contains everything is __top_level__
#[derive(Clone, Debug, PartialEq)]
pub struct Pair {
    pub key: String,
    pub value: Vec<Pair>
}

impl Pair {
    pub fn new(key: &str) -> Self {
        Pair {
            key: key.to_owned(),
            value: vec![]
        }
    }

    pub fn pretty_print(&self) {
        self.pp_rec(0);
    }

    fn pp_rec(&self, indent: u32) {
        for _ in 0..indent {
            print!("    ");
        }
        println!("{}", self.key);
        for value in self.value.iter() {
            value.pp_rec(indent + 1);
        }
    }

    pub fn add(&mut self, value: &str) {
        self.value.push(Pair::new(value));
    }

    pub fn add_slice(&mut self, path: &[String]) {
        let mut s = self.traverse_path(&path[0..path.len() - 1]);
        if !s.has_key(&path[path.len() - 1]) {
            s.add(&path[path.len() - 1]);
        }
    }

    pub fn traverse_path(&mut self, path: &[String]) -> &mut Pair {
        if path.len() == 0 {
            self
        } else {
            if !self.has_key(&path[0]) {
                self.add(&path[0]);
            }
            self.get(&path[0]).unwrap().traverse_path(&path[1..path.len()])
        }
    }

    pub fn add_pair(&mut self, pair: Pair) {
        if !self.keys().contains(&pair.key) {
            self.value.push(pair);
        } else {
            self[&pair.key].value = pair.value;
        }
    }

    pub fn has_key(&self, key: &str) -> bool {
        for item in self.value.iter() {
            if &item.key == key {
                return true;
            }
        }

        return false;
    }

    pub fn get(&mut self, value: &str) -> Result<&mut Pair, NcclError> {
        let value = value.to_owned();

        if self.value.is_empty() {
            return Err(NcclError::new(ErrorKind::KeyNotFound, &format!("Pair does not have key: {}", value), 0));
        } else {
            for item in self.value.iter_mut() {
                if item.key == value {
                    return Ok(item);
                }
            }
        }

        Err(NcclError::new(ErrorKind::KeyNotFound, &format!("Could not find key: {}", value), 0))
    }

    pub fn get_ref(&self, value: &str) -> Result<&Pair, NcclError> {
        let value_owned = value.to_owned();

        if self.value.is_empty() {
            return Ok(self);
        } else {
            for item in self.value.iter() {
                if item.key == value_owned {
                    return Ok(item);
                }
            }
        }

        Err(NcclError::new(ErrorKind::KeyNotFound, "Cound not find key", 0))
    }

    pub fn value(&self) -> Option<String>  {
        if self.value.len() == 1 {
            Some(self.value[0].key.clone())
        } else {
            None
        }
    }

    pub fn value_as<T>(&self) -> Result<T, NcclError> where T: FromStr {
        match self.value() {
            Some(value) => match value.parse::<T>() {
                Ok(ok) => Ok(ok),
                Err(_) => Err(NcclError::new(ErrorKind::ParseError, "Could not parse value", 0))
            },
            None => Err(NcclError::new(ErrorKind::NoValue, "Key has no or multiple associated values", 0))
        }
    }

    pub fn keys(&self) -> Vec<String> {
        self.value.clone().into_iter().map(|x| x.key).collect()
    }

    pub fn keys_as<T: FromStr>(&self) -> Result<Vec<T>, NcclError> {
        // XXX this is gross
        match self.keys().iter().map(|s| s.parse::<T>()).collect::<Result<Vec<T>, _>>() {
            Ok(ok) => Ok(ok),
            Err(_) => Err(NcclError::new(ErrorKind::FromStrError, "Could not parse keys", 0))
        }
    }

    pub fn as_tokens(&self) -> Vec<Token> {
        self.as_tokens_rec(0)
    }

    fn as_tokens_rec(&self, indent: u32) -> Vec<Token> {
        let mut tokens: Vec<Token> = vec![];
        tokens.push(Token::new(TokenKind::Value, self.key.clone(), 0));
        tokens.push(Token::new(TokenKind::Newline, "\n".into(), 0));
        for value in self.value.iter() {
            for _ in 0..indent {
                tokens.push(Token::new(TokenKind::Indent, "".into(), 0));
            }
            tokens.append(&mut value.as_tokens_rec(indent + 1));
            tokens.push(Token::new(TokenKind::Newline, "\n".into(), 0));
        }
        tokens
    }
}

impl<'a> Index<&'a str> for Pair {
    type Output = Pair;
    fn index(&self, i: &str) -> &Pair {
        self.get_ref(i).unwrap()
    }
}

impl<'a> IndexMut<&'a str> for Pair {
    fn index_mut(&mut self, i: &str) -> &mut Pair {
        self.get(i).unwrap()
    }
}

<|endoftext|>