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

use bit_vec::BitVec;
use heap::{Heap, HeapSessionId};
use marking::MarkingTracer;
use ptr::{Pointer, UntypedPointer};
use std::{cmp, mem, ptr};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use traits::{IntoHeapAllocation, Tracer};

/// 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>(addr: UntypedPointer, tracer: &mut MarkingTracer)
where
    T: IntoHeapAllocation<'h>,
{
    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: IntoHeapAllocation<'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,
    next_page: *mut PageHeader,
    mark_bits: BitVec,
    allocated_bits: BitVec,
    mark_fn: unsafe fn(UntypedPointer, &mut MarkingTracer),
    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 fn type_id(&self) -> usize {
        self.mark_fn as usize
    }

    pub fn downcast_mut<'h, T>(&mut self) -> Option<&mut TypedPage<T::In>>
    where
        T: IntoHeapAllocation<'h>,
    {
        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>,
}

impl<U> Deref for TypedPage<U> {
    type Target = PageHeader;

    fn deref(&self) -> &PageHeader {
        &self.header
    }
}

impl<U> DerefMut for TypedPage<U> {
    fn deref_mut(&mut self) -> &mut PageHeader {
        &mut self.header
    }
}

/// 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_freelist(&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();
        }
    }
}

/// Sweep a page.
///
/// # Safety
///
/// This must be called only after a full mark phase, to avoid sweeping objects
/// that are still reachable.
unsafe fn sweep_entry_point<'h, T: IntoHeapAllocation<'h>>(header: &mut PageHeader) {
    header.downcast_mut::<T>().unwrap().sweep();
}

/// An unordered collection of memory pages that all share an allocation type.
pub struct PageSet {
    heap: *mut Heap,

    sweep_fn: unsafe fn(&mut PageHeader),

    /// The collection of pages.
    ///
    /// All pages in this collection have matching `.heap`, `.mark_fn`, and
    /// `.sweep_fn` fields.
    pages: *mut PageHeader,

    /// The maximum number of pages, or None for no limit.
    limit: Option<usize>,
}

impl Drop for PageSet {
    fn drop(&mut self) {
        unsafe {
            let mut p = self.pages;
            while !p.is_null() {
                let next = (*p).next_page;
                ptr::drop_in_place(p); // drop the header
                Vec::from_raw_parts(p as *mut u8, 0, PAGE_SIZE); // free the page
                p = next;
            }
        }
    }
}

impl PageSet {
    /// Create a new PageSet.
    ///
    /// # Safety
    ///
    /// Safe as long as `heap` is a valid pointer.
    pub unsafe fn new<'h, T: IntoHeapAllocation<'h>>(heap: *mut Heap) -> PageSet {
        PageSet {
            heap,
            sweep_fn: sweep_entry_point::<T>,
            pages: ptr::null_mut(),
            limit: None,
        }
    }

    /// Downcast to a typed PageSetRef.
    ///
    /// # Panics
    ///
    /// If T is not the actual allocation type for this page set.
    pub fn downcast_mut<'a, 'h, T>(&'a mut self) -> PageSetRef<'a, 'h, T>
    where
        T: IntoHeapAllocation<'h> + 'a,
    {
        assert_eq!(
            self.sweep_fn as *const (),
            sweep_entry_point::<T> as *const ()
        );

        PageSetRef {
            page_set: self,
            id: PhantomData,
            also: PhantomData,
        }
    }

    /// Clear mark bits from each page in this set.
    ///
    /// # Safety
    ///
    /// This must be called only at the beginning of a GC cycle.
    pub unsafe fn clear_mark_bits(&mut self) {
        let mut page = self.pages;
        while !page.is_null() {
            (*page).clear_mark_bits();
            page = (*page).next_page;
        }
    }

    /// Sweep all unmarked objects from all pages.
    ///
    /// # Safety
    ///
    /// Safe to call only as the final part of GC.
    pub unsafe fn sweep(&mut self) {
        let mut page = self.pages;
        while !page.is_null() {
            (self.sweep_fn)(&mut *page);
            page = (*page).next_page;
        }
    }

    /// Assert that nothing is allocated in this set of pages.
    pub fn assert_no_allocations(&self) {
        unsafe {
            let mut page = self.pages;
            while !page.is_null() {
                assert!((*page).is_empty());
                page = (*page).next_page;
            }
        }
    }
}

pub struct PageSetRef<'a, 'h, T: IntoHeapAllocation<'h> + 'a> {
    page_set: &'a mut PageSet,
    id: HeapSessionId<'h>,
    also: PhantomData<&'a mut T>,
}

impl<'a, 'h, T: IntoHeapAllocation<'h> + 'a> PageSetRef<'a, 'h, T> {
    pub fn set_page_limit(&mut self, limit: Option<usize>) {
        self.page_set.limit = limit;
    }

    /// Allocate memory for a value of type `T::In`.
    ///
    /// # Safety
    ///
    /// Safe to call as long as GC is not happening.
    pub unsafe fn try_alloc(&mut self) -> Option<Pointer<T::In>> {
        // First, try to allocate from each existing page. (Obviously slow.)
        let mut page = self.page_set.pages;
        let mut page_count = 0;
        while !page.is_null() {
            let t_page = (*page).downcast_mut::<T>().unwrap();
            if let Some(ptr) = t_page.try_alloc() {
                return Some(ptr);
            }

            page_count += 1;
            page = (*page).next_page;
        }

        // If there is a limit and we already have at least that many pages, fail.
        match self.page_set.limit {
            Some(limit) if page_count >= limit => None,
            _ => self.new_page().try_alloc(),
        }
    }

    /// Allocate a page from the operating system.
    ///
    /// Initialize its header and freelist and link it into this page set's
    /// linked list of pages.
    fn new_page(&mut self) -> &mut TypedPage<T::In> {
        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 mut vec: Vec<u8> = Vec::with_capacity(PAGE_SIZE);
        let raw_page = vec.as_mut_ptr() as *mut ();

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

        let page_ptr: *mut TypedPage<T::In> = raw_page as *mut TypedPage<T::In>;
        let capacity = TypedPage::<T::In>::capacity();
        unsafe {
            ptr::write(
                page_ptr,
                TypedPage {
                    header: PageHeader {
                        heap: self.page_set.heap,
                        next_page: self.page_set.pages,
                        mark_bits: BitVec::from_elem(capacity, false),
                        allocated_bits: BitVec::from_elem(capacity, false),
                        mark_fn: mark_entry_point::<T>,
                        freelist: ptr::null_mut(),
                    },
                    allocations: PhantomData,
                },
            );

            let page = &mut *page_ptr;
            page.init_freelist();

            // Remove the memory from the vector and link it into
            // the PageSet's linked list.
            mem::forget(vec);
            self.page_set.pages = &mut page.header;

            page
        }
    }
}
<commit_msg>Pull expressions into vars for better formatting<commit_after>//! Allocating pages of memory from the OS and carving them into individual
//! allocations.

use bit_vec::BitVec;
use heap::{Heap, HeapSessionId};
use marking::MarkingTracer;
use ptr::{Pointer, UntypedPointer};
use std::{cmp, mem, ptr};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use traits::{IntoHeapAllocation, Tracer};

/// 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>(addr: UntypedPointer, tracer: &mut MarkingTracer)
where
    T: IntoHeapAllocation<'h>,
{
    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: IntoHeapAllocation<'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,
    next_page: *mut PageHeader,
    mark_bits: BitVec,
    allocated_bits: BitVec,
    mark_fn: unsafe fn(UntypedPointer, &mut MarkingTracer),
    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 fn type_id(&self) -> usize {
        self.mark_fn as usize
    }

    pub fn downcast_mut<'h, T>(&mut self) -> Option<&mut TypedPage<T::In>>
    where
        T: IntoHeapAllocation<'h>,
    {
        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>,
}

impl<U> Deref for TypedPage<U> {
    type Target = PageHeader;

    fn deref(&self) -> &PageHeader {
        &self.header
    }
}

impl<U> DerefMut for TypedPage<U> {
    fn deref_mut(&mut self) -> &mut PageHeader {
        &mut self.header
    }
}

/// 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_freelist(&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();
        }
    }
}

/// Sweep a page.
///
/// # Safety
///
/// This must be called only after a full mark phase, to avoid sweeping objects
/// that are still reachable.
unsafe fn sweep_entry_point<'h, T: IntoHeapAllocation<'h>>(header: &mut PageHeader) {
    header.downcast_mut::<T>().unwrap().sweep();
}

/// An unordered collection of memory pages that all share an allocation type.
pub struct PageSet {
    heap: *mut Heap,

    sweep_fn: unsafe fn(&mut PageHeader),

    /// The collection of pages.
    ///
    /// All pages in this collection have matching `.heap`, `.mark_fn`, and
    /// `.sweep_fn` fields.
    pages: *mut PageHeader,

    /// The maximum number of pages, or None for no limit.
    limit: Option<usize>,
}

impl Drop for PageSet {
    fn drop(&mut self) {
        unsafe {
            let mut p = self.pages;
            while !p.is_null() {
                let next = (*p).next_page;
                ptr::drop_in_place(p); // drop the header
                Vec::from_raw_parts(p as *mut u8, 0, PAGE_SIZE); // free the page
                p = next;
            }
        }
    }
}

impl PageSet {
    /// Create a new PageSet.
    ///
    /// # Safety
    ///
    /// Safe as long as `heap` is a valid pointer.
    pub unsafe fn new<'h, T: IntoHeapAllocation<'h>>(heap: *mut Heap) -> PageSet {
        PageSet {
            heap,
            sweep_fn: sweep_entry_point::<T>,
            pages: ptr::null_mut(),
            limit: None,
        }
    }

    /// Downcast to a typed PageSetRef.
    ///
    /// # Panics
    ///
    /// If T is not the actual allocation type for this page set.
    pub fn downcast_mut<'a, 'h, T>(&'a mut self) -> PageSetRef<'a, 'h, T>
    where
        T: IntoHeapAllocation<'h> + 'a,
    {
        assert_eq!(
            self.sweep_fn as *const (),
            sweep_entry_point::<T> as *const ()
        );

        PageSetRef {
            page_set: self,
            id: PhantomData,
            also: PhantomData,
        }
    }

    /// Clear mark bits from each page in this set.
    ///
    /// # Safety
    ///
    /// This must be called only at the beginning of a GC cycle.
    pub unsafe fn clear_mark_bits(&mut self) {
        let mut page = self.pages;
        while !page.is_null() {
            (*page).clear_mark_bits();
            page = (*page).next_page;
        }
    }

    /// Sweep all unmarked objects from all pages.
    ///
    /// # Safety
    ///
    /// Safe to call only as the final part of GC.
    pub unsafe fn sweep(&mut self) {
        let mut page = self.pages;
        while !page.is_null() {
            (self.sweep_fn)(&mut *page);
            page = (*page).next_page;
        }
    }

    /// Assert that nothing is allocated in this set of pages.
    pub fn assert_no_allocations(&self) {
        unsafe {
            let mut page = self.pages;
            while !page.is_null() {
                assert!((*page).is_empty());
                page = (*page).next_page;
            }
        }
    }
}

pub struct PageSetRef<'a, 'h, T: IntoHeapAllocation<'h> + 'a> {
    page_set: &'a mut PageSet,
    id: HeapSessionId<'h>,
    also: PhantomData<&'a mut T>,
}

impl<'a, 'h, T: IntoHeapAllocation<'h> + 'a> PageSetRef<'a, 'h, T> {
    pub fn set_page_limit(&mut self, limit: Option<usize>) {
        self.page_set.limit = limit;
    }

    /// Allocate memory for a value of type `T::In`.
    ///
    /// # Safety
    ///
    /// Safe to call as long as GC is not happening.
    pub unsafe fn try_alloc(&mut self) -> Option<Pointer<T::In>> {
        // First, try to allocate from each existing page. (Obviously slow.)
        let mut page = self.page_set.pages;
        let mut page_count = 0;
        while !page.is_null() {
            let t_page = (*page).downcast_mut::<T>().unwrap();
            if let Some(ptr) = t_page.try_alloc() {
                return Some(ptr);
            }

            page_count += 1;
            page = (*page).next_page;
        }

        // If there is a limit and we already have at least that many pages, fail.
        match self.page_set.limit {
            Some(limit) if page_count >= limit => None,
            _ => self.new_page().try_alloc(),
        }
    }

    /// Allocate a page from the operating system.
    ///
    /// Initialize its header and freelist and link it into this page set's
    /// linked list of pages.
    fn new_page(&mut self) -> &mut TypedPage<T::In> {
        assert!({
            let size_of_page = mem::size_of::<TypedPage<T::In>>();
            let alloc_offset = TypedPage::<T::In>::first_allocation_offset();
            size_of_page <= alloc_offset
        });
        assert!({
            let alloc_offset = TypedPage::<T::In>::first_allocation_offset();
            let alloc_size = TypedPage::<T::In>::allocation_size();
            let capacity = TypedPage::<T::In>::capacity();
            alloc_offset + capacity * alloc_size <= PAGE_SIZE
        });

        let mut vec: Vec<u8> = Vec::with_capacity(PAGE_SIZE);
        let raw_page = vec.as_mut_ptr() as *mut ();

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

        let page_ptr: *mut TypedPage<T::In> = raw_page as *mut TypedPage<T::In>;
        let capacity = TypedPage::<T::In>::capacity();
        unsafe {
            ptr::write(
                page_ptr,
                TypedPage {
                    header: PageHeader {
                        heap: self.page_set.heap,
                        next_page: self.page_set.pages,
                        mark_bits: BitVec::from_elem(capacity, false),
                        allocated_bits: BitVec::from_elem(capacity, false),
                        mark_fn: mark_entry_point::<T>,
                        freelist: ptr::null_mut(),
                    },
                    allocations: PhantomData,
                },
            );

            let page = &mut *page_ptr;
            page.init_freelist();

            // Remove the memory from the vector and link it into
            // the PageSet's linked list.
            mem::forget(vec);
            self.page_set.pages = &mut page.header;

            page
        }
    }
}
<|endoftext|>


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

/**
 * Parsed JSON is stored as a byte array of compact JSON and an array of nodes.
 * Each node represents a JSON object, array or value.
 *
 * The ``children`` field is the total number of children under this node.
 * The child nodes come directly after the parent node in the array.
 * This means that the next sibling of a node can be found at an offset
 * of ``children + 1`` into the array.
 *
 * The ``length_in_bytes`` gives the length of the value in bytes.
 * This allows the offset of a node to be computed as follows.
 * The root node is at offset 0.
 * The first child node starts at its parent offset + 1.
 * Each subsequent child node starts 1 byte after the end of previous node.
 *
 * JSON scalars never have children and are identified by their first byte.
 * * JSON true values start with ``b't' == 0x74``.
 * * JSON false values start with ``b'f' == 0x66``.
 * * JSON null values start with ``b'n' == 0x6E``.
 * * JSON string values start with ``b'"' == 0x22``.
 * * JSON number values start with either ``b'-' == 0x2B``
 *   or one of ``b"0123456789"` == [0x30..0x39]``.
 *
 * JSON arrays start with ``b'[' == 0x5B``. The direct children of the node
 *      are the elements of the array.
 *
 * JSON objects start with ``b'{' == 0x7B``. The direct children of the node
 * alternate between JSON string keys and their values.
 */
#[derive(PartialEq, Debug)]
pub struct Node {
    children: u32,
    length_in_bytes: u32,
}

pub fn parse(input: &[u8], output: &mut Vec<Node>, stack: &mut Vec<u32>) -> Result<(),()> {
    if parse_(input, output, stack) {
        Ok(())
    } else {
        Err(())
    }
}

fn parse_(input: &[u8], output: &mut Vec<Node>, stack: &mut Vec<u32>) -> bool {
    let mut iter = input.iter().peekable();
    let mut parsing_object = false;
    if iter.len() == 2 {
        // If the input is two bytes long then it is an empty object
        // or an empty array.
        output.push(Node {children: 0, length_in_bytes: 2});
        return true;
    }
    'node_end: loop {
        match stack.pop() {
            // On the first iteration of the loop the stack is empty.
            // So we fall through to start parsing the root array or
            // object.
            None => {},
            // Otherwise we've reached the end of an array or object.
            Some(offset_and_state) => {
                // Grab a copy of the length to appease the borrow checker.
                let output_len = output.len() as u32;
                let offset = offset_and_state >> 1;
                // The stack held the where the node was in the output array.
                // Grab a mutable copy of the node so we can fill it out with
                // the number of children and update the length of the node.
                // This lookup should never fail.
                let node = match output.get_mut(offset as usize) {
                    Some(node) => node,
                    None => return false
                };
                // The node length contined the number of bytes left in the
                // iterator when the node began. Subtracting the number of
                // bytes left now will give us the length.
                node.length_in_bytes -= iter.len() as u32;
                node.children = output_len - offset - 1;
                // Take a look at the next entry in the stack to get whether we
                // are parsing an array or parsing an object.
                // If the stack is empty then we've parsed the root object or
                // array and we can return.
                let prev_offset_and_state = match stack.last() {
                    Some(value) => value,
                    None => return true // <-- This is where the parser exits.
                };
                // Whether we were parsing an object or and array is stored in
                // the first bit of the stack entry.
                parsing_object = (prev_offset_and_state & 1) == 1;
                // We've finished parsing a node. There's either a comma b','
                // followed by more stuff in the outer node. or the outer node
                // is ending with a b']' or a b'}'.
                let input_char = match iter.next() {
                    None => return false,
                    Some(value) => *value
                };
                // If the node ends then jump to handling the end of a node.
                if input_char != b',' {
                    continue 'node_end;
                }
                // Otherwise fallthrough to parsing the start of a value.
            }
        };
        'value_start: loop {
            if parsing_object {
                // If we are parsing an object then parse the string key.
                let start = iter.len();
                // We can assume it's a string so skip the opening b'"'.
                if iter.next() == None {
                    return false;
                }
                // Loop through the characters until we find a closing b'"'.
                loop {
                    let input_char = match iter.next() {
                        None => return false,
                        Some(value) => *value
                    };
                    if input_char == b'"' {
                        break;
                    }
                    if input_char == b'\\' {
                        if iter.next() == None {
                            return false;
                        }
                    }
                }
                // Add a node with the string.
                output.push(Node {
                    children: 0, length_in_bytes: (start - iter.len()) as u32
                });
                // Skip over the b':'.
                if iter.next() == None {
                    return false;
                }
            }
            // Parse a JSON value.
            let start = iter.len();
            let input_char = match iter.next() {
                None => return false,
                Some(value) => *value
            };
            if input_char == b'{' {
                // This is the start of a JSON object.
                // Look at the next char to check if the object is empty.
                let peek_char = match iter.peek() {
                    None => return false,
                    Some(value) => **value
                };
                if peek_char == b'}' {
                    // The object was empty, output a 2 byte node.
                    output.push(Node {children: 0, length_in_bytes: 2});
                    // Consume the b'}' character.
                    let _ = iter.next();
                } else {
                    // The object is not empty.
                    // Add a placeholder node to the output vector recording
                    // where the start of the object was. The placeholder
                    // will be filled out with the correct info when the node
                    // ends.
                    // Add the index of the placeholder node in the output
                    // vector to the stack. Set the low bit to indicate we are
                    // parsing an object.
                    let index = output.len() as u32;
                    stack.push((index << 1) | 1);
                    output.push(Node {
                        children: 0, length_in_bytes: start as u32,
                    });
                    parsing_object = true;
                    // Jump to parsing the start of a value.
                    continue 'value_start;
                }
            } else if input_char == b'[' {
                // This is the start of a JSON array.
                // Look at the next char to check if the array is empty.
                let peek_char = match iter.peek() {
                    None => return false,
                    Some(value) => **value
                };
                if peek_char == b']' {
                    // The array is empty, output a 2 byte node.
                    output.push(Node {children: 0, length_in_bytes: 2});
                    // Consume the ']' character.
                    let _ = iter.next();
                } else {
                    // The array is not empty.
                    let index = output.len() as u32;
                    // Add a placeholder node to the output vector recording
                    // where the start of the array was. The placeholder
                    // will be filled out with the correct info when the node
                    // ends.
                    // Add the index of the placeholder node in the output
                    // vector to the stack. Leave the low bit unset to indicate
                    // we are parsing an array.
                    stack.push(index << 1);
                    output.push(Node {
                        children: 0, length_in_bytes: start as u32,
                    });
                    parsing_object = false;
                    // Jump to parsing the start of a value.
                    continue 'value_start;
                }
            } else if input_char == b'"' {
                // We are parsing a string. Loop until we see a closing b'"'.
                loop {
                    let input_char = match iter.next() {
                        None => return false,
                        Some(value) => *value
                    };
                    if input_char == b'"' {
                        break;
                    }
                    if input_char == b'\\' {
                        if iter.next() == None {
                            return false;
                        }
                    }
                }
                output.push(Node {
                    children: 0,
                    length_in_bytes: (start - iter.len()) as u32
                });
            } else {
                // We are parsing a number or one of true, false or null.
                // Loop until we see a b',', a b'}', or a b']'.
                loop {
                    let input_char = match iter.next() {
                        None => return false,
                        Some(value) => *value
                    };
                    if input_char == b',' {
                        output.push(Node {
                            children: 0,
                            length_in_bytes: (start - iter.len() - 1) as u32
                        });
                        // Jump to parsing the start of a value.
                        continue 'value_start;
                    } else if (input_char & 0xDF) == b']' {
                        output.push(Node {
                            children: 0,
                            length_in_bytes: (start - iter.len() - 1) as u32
                        });
                        // Jump to parsing the end of a node.
                        continue 'node_end;
                    }
                }
            }
            // Strings, empty objects and empty arrays fall through to here to
            // handle the end of a value.
            // The next character is either a b',' if there is another value
            // to parse in the containing object or array or the character
            // is a b']' or a b'}' if the contaning object or array is ending.
            let input_char = match iter.next() {
                None => return false,
                Some(value) => *value
            };
            if input_char == b',' {
                // Jump to parsing the start of a value.
                continue 'value_start;
            } else {
                // Jump to parsing the end of a node.
                continue 'node_end;
            }
        }
    }
}

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

    fn parse(input: &[u8]) -> Vec<Node> {
        let mut output : Vec<Node> = Vec::new();
        let mut stack : Vec<u32> = Vec::new();
        super::parse(input, &mut output, &mut stack).unwrap();
        return output;
    }

    #[test]
    fn parse_empty_array() {
        let result = parse(b"[]");
        assert_eq!(vec![
            Node {children: 0, length_in_bytes: 2},
        ], result);
    }

    #[test]
    fn parse_nested_arrays() {
        let result = parse(b"[[[]],[]]");
        assert_eq!(vec![
            Node {children: 3, length_in_bytes: 9},
            Node {children: 1, length_in_bytes: 4},
            Node {children: 0, length_in_bytes: 2},
            Node {children: 0, length_in_bytes: 2},
        ], result);
    }

    #[test]
    fn parse_nested_objects() {
        let result = parse(br#"{"A":{"B":{}},"C":{}}"#);
        assert_eq!(vec![
            Node {children: 6, length_in_bytes: 21},
            Node {children: 0, length_in_bytes: 3},
            Node {children: 2, length_in_bytes: 8},
            Node {children: 0, length_in_bytes: 3},
            Node {children: 0, length_in_bytes: 2},
            Node {children: 0, length_in_bytes: 3},
            Node {children: 0, length_in_bytes: 2},
        ], result);
    }

    #[test]
    fn parse_scalars() {
        let result = parse(br#"[false,null,true]"#);
        assert_eq!(vec![
            Node {children: 3, length_in_bytes: 17},
            Node {children: 0, length_in_bytes: 5},
            Node {children: 0, length_in_bytes: 4},
            Node {children: 0, length_in_bytes: 4},
        ], result);
    }
}
<commit_msg>Split out some helper functions for parse<commit_after>/* Copyright 2016 Mark Haines
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Parsed JSON is stored as a byte array of compact JSON and an array of nodes.
 * Each node represents a JSON object, array or value.
 *
 * The ``children`` field is the total number of children under this node.
 * The child nodes come directly after the parent node in the array.
 * This means that the next sibling of a node can be found at an offset
 * of ``children + 1`` into the array.
 *
 * The ``length_in_bytes`` gives the length of the value in bytes.
 * This allows the offset of a node to be computed as follows.
 * The root node is at offset 0.
 * The first child node starts at its parent offset + 1.
 * Each subsequent child node starts 1 byte after the end of previous node.
 *
 * JSON scalars never have children and are identified by their first byte.
 * * JSON true values start with ``b't' == 0x74``.
 * * JSON false values start with ``b'f' == 0x66``.
 * * JSON null values start with ``b'n' == 0x6E``.
 * * JSON string values start with ``b'"' == 0x22``.
 * * JSON number values start with either ``b'-' == 0x2B``
 *   or one of ``b"0123456789"` == [0x30..0x39]``.
 *
 * JSON arrays start with ``b'[' == 0x5B``. The direct children of the node
 *      are the elements of the array.
 *
 * JSON objects start with ``b'{' == 0x7B``. The direct children of the node
 * alternate between JSON string keys and their values.
 */
#[derive(PartialEq, Debug)]
pub struct Node {
    children: u32,
    length_in_bytes: u32,
}

pub fn parse(input: &[u8], output: &mut Vec<Node>, stack: &mut Vec<u32>) -> Result<(),()> {
    if parse_(input, output, stack) {
        Ok(())
    } else {
        Err(())
    }
}

fn parse_(input: &[u8], output: &mut Vec<Node>, stack: &mut Vec<u32>) -> bool {
    let mut iter = input.iter().peekable();
    let mut parsing_object = false;
    if iter.len() == 2 {
        // If the input is two bytes long then it is an empty object
        // or an empty array.
        push_node(output, 2);
        return true;
    }
    'node_end: loop {
        match stack.pop() {
            // On the first iteration of the loop the stack is empty.
            // So we fall through to start parsing the root array or
            // object.
            None => {},
            // Otherwise we've reached the end of an array or object.
            Some(offset_and_state) => {
                // Grab a copy of the length to appease the borrow checker.
                let output_len = output.len() as u32;
                let offset = offset_and_state >> 1;
                // The stack held the where the node was in the output array.
                // Grab a mutable copy of the node so we can fill it out with
                // the number of children and update the length of the node.
                // This lookup should never fail.
                let node = match output.get_mut(offset as usize) {
                    Some(node) => node,
                    None => return false
                };
                // The node length contined the number of bytes left in the
                // iterator when the node began. Subtracting the number of
                // bytes left now will give us the length.
                node.length_in_bytes -= iter.len() as u32;
                node.children = output_len - offset - 1;
                // Take a look at the next entry in the stack to get whether we
                // are parsing an array or parsing an object.
                // If the stack is empty then we've parsed the root object or
                // array and we can return.
                let prev_offset_and_state = match stack.last() {
                    Some(value) => value,
                    None => return true // <-- This is where the parser exits.
                };
                // Whether we were parsing an object or and array is stored in
                // the first bit of the stack entry.
                parsing_object = (prev_offset_and_state & 1) == 1;
                // We've finished parsing a node. There's either a comma b','
                // followed by more stuff in the outer node. or the outer node
                // is ending with a b']' or a b'}'.
                let input_char = match iter.next() {
                    None => return false,
                    Some(value) => *value
                };
                // If the node ends then jump to handling the end of a node.
                if input_char != b',' {
                    continue 'node_end;
                }
                // Otherwise fallthrough to parsing the start of a value.
            }
        };
        'value_start: loop {
            if parsing_object {
                // If we are parsing an object then parse the string key.
                let start = iter.len();
                // We can assume it's a string so skip the opening b'"'.
                if iter.next() == None {
                    return false;
                }
                // Loop through the characters until we find a closing b'"'.
                if !parse_string(&mut iter) {
                    return false;
                }
                // Add a node with the string.
                push_node(output, start - iter.len());
                // Skip over the b':'.
                if iter.next() == None {
                    return false;
                }
            }
            // Parse a JSON value.
            let start = iter.len();
            let input_char = match iter.next() {
                None => return false,
                Some(value) => *value
            };
            if input_char == b'{' {
                // This is the start of a JSON object.
                // Look at the next char to check if the object is empty.
                let peek_char = match iter.peek() {
                    None => return false,
                    Some(value) => **value
                };
                if peek_char == b'}' {
                    // The object was empty, output a 2 byte node.
                    push_node(output, 2);
                    // Consume the b'}' character.
                    let _ = iter.next();
                } else {
                    // The object is not empty.
                    // Add a placeholder node to the output vector recording
                    // where the start of the object was. The placeholder
                    // will be filled out with the correct info when the node
                    // ends.
                    // Add the index of the placeholder node in the output
                    // vector to the stack. Set the low bit to indicate we are
                    // parsing an object.
                    let index = output.len() as u32;
                    stack.push((index << 1) | 1);
                    push_node(output, start);
                    parsing_object = true;
                    // Jump to parsing the start of a value.
                    continue 'value_start;
                }
            } else if input_char == b'[' {
                // This is the start of a JSON array.
                // Look at the next char to check if the array is empty.
                let peek_char = match iter.peek() {
                    None => return false,
                    Some(value) => **value
                };
                if peek_char == b']' {
                    // The array is empty, output a 2 byte node.
                    push_node(output, 2);
                    // Consume the ']' character.
                    let _ = iter.next();
                } else {
                    // The array is not empty.
                    let index = output.len() as u32;
                    // Add a placeholder node to the output vector recording
                    // where the start of the array was. The placeholder
                    // will be filled out with the correct info when the node
                    // ends.
                    // Add the index of the placeholder node in the output
                    // vector to the stack. Leave the low bit unset to indicate
                    // we are parsing an array.
                    stack.push(index << 1);
                    push_node(output, start);
                    parsing_object = false;
                    // Jump to parsing the start of a value.
                    continue 'value_start;
                }
            } else if input_char == b'"' {
                // We are parsing a string. Loop until we see a closing b'"'.
                if !parse_string(&mut iter) {
                    return false;
                }
                push_node(output, start - iter.len());
            } else {
                // We are parsing a number or one of true, false or null.
                // Loop until we see a b',', a b'}', or a b']'.
                loop {
                    let input_char = match iter.next() {
                        None => return false,
                        Some(value) => *value
                    };
                    if input_char == b',' {
                        push_node(output, start - iter.len() - 1);
                        // Jump to parsing the start of a value.
                        continue 'value_start;
                    } else if (input_char & 0xDF) == b']' {
                        push_node(output, start - iter.len() - 1);
                        // Jump to parsing the end of a node.
                        continue 'node_end;
                    }
                }
            }
            // Strings, empty objects and empty arrays fall through to here to
            // handle the end of a value.
            // The next character is either a b',' if there is another value
            // to parse in the containing object or array or the character
            // is a b']' or a b'}' if the contaning object or array is ending.
            let input_char = match iter.next() {
                None => return false,
                Some(value) => *value
            };
            if input_char == b',' {
                // Jump to parsing the start of a value.
                continue 'value_start;
            } else {
                // Jump to parsing the end of a node.
                continue 'node_end;
            }
        }
    }
}

fn parse_string<'a, T: Iterator<Item=&'a u8>>(iter: &mut T) -> bool {
    loop {
        let input_char = match iter.next() {
            None => return false,
            Some(value) => *value
        };
        if input_char == b'"' {
            break;
        }
        if input_char == b'\\' {
            if iter.next() == None {
                return false;
            }
        }
    }
    return true;
}

fn push_node(output: &mut Vec<Node>, len : usize) {
    output.push( Node {
        children: 0,
        length_in_bytes: len as u32,
    });
}

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

    fn parse(input: &[u8]) -> Vec<Node> {
        let mut output : Vec<Node> = Vec::new();
        let mut stack : Vec<u32> = Vec::new();
        super::parse(input, &mut output, &mut stack).unwrap();
        return output;
    }

    #[test]
    fn parse_empty_array() {
        let result = parse(b"[]");
        assert_eq!(vec![
            Node {children: 0, length_in_bytes: 2},
        ], result);
    }

    #[test]
    fn parse_nested_arrays() {
        let result = parse(b"[[[]],[]]");
        assert_eq!(vec![
            Node {children: 3, length_in_bytes: 9},
            Node {children: 1, length_in_bytes: 4},
            Node {children: 0, length_in_bytes: 2},
            Node {children: 0, length_in_bytes: 2},
        ], result);
    }

    #[test]
    fn parse_nested_objects() {
        let result = parse(br#"{"A":{"B":{}},"C":{}}"#);
        assert_eq!(vec![
            Node {children: 6, length_in_bytes: 21},
            Node {children: 0, length_in_bytes: 3},
            Node {children: 2, length_in_bytes: 8},
            Node {children: 0, length_in_bytes: 3},
            Node {children: 0, length_in_bytes: 2},
            Node {children: 0, length_in_bytes: 3},
            Node {children: 0, length_in_bytes: 2},
        ], result);
    }

    #[test]
    fn parse_scalars() {
        let result = parse(br#"[false,null,true]"#);
        assert_eq!(vec![
            Node {children: 3, length_in_bytes: 17},
            Node {children: 0, length_in_bytes: 5},
            Node {children: 0, length_in_bytes: 4},
            Node {children: 0, length_in_bytes: 4},
        ], result);
    }
}
<|endoftext|>


<commit_before>//! Support for sending and receiving data link layer packets using libpcap.
//! Also has support for reading pcap files.

extern crate pcap;

use std::io;
use std::marker::{Send, Sync};
use std::path::Path;
use std::sync::{Arc, Mutex};
use std::time::Duration;

use self::pcap::{Activated, Active};

use Channel::Ethernet;
use {DataLinkReceiver, DataLinkSender, NetworkInterface};

/// Configuration for the pcap datalink backend.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Config {
    /// The size of buffer to use when reading packets. Must be at least
    /// 65516 with pcap.
    pub read_buffer_size: usize,

    /// The read timeout. Defaults to None.
    pub read_timeout: Option<Duration>,
}

impl<'a> From<&'a super::Config> for Config {
    fn from(config: &super::Config) -> Config {
        let mut c = Config {
            read_buffer_size: config.read_buffer_size,
            read_timeout: config.read_timeout,
        };
        // pcap is unique in that the buffer size must be greater or equal to
        // MAXIMUM_SNAPLEN, which is currently hard-coded to 65536
        // So, just reset it to the default.
        if c.read_buffer_size < 65536 {
            c.read_buffer_size = Config::default().read_buffer_size;
        }
        c
    }
}

impl Default for Config {
    fn default() -> Config {
        Config {
            // Just let pcap pick the default size
            read_buffer_size: 0,
            read_timeout: None,
        }
    }
}

/// Create a datalink channel from the provided pcap device.
#[inline]
pub fn channel(network_interface: &NetworkInterface, config: Config) -> io::Result<super::Channel> {
    let cap = match pcap::Capture::from_device(&*network_interface.name) {
        Ok(cap) => cap,
        Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
    }
    .buffer_size(config.read_buffer_size as i32);
    let cap = match config.read_timeout {
        Some(to) => cap.timeout((to.as_secs() * 1000 + (to.subsec_nanos() / 1000) as u64) as i32),
        None => cap,
    };
    let cap = match cap.open() {
        Ok(cap) => cap,
        Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
    };
    let cap = Arc::new(Mutex::new(cap));
    Ok(Ethernet(
        Box::new(DataLinkSenderImpl {
            capture: cap.clone(),
        }),
        Box::new(DataLinkReceiverImpl {
            capture: cap.clone(),
            read_buffer: vec![0; config.read_buffer_size],
        }),
    ))
}

/// Create a datalink channel from a pcap file.
#[inline]
pub fn from_file<P: AsRef<Path>>(path: P, config: Config) -> io::Result<super::Channel> {
    let cap = match pcap::Capture::from_file(path) {
        Ok(cap) => cap,
        Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
    };
    let cap = Arc::new(Mutex::new(cap));
    Ok(Ethernet(
        Box::new(InvalidDataLinkSenderImpl {}),
        Box::new(DataLinkReceiverImpl {
            capture: cap.clone(),
            read_buffer: vec![0; config.read_buffer_size],
        }),
    ))
}

struct DataLinkSenderImpl {
    capture: Arc<Mutex<pcap::Capture<Active>>>,
}

impl DataLinkSender for DataLinkSenderImpl {
    #[inline]
    fn build_and_send(
        &mut self,
        num_packets: usize,
        packet_size: usize,
        func: &mut dyn FnMut(&mut [u8]),
    ) -> Option<io::Result<()>> {
        for _ in 0..num_packets {
            let mut data = vec![0; packet_size];
            func(&mut data);
            let mut cap = self.capture.lock().unwrap();
            if let Err(e) = cap.sendpacket(data) {
                return Some(Err(io::Error::new(io::ErrorKind::Other, e)));
            }
        }
        Some(Ok(()))
    }

    #[inline]
    fn send_to(&mut self, packet: &[u8], _dst: Option<NetworkInterface>) -> Option<io::Result<()>> {
        let mut cap = self.capture.lock().unwrap();
        Some(match cap.sendpacket(packet) {
            Ok(()) => Ok(()),
            Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)),
        })
    }
}

struct InvalidDataLinkSenderImpl {}

impl DataLinkSender for InvalidDataLinkSenderImpl {
    #[inline]
    fn build_and_send(
        &mut self,
        _num_packets: usize,
        _packet_size: usize,
        _func: &mut dyn FnMut(&mut [u8]),
    ) -> Option<io::Result<()>> {
        None
    }

    #[inline]
    fn send_to(
        &mut self,
        _packet: &[u8],
        _dst: Option<NetworkInterface>,
    ) -> Option<io::Result<()>> {
        None
    }
}

struct DataLinkReceiverImpl<T: Activated + Send + Sync> {
    capture: Arc<Mutex<pcap::Capture<T>>>,
    read_buffer: Vec<u8>,
}

impl<T: Activated + Send + Sync> DataLinkReceiver for DataLinkReceiverImpl<T> {
    fn next(&mut self) -> io::Result<&[u8]> {
        let mut cap = self.capture.lock().unwrap();
        match cap.next() {
            Ok(pkt) => {
                self.read_buffer.truncate(0);
                self.read_buffer.extend(pkt.data);
            }
            Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
        };
        Ok(&self.read_buffer)
    }
}

/// Get a list of available network interfaces for the current machine.
pub fn interfaces() -> Vec<NetworkInterface> {
    if let Ok(devices) = pcap::Device::list() {
        devices
            .iter()
            .enumerate()
            .map(|(i, dev)| NetworkInterface {
                name: dev.name.clone(),
                index: i as u32,
                mac: None,
                ips: Vec::new(),
                flags: 0,
            })
            .collect()
    } else {
        vec![]
    }
}
<commit_msg>Enable promiscuous capture for pcap<commit_after>//! Support for sending and receiving data link layer packets using libpcap.
//! Also has support for reading pcap files.

extern crate pcap;

use std::io;
use std::marker::{Send, Sync};
use std::path::Path;
use std::sync::{Arc, Mutex};
use std::time::Duration;

use self::pcap::{Activated, Active};

use Channel::Ethernet;
use {DataLinkReceiver, DataLinkSender, NetworkInterface};

/// Configuration for the pcap datalink backend.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Config {
    /// The size of buffer to use when reading packets. Must be at least
    /// 65516 with pcap.
    pub read_buffer_size: usize,

    /// The read timeout. Defaults to None.
    pub read_timeout: Option<Duration>,
}

impl<'a> From<&'a super::Config> for Config {
    fn from(config: &super::Config) -> Config {
        let mut c = Config {
            read_buffer_size: config.read_buffer_size,
            read_timeout: config.read_timeout,
        };
        // pcap is unique in that the buffer size must be greater or equal to
        // MAXIMUM_SNAPLEN, which is currently hard-coded to 65536
        // So, just reset it to the default.
        if c.read_buffer_size < 65536 {
            c.read_buffer_size = Config::default().read_buffer_size;
        }
        c
    }
}

impl Default for Config {
    fn default() -> Config {
        Config {
            // Just let pcap pick the default size
            read_buffer_size: 0,
            read_timeout: None,
        }
    }
}

/// Create a datalink channel from the provided pcap device.
#[inline]
pub fn channel(network_interface: &NetworkInterface, config: Config) -> io::Result<super::Channel> {
    let cap = match pcap::Capture::from_device(&*network_interface.name) {
        Ok(cap) => cap,
        Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
    }
    .buffer_size(config.read_buffer_size as i32);
    let cap = match config.read_timeout {
        Some(to) => cap.timeout((to.as_secs() * 1000 + (to.subsec_nanos() / 1000) as u64) as i32),
        None => cap,
    };
    // Enable promiscuous capture
    let cap = cap.promisc(true);
    let cap = match cap.open() {
        Ok(cap) => cap,
        Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
    };
    let cap = Arc::new(Mutex::new(cap));
    Ok(Ethernet(
        Box::new(DataLinkSenderImpl {
            capture: cap.clone(),
        }),
        Box::new(DataLinkReceiverImpl {
            capture: cap.clone(),
            read_buffer: vec![0; config.read_buffer_size],
        }),
    ))
}

/// Create a datalink channel from a pcap file.
#[inline]
pub fn from_file<P: AsRef<Path>>(path: P, config: Config) -> io::Result<super::Channel> {
    let cap = match pcap::Capture::from_file(path) {
        Ok(cap) => cap,
        Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
    };
    let cap = Arc::new(Mutex::new(cap));
    Ok(Ethernet(
        Box::new(InvalidDataLinkSenderImpl {}),
        Box::new(DataLinkReceiverImpl {
            capture: cap.clone(),
            read_buffer: vec![0; config.read_buffer_size],
        }),
    ))
}

struct DataLinkSenderImpl {
    capture: Arc<Mutex<pcap::Capture<Active>>>,
}

impl DataLinkSender for DataLinkSenderImpl {
    #[inline]
    fn build_and_send(
        &mut self,
        num_packets: usize,
        packet_size: usize,
        func: &mut dyn FnMut(&mut [u8]),
    ) -> Option<io::Result<()>> {
        for _ in 0..num_packets {
            let mut data = vec![0; packet_size];
            func(&mut data);
            let mut cap = self.capture.lock().unwrap();
            if let Err(e) = cap.sendpacket(data) {
                return Some(Err(io::Error::new(io::ErrorKind::Other, e)));
            }
        }
        Some(Ok(()))
    }

    #[inline]
    fn send_to(&mut self, packet: &[u8], _dst: Option<NetworkInterface>) -> Option<io::Result<()>> {
        let mut cap = self.capture.lock().unwrap();
        Some(match cap.sendpacket(packet) {
            Ok(()) => Ok(()),
            Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)),
        })
    }
}

struct InvalidDataLinkSenderImpl {}

impl DataLinkSender for InvalidDataLinkSenderImpl {
    #[inline]
    fn build_and_send(
        &mut self,
        _num_packets: usize,
        _packet_size: usize,
        _func: &mut dyn FnMut(&mut [u8]),
    ) -> Option<io::Result<()>> {
        None
    }

    #[inline]
    fn send_to(
        &mut self,
        _packet: &[u8],
        _dst: Option<NetworkInterface>,
    ) -> Option<io::Result<()>> {
        None
    }
}

struct DataLinkReceiverImpl<T: Activated + Send + Sync> {
    capture: Arc<Mutex<pcap::Capture<T>>>,
    read_buffer: Vec<u8>,
}

impl<T: Activated + Send + Sync> DataLinkReceiver for DataLinkReceiverImpl<T> {
    fn next(&mut self) -> io::Result<&[u8]> {
        let mut cap = self.capture.lock().unwrap();
        match cap.next() {
            Ok(pkt) => {
                self.read_buffer.truncate(0);
                self.read_buffer.extend(pkt.data);
            }
            Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
        };
        Ok(&self.read_buffer)
    }
}

/// Get a list of available network interfaces for the current machine.
pub fn interfaces() -> Vec<NetworkInterface> {
    if let Ok(devices) = pcap::Device::list() {
        devices
            .iter()
            .enumerate()
            .map(|(i, dev)| NetworkInterface {
                name: dev.name.clone(),
                index: i as u32,
                mac: None,
                ips: Vec::new(),
                flags: 0,
            })
            .collect()
    } else {
        vec![]
    }
}
<|endoftext|>


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

// Targets the Cortex-R4F/R5F processor (ARMv7-R)

use std::default::Default;
use spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
    Ok(Target {
        llvm_target: "armebv7r-none-eabihf".to_string(),
        target_endian: "big".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        data_layout: "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
        arch: "arm".to_string(),
        target_os: "none".to_string(),
        target_env: String::new(),
        target_vendor: String::new(),
        linker_flavor: LinkerFlavor::Gcc,

        options: TargetOptions {
            executables: true,
            relocation_model: "static".to_string(),
            panic_strategy: PanicStrategy::Abort,
            features: "+v7,+vfp3,+d16,+fp-only-sp".to_string(),
            max_atomic_width: Some(32),
            abi_blacklist: super::arm_base::abi_blacklist(),
            emit_debug_gdb_scripts: false,
            .. Default::default()
        },
    })
}
<commit_msg>make the armebv7r target more consistent with the armv7r one<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Targets the Cortex-R4F/R5F processor (ARMv7-R)

use std::default::Default;
use spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
    Ok(Target {
        llvm_target: "armebv7r-none-eabihf".to_string(),
        target_endian: "big".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        data_layout: "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
        arch: "arm".to_string(),
        target_os: "none".to_string(),
        target_env: String::new(),
        target_vendor: String::new(),
        linker_flavor: LinkerFlavor::Gcc,

        options: TargetOptions {
            executables: true,
            relocation_model: "static".to_string(),
            panic_strategy: PanicStrategy::Abort,
            features: "+vfp3,+d16,+fp-only-sp".to_string(),
            max_atomic_width: Some(32),
            abi_blacklist: super::arm_base::abi_blacklist(),
            emit_debug_gdb_scripts: false,
            .. Default::default()
        },
    })
}
<|endoftext|>


<commit_before>//! SUBACK

use std::io::{self, Read, Write};
use std::error::Error;
use std::fmt;
use std::convert::From;

use byteorder::{WriteBytesExt, ReadBytesExt};

use control::{FixedHeader, PacketType, ControlType};
use control::variable_header::PacketIdentifier;
use packet::{Packet, PacketError};
use {Encodable, Decodable};

/// Subscribe code
#[repr(u8)]
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum SubscribeReturnCode {
    MaximumQoSLevel0 = 0x00,
    MaximumQoSLevel1 = 0x01,
    MaximumQoSLevel2 = 0x02,
    Failure = 0x80,
}

/// `SUBACK` packet
#[derive(Debug, Eq, PartialEq)]
pub struct SubackPacket {
    fixed_header: FixedHeader,
    packet_identifier: PacketIdentifier,
    payload: SubackPacketPayload,
}

impl SubackPacket {
    pub fn new(pkid: u16, subscribes: Vec<SubscribeReturnCode>) -> SubackPacket {
        let mut pk = SubackPacket {
            fixed_header: FixedHeader::new(PacketType::with_default(ControlType::SubscribeAcknowledgement),
                                           0),
            packet_identifier: PacketIdentifier(pkid),
            payload: SubackPacketPayload::new(subscribes),
        };
        pk.fixed_header.remaining_length = pk.encoded_variable_headers_length() + pk.payload.encoded_length();
        pk
    }

    pub fn packet_identifier(&self) -> u16 {
        self.packet_identifier.0
    }

    pub fn set_packet_identifier(&mut self, pkid: u16) {
        self.packet_identifier.0 = pkid;
    }
}

impl<'a> Packet<'a> for SubackPacket {
    type Payload = SubackPacketPayload;

    fn fixed_header(&self) -> &FixedHeader {
        &self.fixed_header
    }

    fn payload(&self) -> &Self::Payload {
        &self.payload
    }

    fn encode_variable_headers<W: Write>(&self, writer: &mut W) -> Result<(), PacketError<'a, Self>> {
        try!(self.packet_identifier.encode(writer));

        Ok(())
    }

    fn encoded_variable_headers_length(&self) -> u32 {
        self.packet_identifier.encoded_length()
    }

    fn decode_packet<R: Read>(reader: &mut R, fixed_header: FixedHeader) -> Result<Self, PacketError<'a, Self>> {
        let packet_identifier: PacketIdentifier = try!(PacketIdentifier::decode(reader));
        let payload: SubackPacketPayload = try!(SubackPacketPayload::decode_with(reader,
                                                                                Some(fixed_header.remaining_length - packet_identifier.encoded_length()))
                                                        .map_err(PacketError::PayloadError));
        Ok(SubackPacket {
               fixed_header: fixed_header,
               packet_identifier: packet_identifier,
               payload: payload,
           })
    }
}

#[derive(Debug, Eq, PartialEq)]
pub struct SubackPacketPayload {
    subscribes: Vec<SubscribeReturnCode>,
}

impl SubackPacketPayload {
    pub fn new(subs: Vec<SubscribeReturnCode>) -> SubackPacketPayload {
        SubackPacketPayload { subscribes: subs }
    }

    pub fn subscribes(&self) -> &[SubscribeReturnCode] {
        &self.subscribes[..]
    }
}

impl<'a> Encodable<'a> for SubackPacketPayload {
    type Err = SubackPacketPayloadError;

    fn encode<W: Write>(&self, writer: &mut W) -> Result<(), Self::Err> {
        for code in self.subscribes.iter() {
            try!(writer.write_u8(*code as u8));
        }

        Ok(())
    }

    fn encoded_length(&self) -> u32 {
        self.subscribes.len() as u32
    }
}

impl<'a> Decodable<'a> for SubackPacketPayload {
    type Err = SubackPacketPayloadError;
    type Cond = u32;

    fn decode_with<R: Read>(reader: &mut R, payload_len: Option<u32>) -> Result<SubackPacketPayload, SubackPacketPayloadError> {
        let payload_len = payload_len.expect("Must provide payload length");
        let mut subs = Vec::new();

        for _ in 0..payload_len {
            let retcode = match try!(reader.read_u8()) {
                0x00 => SubscribeReturnCode::MaximumQoSLevel0,
                0x01 => SubscribeReturnCode::MaximumQoSLevel1,
                0x02 => SubscribeReturnCode::MaximumQoSLevel2,
                0x80 => SubscribeReturnCode::Failure,
                code => return Err(SubackPacketPayloadError::InvalidSubscribeReturnCode(code)),
            };

            subs.push(retcode);
        }

        Ok(SubackPacketPayload::new(subs))
    }
}

#[derive(Debug)]
pub enum SubackPacketPayloadError {
    IoError(io::Error),
    InvalidSubscribeReturnCode(u8),
}

impl fmt::Display for SubackPacketPayloadError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &SubackPacketPayloadError::IoError(ref err) => err.fmt(f),
            &SubackPacketPayloadError::InvalidSubscribeReturnCode(code) => write!(f, "Invalid subscribe return code {}", code),
        }
    }
}

impl Error for SubackPacketPayloadError {
    fn description(&self) -> &str {
        match self {
            &SubackPacketPayloadError::IoError(ref err) => err.description(),
            &SubackPacketPayloadError::InvalidSubscribeReturnCode(..) => "Invalid subscribe return code",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self {
            &SubackPacketPayloadError::IoError(ref err) => Some(err),
            &SubackPacketPayloadError::InvalidSubscribeReturnCode(..) => None,
        }
    }
}

impl From<io::Error> for SubackPacketPayloadError {
    fn from(err: io::Error) -> SubackPacketPayloadError {
        SubackPacketPayloadError::IoError(err)
    }
}
<commit_msg>Custom ordering and conversion for SubscribeReturnCode<commit_after>//! SUBACK

use std::io::{self, Read, Write};
use std::error::Error;
use std::fmt;
use std::convert::From;
use std::cmp::Ordering;

use byteorder::{WriteBytesExt, ReadBytesExt};

use control::{FixedHeader, PacketType, ControlType};
use control::variable_header::PacketIdentifier;
use packet::{Packet, PacketError};
use qos::QualityOfService;
use {Encodable, Decodable};

/// Subscribe code
#[repr(u8)]
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum SubscribeReturnCode {
    MaximumQoSLevel0 = 0x00,
    MaximumQoSLevel1 = 0x01,
    MaximumQoSLevel2 = 0x02,
    Failure = 0x80,
}

impl PartialOrd for SubscribeReturnCode {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        use self::SubscribeReturnCode::*;
        match (self, other) {
            (&Failure, _) => None,
            (_, &Failure) => None,
            (&MaximumQoSLevel0, &MaximumQoSLevel0) => Some(Ordering::Equal),
            (&MaximumQoSLevel1, &MaximumQoSLevel1) => Some(Ordering::Equal),
            (&MaximumQoSLevel2, &MaximumQoSLevel2) => Some(Ordering::Equal),
            (&MaximumQoSLevel0, _) => Some(Ordering::Less),
            (&MaximumQoSLevel1, &MaximumQoSLevel0) => Some(Ordering::Greater),
            (&MaximumQoSLevel1, &MaximumQoSLevel2) => Some(Ordering::Less),
            (&MaximumQoSLevel2, _) => Some(Ordering::Greater),
        }
    }
}

impl From<QualityOfService> for SubscribeReturnCode {
    fn from(qos: QualityOfService) -> Self {
        match qos {
            QualityOfService::Level0 => SubscribeReturnCode::MaximumQoSLevel0,
            QualityOfService::Level1 => SubscribeReturnCode::MaximumQoSLevel1,
            QualityOfService::Level2 => SubscribeReturnCode::MaximumQoSLevel2,
        }
    }
}

/// `SUBACK` packet
#[derive(Debug, Eq, PartialEq)]
pub struct SubackPacket {
    fixed_header: FixedHeader,
    packet_identifier: PacketIdentifier,
    payload: SubackPacketPayload,
}

impl SubackPacket {
    pub fn new(pkid: u16, subscribes: Vec<SubscribeReturnCode>) -> SubackPacket {
        let mut pk = SubackPacket {
            fixed_header: FixedHeader::new(PacketType::with_default(ControlType::SubscribeAcknowledgement),
                                           0),
            packet_identifier: PacketIdentifier(pkid),
            payload: SubackPacketPayload::new(subscribes),
        };
        pk.fixed_header.remaining_length = pk.encoded_variable_headers_length() + pk.payload.encoded_length();
        pk
    }

    pub fn packet_identifier(&self) -> u16 {
        self.packet_identifier.0
    }

    pub fn set_packet_identifier(&mut self, pkid: u16) {
        self.packet_identifier.0 = pkid;
    }
}

impl<'a> Packet<'a> for SubackPacket {
    type Payload = SubackPacketPayload;

    fn fixed_header(&self) -> &FixedHeader {
        &self.fixed_header
    }

    fn payload(&self) -> &Self::Payload {
        &self.payload
    }

    fn encode_variable_headers<W: Write>(&self, writer: &mut W) -> Result<(), PacketError<'a, Self>> {
        try!(self.packet_identifier.encode(writer));

        Ok(())
    }

    fn encoded_variable_headers_length(&self) -> u32 {
        self.packet_identifier.encoded_length()
    }

    fn decode_packet<R: Read>(reader: &mut R, fixed_header: FixedHeader) -> Result<Self, PacketError<'a, Self>> {
        let packet_identifier: PacketIdentifier = try!(PacketIdentifier::decode(reader));
        let payload: SubackPacketPayload = try!(SubackPacketPayload::decode_with(reader,
                                                                                Some(fixed_header.remaining_length - packet_identifier.encoded_length()))
                                                        .map_err(PacketError::PayloadError));
        Ok(SubackPacket {
               fixed_header: fixed_header,
               packet_identifier: packet_identifier,
               payload: payload,
           })
    }
}

#[derive(Debug, Eq, PartialEq)]
pub struct SubackPacketPayload {
    subscribes: Vec<SubscribeReturnCode>,
}

impl SubackPacketPayload {
    pub fn new(subs: Vec<SubscribeReturnCode>) -> SubackPacketPayload {
        SubackPacketPayload { subscribes: subs }
    }

    pub fn subscribes(&self) -> &[SubscribeReturnCode] {
        &self.subscribes[..]
    }
}

impl<'a> Encodable<'a> for SubackPacketPayload {
    type Err = SubackPacketPayloadError;

    fn encode<W: Write>(&self, writer: &mut W) -> Result<(), Self::Err> {
        for code in self.subscribes.iter() {
            try!(writer.write_u8(*code as u8));
        }

        Ok(())
    }

    fn encoded_length(&self) -> u32 {
        self.subscribes.len() as u32
    }
}

impl<'a> Decodable<'a> for SubackPacketPayload {
    type Err = SubackPacketPayloadError;
    type Cond = u32;

    fn decode_with<R: Read>(reader: &mut R, payload_len: Option<u32>) -> Result<SubackPacketPayload, SubackPacketPayloadError> {
        let payload_len = payload_len.expect("Must provide payload length");
        let mut subs = Vec::new();

        for _ in 0..payload_len {
            let retcode = match try!(reader.read_u8()) {
                0x00 => SubscribeReturnCode::MaximumQoSLevel0,
                0x01 => SubscribeReturnCode::MaximumQoSLevel1,
                0x02 => SubscribeReturnCode::MaximumQoSLevel2,
                0x80 => SubscribeReturnCode::Failure,
                code => return Err(SubackPacketPayloadError::InvalidSubscribeReturnCode(code)),
            };

            subs.push(retcode);
        }

        Ok(SubackPacketPayload::new(subs))
    }
}

#[derive(Debug)]
pub enum SubackPacketPayloadError {
    IoError(io::Error),
    InvalidSubscribeReturnCode(u8),
}

impl fmt::Display for SubackPacketPayloadError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &SubackPacketPayloadError::IoError(ref err) => err.fmt(f),
            &SubackPacketPayloadError::InvalidSubscribeReturnCode(code) => write!(f, "Invalid subscribe return code {}", code),
        }
    }
}

impl Error for SubackPacketPayloadError {
    fn description(&self) -> &str {
        match self {
            &SubackPacketPayloadError::IoError(ref err) => err.description(),
            &SubackPacketPayloadError::InvalidSubscribeReturnCode(..) => "Invalid subscribe return code",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self {
            &SubackPacketPayloadError::IoError(ref err) => Some(err),
            &SubackPacketPayloadError::InvalidSubscribeReturnCode(..) => None,
        }
    }
}

impl From<io::Error> for SubackPacketPayloadError {
    fn from(err: io::Error) -> SubackPacketPayloadError {
        SubackPacketPayloadError::IoError(err)
    }
}
<|endoftext|>


<commit_before>//! A catchall LiDAR point.

use std::u16;

/// A point.
#[derive(Clone, Copy, Debug, Default)]
pub struct Point {
    /// The x dimension of a point. All points must have these.
    pub x: f64,
    /// The y dimension of a point. All points must have these.
    pub y: f64,
    /// The z dimension of a point. All points must have these.
    pub z: f64,
    /// This is the intensity of the backscattered energy, as detected by the LiDAR sensor. Since
    /// each sensor has its own dynamic range, an intensity value is actually three values — the
    /// intensity value itself, the minimum possible value, and the maximum possible value.
    pub intensity: Intensity,
    /// The return number of this point.
    pub return_number: Option<usize>,
    /// The total number of returns in the pulse of this point.
    pub number_of_returns: Option<usize>,
    /// The direction that the scanner mirror was travelling when the point was collected. The only
    /// reason we include this field is that it is in the las standard. Anyone that doesn't collect
    /// scan direction information should just keep this at the default of
    /// `ScanDirection::Unknown`, and let the las sink deal with it.
    pub scan_direction: ScanDirection,
    /// Is this point at the edge of a flight line? Again, a crappy field that was included just
    /// becuase las.
    pub edge_of_flight_line: bool,
    /// The classification of this point.
    ///
    /// I'm not sure if I want to really define out the ASPRS classification mappings in this
    /// library, or leave that to the las library. I'm leaning towards keeping that in las just
    /// because I don't like classifications as a general concept, and so I try to stay away from
    /// them whenever I can.
    ///
    /// The value of `0` is "Created, never classified" according to at least one of the las
    /// specifications, so this is a sensible default value.
    pub classification: u8,
    /// Is this a synthetic point? Urgh. las again. Just keep this false unless someone out there
    /// is actually using the synthetic field.
    pub synthetic: bool,
    /// Okay, las, model key point? Really? You're taking up a perfectly good bit in *every single
    /// las point* just for this field? Really?
    pub key_point: bool,
    /// It's not even worth complaining anymore. Just look at a las standard to see what all these
    /// crappy fields mean. And while you're at it, try clicking on some of the URLs *in the las
    /// standards*. I'll bet some of them are broken. That's how good ASPRS are (is?).
    pub withheld: bool,
    /// Whew, back into the normal realm of fields. This is the angle of the mirror when the point
    /// was captured. Angle is usually defined with zero being straight out of the scanner.
    ///
    /// Las, in all of its wisdom, only stores these as integers, but more sensible formats allow
    /// for finer resolution, so we dial this up to `f64` and let the las sink throw away perfectly
    /// good data.
    pub scan_angle: Option<f64>,
    /// Why, las, why. What is this, even.
    pub point_source_id: Option<u16>,
    /// Okay, I'm done complaining now. In all seriousness, I thought about throwing this field
    /// out, in particular, but I figure since las is so used I should just mirror it. But that
    /// doesn't mean I can't whine about it.
    pub user_data: Option<u8>,
    /// GNSS synchronized time.
    pub gps_time: Option<f64>,
    /// The range of the point from the scanner. Note that for some formats, this explicity *does
    /// not* equal the cartesian distance to the x, y, z location of the point. This is a bit of an
    /// esoteric field but we include it because Riegl uses it a decent amount.
    pub range: Option<f64>,
    /// The width of the received pulse. Again, a pretty esoteric field, this time from the Riegl
    /// side of things. I get thinking more and more how to deal with these strange fields like
    /// this.
    pub width: Option<f64>,
    /// Man, this is the range index, and I have *no* idea what it means.
    pub rg_index: Option<f64>,
    /// The number of the mirror facet that was used to send this pulse.
    pub facet_number: Option<u8>,
    /// The target type, as an integer. Riegl uses some coded values for target type (Gaussian,
    /// Center of Gravity, etc), but at this point we don't choose to propagate those values up to
    /// this level.
    pub target_type: Option<u8>,
    /// Is this point from a high channel?
    ///
    /// TODO this field should be turned into a newtype or enum
    pub high_channel: Option<bool>,
}

/// The direction that the scanner mirror was moving when the pulse was emitted.
#[derive(Clone, Copy, Debug)]
pub enum ScanDirection {
    /// Forward.
    Forward,
    /// Backwards.
    Backward,
    /// The scan direction is undefined.
    Unknown,
}

impl Default for ScanDirection {
    fn default() -> ScanDirection {
        ScanDirection::Unknown
    }
}

/// An intensity value, with information about its minimum and maximum possible values.
#[derive(Clone, Copy, Debug, Default)]
pub struct Intensity {
    value: f64,
    min: f64,
    max: f64,
}

impl Intensity {
    /// Creates a new intensity with the min and the max set to the u16 bounds.
    ///
    /// # Examples
    ///
    /// ```
    /// use pabst::point::Intensity;
    /// let intensity = Intensity::from_u16(10);
    /// ```
    pub fn from_u16(value: u16) -> Intensity {
        Intensity {
            value: value as f64,
            min: u16::MIN as f64,
            max: u16::MAX as f64,
        }
    }

    /// Creates a new intensity with the value, minimu, and maximum.
    ///
    /// # Examples
    ///
    /// ```
    /// use pabst::point::Intensity;
    /// let intensity = Intensity::new(1.0, 0.0, 2.0);
    /// assert_eq!(32767, intensity.as_u16());
    /// ```
    pub fn new(value: f64, min: f64, max: f64) -> Intensity {
        Intensity {
            value: value,
            min: min,
            max: max,
        }
    }

    /// Returns this intensity value as a u16.
    ///
    /// # Examples
    ///
    /// ```
    /// use pabst::point::Intensity;
    /// let intensity = Intensity::from_u16(10);
    /// assert_eq!(10, intensity.as_u16());
    /// ```
    pub fn as_u16(&self) -> u16 {
        (u16::MAX as f64 * (self.value - self.min) / (self.max - self.min)) as u16
    }
}
<commit_msg>Add partials field to a point<commit_after>//! A catchall LiDAR point.

use std::u16;

/// A point.
#[derive(Clone, Copy, Debug, Default)]
pub struct Point {
    /// The x dimension of a point. All points must have these.
    pub x: f64,
    /// The y dimension of a point. All points must have these.
    pub y: f64,
    /// The z dimension of a point. All points must have these.
    pub z: f64,
    /// This is the intensity of the backscattered energy, as detected by the LiDAR sensor. Since
    /// each sensor has its own dynamic range, an intensity value is actually three values — the
    /// intensity value itself, the minimum possible value, and the maximum possible value.
    pub intensity: Intensity,
    /// The return number of this point.
    pub return_number: Option<usize>,
    /// The total number of returns in the pulse of this point.
    pub number_of_returns: Option<usize>,
    /// The direction that the scanner mirror was travelling when the point was collected. The only
    /// reason we include this field is that it is in the las standard. Anyone that doesn't collect
    /// scan direction information should just keep this at the default of
    /// `ScanDirection::Unknown`, and let the las sink deal with it.
    pub scan_direction: ScanDirection,
    /// Is this point at the edge of a flight line? Again, a crappy field that was included just
    /// becuase las.
    pub edge_of_flight_line: bool,
    /// The classification of this point.
    ///
    /// I'm not sure if I want to really define out the ASPRS classification mappings in this
    /// library, or leave that to the las library. I'm leaning towards keeping that in las just
    /// because I don't like classifications as a general concept, and so I try to stay away from
    /// them whenever I can.
    ///
    /// The value of `0` is "Created, never classified" according to at least one of the las
    /// specifications, so this is a sensible default value.
    pub classification: u8,
    /// Is this a synthetic point? Urgh. las again. Just keep this false unless someone out there
    /// is actually using the synthetic field.
    pub synthetic: bool,
    /// Okay, las, model key point? Really? You're taking up a perfectly good bit in *every single
    /// las point* just for this field? Really?
    pub key_point: bool,
    /// It's not even worth complaining anymore. Just look at a las standard to see what all these
    /// crappy fields mean. And while you're at it, try clicking on some of the URLs *in the las
    /// standards*. I'll bet some of them are broken. That's how good ASPRS are (is?).
    pub withheld: bool,
    /// Whew, back into the normal realm of fields. This is the angle of the mirror when the point
    /// was captured. Angle is usually defined with zero being straight out of the scanner.
    ///
    /// Las, in all of its wisdom, only stores these as integers, but more sensible formats allow
    /// for finer resolution, so we dial this up to `f64` and let the las sink throw away perfectly
    /// good data.
    pub scan_angle: Option<f64>,
    /// Why, las, why. What is this, even.
    pub point_source_id: Option<u16>,
    /// Okay, I'm done complaining now. In all seriousness, I thought about throwing this field
    /// out, in particular, but I figure since las is so used I should just mirror it. But that
    /// doesn't mean I can't whine about it.
    pub user_data: Option<u8>,
    /// GNSS synchronized time.
    pub gps_time: Option<f64>,
    /// The range of the point from the scanner. Note that for some formats, this explicity *does
    /// not* equal the cartesian distance to the x, y, z location of the point. This is a bit of an
    /// esoteric field but we include it because Riegl uses it a decent amount.
    pub range: Option<f64>,
    /// The width of the received pulse. Again, a pretty esoteric field, this time from the Riegl
    /// side of things. I get thinking more and more how to deal with these strange fields like
    /// this.
    pub width: Option<f64>,
    /// Man, this is the range index, and I have *no* idea what it means.
    pub rg_index: Option<f64>,
    /// The number of the mirror facet that was used to send this pulse.
    pub facet_number: Option<u8>,
    /// The target type, as an integer. Riegl uses some coded values for target type (Gaussian,
    /// Center of Gravity, etc), but at this point we don't choose to propagate those values up to
    /// this level.
    pub target_type: Option<u8>,
    /// Is this point from a high channel?
    ///
    /// TODO this field should be turned into a newtype or enum
    pub high_channel: Option<bool>,
    /// When doing error propagation, it can be useful to carry along a point's partial derivatives
    /// with respect to each of the fourteen degrees of freedom in the LiDAR georeferencing
    /// equation. If we have the partials, we can combine them with compoment errors to get final
    /// propagated error.
    pub partials: Option<Partials>,
}

/// The direction that the scanner mirror was moving when the pulse was emitted.
#[derive(Clone, Copy, Debug)]
pub enum ScanDirection {
    /// Forward.
    Forward,
    /// Backwards.
    Backward,
    /// The scan direction is undefined.
    Unknown,
}

impl Default for ScanDirection {
    fn default() -> ScanDirection {
        ScanDirection::Unknown
    }
}

/// An intensity value, with information about its minimum and maximum possible values.
#[derive(Clone, Copy, Debug, Default)]
pub struct Intensity {
    value: f64,
    min: f64,
    max: f64,
}

impl Intensity {
    /// Creates a new intensity with the min and the max set to the u16 bounds.
    ///
    /// # Examples
    ///
    /// ```
    /// use pabst::point::Intensity;
    /// let intensity = Intensity::from_u16(10);
    /// ```
    pub fn from_u16(value: u16) -> Intensity {
        Intensity {
            value: value as f64,
            min: u16::MIN as f64,
            max: u16::MAX as f64,
        }
    }

    /// Creates a new intensity with the value, minimu, and maximum.
    ///
    /// # Examples
    ///
    /// ```
    /// use pabst::point::Intensity;
    /// let intensity = Intensity::new(1.0, 0.0, 2.0);
    /// assert_eq!(32767, intensity.as_u16());
    /// ```
    pub fn new(value: f64, min: f64, max: f64) -> Intensity {
        Intensity {
            value: value,
            min: min,
            max: max,
        }
    }

    /// Returns this intensity value as a u16.
    ///
    /// # Examples
    ///
    /// ```
    /// use pabst::point::Intensity;
    /// let intensity = Intensity::from_u16(10);
    /// assert_eq!(10, intensity.as_u16());
    /// ```
    pub fn as_u16(&self) -> u16 {
        (u16::MAX as f64 * (self.value - self.min) / (self.max - self.min)) as u16
    }
}

/// A 3x14 collection of partial derivates for the x, y, and z components of a LiDAR point.
#[derive(Clone, Copy, Debug)]
pub struct Partials {
    range: Xyz,
    scan_angle: Xyz,
    boresight_roll: Xyz,
    boresight_pitch: Xyz,
    boresight_yaw: Xyz,
    lever_arm_x: Xyz,
    lever_arm_y: Xyz,
    lever_arm_z: Xyz,
    roll: Xyz,
    pitch: Xyz,
    yaw: Xyz,
    gnss_x: Xyz,
    gnss_y: Xyz,
    gnss_z: Xyz,
}

/// A dumb structure of xyz f64s.
#[derive(Clone, Copy, Debug)]
pub struct Xyz {
    x: f64,
    y: f64,
    z: f64,
}
<|endoftext|>