<commit_before>//! TODO Documentation

use std::{panic, ptr};
use std::ffi::CStr;
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};

use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wlroots_sys::{wl_list, wl_output_transform, wlr_output, wlr_output_effective_resolution,
                  wlr_output_events, wlr_output_make_current, wlr_output_mode,
                  wlr_output_set_mode, wlr_output_set_transform, wlr_output_swap_buffers};

use super::output_layout::OutputLayoutHandle;
use errors::{UpgradeHandleErr, UpgradeHandleResult};

pub(crate) struct OutputState {
    pub layout_handle: OutputLayoutHandle
}

#[derive(Debug)]
pub struct Output {
    /// The structure that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `OutputHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `OutputHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The output ptr that refers to this `Output`
    output: *mut wlr_output
}

/// A wrapper around a wlr_output.
#[derive(Debug)]
pub struct OutputHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the pointer associated with this handle,
    /// this can no longer be used.
    handle: Weak<AtomicBool>,
    /// The output ptr that refers to this `Output`
    output: *mut wlr_output
}

impl Output {
    /// Just like `std::clone::Clone`, but unsafe.
    ///
    /// # Unsafety
    /// You can create a reference leak using this method very easily,
    /// and it could make it so that weak handles to an output are dangling.
    ///
    /// This exists due to an issue in output_manager.rs that might be fixed
    /// with NLL, so if this is no longer necessary it should be removed asap.
    pub(crate) unsafe fn clone(&self) -> Output {
        Output { liveliness: self.liveliness.clone(),
                 output: self.output }
    }

    /// Makes a new `Output` from a `wlr_output`.
    ///
    /// # Safety
    /// This creates a totally new Output (e.g with its own reference count)
    /// so only do this once per `wlr_output`!
    pub(crate) unsafe fn new(output: *mut wlr_output) -> Self {
        (*output).data = ptr::null_mut();
        Output { liveliness: Some(Rc::new(AtomicBool::new(false))),
                 output }
    }

    pub(crate) unsafe fn set_user_data(&mut self, data: Box<OutputState>) {
        self.remove_from_output_layout();
        (*self.output).data = Box::into_raw(data) as *mut _
    }

    pub(crate) unsafe fn user_data(&mut self) -> *mut OutputState {
        (*self.output).data as *mut _
    }

    /// Used to clear the pointer to an OutputLayout when the OutputLayout
    /// removes this Output from its listing.
    pub(crate) unsafe fn clear_user_data(&mut self) {
        let user_data = self.user_data();
        if user_data.is_null() {
            return
        }
        let _ = Box::from_raw(user_data);
        (*self.output).data = ptr::null_mut();
    }

    /// Remove this Output from an OutputLayout, if it is part of an
    /// OutputLayout.
    pub(crate) unsafe fn remove_from_output_layout(&mut self) {
        if !(*self.output).data.is_null() {
            // Remove output from previous output layout.
            let mut layout_handle = (*self.user_data()).layout_handle.clone();
            match layout_handle.run(|layout| layout.remove(self)) {
                Ok(_) | Err(UpgradeHandleErr::AlreadyDropped) => {}
                Err(UpgradeHandleErr::AlreadyBorrowed) => {
                    panic!("Could not add OutputLayout to Output user data!")
                }
            }
        }
    }

    /// Gets the OutputLayout this Output is a part of, if it is part
    /// of an OutputLayout.
    ///
    /// # Safety
    /// Note that this isn't exposed to user space, as they could easily
    /// create two mutable pointers to the same structure. We keep it internally
    /// though because we use it during the cleanup process.
    pub(crate) unsafe fn layout(&mut self) -> Option<OutputLayoutHandle> {
        let data = self.user_data();
        if data.is_null() {
            None
        } else {
            Some((*data).layout_handle.clone())
        }
    }

    /// Sets the best modesetting for an output.
    ///
    /// NOTE You _cannot_ call this when the output will be removed.
    ///
    /// I'm still marking it as safe though because we protect against that
    /// action in the output destruction callback.
    pub fn choose_best_mode(&mut self) {
        unsafe {
            let length = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_list_length, self.modes() as _);
            if length > 0 {
                // TODO Better logging
                wlr_log!(L_DEBUG, "output added {:?}", self);
                let first_mode_ptr: *mut wlr_output_mode;
                first_mode_ptr = container_of!(&mut (*(*self.modes()).prev) as *mut _,
                                               wlr_output_mode,
                                               link);
                wlr_output_set_mode(self.as_ptr(), first_mode_ptr);
            }
        }
    }

    /// Gets the name of the output in UTF-8.
    pub fn name(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).name.as_ptr()).to_string_lossy()
                                                        .into_owned()
        }
    }

    /// Gets the make of the output in UTF-8.
    pub fn make(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).make.as_ptr()).to_string_lossy()
                                                        .into_owned()
        }
    }

    /// Gets the model of the output in UTF-8.
    pub fn model(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).model.as_ptr()).to_string_lossy()
                                                         .into_owned()
        }
    }

    pub fn make_current(&mut self) {
        unsafe { wlr_output_make_current(self.output) }
    }

    pub fn swap_buffers(&mut self) {
        unsafe { wlr_output_swap_buffers(self.output) }
    }

    /// Get the dimensions of the output as (width, height).
    pub fn dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).width, (*self.output).height) }
    }

    /// Get the physical dimensions of the output as (width, height).
    pub fn physical_dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).phys_width, (*self.output).phys_height) }
    }

    pub fn effective_resolution(&self) -> (i32, i32) {
        unsafe {
            let (mut x, mut y) = (0, 0);
            wlr_output_effective_resolution(self.output, &mut x, &mut y);
            (x, y)
        }
    }

    pub fn transform_matrix(&self) -> [f32; 16] {
        unsafe { (*self.output).transform_matrix }
    }

    pub fn transform(&mut self, transform: wl_output_transform) {
        unsafe {
            wlr_output_set_transform(self.output, transform);
        }
    }

    /// TODO Make safe
    pub unsafe fn modes(&self) -> *mut wl_list {
        &mut (*self.output).modes
    }

    /// TODO Make safe
    pub unsafe fn events(&self) -> wlr_output_events {
        (*self.output).events
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_output {
        self.output
    }

    /// Creates a weak reference to an `Output`.
    ///
    /// # Panics
    /// If this `Output` is a previously upgraded `OutputHandle`,
    /// then this function will panic.
    pub fn weak_reference(&self) -> OutputHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade a previously upgraded OutputHandle");
        OutputHandle { handle: Rc::downgrade(arc),
                       output: self.output }
    }

    unsafe fn from_handle(handle: &OutputHandle) -> Self {
        Output { liveliness: None,
                 output: handle.as_ptr() }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Output")
            .store(val, Ordering::Release);
    }
}

impl Drop for Output {
    fn drop(&mut self) {
        // NOTE
        // We do _not_ need to call wlr_output_destroy for the output
        // That is handled by the backend automatically
        match self.liveliness {
            None => return,
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) == 1 {
                    wlr_log!(L_DEBUG, "Dropped output {:p}", self.output);
                    let weak_count = Rc::weak_count(liveliness);
                    if weak_count > 0 {
                        wlr_log!(L_DEBUG,
                                 "Still {} weak pointers to Output {:p}",
                                 weak_count,
                                 self.output);
                    }
                } else {
                    return
                }
            }
        }
        // TODO Move back up in the some after NLL is a thing.
        unsafe {
            self.remove_from_output_layout();
        }
    }
}

impl OutputHandle {
    /// Upgrades the output handle to a reference to the backing `Output`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbound `Output`
    /// which may live forever..
    /// But no output lives forever and might be disconnected at any time.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Output> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::AlreadyDropped)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                let output = Output::from_handle(self);
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(output)
            })
    }

    /// Run a function on the referenced Output, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the output
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Output does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Output`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<Option<R>>
        where F: FnOnce(&mut Output) -> R
    {
        let mut output = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| Some(runner(&mut output))));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running output callback, mutable lock \
                                                    was false for: {:?}",
                                                   output);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_output {
        self.output
    }
}
<commit_msg>Cleaned up unsafe code, made user_data un-pub<commit_after>//! TODO Documentation

use std::{panic, ptr};
use std::ffi::CStr;
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};

use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wlroots_sys::{wl_list, wl_output_transform, wlr_output, wlr_output_effective_resolution,
                  wlr_output_events, wlr_output_make_current, wlr_output_mode,
                  wlr_output_set_mode, wlr_output_set_transform, wlr_output_swap_buffers};

use super::output_layout::OutputLayoutHandle;
use errors::{UpgradeHandleErr, UpgradeHandleResult};

pub(crate) struct OutputState {
    pub layout_handle: OutputLayoutHandle
}

#[derive(Debug)]
pub struct Output {
    /// The structure that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `OutputHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `OutputHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The output ptr that refers to this `Output`
    output: *mut wlr_output
}

/// A wrapper around a wlr_output.
#[derive(Debug)]
pub struct OutputHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the pointer associated with this handle,
    /// this can no longer be used.
    handle: Weak<AtomicBool>,
    /// The output ptr that refers to this `Output`
    output: *mut wlr_output
}

impl Output {
    /// Just like `std::clone::Clone`, but unsafe.
    ///
    /// # Unsafety
    /// You can create a reference leak using this method very easily,
    /// and it could make it so that weak handles to an output are dangling.
    ///
    /// This exists due to an issue in output_manager.rs that might be fixed
    /// with NLL, so if this is no longer necessary it should be removed asap.
    pub(crate) unsafe fn clone(&self) -> Output {
        Output { liveliness: self.liveliness.clone(),
                 output: self.output }
    }

    /// Makes a new `Output` from a `wlr_output`.
    ///
    /// # Safety
    /// This creates a totally new Output (e.g with its own reference count)
    /// so only do this once per `wlr_output`!
    pub(crate) unsafe fn new(output: *mut wlr_output) -> Self {
        (*output).data = ptr::null_mut();
        Output { liveliness: Some(Rc::new(AtomicBool::new(false))),
                 output }
    }

    pub(crate) unsafe fn set_user_data(&mut self, data: Box<OutputState>) {
        self.remove_from_output_layout();
        (*self.output).data = Box::into_raw(data) as *mut _
    }

    unsafe fn user_data(&mut self) -> *mut OutputState {
        (*self.output).data as *mut _
    }

    /// Used to clear the pointer to an OutputLayout when the OutputLayout
    /// removes this Output from its listing.
    pub(crate) unsafe fn clear_user_data(&mut self) {
        let user_data = self.user_data();
        if user_data.is_null() {
            return
        }
        let _ = Box::from_raw(user_data);
        (*self.output).data = ptr::null_mut();
    }

    /// Remove this Output from an OutputLayout, if it is part of an
    /// OutputLayout.
    pub(crate) unsafe fn remove_from_output_layout(&mut self) {
        let output_data = (*self.output).data;
        if output_data.is_null() {
            return
        }
        // Remove output from previous output layout.
        let mut layout_handle = (*output_data).layout_handle.clone();
        // NOTE This function will remove the OutputLayout pointer from this
        // output if it completes successfully.
        match layout_handle.run(|layout| layout.remove(self)) {
            Ok(_) | Err(UpgradeHandleErr::AlreadyDropped) => {}
            Err(UpgradeHandleErr::AlreadyBorrowed) => {
                panic!("Could not add OutputLayout to Output user data!")
            }
        }
    }

    /// Gets the OutputLayout this Output is a part of, if it is part
    /// of an OutputLayout.
    ///
    /// # Safety
    /// Note that this isn't exposed to user space, as they could easily
    /// create two mutable pointers to the same structure. We keep it internally
    /// though because we use it during the cleanup process.
    pub(crate) unsafe fn layout(&mut self) -> Option<OutputLayoutHandle> {
        let data = self.user_data();
        if data.is_null() {
            None
        } else {
            Some((*data).layout_handle.clone())
        }
    }

    /// Sets the best modesetting for an output.
    ///
    /// NOTE You _cannot_ call this when the output will be removed.
    ///
    /// I'm still marking it as safe though because we protect against that
    /// action in the output destruction callback.
    pub fn choose_best_mode(&mut self) {
        unsafe {
            let length = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_list_length, self.modes() as _);
            if length > 0 {
                // TODO Better logging
                wlr_log!(L_DEBUG, "output added {:?}", self);
                let first_mode_ptr: *mut wlr_output_mode;
                first_mode_ptr = container_of!(&mut (*(*self.modes()).prev) as *mut _,
                                               wlr_output_mode,
                                               link);
                wlr_output_set_mode(self.as_ptr(), first_mode_ptr);
            }
        }
    }

    /// Gets the name of the output in UTF-8.
    pub fn name(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).name.as_ptr()).to_string_lossy()
                                                        .into_owned()
        }
    }

    /// Gets the make of the output in UTF-8.
    pub fn make(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).make.as_ptr()).to_string_lossy()
                                                        .into_owned()
        }
    }

    /// Gets the model of the output in UTF-8.
    pub fn model(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).model.as_ptr()).to_string_lossy()
                                                         .into_owned()
        }
    }

    pub fn make_current(&mut self) {
        unsafe { wlr_output_make_current(self.output) }
    }

    pub fn swap_buffers(&mut self) {
        unsafe { wlr_output_swap_buffers(self.output) }
    }

    /// Get the dimensions of the output as (width, height).
    pub fn dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).width, (*self.output).height) }
    }

    /// Get the physical dimensions of the output as (width, height).
    pub fn physical_dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).phys_width, (*self.output).phys_height) }
    }

    pub fn effective_resolution(&self) -> (i32, i32) {
        unsafe {
            let (mut x, mut y) = (0, 0);
            wlr_output_effective_resolution(self.output, &mut x, &mut y);
            (x, y)
        }
    }

    pub fn transform_matrix(&self) -> [f32; 16] {
        unsafe { (*self.output).transform_matrix }
    }

    pub fn transform(&mut self, transform: wl_output_transform) {
        unsafe {
            wlr_output_set_transform(self.output, transform);
        }
    }

    /// TODO Make safe
    pub unsafe fn modes(&self) -> *mut wl_list {
        &mut (*self.output).modes
    }

    /// TODO Make safe
    pub unsafe fn events(&self) -> wlr_output_events {
        (*self.output).events
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_output {
        self.output
    }

    /// Creates a weak reference to an `Output`.
    ///
    /// # Panics
    /// If this `Output` is a previously upgraded `OutputHandle`,
    /// then this function will panic.
    pub fn weak_reference(&self) -> OutputHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade a previously upgraded OutputHandle");
        OutputHandle { handle: Rc::downgrade(arc),
                       output: self.output }
    }

    unsafe fn from_handle(handle: &OutputHandle) -> Self {
        Output { liveliness: None,
                 output: handle.as_ptr() }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Output")
            .store(val, Ordering::Release);
    }
}

impl Drop for Output {
    fn drop(&mut self) {
        // NOTE
        // We do _not_ need to call wlr_output_destroy for the output
        // That is handled by the backend automatically
        match self.liveliness {
            None => return,
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) == 1 {
                    wlr_log!(L_DEBUG, "Dropped output {:p}", self.output);
                    let weak_count = Rc::weak_count(liveliness);
                    if weak_count > 0 {
                        wlr_log!(L_DEBUG,
                                 "Still {} weak pointers to Output {:p}",
                                 weak_count,
                                 self.output);
                    }
                } else {
                    return
                }
            }
        }
        // TODO Move back up in the some after NLL is a thing.
        unsafe {
            self.remove_from_output_layout();
        }
    }
}

impl OutputHandle {
    /// Upgrades the output handle to a reference to the backing `Output`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbound `Output`
    /// which may live forever..
    /// But no output lives forever and might be disconnected at any time.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Output> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::AlreadyDropped)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                let output = Output::from_handle(self);
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(output)
            })
    }

    /// Run a function on the referenced Output, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the output
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Output does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Output`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<Option<R>>
        where F: FnOnce(&mut Output) -> R
    {
        let mut output = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| Some(runner(&mut output))));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running output callback, mutable lock \
                                                    was false for: {:?}",
                                                   output);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_output {
        self.output
    }
}
<|endoftext|>


<commit_before>use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::collections::hash_state::HashState;
use std::default::Default;
use std::hash::{Hash, Hasher};

use super::traits::{SortedMap, SortedSet};

macro_rules! sortedset_impl {
    ($typ:ty) => (
        fn first(&mut self, remove: bool) -> Option<T> {
            if self.is_empty() { return None }

            let ret = self.iter().min().unwrap().clone();
            if remove {
                self.remove(&ret);
            }
            Some(ret)
        }

        fn last(&mut self, remove: bool) -> Option<T> {
            if self.is_empty() { return None }

            let ret = self.iter().max().unwrap().clone();
            if remove {
                self.remove(&ret);
            }
            Some(ret)
        }

        fn head_set(&self, elem: &T, inclusive: bool) -> $typ {
            if inclusive {
                return self.iter().cloned().filter(|x| x <= elem).collect();
            } else {
                return self.iter().cloned().filter(|x| x < elem).collect();
            }
        }

        fn sub_set(&self, from_elem: &T, from_inclusive: bool, to_elem: &T, to_inclusive:bool) -> $typ {
            assert!(from_elem <= to_elem);

            if from_inclusive && to_inclusive {
                return self.iter().cloned().filter(|x| x >= from_elem && x <= to_elem).collect();
            } else if from_inclusive && !to_inclusive {
                return self.iter().cloned().filter(|x| x >= from_elem && x < to_elem).collect();
            } else if !from_inclusive && to_inclusive {
                return self.iter().cloned().filter(|x| x > from_elem && x <= to_elem).collect();
            } else {
                return self.iter().cloned().filter(|x| x > from_elem && x < to_elem).collect();
            }
        }

        fn tail_set(&self, elem: &T, inclusive: bool) -> $typ {
            if inclusive {
                return self.iter().cloned().filter(|x| x >= elem).collect();
            } else {
                return self.iter().cloned().filter(|x| x > elem).collect();
            }
        }
    );
}

impl<T> SortedSet<T> for BTreeSet<T>
    where T: Clone + Ord {
    sortedset_impl!(BTreeSet<T>);
}
impl<T, S, H> SortedSet<T> for HashSet<T, S>
    where T: Clone + Eq + Hash<H> + Ord,
          S: HashState<Hasher=H> + Default,
          H: Hasher<Output=u64> {
    sortedset_impl!(HashSet<T, S>);
}

macro_rules! sortedmap_impl {
    ($typ:ty) => (
        fn first_key(&mut self, remove: bool) -> Option<(K, V)> {
            if self.is_empty() { return None }

            let key = self.keys().min().unwrap().clone();
            let val: V;

            if remove {
                val = self.remove(&key).unwrap();
            } else {
                val = self.get(&key).unwrap().clone();
            }

            Some((key, val))
        }

        fn last_key(&mut self, remove: bool) -> Option<(K, V)> {
            if self.is_empty() { return None }

            let key = self.keys().max().unwrap().clone();
            let val: V;

            if remove {
                val = self.remove(&key).unwrap();
            } else {
                val = self.get(&key).unwrap().clone();
            }

            Some((key, val))
        }

        fn head_map(&self, key: &K, inclusive: bool) -> $typ {
            let it = self.keys().cloned().zip(self.values().cloned());
            if inclusive {
                return it.filter_map(|(k, v)| if k <= *key { Some((k, v)) } else { None }).collect();
            } else {
                return it.filter_map(|(k, v)| if k < *key { Some((k, v)) } else { None }).collect();
            }
        }

        fn sub_map(&self, from_key: &K, from_inclusive: bool, to_key: &K, to_inclusive: bool) -> $typ {
            let it = self.keys().cloned().zip(self.values().cloned());
            if from_inclusive && to_inclusive {
                return it.filter_map(|(k, v)| if k >= *from_key && k <= *to_key { Some((k, v)) } else { None }).collect();
            } else if from_inclusive && !to_inclusive {
                return it.filter_map(|(k, v)| if k >= *from_key && k < *to_key { Some((k, v)) } else { None }).collect();
            } else if !from_inclusive && to_inclusive {
                return it.filter_map(|(k, v)| if k > *from_key && k <= *to_key { Some((k, v)) } else { None }).collect();
            } else {
                return it.filter_map(|(k, v)| if k > *from_key && k < *to_key { Some((k, v)) } else { None }).collect();
            }
        }

        fn tail_map(&self, key: &K, inclusive: bool) -> $typ {
            let it = self.keys().cloned().zip(self.values().cloned());
            if inclusive {
                return it.filter_map(|(k, v)| if k >= *key { Some((k, v)) } else { None }).collect();
            } else {
                return it.filter_map(|(k, v)| if k > *key { Some((k, v)) } else { None }).collect();
            }
        }
    );
}

impl<K, V> SortedMap<K, V> for BTreeMap<K, V>
    where K: Clone + Ord,
          V: Clone {
    sortedmap_impl!(BTreeMap<K, V>);
}
impl<K, V, S, H> SortedMap<K, V> for HashMap<K, V, S>
    where K: Clone + Eq + Hash<H> + Ord,
          V: Clone,
          S: HashState<Hasher=H> + Default,
          H: Hasher<Output=u64> {
    sortedmap_impl!(HashMap<K, V, S>);
}

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

    use std::collections::BTreeSet;

    #[test]
    fn test_first_noremove() {
        let mut set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        assert_eq!(set.first(false).unwrap(), 1u32);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
    }

    #[test]
    fn test_first_remove() {
        let mut set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        assert_eq!(set.first(true).unwrap(), 1u32);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![2u32, 3, 4, 5]);
    }

    #[test]
    fn test_last_noremove() {
        let mut set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        assert_eq!(set.last(false).unwrap(), 5u32);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
    }

    #[test]
    fn test_last_remove() {
        let mut set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        assert_eq!(set.last(true).unwrap(), 5u32);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4]);
    }

    #[test]
    fn test_head_set_noinclusive() {
        let set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        let head_set = set.head_set(&3, false);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
        assert_eq!(head_set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2]);
    }

    #[test]
    fn test_head_set_inclusive() {
        let set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        let head_set = set.head_set(&3, true);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
        assert_eq!(head_set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3]);

    }

    // FIXME: Add subset tests!

    #[test]
    fn test_tail_set_noinclusive() {
        let set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        let tail_set = set.tail_set(&3, false);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
        assert_eq!(tail_set.into_iter().collect::<Vec<u32>>(), vec![4u32, 5]);
    }

    #[test]
    fn test_tail_set_inclusive() {
        let set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        let tail_set = set.tail_set(&3, true);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
        assert_eq!(tail_set.into_iter().collect::<Vec<u32>>(), vec![3u32, 4, 5]);
    }

    // FIXME: Add provided fn tests!

    // FIXME: Add map tests!
}
<commit_msg>Add some more tests.<commit_after>use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::collections::hash_state::HashState;
use std::default::Default;
use std::hash::{Hash, Hasher};

use super::traits::{SortedMap, SortedSet};

macro_rules! sortedset_impl {
    ($typ:ty) => (
        fn first(&mut self, remove: bool) -> Option<T> {
            if self.is_empty() { return None }

            let ret = self.iter().min().unwrap().clone();
            if remove {
                self.remove(&ret);
            }
            Some(ret)
        }

        fn last(&mut self, remove: bool) -> Option<T> {
            if self.is_empty() { return None }

            let ret = self.iter().max().unwrap().clone();
            if remove {
                self.remove(&ret);
            }
            Some(ret)
        }

        fn head_set(&self, elem: &T, inclusive: bool) -> $typ {
            if inclusive {
                return self.iter().cloned().filter(|x| x <= elem).collect();
            } else {
                return self.iter().cloned().filter(|x| x < elem).collect();
            }
        }

        fn sub_set(&self, from_elem: &T, from_inclusive: bool, to_elem: &T, to_inclusive:bool) -> $typ {
            assert!(from_elem <= to_elem);

            if from_inclusive && to_inclusive {
                return self.iter().cloned().filter(|x| x >= from_elem && x <= to_elem).collect();
            } else if from_inclusive && !to_inclusive {
                return self.iter().cloned().filter(|x| x >= from_elem && x < to_elem).collect();
            } else if !from_inclusive && to_inclusive {
                return self.iter().cloned().filter(|x| x > from_elem && x <= to_elem).collect();
            } else {
                return self.iter().cloned().filter(|x| x > from_elem && x < to_elem).collect();
            }
        }

        fn tail_set(&self, elem: &T, inclusive: bool) -> $typ {
            if inclusive {
                return self.iter().cloned().filter(|x| x >= elem).collect();
            } else {
                return self.iter().cloned().filter(|x| x > elem).collect();
            }
        }
    );
}

impl<T> SortedSet<T> for BTreeSet<T>
    where T: Clone + Ord {
    sortedset_impl!(BTreeSet<T>);
}
impl<T, S, H> SortedSet<T> for HashSet<T, S>
    where T: Clone + Eq + Hash<H> + Ord,
          S: HashState<Hasher=H> + Default,
          H: Hasher<Output=u64> {
    sortedset_impl!(HashSet<T, S>);
}

macro_rules! sortedmap_impl {
    ($typ:ty) => (
        fn first_key(&mut self, remove: bool) -> Option<(K, V)> {
            if self.is_empty() { return None }

            let key = self.keys().min().unwrap().clone();
            let val: V;

            if remove {
                val = self.remove(&key).unwrap();
            } else {
                val = self.get(&key).unwrap().clone();
            }

            Some((key, val))
        }

        fn last_key(&mut self, remove: bool) -> Option<(K, V)> {
            if self.is_empty() { return None }

            let key = self.keys().max().unwrap().clone();
            let val: V;

            if remove {
                val = self.remove(&key).unwrap();
            } else {
                val = self.get(&key).unwrap().clone();
            }

            Some((key, val))
        }

        fn head_map(&self, key: &K, inclusive: bool) -> $typ {
            let it = self.keys().cloned().zip(self.values().cloned());
            if inclusive {
                return it.filter_map(|(k, v)| if k <= *key { Some((k, v)) } else { None }).collect();
            } else {
                return it.filter_map(|(k, v)| if k < *key { Some((k, v)) } else { None }).collect();
            }
        }

        fn sub_map(&self, from_key: &K, from_inclusive: bool, to_key: &K, to_inclusive: bool) -> $typ {
            let it = self.keys().cloned().zip(self.values().cloned());
            if from_inclusive && to_inclusive {
                return it.filter_map(|(k, v)| if k >= *from_key && k <= *to_key { Some((k, v)) } else { None }).collect();
            } else if from_inclusive && !to_inclusive {
                return it.filter_map(|(k, v)| if k >= *from_key && k < *to_key { Some((k, v)) } else { None }).collect();
            } else if !from_inclusive && to_inclusive {
                return it.filter_map(|(k, v)| if k > *from_key && k <= *to_key { Some((k, v)) } else { None }).collect();
            } else {
                return it.filter_map(|(k, v)| if k > *from_key && k < *to_key { Some((k, v)) } else { None }).collect();
            }
        }

        fn tail_map(&self, key: &K, inclusive: bool) -> $typ {
            let it = self.keys().cloned().zip(self.values().cloned());
            if inclusive {
                return it.filter_map(|(k, v)| if k >= *key { Some((k, v)) } else { None }).collect();
            } else {
                return it.filter_map(|(k, v)| if k > *key { Some((k, v)) } else { None }).collect();
            }
        }
    );
}

impl<K, V> SortedMap<K, V> for BTreeMap<K, V>
    where K: Clone + Ord,
          V: Clone {
    sortedmap_impl!(BTreeMap<K, V>);
}
impl<K, V, S, H> SortedMap<K, V> for HashMap<K, V, S>
    where K: Clone + Eq + Hash<H> + Ord,
          V: Clone,
          S: HashState<Hasher=H> + Default,
          H: Hasher<Output=u64> {
    sortedmap_impl!(HashMap<K, V, S>);
}

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

    use std::collections::BTreeSet;

    #[test]
    fn test_first_noremove() {
        let mut set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        assert_eq!(set.first(false).unwrap(), 1u32);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
    }

    #[test]
    fn test_first_remove() {
        let mut set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        assert_eq!(set.first(true).unwrap(), 1u32);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![2u32, 3, 4, 5]);
    }

    #[test]
    fn test_last_noremove() {
        let mut set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        assert_eq!(set.last(false).unwrap(), 5u32);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
    }

    #[test]
    fn test_last_remove() {
        let mut set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        assert_eq!(set.last(true).unwrap(), 5u32);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4]);
    }

    #[test]
    fn test_head_set_noinclusive() {
        let set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        let head_set = set.head_set(&3, false);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
        assert_eq!(head_set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2]);
    }

    #[test]
    fn test_head_set_inclusive() {
        let set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        let head_set = set.head_set(&3, true);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
        assert_eq!(head_set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3]);

    }

    #[test]
    fn test_sub_set_noinclusive() {
        let set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        let sub_set = set.sub_set(&2, false, &4, false);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
        assert_eq!(sub_set.into_iter().collect::<Vec<u32>>(), vec![3u32]);
    }

    #[test]
    fn test_sub_set_nofrom_to() {
        let set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        let sub_set = set.sub_set(&2, false, &4, true);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
        assert_eq!(sub_set.into_iter().collect::<Vec<u32>>(), vec![3u32, 4]);
    }

    #[test]
    fn test_sub_set_from_noto() {
        let set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        let sub_set = set.sub_set(&2, true, &4, false);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
        assert_eq!(sub_set.into_iter().collect::<Vec<u32>>(), vec![2u32, 3]);
    }

    #[test]
    fn test_sub_set_inclusive() {
        let set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        let sub_set = set.sub_set(&2, true, &4, true);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
        assert_eq!(sub_set.into_iter().collect::<Vec<u32>>(), vec![2u32, 3, 4]);
    }

    #[test]
    fn test_tail_set_noinclusive() {
        let set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        let tail_set = set.tail_set(&3, false);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
        assert_eq!(tail_set.into_iter().collect::<Vec<u32>>(), vec![4u32, 5]);
    }

    #[test]
    fn test_tail_set_inclusive() {
        let set: BTreeSet<u32> = vec![1u32, 2, 3, 4, 5].into_iter().collect();
        let tail_set = set.tail_set(&3, true);
        assert_eq!(set.into_iter().collect::<Vec<u32>>(), vec![1u32, 2, 3, 4, 5]);
        assert_eq!(tail_set.into_iter().collect::<Vec<u32>>(), vec![3u32, 4, 5]);
    }

    // FIXME: Add map tests!
}
<|endoftext|>


<commit_before>use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::owned_slice::OwnedSlice;
use syntax::ptr::P;

use invoke::{Invoke, Identity};
use lifetime::{IntoLifetime, IntoLifetimeDef, LifetimeDefBuilder};
use name::ToName;
use path::IntoPath;
use ty::TyBuilder;
use ty_param::{TyParamBoundBuilder, PolyTraitRefBuilder, TraitTyParamBoundBuilder};

//////////////////////////////////////////////////////////////////////////////

pub struct WherePredicateBuilder<F=Identity> {
    callback: F,
    span: Span,
}

impl WherePredicateBuilder {
    pub fn new() -> Self {
        WherePredicateBuilder::with_callback(Identity)
    }
}

impl<F> WherePredicateBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    pub fn with_callback(callback: F) -> Self {
        WherePredicateBuilder {
            callback: callback,
            span: DUMMY_SP,
        }
    }

    pub fn span(mut self, span: Span) -> Self {
        self.span = span;
        self
    }

    pub fn bound(self) -> TyBuilder<Self> {
        TyBuilder::with_callback(self)
    }

    pub fn lifetime<L>(self, lifetime: L) -> WhereRegionPredicateBuilder<F>
        where L: IntoLifetime,
    {
        WhereRegionPredicateBuilder {
            callback: self.callback,
            span: self.span,
            lifetime: lifetime.into_lifetime(),
            bounds: Vec::new(),
        }
    }

    pub fn eq<P>(self, path: P) -> WhereEqPredicateBuilder<F>
        where P: IntoPath,
    {
        WhereEqPredicateBuilder {
            callback: self.callback,
            span: self.span,
            path: path.into_path(),
        }
    }
}

impl<F> Invoke<P<ast::Ty>> for WherePredicateBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    type Result = WhereBoundPredicateTyBuilder<F>;

    fn invoke(self, ty: P<ast::Ty>) -> Self::Result {
        WhereBoundPredicateTyBuilder {
            callback: self.callback,
            span: self.span,
            ty: ty,
            bound_lifetimes: Vec::new(),
            bounds: Vec::new(),
        }
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct WhereBoundPredicateBuilder<F> {
    callback: F,
    span: Span,
}

impl<F> Invoke<P<ast::Ty>> for WhereBoundPredicateBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    type Result = WhereBoundPredicateTyBuilder<F>;

    fn invoke(self, ty: P<ast::Ty>) -> Self::Result {
        WhereBoundPredicateTyBuilder {
            callback: self.callback,
            span: self.span,
            ty: ty,
            bound_lifetimes: Vec::new(),
            bounds: Vec::new(),
        }
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct WhereBoundPredicateTyBuilder<F> {
    callback: F,
    span: Span,
    ty: P<ast::Ty>,
    bound_lifetimes: Vec<ast::LifetimeDef>,
    bounds: Vec<ast::TyParamBound>,
}

impl<F> WhereBoundPredicateTyBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    pub fn with_for_lifetime<L>(mut self, lifetime: L) -> Self
        where L: IntoLifetimeDef,
    {
        self.bound_lifetimes.push(lifetime.into_lifetime_def());
        self
    }

    pub fn for_lifetime<N>(self, name: N) -> LifetimeDefBuilder<Self>
        where N: ToName,
    {
        LifetimeDefBuilder::with_callback(name, self)
    }

    pub fn with_bound(mut self, bound: ast::TyParamBound) -> Self {
        self.bounds.push(bound);
        self
    }

    pub fn bound(self) -> TyParamBoundBuilder<Self> {
        let span = self.span;
        TyParamBoundBuilder::with_callback(self).span(span)
    }

    pub fn trait_<P>(self, path: P)
        -> PolyTraitRefBuilder<TraitTyParamBoundBuilder<Self>>
        where P: IntoPath,
    {
        self.bound().trait_(path)
    }

    pub fn lifetime<L>(self, lifetime: L) -> Self
        where L: IntoLifetime,
    {
        self.bound().lifetime(lifetime)
    }

    pub fn build(self) -> F::Result {
        assert!(!self.bounds.is_empty());

        let WhereBoundPredicateTyBuilder {
            callback,
            span,
            ty,
            bound_lifetimes,
            bounds,
        } = self;

        let predicate = ast::WhereBoundPredicate {
            span: span,
            bound_lifetimes: bound_lifetimes,
            bounded_ty: ty,
            bounds: OwnedSlice::from_vec(bounds),
        };

        callback.invoke(ast::WherePredicate::BoundPredicate(predicate))
    }
}

impl<F> Invoke<ast::LifetimeDef> for WhereBoundPredicateTyBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    type Result = Self;

    fn invoke(self, lifetime: ast::LifetimeDef) -> Self {
        self.with_for_lifetime(lifetime)
    }
}

impl<F> Invoke<ast::TyParamBound> for WhereBoundPredicateTyBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    type Result = Self;

    fn invoke(self, bound: ast::TyParamBound) -> Self {
        self.with_bound(bound)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct WhereRegionPredicateBuilder<F> {
    callback: F,
    span: Span,
    lifetime: ast::Lifetime,
    bounds: Vec<ast::Lifetime>,
}

impl<F> WhereRegionPredicateBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    pub fn bound<L>(mut self, lifetime: L) -> Self
        where L: IntoLifetime,
    {
        self.bounds.push(lifetime.into_lifetime());
        self
    }

    pub fn build(self) -> F::Result {
        let WhereRegionPredicateBuilder {
            callback,
            span,
            lifetime,
            bounds,
        } = self;

        let predicate = ast::WhereRegionPredicate {
            span: span,
            lifetime: lifetime,
            bounds: bounds,
        };

        callback.invoke(ast::WherePredicate::RegionPredicate(predicate))
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct WhereEqPredicateBuilder<F> {
    callback: F,
    span: Span,
    path: ast::Path,
}

impl<F> WhereEqPredicateBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    pub fn ty(self) -> TyBuilder<Self> {
        TyBuilder::with_callback(self)
    }

    pub fn build_ty(self, ty: P<ast::Ty>) -> F::Result {
        let WhereEqPredicateBuilder { callback, span, path } = self;

        let predicate = ast::WhereEqPredicate {
            id: ast::DUMMY_NODE_ID,
            span: span,
            path: path,
            ty: ty,
        };

        callback.invoke(ast::WherePredicate::EqPredicate(predicate))
    }
}

impl<F> Invoke<P<ast::Ty>> for WhereEqPredicateBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    type Result = F::Result;

    fn invoke(self, ty: P<ast::Ty>) -> F::Result {
        self.build_ty(ty)
    }
}
<commit_msg>feat(predicates): Statically guarantee bounds are set<commit_after>use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::owned_slice::OwnedSlice;
use syntax::ptr::P;

use invoke::{Invoke, Identity};
use lifetime::{IntoLifetime, IntoLifetimeDef, LifetimeDefBuilder};
use name::ToName;
use path::IntoPath;
use ty::TyBuilder;
use ty_param::{TyParamBoundBuilder, PolyTraitRefBuilder, TraitTyParamBoundBuilder};

//////////////////////////////////////////////////////////////////////////////

pub struct WherePredicateBuilder<F=Identity> {
    callback: F,
    span: Span,
}

impl WherePredicateBuilder {
    pub fn new() -> Self {
        WherePredicateBuilder::with_callback(Identity)
    }
}

impl<F> WherePredicateBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    pub fn with_callback(callback: F) -> Self {
        WherePredicateBuilder {
            callback: callback,
            span: DUMMY_SP,
        }
    }

    pub fn span(mut self, span: Span) -> Self {
        self.span = span;
        self
    }

    pub fn bound(self) -> TyBuilder<Self> {
        TyBuilder::with_callback(self)
    }

    pub fn lifetime<L>(self, lifetime: L) -> WhereRegionPredicateBuilder<F>
        where L: IntoLifetime,
    {
        WhereRegionPredicateBuilder {
            callback: self.callback,
            span: self.span,
            lifetime: lifetime.into_lifetime(),
            bounds: Vec::new(),
        }
    }

    pub fn eq<P>(self, path: P) -> WhereEqPredicateBuilder<F>
        where P: IntoPath,
    {
        WhereEqPredicateBuilder {
            callback: self.callback,
            span: self.span,
            path: path.into_path(),
        }
    }
}

impl<F> Invoke<P<ast::Ty>> for WherePredicateBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    type Result = WhereBoundPredicateTyBuilder<F>;

    fn invoke(self, ty: P<ast::Ty>) -> Self::Result {
        WhereBoundPredicateTyBuilder {
            callback: self.callback,
            span: self.span,
            ty: ty,
            bound_lifetimes: Vec::new(),
        }
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct WhereBoundPredicateBuilder<F> {
    callback: F,
    span: Span,
}

impl<F> Invoke<P<ast::Ty>> for WhereBoundPredicateBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    type Result = WhereBoundPredicateTyBuilder<F>;

    fn invoke(self, ty: P<ast::Ty>) -> Self::Result {
        WhereBoundPredicateTyBuilder {
            callback: self.callback,
            span: self.span,
            ty: ty,
            bound_lifetimes: Vec::new(),
        }
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct WhereBoundPredicateTyBuilder<F> {
    callback: F,
    span: Span,
    ty: P<ast::Ty>,
    bound_lifetimes: Vec<ast::LifetimeDef>,
}

impl<F> WhereBoundPredicateTyBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    pub fn with_for_lifetime<L>(mut self, lifetime: L) -> Self
        where L: IntoLifetimeDef,
    {
        self.bound_lifetimes.push(lifetime.into_lifetime_def());
        self
    }

    pub fn for_lifetime<N>(self, name: N) -> LifetimeDefBuilder<Self>
        where N: ToName,
    {
        LifetimeDefBuilder::with_callback(name, self)
    }

    pub fn with_bound(self, bound: ast::TyParamBound) -> WhereBoundPredicateTyBoundsBuilder<F> {
        WhereBoundPredicateTyBoundsBuilder {
            callback: self.callback,
            span: self.span,
            ty: self.ty,
            bound_lifetimes: self.bound_lifetimes,
            bounds: vec![bound],
        }
    }

    pub fn bound(self) -> TyParamBoundBuilder<WhereBoundPredicateTyBoundsBuilder<F>> {
        let span = self.span;
        let builder = WhereBoundPredicateTyBoundsBuilder {
            callback: self.callback,
            span: self.span,
            ty: self.ty,
            bound_lifetimes: self.bound_lifetimes,
            bounds: vec![],
        };
        TyParamBoundBuilder::with_callback(builder).span(span)
    }

    pub fn trait_<P>(self, path: P)
        -> PolyTraitRefBuilder<
            TraitTyParamBoundBuilder<
                WhereBoundPredicateTyBoundsBuilder<F>
            >
        >
        where P: IntoPath,
    {
        self.bound().trait_(path)
    }

    pub fn lifetime<L>(self, lifetime: L) -> WhereBoundPredicateTyBoundsBuilder<F>
        where L: IntoLifetime,
    {
        self.bound().lifetime(lifetime)
    }
}

impl<F> Invoke<ast::LifetimeDef> for WhereBoundPredicateTyBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    type Result = Self;

    fn invoke(self, lifetime: ast::LifetimeDef) -> Self {
        self.with_for_lifetime(lifetime)
    }
}

impl<F> Invoke<ast::TyParamBound> for WhereBoundPredicateTyBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    type Result = WhereBoundPredicateTyBoundsBuilder<F>;

    fn invoke(self, bound: ast::TyParamBound) -> Self::Result {
        self.with_bound(bound)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct WhereBoundPredicateTyBoundsBuilder<F> {
    callback: F,
    span: Span,
    ty: P<ast::Ty>,
    bound_lifetimes: Vec<ast::LifetimeDef>,
    bounds: Vec<ast::TyParamBound>,
}

impl<F> WhereBoundPredicateTyBoundsBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    pub fn with_for_lifetime<L>(mut self, lifetime: L) -> Self
        where L: IntoLifetimeDef,
    {
        self.bound_lifetimes.push(lifetime.into_lifetime_def());
        self
    }

    pub fn for_lifetime<N>(self, name: N) -> LifetimeDefBuilder<Self>
        where N: ToName,
    {
        LifetimeDefBuilder::with_callback(name, self)
    }

    pub fn with_bound(mut self, bound: ast::TyParamBound) -> Self {
        self.bounds.push(bound);
        self
    }

    pub fn bound(self) -> TyParamBoundBuilder<Self> {
        let span = self.span;
        TyParamBoundBuilder::with_callback(self).span(span)
    }

    pub fn trait_<P>(self, path: P)
        -> PolyTraitRefBuilder<TraitTyParamBoundBuilder<Self>>
        where P: IntoPath,
    {
        self.bound().trait_(path)
    }

    pub fn lifetime<L>(self, lifetime: L) -> Self
        where L: IntoLifetime,
    {
        self.bound().lifetime(lifetime)
    }

    pub fn build(self) -> F::Result {
        let predicate = ast::WhereBoundPredicate {
            span: self.span,
            bound_lifetimes: self.bound_lifetimes,
            bounded_ty: self.ty,
            bounds: OwnedSlice::from_vec(self.bounds),
        };

        self.callback.invoke(ast::WherePredicate::BoundPredicate(predicate))
    }
}

impl<F> Invoke<ast::LifetimeDef> for WhereBoundPredicateTyBoundsBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    type Result = Self;

    fn invoke(self, lifetime: ast::LifetimeDef) -> Self {
        self.with_for_lifetime(lifetime)
    }
}

impl<F> Invoke<ast::TyParamBound> for WhereBoundPredicateTyBoundsBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    type Result = Self;

    fn invoke(self, bound: ast::TyParamBound) -> Self {
        self.with_bound(bound)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct WhereRegionPredicateBuilder<F> {
    callback: F,
    span: Span,
    lifetime: ast::Lifetime,
    bounds: Vec<ast::Lifetime>,
}

impl<F> WhereRegionPredicateBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    pub fn bound<L>(mut self, lifetime: L) -> Self
        where L: IntoLifetime,
    {
        self.bounds.push(lifetime.into_lifetime());
        self
    }

    pub fn build(self) -> F::Result {
        let predicate = ast::WhereRegionPredicate {
            span: self.span,
            lifetime: self.lifetime,
            bounds: self.bounds,
        };

        self.callback.invoke(ast::WherePredicate::RegionPredicate(predicate))
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct WhereEqPredicateBuilder<F> {
    callback: F,
    span: Span,
    path: ast::Path,
}

impl<F> WhereEqPredicateBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    pub fn ty(self) -> TyBuilder<Self> {
        TyBuilder::with_callback(self)
    }

    pub fn build_ty(self, ty: P<ast::Ty>) -> F::Result {
        let WhereEqPredicateBuilder { callback, span, path } = self;

        let predicate = ast::WhereEqPredicate {
            id: ast::DUMMY_NODE_ID,
            span: span,
            path: path,
            ty: ty,
        };

        callback.invoke(ast::WherePredicate::EqPredicate(predicate))
    }
}

impl<F> Invoke<P<ast::Ty>> for WhereEqPredicateBuilder<F>
    where F: Invoke<ast::WherePredicate>,
{
    type Result = F::Result;

    fn invoke(self, ty: P<ast::Ty>) -> F::Result {
        self.build_ty(ty)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2016 Robert Clipsham <robert@octarineparrot.com>
//
// 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.

//! Support for sending and receiving data link layer packets.

extern crate ipnetwork;
extern crate libc;
extern crate pnet_base;
extern crate pnet_sys;

use std::io;
use std::option::Option;
use std::time::Duration;

use ipnetwork::IpNetwork;

pub use pnet_base::{MacAddr, ParseMacAddrErr};

mod bindings;

#[cfg(windows)]
#[path = "winpcap.rs"]
mod backend;

#[cfg(windows)]
pub mod winpcap;

#[cfg(all(
    not(feature = "netmap"),
    any(target_os = "linux", target_os = "android")
))]
#[path = "linux.rs"]
mod backend;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod linux;

#[cfg(all(
    not(feature = "netmap"),
    any(target_os = "freebsd", target_os = "openbsd", target_os = "macos")
))]
#[path = "bpf.rs"]
mod backend;

#[cfg(any(target_os = "freebsd", target_os = "macos"))]
pub mod bpf;

#[cfg(feature = "netmap")]
#[path = "netmap.rs"]
mod backend;

#[cfg(feature = "netmap")]
pub mod netmap;

#[cfg(feature = "pcap")]
pub mod pcap;

pub mod dummy;

/// Type alias for an `EtherType`.
pub type EtherType = u16;

/// Type of data link channel to present (Linux only).
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum ChannelType {
    /// Send and receive layer 2 packets directly, including headers.
    Layer2,
    /// Send and receive "cooked" packets - send and receive network layer packets.
    Layer3(EtherType),
}

/// A channel for sending and receiving at the data link layer.
///
/// NOTE: It is important to always include a catch-all variant in match statements using this
/// enum, since new variants may be added. For example:
///
/// ```ignore
/// match some_channel {
///     Ethernet(tx, rx) => { /* Handle Ethernet packets */ },
///     _ => panic!("Unhandled channel type")
/// }
/// ```
pub enum Channel {
    /// A datalink channel which sends and receives Ethernet packets.
    Ethernet(Box<dyn DataLinkSender>, Box<dyn DataLinkReceiver>),

    /// This variant should never be used.
    ///
    /// Including it allows new variants to be added to `Channel` without breaking existing code.
    PleaseIncludeACatchAllVariantWhenMatchingOnThisEnum,
}

/// Socket fanout type (Linux only).
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum FanoutType {
    HASH,
    LB,
    CPU,
    ROLLOVER,
    RND,
    QM,
    CBPF,
    EBPF,
}

/// Fanout settings (Linux only).
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct FanoutOption {
    pub group_id: u16,
    pub fanout_type: FanoutType,
    pub defrag: bool,
    pub rollover: bool,
}

/// A generic configuration type, encapsulating all options supported by each backend.
///
/// Each option should be treated as a hint - each backend is free to ignore any and all
/// options which don't apply to it.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Config {
    /// The size of buffer to use when writing packets. Defaults to 4096.
    pub write_buffer_size: usize,

    /// The size of buffer to use when reading packets. Defaults to 4096.
    pub read_buffer_size: usize,

    /// Linux/BPF/Netmap only: The read timeout. Defaults to None.
    pub read_timeout: Option<Duration>,

    /// Linux/BPF/Netmap only: The write timeout. Defaults to None.
    pub write_timeout: Option<Duration>,

    /// Linux only: Specifies whether to read packets at the datalink layer or network layer.
    /// Defaults to Layer2
    pub channel_type: ChannelType,

    /// BPF/OS X only: The number of /dev/bpf* file descriptors to attempt before failing. Defaults
    /// to: 1000.
    pub bpf_fd_attempts: usize,

    pub linux_fanout: Option<FanoutOption>,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            write_buffer_size: 4096,
            read_buffer_size: 4096,
            read_timeout: None,
            write_timeout: None,
            channel_type: ChannelType::Layer2,
            bpf_fd_attempts: 1000,
            linux_fanout: None,
        }
    }
}

/// Create a new datalink channel for sending and receiving data.
///
/// This allows for sending and receiving packets at the data link layer.
///
/// A list of network interfaces can be retrieved using datalink::interfaces().
///
/// The configuration serves as a hint to the backend - some or all of it may be used or ignored,
/// depending on which backend is used.
///
/// When matching on the returned channel, make sure to include a catch-all so that code doesn't
/// break when new channel types are added.
#[inline]
pub fn channel(network_interface: &NetworkInterface, configuration: Config) -> io::Result<Channel> {
    backend::channel(network_interface, (&configuration).into())
}

/// Trait to enable sending `$packet` packets.
pub trait DataLinkSender: Send {
    /// Create and send a number of packets.
    ///
    /// This will call `func` `num_packets` times. The function will be provided with a
    /// mutable packet to manipulate, which will then be sent. This allows packets to be
    /// built in-place, avoiding the copy required for `send`. If there is not sufficient
    /// capacity in the buffer, None will be returned.
    fn build_and_send(
        &mut self,
        num_packets: usize,
        packet_size: usize,
        func: &mut dyn FnMut(&mut [u8]),
    ) -> Option<io::Result<()>>;

    /// Send a packet.
    ///
    /// This may require an additional copy compared to `build_and_send`, depending on the
    /// operating system being used. The second parameter is currently ignored, however
    /// `None` should be passed.
    fn send_to(&mut self, packet: &[u8], dst: Option<NetworkInterface>) -> Option<io::Result<()>>;
}

/// Structure for receiving packets at the data link layer. Should be constructed using
/// `datalink_channel()`.
pub trait DataLinkReceiver: Send {
    /// Get the next ethernet frame in the channel.
    fn next(&mut self) -> io::Result<&[u8]>;
}

/// Represents a network interface and its associated addresses.
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct NetworkInterface {
    /// The name of the interface.
    pub name: String,
    /// The interface index (operating system specific).
    pub index: u32,
    /// A MAC address for the interface.
    pub mac: Option<MacAddr>,
    /// IP addresses and netmasks for the interface.
    pub ips: Vec<IpNetwork>,
    /// Operating system specific flags for the interface.
    pub flags: u32,
}

impl NetworkInterface {
    /// Retrieve the MAC address associated with the interface.
    pub fn mac_address(&self) -> MacAddr {
        self.mac.unwrap()
    }

    pub fn is_up(&self) -> bool {
        self.flags & (pnet_sys::IFF_UP as u32) != 0
    }
    pub fn is_broadcast(&self) -> bool {
        self.flags & (pnet_sys::IFF_BROADCAST as u32) != 0
    }
    /// Is the interface a loopback interface?
    pub fn is_loopback(&self) -> bool {
        self.flags & (pnet_sys::IFF_LOOPBACK as u32) != 0
    }
    pub fn is_point_to_point(&self) -> bool {
        self.flags & (pnet_sys::IFF_POINTOPOINT as u32) != 0
    }
    pub fn is_multicast(&self) -> bool {
        self.flags & (pnet_sys::IFF_MULTICAST as u32) != 0
    }
}

impl ::std::fmt::Display for NetworkInterface {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        const FLAGS: [&'static str; 5] =
            ["UP", "BROADCAST", "LOOPBACK", "POINTOPOINT", "MULTICAST"];
        let flags = if self.flags > 0 {
            let rets = [
                self.is_up(),
                self.is_broadcast(),
                self.is_loopback(),
                self.is_point_to_point(),
                self.is_multicast(),
            ];
            format!(
                "{:X}<{}>",
                self.flags,
                rets.iter()
                    .zip(FLAGS.iter())
                    .filter(|&(ret, _)| ret == &true)
                    .map(|(_, name)| name.to_string())
                    .collect::<Vec<String>>()
                    .join(",")
            )
        } else {
            format!("{:X}", self.flags)
        };

        let mac = self
            .mac
            .map(|mac| mac.to_string())
            .unwrap_or("N/A".to_owned());
        let ips = if self.ips.len() > 0 {
            format!(
                "\n{}",
                self.ips
                    .iter()
                    .map(|ip| {
                        if ip.is_ipv4() {
                            format!("       inet: {}", ip)
                        } else {
                            format!("      inet6: {}", ip)
                        }
                    })
                    .collect::<Vec<String>>()
                    .join("\n")
            )
        } else {
            "".to_string()
        };

        write!(
            f,
            "{}: flags={}
      index: {}
      ether: {}{}",
            self.name, flags, self.index, mac, ips
        )
    }
}

/// Get a list of available network interfaces for the current machine.
///
/// If you need the default network interface, you can choose the first
/// one that is up, not loopback and has an IP. This is not guaranteed to
/// work on each system but should work for basic packet sniffing:
///
/// ```
/// use pnet_datalink::interfaces;
///
/// // Get a vector with all network interfaces found
/// let all_interfaces = interfaces();
///
/// // Search for the default interface - the one that is
/// // up, not loopback and has an IP.
/// let default_interface = all_interfaces
///     .iter()
///     .filter(|e| e.is_up() && !e.is_loopback() && e.ips.len() > 0)
///     .next();
///
/// match default_interface {
///     Some(interface) => println!("Found default interface with [{}].", interface.name),
///     None => println!("Error while finding the default interface."),
/// }
///
/// ```
///
pub fn interfaces() -> Vec<NetworkInterface> {
    backend::interfaces()
}
<commit_msg>deprecate mac_address() since it uses unwrap().  Suggest to use NetworkInterface.mac field instead.<commit_after>// Copyright (c) 2014-2016 Robert Clipsham <robert@octarineparrot.com>
//
// 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.

//! Support for sending and receiving data link layer packets.

extern crate ipnetwork;
extern crate libc;
extern crate pnet_base;
extern crate pnet_sys;

use std::io;
use std::option::Option;
use std::time::Duration;

use ipnetwork::IpNetwork;

pub use pnet_base::{MacAddr, ParseMacAddrErr};

mod bindings;

#[cfg(windows)]
#[path = "winpcap.rs"]
mod backend;

#[cfg(windows)]
pub mod winpcap;

#[cfg(all(
    not(feature = "netmap"),
    any(target_os = "linux", target_os = "android")
))]
#[path = "linux.rs"]
mod backend;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod linux;

#[cfg(all(
    not(feature = "netmap"),
    any(target_os = "freebsd", target_os = "openbsd", target_os = "macos")
))]
#[path = "bpf.rs"]
mod backend;

#[cfg(any(target_os = "freebsd", target_os = "macos"))]
pub mod bpf;

#[cfg(feature = "netmap")]
#[path = "netmap.rs"]
mod backend;

#[cfg(feature = "netmap")]
pub mod netmap;

#[cfg(feature = "pcap")]
pub mod pcap;

pub mod dummy;

/// Type alias for an `EtherType`.
pub type EtherType = u16;

/// Type of data link channel to present (Linux only).
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum ChannelType {
    /// Send and receive layer 2 packets directly, including headers.
    Layer2,
    /// Send and receive "cooked" packets - send and receive network layer packets.
    Layer3(EtherType),
}

/// A channel for sending and receiving at the data link layer.
///
/// NOTE: It is important to always include a catch-all variant in match statements using this
/// enum, since new variants may be added. For example:
///
/// ```ignore
/// match some_channel {
///     Ethernet(tx, rx) => { /* Handle Ethernet packets */ },
///     _ => panic!("Unhandled channel type")
/// }
/// ```
pub enum Channel {
    /// A datalink channel which sends and receives Ethernet packets.
    Ethernet(Box<dyn DataLinkSender>, Box<dyn DataLinkReceiver>),

    /// This variant should never be used.
    ///
    /// Including it allows new variants to be added to `Channel` without breaking existing code.
    PleaseIncludeACatchAllVariantWhenMatchingOnThisEnum,
}

/// Socket fanout type (Linux only).
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum FanoutType {
    HASH,
    LB,
    CPU,
    ROLLOVER,
    RND,
    QM,
    CBPF,
    EBPF,
}

/// Fanout settings (Linux only).
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct FanoutOption {
    pub group_id: u16,
    pub fanout_type: FanoutType,
    pub defrag: bool,
    pub rollover: bool,
}

/// A generic configuration type, encapsulating all options supported by each backend.
///
/// Each option should be treated as a hint - each backend is free to ignore any and all
/// options which don't apply to it.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Config {
    /// The size of buffer to use when writing packets. Defaults to 4096.
    pub write_buffer_size: usize,

    /// The size of buffer to use when reading packets. Defaults to 4096.
    pub read_buffer_size: usize,

    /// Linux/BPF/Netmap only: The read timeout. Defaults to None.
    pub read_timeout: Option<Duration>,

    /// Linux/BPF/Netmap only: The write timeout. Defaults to None.
    pub write_timeout: Option<Duration>,

    /// Linux only: Specifies whether to read packets at the datalink layer or network layer.
    /// Defaults to Layer2
    pub channel_type: ChannelType,

    /// BPF/OS X only: The number of /dev/bpf* file descriptors to attempt before failing. Defaults
    /// to: 1000.
    pub bpf_fd_attempts: usize,

    pub linux_fanout: Option<FanoutOption>,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            write_buffer_size: 4096,
            read_buffer_size: 4096,
            read_timeout: None,
            write_timeout: None,
            channel_type: ChannelType::Layer2,
            bpf_fd_attempts: 1000,
            linux_fanout: None,
        }
    }
}

/// Create a new datalink channel for sending and receiving data.
///
/// This allows for sending and receiving packets at the data link layer.
///
/// A list of network interfaces can be retrieved using datalink::interfaces().
///
/// The configuration serves as a hint to the backend - some or all of it may be used or ignored,
/// depending on which backend is used.
///
/// When matching on the returned channel, make sure to include a catch-all so that code doesn't
/// break when new channel types are added.
#[inline]
pub fn channel(network_interface: &NetworkInterface, configuration: Config) -> io::Result<Channel> {
    backend::channel(network_interface, (&configuration).into())
}

/// Trait to enable sending `$packet` packets.
pub trait DataLinkSender: Send {
    /// Create and send a number of packets.
    ///
    /// This will call `func` `num_packets` times. The function will be provided with a
    /// mutable packet to manipulate, which will then be sent. This allows packets to be
    /// built in-place, avoiding the copy required for `send`. If there is not sufficient
    /// capacity in the buffer, None will be returned.
    fn build_and_send(
        &mut self,
        num_packets: usize,
        packet_size: usize,
        func: &mut dyn FnMut(&mut [u8]),
    ) -> Option<io::Result<()>>;

    /// Send a packet.
    ///
    /// This may require an additional copy compared to `build_and_send`, depending on the
    /// operating system being used. The second parameter is currently ignored, however
    /// `None` should be passed.
    fn send_to(&mut self, packet: &[u8], dst: Option<NetworkInterface>) -> Option<io::Result<()>>;
}

/// Structure for receiving packets at the data link layer. Should be constructed using
/// `datalink_channel()`.
pub trait DataLinkReceiver: Send {
    /// Get the next ethernet frame in the channel.
    fn next(&mut self) -> io::Result<&[u8]>;
}

/// Represents a network interface and its associated addresses.
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct NetworkInterface {
    /// The name of the interface.
    pub name: String,
    /// The interface index (operating system specific).
    pub index: u32,
    /// A MAC address for the interface.
    pub mac: Option<MacAddr>,
    /// IP addresses and netmasks for the interface.
    pub ips: Vec<IpNetwork>,
    /// Operating system specific flags for the interface.
    pub flags: u32,
}

impl NetworkInterface {
    /// Retrieve the MAC address associated with the interface.
    #[deprecated(
        since = "0.26.0",
        note = "Please use NetworkInterface's field 'mac' instead."
    )]
    pub fn mac_address(&self) -> MacAddr {
        self.mac.unwrap()
    }

    pub fn is_up(&self) -> bool {
        self.flags & (pnet_sys::IFF_UP as u32) != 0
    }
    pub fn is_broadcast(&self) -> bool {
        self.flags & (pnet_sys::IFF_BROADCAST as u32) != 0
    }
    /// Is the interface a loopback interface?
    pub fn is_loopback(&self) -> bool {
        self.flags & (pnet_sys::IFF_LOOPBACK as u32) != 0
    }
    pub fn is_point_to_point(&self) -> bool {
        self.flags & (pnet_sys::IFF_POINTOPOINT as u32) != 0
    }
    pub fn is_multicast(&self) -> bool {
        self.flags & (pnet_sys::IFF_MULTICAST as u32) != 0
    }
}

impl ::std::fmt::Display for NetworkInterface {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        const FLAGS: [&'static str; 5] =
            ["UP", "BROADCAST", "LOOPBACK", "POINTOPOINT", "MULTICAST"];
        let flags = if self.flags > 0 {
            let rets = [
                self.is_up(),
                self.is_broadcast(),
                self.is_loopback(),
                self.is_point_to_point(),
                self.is_multicast(),
            ];
            format!(
                "{:X}<{}>",
                self.flags,
                rets.iter()
                    .zip(FLAGS.iter())
                    .filter(|&(ret, _)| ret == &true)
                    .map(|(_, name)| name.to_string())
                    .collect::<Vec<String>>()
                    .join(",")
            )
        } else {
            format!("{:X}", self.flags)
        };

        let mac = self
            .mac
            .map(|mac| mac.to_string())
            .unwrap_or("N/A".to_owned());
        let ips = if self.ips.len() > 0 {
            format!(
                "\n{}",
                self.ips
                    .iter()
                    .map(|ip| {
                        if ip.is_ipv4() {
                            format!("       inet: {}", ip)
                        } else {
                            format!("      inet6: {}", ip)
                        }
                    })
                    .collect::<Vec<String>>()
                    .join("\n")
            )
        } else {
            "".to_string()
        };

        write!(
            f,
            "{}: flags={}
      index: {}
      ether: {}{}",
            self.name, flags, self.index, mac, ips
        )
    }
}

/// Get a list of available network interfaces for the current machine.
///
/// If you need the default network interface, you can choose the first
/// one that is up, not loopback and has an IP. This is not guaranteed to
/// work on each system but should work for basic packet sniffing:
///
/// ```
/// use pnet_datalink::interfaces;
///
/// // Get a vector with all network interfaces found
/// let all_interfaces = interfaces();
///
/// // Search for the default interface - the one that is
/// // up, not loopback and has an IP.
/// let default_interface = all_interfaces
///     .iter()
///     .filter(|e| e.is_up() && !e.is_loopback() && e.ips.len() > 0)
///     .next();
///
/// match default_interface {
///     Some(interface) => println!("Found default interface with [{}].", interface.name),
///     None => println!("Error while finding the default interface."),
/// }
///
/// ```
///
pub fn interfaces() -> Vec<NetworkInterface> {
    backend::interfaces()
}
<|endoftext|>


<commit_before>use std::{mem, slice};
use allocator::*;

use super::entry_location::*;

#[derive(Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum EntryType {
    Alias = 0xA,
    Entry,
    Deleted,
}

#[repr(C)]
pub struct ByteStringEntryAlias {
    entry_type: EntryType,
    num_segments: usize,
    // sizeof(EntryLocation) * num_segments
}

#[repr(C)]
pub struct ByteStringEntry {
    entry_type: EntryType,
    data_size: usize,
    // data_size bytes of data
}

/// Decrement the ref count for the given byte string
/// Follow aliases to release all their byte strings
pub fn release_byte_string(entry: &EntryLocation, pool: &Pool) {
    match get_entry_type(entry, pool) {
        EntryType::Entry => {
            pool.release(entry.page_index);
        },
        EntryType::Deleted => {},
        EntryType::Alias => {
            for e in get_aliased_entries(entry, pool) {
                release_byte_string(e, pool);
            }
            // Once we've followed and release all the aliased
            // strings, release this alias.
            pool.release(entry.page_index);
        }
    }
}

/// Get the type of the entry pointed to by the location
fn get_entry_type(entry: &EntryLocation, pool: &Pool) -> EntryType {
    pool[entry.page_index]
        .transmute_segment::<EntryType>(entry.offset)
        .clone()
}

/// Returns a slice of the entries which are aliased by the given entry
pub fn get_aliased_entries<'a>(entry: &EntryLocation, pool: &'a Pool) -> &'a[EntryLocation] {
    let header: &ByteStringEntryAlias = pool[entry.page_index]
        .transmute_segment(entry.offset);
    assert_eq!(EntryType::Alias, header.entry_type);

    let start = entry.offset + mem::size_of::<ByteStringEntryAlias>();
    let start_ptr: *const u8 = &pool[entry.page_index][start];

    unsafe {
        let start_ptr: *const EntryLocation = mem::transmute(start_ptr);
        slice::from_raw_parts(start_ptr, header.num_segments)
    }
}

/// Treates the entry location as a ByteStringEntry
/// Panics if not given the correct entry
pub fn get_slice<'a>(entry: &EntryLocation, pool: &'a Pool) -> &'a[u8] {
    let header: &ByteStringEntry = pool[entry.page_index]
        .transmute_segment(entry.offset);
    assert_eq!(EntryType::Entry, header.entry_type);

    let start = entry.offset + mem::size_of::<ByteStringEntry>();
    &pool[entry.page_index][start..start+header.data_size]
}

/// Treates the entry location as a ByteStringEntry
/// Panics if not given the correct entry
pub fn get_slice_mut<'a>(entry: &EntryLocation, pool: &'a Pool) -> &'a mut [u8] {
    let header: &ByteStringEntry = pool[entry.page_index]
        .transmute_segment(entry.offset);
    assert_eq!(EntryType::Entry, header.entry_type);

    let start = entry.offset + mem::size_of::<ByteStringEntry>();

    let page: &mut Page = pool[entry.page_index].borrow_mut();
    &mut page[start..start+header.data_size]
}

/// ITERATION
/// Provides byte string iters

pub struct ByteStringIter<'a> {
    entry: &'a EntryLocation,
    pool: &'a Pool,

    is_aliased: bool,
    current_page: &'a Page,
    curent_entry: &'a EntryLocation,
    current_string: &'a ByteStringEntry,
    alias_index: usize,
    byte_index: usize,
}

impl <'a> Iterator for ByteStringIter<'a> {
    type Item = &'a u8;

    fn next(&mut self) -> Option<&'a u8> {
        let current_byte = &self.current_page
            [self.current_entry.offset+self.byte_index];

        // Increment our count, and roll over if necessary
        self.byte_index += 1;
        if self.byte_index >= self.current_entry.data_size {
            if self.is_aliased {
                self.alias_index += 1;
                let entries = get_aliased_entries(self.entry, self.pool);
                if self.alias_index >= entries.len() {
                    return None
                }
                self.current_entry = &entries[self.alias_index];
                self.current_string = self.pool[self.current_entry.page_index]
                    .transmute_segment(self.current_entry.offset);
                self.byte_index = 0;
                self.current_page = self.pool[self.current_entry.page_index];
            } else {
                return None
            }
        }
        Some(current_byte)
    }
}
<commit_msg>Added test for iterator<commit_after>use std::{mem, slice};
use allocator::*;

use super::entry_location::*;

#[derive(Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum EntryType {
    Alias = 0xA,
    Entry,
    Deleted,
}

/// If the entry is an alias, contents_size is the number
/// of segments in the alias. If it's an entry, contents_size
/// represents the number of bytes in the entry.
#[derive(Clone, PartialEq, Debug)]
#[repr(C)]
pub struct ByteStringEntry {
    entry_type: EntryType,
    contents_size: usize,
    // contents_size bytes of data
}

/// Decrement the ref count for the given byte string
/// Follow aliases to release all their byte strings
pub fn release_byte_string(entry: &EntryLocation, pool: &Pool) {
    match get_entry_type(entry, pool) {
        EntryType::Entry => {
            pool.release(entry.page_index);
        },
        EntryType::Deleted => {},
        EntryType::Alias => {
            for e in get_aliased_entries(entry, pool) {
                release_byte_string(e, pool);
            }
            // Once we've followed and release all the aliased
            // strings, release this alias.
            pool.release(entry.page_index);
        }
    }
}

/// Get the type of the entry pointed to by the location
fn get_entry_type(entry: &EntryLocation, pool: &Pool) -> EntryType {
    pool[entry.page_index]
        .transmute_segment::<EntryType>(entry.offset)
        .clone()
}

/// Returns a slice of the entries which are aliased by the given entry
pub fn get_aliased_entries<'a>(entry: &EntryLocation, pool: &'a Pool) -> &'a[EntryLocation] {
    let header: &ByteStringEntry = pool[entry.page_index]
        .transmute_segment(entry.offset);
    assert_eq!(EntryType::Alias, header.entry_type);

    let start = entry.offset + mem::size_of::<ByteStringEntry>();
    let start_ptr: *const u8 = &pool[entry.page_index][start];

    unsafe {
        let start_ptr: *const EntryLocation = mem::transmute(start_ptr);
        slice::from_raw_parts(start_ptr, header.contents_size)
    }
}

/// Treates the entry location as a ByteStringEntry
/// Panics if not given the correct entry
pub fn get_slice<'a>(entry: &EntryLocation, pool: &'a Pool) -> &'a[u8] {
    let header: &ByteStringEntry = pool[entry.page_index]
        .transmute_segment(entry.offset);
    assert_eq!(EntryType::Entry, header.entry_type);

    let start = entry.offset + mem::size_of::<ByteStringEntry>();
    &pool[entry.page_index][start..start+header.contents_size]
}

/// Treates the entry location as a ByteStringEntry
/// Panics if not given the correct entry
pub fn get_slice_mut<'a>(entry: &EntryLocation, pool: &'a Pool) -> &'a mut [u8] {
    let header: &ByteStringEntry = pool[entry.page_index]
        .transmute_segment(entry.offset);
    assert_eq!(EntryType::Entry, header.entry_type);

    let start = entry.offset + mem::size_of::<ByteStringEntry>();

    let page: &mut Page = pool[entry.page_index].borrow_mut();
    &mut page[start..start+header.contents_size]
}

/// Get the iter over the memory represented by the bytestring
pub fn get_iter<'a>(entry: &'a EntryLocation, pool: &'a Pool) -> ByteStringIter<'a> {
    let page = &pool[entry.page_index];
    match get_entry_type(entry, pool) {
        EntryType::Entry => {
            ByteStringIter {
                entry: entry,
                pool: pool,

                is_aliased: false,
                current_page: page,
                current_entry: entry,
                current_string: pool[entry.page_index].transmute_segment(entry.offset),
                alias_index: 0,
                byte_index: 0,
            }
        },
        EntryType::Alias => {
            let first_entry = &get_aliased_entries(entry, pool)[0];
            ByteStringIter {
                entry: entry,
                pool: pool,

                is_aliased: true,
                current_page: page,
                current_entry: first_entry,
                current_string:  pool[first_entry.page_index].transmute_segment(first_entry.offset),
                alias_index: 0,
                byte_index: 0,
            }
        },
        EntryType::Deleted => {
            panic!("get_iter called on a deleted entry");
        },
    }
}

/// ITERATION
/// Provides byte string iters

pub struct ByteStringIter<'a> {
    entry: &'a EntryLocation,
    pool: &'a Pool,

    is_aliased: bool,
    current_page: &'a Page,
    current_entry: &'a EntryLocation,
    current_string: &'a ByteStringEntry,
    alias_index: usize,
    byte_index: usize,
}

impl <'a> Iterator for ByteStringIter<'a> {
    type Item = &'a u8;

    fn next(&mut self) -> Option<&'a u8> {
        let current_byte = &self.current_page
            [self.current_entry.offset+mem::size_of::<ByteStringEntry>()+self.byte_index];

        // Increment our count, and roll over if necessary
        self.byte_index += 1;
        println!("{}/{}", self.byte_index, self.current_string.contents_size);
        if self.byte_index >= self.current_string.contents_size {
            if self.is_aliased {
                self.alias_index += 1;
                let entries = get_aliased_entries(self.entry, self.pool);
                if self.alias_index >= entries.len() {
                    return None
                }
                self.current_entry = &entries[self.alias_index];
                self.current_string = self.pool[self.current_entry.page_index]
                    .transmute_segment(self.current_entry.offset);
                self.byte_index = 0;
                self.current_page = &self.pool[self.current_entry.page_index];
            } else {
                return None
            }
        }
        Some(current_byte)
    }
}

#[test]
fn test_get_slice_mut() {
    let mut buf = [0u8; 0x2000];
    let pool = Pool::new(&mut buf);

    let page_index = pool.alloc().unwrap();
    let mut p: &Page = &pool[page_index];
    let loc = EntryLocation {
        page_index: page_index,
        offset: 0,
    };

    let mut entry = p.transmute_page_mut::<ByteStringEntry>();
    entry.entry_type = EntryType::Entry;
    entry.contents_size = 10;

    // Init the data as a slice
    for iv in get_slice_mut(&loc, &pool).iter_mut().enumerate() {
        *iv.1 = iv.0 as u8;
    }

    // check the data via iterator
    get_iter(&loc, &pool).zip((0u8..)).fold(true, |b, actual_exp| {
        assert_eq!(*actual_exp.0, actual_exp.1);
        b && *actual_exp.0 == actual_exp.1
    });
}
<|endoftext|>


<commit_before>// run-pass
// pretty-expanded FIXME #23616

#![allow(warnings)]

use std::iter::{empty, once, repeat};

fn is_sync<T>(_: T) where T: Sync {}
fn is_send<T>(_: T) where T: Send {}

macro_rules! all_sync_send {
    ($ctor:expr, $iter:ident) => ({
        let mut x = $ctor;
        is_sync(x.$iter());
        let mut y = $ctor;
        is_send(y.$iter());
    });
    ($ctor:expr, $iter:ident($($param:expr),+)) => ({
        let mut x = $ctor;
        is_sync(x.$iter($( $param ),+));
        let mut y = $ctor;
        is_send(y.$iter($( $param ),+));
    });
    ($ctor:expr, $iter:ident, $($rest:tt)*) => ({
        all_sync_send!($ctor, $iter);
        all_sync_send!($ctor, $($rest)*);
    });
    ($ctor:expr, $iter:ident($($param:expr),+), $($rest:tt)*) => ({
        all_sync_send!($ctor, $iter($( $param ),+));
        all_sync_send!($ctor, $($rest)*);
    });
}

macro_rules! all_sync_send_mutable_ref {
    ($ctor:expr, $($iter:ident),+) => ({
        $(
            let mut x = $ctor;
            is_sync((&mut x).$iter());
            let mut y = $ctor;
            is_send((&mut y).$iter());
        )+
    })
}

macro_rules! is_sync_send {
    ($ctor:expr) => ({
        let x = $ctor;
        is_sync(x);
        let y = $ctor;
        is_send(y);
    })
}

fn main() {
    // for char.rs
    all_sync_send!("Я", escape_debug, escape_default, escape_unicode);

    // for iter.rs
    all_sync_send_mutable_ref!([1], iter);

    // Bytes implements DoubleEndedIterator
    all_sync_send!("a".bytes(), rev);

    let a = [1];
    let b = [2];
    all_sync_send!(a.iter(),
                   cloned,
                   cycle,
                   chain([2].iter()),
                   zip([2].iter()),
                   map(|_| 1),
                   filter(|_| true),
                   filter_map(|_| Some(1)),
                   enumerate,
                   peekable,
                   skip_while(|_| true),
                   take_while(|_| true),
                   skip(1),
                   take(1),
                   scan(1, |_, _| Some(1)),
                   flat_map(|_| b.iter()),
                   fuse,
                   inspect(|_| ()));

    is_sync_send!((1..).step_by(2));
    is_sync_send!((1..2).step_by(2));
    is_sync_send!((1..2));
    is_sync_send!((1..));
    is_sync_send!(repeat(1));
    is_sync_send!(empty::<usize>());
    is_sync_send!(once(1));

    // for option.rs
    // FIXME

    // for result.rs
    // FIXME

    // for slice.rs
    // FIXME

    // for str/mod.rs
    // FIXME
}
<commit_msg>Add a test for iter::empty::<*mut i32> being Sync and Send<commit_after>// run-pass
// pretty-expanded FIXME #23616

#![allow(warnings)]

use std::iter::{empty, once, repeat};

fn is_sync<T>(_: T) where T: Sync {}
fn is_send<T>(_: T) where T: Send {}

macro_rules! all_sync_send {
    ($ctor:expr, $iter:ident) => ({
        let mut x = $ctor;
        is_sync(x.$iter());
        let mut y = $ctor;
        is_send(y.$iter());
    });
    ($ctor:expr, $iter:ident($($param:expr),+)) => ({
        let mut x = $ctor;
        is_sync(x.$iter($( $param ),+));
        let mut y = $ctor;
        is_send(y.$iter($( $param ),+));
    });
    ($ctor:expr, $iter:ident, $($rest:tt)*) => ({
        all_sync_send!($ctor, $iter);
        all_sync_send!($ctor, $($rest)*);
    });
    ($ctor:expr, $iter:ident($($param:expr),+), $($rest:tt)*) => ({
        all_sync_send!($ctor, $iter($( $param ),+));
        all_sync_send!($ctor, $($rest)*);
    });
}

macro_rules! all_sync_send_mutable_ref {
    ($ctor:expr, $($iter:ident),+) => ({
        $(
            let mut x = $ctor;
            is_sync((&mut x).$iter());
            let mut y = $ctor;
            is_send((&mut y).$iter());
        )+
    })
}

macro_rules! is_sync_send {
    ($ctor:expr) => ({
        let x = $ctor;
        is_sync(x);
        let y = $ctor;
        is_send(y);
    })
}

fn main() {
    // for char.rs
    all_sync_send!("Я", escape_debug, escape_default, escape_unicode);

    // for iter.rs
    all_sync_send_mutable_ref!([1], iter);

    // Bytes implements DoubleEndedIterator
    all_sync_send!("a".bytes(), rev);

    let a = [1];
    let b = [2];
    all_sync_send!(a.iter(),
                   cloned,
                   cycle,
                   chain([2].iter()),
                   zip([2].iter()),
                   map(|_| 1),
                   filter(|_| true),
                   filter_map(|_| Some(1)),
                   enumerate,
                   peekable,
                   skip_while(|_| true),
                   take_while(|_| true),
                   skip(1),
                   take(1),
                   scan(1, |_, _| Some(1)),
                   flat_map(|_| b.iter()),
                   fuse,
                   inspect(|_| ()));

    is_sync_send!((1..).step_by(2));
    is_sync_send!((1..2).step_by(2));
    is_sync_send!((1..2));
    is_sync_send!((1..));
    is_sync_send!(repeat(1));
    is_sync_send!(empty::<usize>());
    is_sync_send!(empty::<*mut i32>());
    is_sync_send!(once(1));

    // for option.rs
    // FIXME

    // for result.rs
    // FIXME

    // for slice.rs
    // FIXME

    // for str/mod.rs
    // FIXME
}
<|endoftext|>


<commit_before>pub mod theon {
    #[doc(hidden)]
    pub use ::theon::*;
}

// Feature modules. These are empty unless Cargo features are enabled.
pub mod cgmath;
pub mod mint;
pub mod nalgebra;
<commit_msg>Document the `integration` module.<commit_after>//! Integration of external crates and foreign types.
//!
//! This module provides implementations of traits in Plexus for foreign types.
//! Integrated crates are re-exported within a sub-module, which can be used to
//! avoid versioning conflicts.
//!
//! Re-exported types are hidden in the documention for Plexus.

pub mod theon {
    #[doc(hidden)]
    pub use ::theon::*;
}

// Feature modules. These are empty unless Cargo features are enabled.
pub mod cgmath;
pub mod mint;
pub mod nalgebra;
<|endoftext|>