<commit_before>//! TODO Documentation

use std::{cell::Cell, rc::{Rc, Weak}, panic, ptr};

use libc::c_void;
use wlroots_sys::{wlr_xdg_popup, wlr_xdg_surface, wlr_xdg_surface_ping,
                  wlr_xdg_surface_role, wlr_xdg_surface_send_close,
                  wlr_xdg_surface_surface_at, wlr_xdg_toplevel,
                  wlr_xdg_toplevel_set_activated, wlr_xdg_toplevel_set_fullscreen,
                  wlr_xdg_toplevel_set_maximized, wlr_xdg_toplevel_set_resizing,
                  wlr_xdg_toplevel_set_size, wlr_xdg_toplevel_state,
                  wlr_xdg_surface_for_each_surface, wlr_surface};

use {area::Area,
     seat,
     surface,
     utils::{self, HandleErr, HandleResult, Handleable, c_to_rust_string}};
pub use manager::xdg_shell_handler::*;
pub(crate) use manager::xdg_shell_manager::Manager;
pub use events::xdg_shell_events as event;

pub mod manager {
    //! XDG shell resources are managed by the XDG shell resource manager.
    //!
    //! To manage XDG shells from clients implement a function with
    //! [`NewSurface`](./type.NewSurface.html) as the signature.
    //!
    //! Pass that function to the [`xdg_shell::Builder`](./struct.Builder.html)
    //! which is then passed to the `compositor::Builder`.
    pub use manager::xdg_shell_manager::*;
}

pub type Handle = utils::Handle<OptionalShellState, wlr_xdg_surface, Surface>;

/// A hack to ensure we can clone a shell handle.
#[derive(Debug, Eq, PartialEq, Hash)]
#[doc(hidden)]
pub struct OptionalShellState(Option<ShellState>);

/// Used internally to reclaim a handle from just a *mut wlr_xdg_surface.
pub(crate) struct SurfaceState {
    /// Pointer to the backing storage.
    pub(crate) shell: *mut XdgShell,
    handle: Weak<Cell<bool>>,
    shell_state: Option<ShellState>
}

impl Clone for OptionalShellState {
    fn clone(&self) -> Self {
        OptionalShellState ( match self.0 {
            None => None,
            // NOTE Rationale for safety:
            // This is only stored in the handle, and it's fine to clone
            // the raw pointer when we just have a handle.
            Some(ref state) => Some(unsafe { state.clone() })
        })
    }
}

#[derive(Debug, Eq, PartialEq, Hash)]
pub struct TopLevel {
    shell_surface: *mut wlr_xdg_surface,
    toplevel: *mut wlr_xdg_toplevel
}

#[derive(Debug, Eq, PartialEq, Hash)]
pub struct Popup {
    shell_surface: *mut wlr_xdg_surface,
    popup: *mut wlr_xdg_popup
}

/// A tagged enum of the different roles used by the xdg shell.
///
/// Uses the tag to disambiguate the union in `wlr_xdg_surface`.
#[derive(Debug, Eq, PartialEq, Hash)]
pub enum ShellState {
    TopLevel(TopLevel),
    Popup(Popup)
}

#[derive(Debug)]
pub struct Surface {
    liveliness: Rc<Cell<bool>>,
    state: Option<ShellState>,
    shell_surface: *mut wlr_xdg_surface
}

impl Surface {
    pub(crate) unsafe fn new<T>(shell_surface: *mut wlr_xdg_surface, state: T) -> Self
        where T: Into<Option<ShellState>>
    {
        let state = state.into();
        (*shell_surface).data = ptr::null_mut();
        let liveliness = Rc::new(Cell::new(false));
        let shell_state =
            Box::new(SurfaceState { shell: ptr::null_mut(),
                                    handle: Rc::downgrade(&liveliness),
                                    shell_state: match state {
                                        None => None,
                                        Some(ref state) => Some(state.clone())
                                    } });
        (*shell_surface).data = Box::into_raw(shell_state) as *mut _;
        Surface { liveliness,
                          state: state,
                          shell_surface }
    }

    /// Gets the surface used by this XDG shell.
    pub fn surface(&mut self) -> surface::Handle {
        unsafe {
            let surface = (*self.shell_surface).surface;
            if surface.is_null() {
                panic!("xdg shell had a null surface!")
            }
            surface::Handle::from_ptr(surface)
        }
    }

    /// Get the role of this XDG surface.
    pub fn role(&self) -> wlr_xdg_surface_role {
        unsafe { (*self.shell_surface).role }
    }

    pub fn state(&mut self) -> Option<&mut ShellState> {
        self.state.as_mut()
    }

    /// Determines if this XDG shell surface has been configured or not.
    pub fn configured(&self) -> bool {
        unsafe { (*self.shell_surface).configured }
    }

    pub fn added(&self) -> bool {
        unsafe { (*self.shell_surface).added }
    }

    pub fn configure_serial(&self) -> u32 {
        unsafe { (*self.shell_surface).configure_serial }
    }

    pub fn configure_next_serial(&self) -> u32 {
        unsafe { (*self.shell_surface).configure_next_serial }
    }

    pub fn has_next_geometry(&self) -> bool {
        unsafe { (*self.shell_surface).has_next_geometry }
    }

    pub fn next_geometry(&self) -> Area {
        unsafe { Area::from_box((*self.shell_surface).next_geometry) }
    }

    pub fn geometry(&self) -> Area {
        unsafe { Area::from_box((*self.shell_surface).geometry) }
    }

    /// Send a ping to the surface.
    ///
    /// If the surface does not respond with a pong within a reasonable amount of time,
    /// the ping timeout event will be emitted.
    pub fn ping(&mut self) {
        unsafe {
            wlr_xdg_surface_ping(self.shell_surface);
        }
    }

    /// Find a surface within this surface at the surface-local coordinates.
    ///
    /// Returns the popup and coordinates in the topmost surface coordinate system
    /// or None if no popup is found at that location.
    pub fn surface_at(&mut self,
                      sx: f64,
                      sy: f64,
                      sub_sx: &mut f64,
                      sub_sy: &mut f64)
                      -> Option<surface::Handle> {
        unsafe {
            let sub_surface =
                wlr_xdg_surface_surface_at(self.shell_surface, sx, sy, sub_sx, sub_sy);
            if sub_surface.is_null() {
                None
            } else {
                Some(surface::Handle::from_ptr(sub_surface))
            }
        }
    }

    pub fn for_each_surface<F>(&self, mut iterator: F)
            where F: FnMut(surface::Handle, i32, i32) {
        let mut iterator_ref: &mut FnMut(surface::Handle, i32, i32) = &mut iterator;
        unsafe {
            unsafe extern "C" fn c_iterator(wlr_surface: *mut wlr_surface, sx: i32, sy: i32, data: *mut c_void) {
                let iterator_fn = &mut *(data as *mut &mut FnMut(surface::Handle, i32, i32));
                let surface = surface::Handle::from_ptr(wlr_surface);
                iterator_fn(surface, sx, sy);
            }
            let iterator_ptr: *mut c_void = &mut iterator_ref as *mut _ as *mut c_void;
            wlr_xdg_surface_for_each_surface(self.shell_surface, Some(c_iterator), iterator_ptr);
        }
    }
}

impl Drop for Surface {
    fn drop(&mut self) {
        if Rc::strong_count(&self.liveliness) == 1 {
            wlr_log!(WLR_DEBUG, "Dropped xdg shell {:p}", self.shell_surface);
            let weak_count = Rc::weak_count(&self.liveliness);
            if weak_count > 0 {
                wlr_log!(WLR_DEBUG,
                         "Still {} weak pointers to xdg shell {:p}",
                         weak_count,
                         self.shell_surface);
            }
        } else {
            return
        }
        unsafe {
            let _ = Box::from_raw((*self.shell_surface).data as *mut SurfaceState);
        }
    }
}

impl Handleable<OptionalShellState, wlr_xdg_surface> for Surface {
    #[doc(hidden)]
    unsafe fn from_ptr(shell_surface: *mut wlr_xdg_surface) -> Self {
        let data = &mut *((*shell_surface).data as *mut SurfaceState);
        let state = match data.shell_state {
            None => None,
            Some(ref state) => Some(state.clone())
        };
        let liveliness = data.handle.upgrade().unwrap();
        Surface { liveliness,
                  state,
                  shell_surface }
    }

    #[doc(hidden)]
    unsafe fn as_ptr(&self) -> *mut wlr_xdg_surface {
        self.shell_surface
    }

    #[doc(hidden)]
    unsafe fn from_handle(handle: &Handle) -> HandleResult<Self> {
        let liveliness = handle.handle
            .upgrade()
            .ok_or_else(|| HandleErr::AlreadyDropped)?;
        Ok(Surface { liveliness,
                     shell_surface: handle.ptr,
                     state: handle.data.clone().0 })
    }

    fn weak_reference(&self) -> Handle {
        Handle { ptr: self.shell_surface,
                 handle: Rc::downgrade(&self.liveliness),
                 data: OptionalShellState(match self.state {
                     None => None,
                     Some(ref state) => Some(unsafe { state.clone() })
                 }),
                 _marker: std::marker::PhantomData }
    }
}

impl TopLevel {
    pub(crate) unsafe fn from_shell(shell_surface: *mut wlr_xdg_surface,
                                    toplevel: *mut wlr_xdg_toplevel)
                                    -> TopLevel {
        TopLevel { shell_surface,
                        toplevel }
    }

    /// Get the title associated with this XDG shell toplevel.
    pub fn title(&self) -> String {
        unsafe { c_to_rust_string((*self.toplevel).title).expect("Could not parse class as UTF-8") }
    }

    /// Get the app id associated with this XDG shell toplevel.
    pub fn app_id(&self) -> String {
        unsafe {
            c_to_rust_string((*self.toplevel).app_id).expect("Could not parse class as UTF-8")
        }
    }

    /// Get a handle to the base surface of the xdg tree.
    pub fn base(&self) -> Handle {
        unsafe { Handle::from_ptr((*self.toplevel).base) }
    }

    /// Get a handle to the parent surface of the xdg tree.
    pub fn parent(&self) -> Handle {
        unsafe { Handle::from_ptr((*self.toplevel).parent) }
    }

    pub fn added(&self) -> bool {
        unsafe { (*self.toplevel).added }
    }

    /// Get the pending client state.
    pub fn client_pending_state(&self) -> wlr_xdg_toplevel_state {
        unsafe { (*self.toplevel).client_pending }
    }

    /// Get the pending server state.
    pub fn server_pending_state(&self) -> wlr_xdg_toplevel_state {
        unsafe { (*self.toplevel).server_pending }
    }

    /// Get the current configure state.
    pub fn current_state(&self) -> wlr_xdg_toplevel_state {
        unsafe { (*self.toplevel).current }
    }

    /// Request that this toplevel surface be the given size.
    ///
    /// Returns the associated configure serial.
    pub fn set_size(&mut self, width: u32, height: u32) -> u32 {
        unsafe { wlr_xdg_toplevel_set_size(self.shell_surface, width, height) }
    }

    /// Request that this toplevel surface show itself in an activated or deactivated
    /// state.
    ///
    /// Returns the associated configure serial.
    pub fn set_activated(&mut self, activated: bool) -> u32 {
        unsafe { wlr_xdg_toplevel_set_activated(self.shell_surface, activated) }
    }

    /// Request that this toplevel surface consider itself maximized or not
    /// maximized.
    ///
    /// Returns the associated configure serial.
    pub fn set_maximized(&mut self, maximized: bool) -> u32 {
        unsafe { wlr_xdg_toplevel_set_maximized(self.shell_surface, maximized) }
    }

    /// Request that this toplevel surface consider itself fullscreen or not
    /// fullscreen.
    ///
    /// Returns the associated configure serial.
    pub fn set_fullscreen(&mut self, fullscreen: bool) -> u32 {
        unsafe { wlr_xdg_toplevel_set_fullscreen(self.shell_surface, fullscreen) }
    }

    /// Request that this toplevel surface consider itself to be resizing or not
    /// resizing.
    ///
    /// Returns the associated configure serial.
    pub fn set_resizing(&mut self, resizing: bool) -> u32 {
        unsafe { wlr_xdg_toplevel_set_resizing(self.shell_surface, resizing) }
    }

    /// Request that this toplevel surface closes.
    pub fn close(&mut self) {
        unsafe { wlr_xdg_surface_send_close(self.shell_surface) }
    }

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

impl Popup {
    pub(crate) unsafe fn from_shell(shell_surface: *mut wlr_xdg_surface,
                                    popup: *mut wlr_xdg_popup)
                                    -> Popup {
        Popup { shell_surface,
                   popup }
    }

    /// Get a handle to the base surface of the xdg tree.
    pub fn base(&self) -> Handle {
        unsafe { Handle::from_ptr((*self.popup).base) }
    }

    /// Get a handle to the parent surface of the xdg tree.
    pub fn parent(&self) -> surface::Handle {
        unsafe { surface::Handle::from_ptr((*self.popup).parent) }
    }

    pub fn committed(&self) -> bool {
        unsafe { (*self.popup).committed }
    }

    /// Get a handle to the seat associated with this popup.
    pub fn seat_handle(&self) -> Option<seat::Handle> {
        unsafe {
            let seat = (*self.popup).seat;
            if seat.is_null() {
                None
            } else {
                Some(seat::Handle::from_ptr(seat))
            }
        }
    }

    pub fn geometry(&self) -> Area {
        unsafe { Area::from_box((*self.popup).geometry) }
    }
}

impl ShellState {
    /// Unsafe copy of the pointer
    unsafe fn clone(&self) -> Self {
        match *self {
            ShellState::TopLevel(TopLevel { shell_surface,
                                     toplevel }) => {
                ShellState::TopLevel(TopLevel { shell_surface,
                                         toplevel })
            }
            ShellState::Popup(Popup { shell_surface,
                               popup }) => {
                ShellState::Popup(Popup { shell_surface,
                                   popup })
            }
        }
    }
}
<commit_msg>Replace xdg shell remove functions<commit_after>//! TODO Documentation

use std::{cell::Cell, rc::{Rc, Weak}, panic, ptr};

use libc::c_void;
use wlroots_sys::{wlr_xdg_popup, wlr_xdg_surface, wlr_xdg_surface_ping,
                  wlr_xdg_surface_role, wlr_xdg_toplevel_send_close,
                  wlr_xdg_popup_destroy, wlr_xdg_surface_surface_at,
                  wlr_xdg_toplevel, wlr_xdg_toplevel_set_activated,
                  wlr_xdg_toplevel_set_fullscreen, wlr_xdg_toplevel_set_maximized,
                  wlr_xdg_toplevel_set_resizing, wlr_xdg_toplevel_set_size,
                  wlr_xdg_toplevel_state, wlr_xdg_surface_for_each_surface, wlr_surface};

use {area::Area,
     seat,
     surface,
     utils::{self, HandleErr, HandleResult, Handleable, c_to_rust_string}};
pub use manager::xdg_shell_handler::*;
pub(crate) use manager::xdg_shell_manager::Manager;
pub use events::xdg_shell_events as event;

pub mod manager {
    //! XDG shell resources are managed by the XDG shell resource manager.
    //!
    //! To manage XDG shells from clients implement a function with
    //! [`NewSurface`](./type.NewSurface.html) as the signature.
    //!
    //! Pass that function to the [`xdg_shell::Builder`](./struct.Builder.html)
    //! which is then passed to the `compositor::Builder`.
    pub use manager::xdg_shell_manager::*;
}

pub type Handle = utils::Handle<OptionalShellState, wlr_xdg_surface, Surface>;

/// A hack to ensure we can clone a shell handle.
#[derive(Debug, Eq, PartialEq, Hash)]
#[doc(hidden)]
pub struct OptionalShellState(Option<ShellState>);

/// Used internally to reclaim a handle from just a *mut wlr_xdg_surface.
pub(crate) struct SurfaceState {
    /// Pointer to the backing storage.
    pub(crate) shell: *mut XdgShell,
    handle: Weak<Cell<bool>>,
    shell_state: Option<ShellState>
}

impl Clone for OptionalShellState {
    fn clone(&self) -> Self {
        OptionalShellState ( match self.0 {
            None => None,
            // NOTE Rationale for safety:
            // This is only stored in the handle, and it's fine to clone
            // the raw pointer when we just have a handle.
            Some(ref state) => Some(unsafe { state.clone() })
        })
    }
}

#[derive(Debug, Eq, PartialEq, Hash)]
pub struct TopLevel {
    shell_surface: *mut wlr_xdg_surface,
    toplevel: *mut wlr_xdg_toplevel
}

#[derive(Debug, Eq, PartialEq, Hash)]
pub struct Popup {
    shell_surface: *mut wlr_xdg_surface,
    popup: *mut wlr_xdg_popup
}

/// A tagged enum of the different roles used by the xdg shell.
///
/// Uses the tag to disambiguate the union in `wlr_xdg_surface`.
#[derive(Debug, Eq, PartialEq, Hash)]
pub enum ShellState {
    TopLevel(TopLevel),
    Popup(Popup)
}

#[derive(Debug)]
pub struct Surface {
    liveliness: Rc<Cell<bool>>,
    state: Option<ShellState>,
    shell_surface: *mut wlr_xdg_surface
}

impl Surface {
    pub(crate) unsafe fn new<T>(shell_surface: *mut wlr_xdg_surface, state: T) -> Self
        where T: Into<Option<ShellState>>
    {
        let state = state.into();
        (*shell_surface).data = ptr::null_mut();
        let liveliness = Rc::new(Cell::new(false));
        let shell_state =
            Box::new(SurfaceState { shell: ptr::null_mut(),
                                    handle: Rc::downgrade(&liveliness),
                                    shell_state: match state {
                                        None => None,
                                        Some(ref state) => Some(state.clone())
                                    } });
        (*shell_surface).data = Box::into_raw(shell_state) as *mut _;
        Surface { liveliness,
                          state: state,
                          shell_surface }
    }

    /// Gets the surface used by this XDG shell.
    pub fn surface(&mut self) -> surface::Handle {
        unsafe {
            let surface = (*self.shell_surface).surface;
            if surface.is_null() {
                panic!("xdg shell had a null surface!")
            }
            surface::Handle::from_ptr(surface)
        }
    }

    /// Get the role of this XDG surface.
    pub fn role(&self) -> wlr_xdg_surface_role {
        unsafe { (*self.shell_surface).role }
    }

    pub fn state(&mut self) -> Option<&mut ShellState> {
        self.state.as_mut()
    }

    /// Determines if this XDG shell surface has been configured or not.
    pub fn configured(&self) -> bool {
        unsafe { (*self.shell_surface).configured }
    }

    pub fn added(&self) -> bool {
        unsafe { (*self.shell_surface).added }
    }

    pub fn configure_serial(&self) -> u32 {
        unsafe { (*self.shell_surface).configure_serial }
    }

    pub fn configure_next_serial(&self) -> u32 {
        unsafe { (*self.shell_surface).configure_next_serial }
    }

    pub fn has_next_geometry(&self) -> bool {
        unsafe { (*self.shell_surface).has_next_geometry }
    }

    pub fn next_geometry(&self) -> Area {
        unsafe { Area::from_box((*self.shell_surface).next_geometry) }
    }

    pub fn geometry(&self) -> Area {
        unsafe { Area::from_box((*self.shell_surface).geometry) }
    }

    /// Send a ping to the surface.
    ///
    /// If the surface does not respond with a pong within a reasonable amount of time,
    /// the ping timeout event will be emitted.
    pub fn ping(&mut self) {
        unsafe {
            wlr_xdg_surface_ping(self.shell_surface);
        }
    }

    /// Find a surface within this surface at the surface-local coordinates.
    ///
    /// Returns the popup and coordinates in the topmost surface coordinate system
    /// or None if no popup is found at that location.
    pub fn surface_at(&mut self,
                      sx: f64,
                      sy: f64,
                      sub_sx: &mut f64,
                      sub_sy: &mut f64)
                      -> Option<surface::Handle> {
        unsafe {
            let sub_surface =
                wlr_xdg_surface_surface_at(self.shell_surface, sx, sy, sub_sx, sub_sy);
            if sub_surface.is_null() {
                None
            } else {
                Some(surface::Handle::from_ptr(sub_surface))
            }
        }
    }

    pub fn for_each_surface<F>(&self, mut iterator: F)
            where F: FnMut(surface::Handle, i32, i32) {
        let mut iterator_ref: &mut FnMut(surface::Handle, i32, i32) = &mut iterator;
        unsafe {
            unsafe extern "C" fn c_iterator(wlr_surface: *mut wlr_surface, sx: i32, sy: i32, data: *mut c_void) {
                let iterator_fn = &mut *(data as *mut &mut FnMut(surface::Handle, i32, i32));
                let surface = surface::Handle::from_ptr(wlr_surface);
                iterator_fn(surface, sx, sy);
            }
            let iterator_ptr: *mut c_void = &mut iterator_ref as *mut _ as *mut c_void;
            wlr_xdg_surface_for_each_surface(self.shell_surface, Some(c_iterator), iterator_ptr);
        }
    }
}

impl Drop for Surface {
    fn drop(&mut self) {
        if Rc::strong_count(&self.liveliness) == 1 {
            wlr_log!(WLR_DEBUG, "Dropped xdg shell {:p}", self.shell_surface);
            let weak_count = Rc::weak_count(&self.liveliness);
            if weak_count > 0 {
                wlr_log!(WLR_DEBUG,
                         "Still {} weak pointers to xdg shell {:p}",
                         weak_count,
                         self.shell_surface);
            }
        } else {
            return
        }
        unsafe {
            let _ = Box::from_raw((*self.shell_surface).data as *mut SurfaceState);
        }
    }
}

impl Handleable<OptionalShellState, wlr_xdg_surface> for Surface {
    #[doc(hidden)]
    unsafe fn from_ptr(shell_surface: *mut wlr_xdg_surface) -> Self {
        let data = &mut *((*shell_surface).data as *mut SurfaceState);
        let state = match data.shell_state {
            None => None,
            Some(ref state) => Some(state.clone())
        };
        let liveliness = data.handle.upgrade().unwrap();
        Surface { liveliness,
                  state,
                  shell_surface }
    }

    #[doc(hidden)]
    unsafe fn as_ptr(&self) -> *mut wlr_xdg_surface {
        self.shell_surface
    }

    #[doc(hidden)]
    unsafe fn from_handle(handle: &Handle) -> HandleResult<Self> {
        let liveliness = handle.handle
            .upgrade()
            .ok_or_else(|| HandleErr::AlreadyDropped)?;
        Ok(Surface { liveliness,
                     shell_surface: handle.ptr,
                     state: handle.data.clone().0 })
    }

    fn weak_reference(&self) -> Handle {
        Handle { ptr: self.shell_surface,
                 handle: Rc::downgrade(&self.liveliness),
                 data: OptionalShellState(match self.state {
                     None => None,
                     Some(ref state) => Some(unsafe { state.clone() })
                 }),
                 _marker: std::marker::PhantomData }
    }
}

impl TopLevel {
    pub(crate) unsafe fn from_shell(shell_surface: *mut wlr_xdg_surface,
                                    toplevel: *mut wlr_xdg_toplevel)
                                    -> TopLevel {
        TopLevel { shell_surface,
                        toplevel }
    }

    /// Get the title associated with this XDG shell toplevel.
    pub fn title(&self) -> String {
        unsafe { c_to_rust_string((*self.toplevel).title).expect("Could not parse class as UTF-8") }
    }

    /// Get the app id associated with this XDG shell toplevel.
    pub fn app_id(&self) -> String {
        unsafe {
            c_to_rust_string((*self.toplevel).app_id).expect("Could not parse class as UTF-8")
        }
    }

    /// Get a handle to the base surface of the xdg tree.
    pub fn base(&self) -> Handle {
        unsafe { Handle::from_ptr((*self.toplevel).base) }
    }

    /// Get a handle to the parent surface of the xdg tree.
    pub fn parent(&self) -> Handle {
        unsafe { Handle::from_ptr((*self.toplevel).parent) }
    }

    pub fn added(&self) -> bool {
        unsafe { (*self.toplevel).added }
    }

    /// Get the pending client state.
    pub fn client_pending_state(&self) -> wlr_xdg_toplevel_state {
        unsafe { (*self.toplevel).client_pending }
    }

    /// Get the pending server state.
    pub fn server_pending_state(&self) -> wlr_xdg_toplevel_state {
        unsafe { (*self.toplevel).server_pending }
    }

    /// Get the current configure state.
    pub fn current_state(&self) -> wlr_xdg_toplevel_state {
        unsafe { (*self.toplevel).current }
    }

    /// Request that this toplevel surface be the given size.
    ///
    /// Returns the associated configure serial.
    pub fn set_size(&mut self, width: u32, height: u32) -> u32 {
        unsafe { wlr_xdg_toplevel_set_size(self.shell_surface, width, height) }
    }

    /// Request that this toplevel surface show itself in an activated or deactivated
    /// state.
    ///
    /// Returns the associated configure serial.
    pub fn set_activated(&mut self, activated: bool) -> u32 {
        unsafe { wlr_xdg_toplevel_set_activated(self.shell_surface, activated) }
    }

    /// Request that this toplevel surface consider itself maximized or not
    /// maximized.
    ///
    /// Returns the associated configure serial.
    pub fn set_maximized(&mut self, maximized: bool) -> u32 {
        unsafe { wlr_xdg_toplevel_set_maximized(self.shell_surface, maximized) }
    }

    /// Request that this toplevel surface consider itself fullscreen or not
    /// fullscreen.
    ///
    /// Returns the associated configure serial.
    pub fn set_fullscreen(&mut self, fullscreen: bool) -> u32 {
        unsafe { wlr_xdg_toplevel_set_fullscreen(self.shell_surface, fullscreen) }
    }

    /// Request that this toplevel surface consider itself to be resizing or not
    /// resizing.
    ///
    /// Returns the associated configure serial.
    pub fn set_resizing(&mut self, resizing: bool) -> u32 {
        unsafe { wlr_xdg_toplevel_set_resizing(self.shell_surface, resizing) }
    }

    /// Request that this toplevel surface closes.
    pub fn close(&mut self) {
        unsafe { wlr_xdg_toplevel_send_close(self.shell_surface) }
    }

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

impl Popup {
    pub(crate) unsafe fn from_shell(shell_surface: *mut wlr_xdg_surface,
                                    popup: *mut wlr_xdg_popup)
                                    -> Popup {
        Popup { shell_surface,
                   popup }
    }

    /// Request that this popup closes.
    pub fn close(&mut self) {
        unsafe { wlr_xdg_popup_destroy(self.shell_surface) }
    }

    /// Get a handle to the base surface of the xdg tree.
    pub fn base(&self) -> Handle {
        unsafe { Handle::from_ptr((*self.popup).base) }
    }

    /// Get a handle to the parent surface of the xdg tree.
    pub fn parent(&self) -> surface::Handle {
        unsafe { surface::Handle::from_ptr((*self.popup).parent) }
    }

    pub fn committed(&self) -> bool {
        unsafe { (*self.popup).committed }
    }

    /// Get a handle to the seat associated with this popup.
    pub fn seat_handle(&self) -> Option<seat::Handle> {
        unsafe {
            let seat = (*self.popup).seat;
            if seat.is_null() {
                None
            } else {
                Some(seat::Handle::from_ptr(seat))
            }
        }
    }

    pub fn geometry(&self) -> Area {
        unsafe { Area::from_box((*self.popup).geometry) }
    }
}

impl ShellState {
    /// Unsafe copy of the pointer
    unsafe fn clone(&self) -> Self {
        match *self {
            ShellState::TopLevel(TopLevel { shell_surface,
                                     toplevel }) => {
                ShellState::TopLevel(TopLevel { shell_surface,
                                         toplevel })
            }
            ShellState::Popup(Popup { shell_surface,
                               popup }) => {
                ShellState::Popup(Popup { shell_surface,
                                   popup })
            }
        }
    }
}
<|endoftext|>


<commit_before>// edition:2018

#![no_core]
#![feature(no_core)]

// @count issue_89852/index.html '//*[@class="macro"]' 2
// @has - '//*[@class="macro"]/@href' 'macro.repro.html'
#[macro_export]
macro_rules! repro {
    () => {};
}

// @!has issue_89852/macro.repro.html '//*[@class="macro"]/@content' 'repro2'
pub use crate::repro as repro2;
<commit_msg>Rework the equivalent test to work with sidebar-items.js<commit_after>// edition:2018

#![no_core]
#![feature(no_core)]

// @matches 'issue_89852/sidebar-items.js' '"repro"'
// @!matches 'issue_89852/sidebar-items.js' '"repro".*"repro"'

#[macro_export]
macro_rules! repro {
    () => {};
}

pub use crate::repro as repro2;
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("Background", inherited=False) %>

${helpers.predefined_type(
    "background-color",
    "Color",
    "computed_value::T::transparent()",
    initial_specified_value="SpecifiedValue::transparent()",
    spec="https://drafts.csswg.org/css-backgrounds/#background-color",
    animation_value_type="AnimatedColor",
    ignored_when_colors_disabled=True,
    allow_quirks=True,
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER \
           CAN_ANIMATE_ON_COMPOSITOR",
)}

${helpers.predefined_type(
    "background-image",
    "ImageLayer",
    initial_value="Either::First(None_)",
    initial_specified_value="Either::First(None_)",
    spec="https://drafts.csswg.org/css-backgrounds/#the-background-image",
    vector="True",
    animation_value_type="discrete",
    ignored_when_colors_disabled="True",
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}

% for (axis, direction, initial) in [("x", "Horizontal", "left"), ("y", "Vertical", "top")]:
    ${helpers.predefined_type(
        "background-position-" + axis,
        "position::" + direction + "Position",
        initial_value="computed::LengthOrPercentage::zero()",
        initial_specified_value="SpecifiedValue::initial_specified_value()",
        spec="https://drafts.csswg.org/css-backgrounds-4/#propdef-background-position-" + axis,
        animation_value_type="ComputedValue",
        vector=True,
        vector_animation_type="repeatable_list",
        flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
    )}
% endfor

${helpers.predefined_type(
    "background-repeat",
    "BackgroundRepeat",
    "computed::BackgroundRepeat::repeat()",
    initial_specified_value="specified::BackgroundRepeat::repeat()",
    animation_value_type="discrete",
    vector=True,
    spec="https://drafts.csswg.org/css-backgrounds/#the-background-repeat",
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}

${helpers.single_keyword(
    "background-attachment",
    "scroll fixed" + (" local" if product == "gecko" else ""),
    vector=True,
    gecko_enum_prefix="StyleImageLayerAttachment",
    spec="https://drafts.csswg.org/css-backgrounds/#the-background-attachment",
    animation_value_type="discrete",
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}

${helpers.single_keyword(
    "background-clip",
    "border-box padding-box content-box",
    extra_gecko_values="text",
    vector=True, extra_prefixes="webkit",
    gecko_enum_prefix="StyleGeometryBox",
    gecko_inexhaustive=True,
    spec="https://drafts.csswg.org/css-backgrounds/#the-background-clip",
    animation_value_type="discrete",
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}

${helpers.single_keyword(
    "background-origin",
    "padding-box border-box content-box",
    vector=True, extra_prefixes="webkit",
    gecko_enum_prefix="StyleGeometryBox",
    gecko_inexhaustive=True,
    spec="https://drafts.csswg.org/css-backgrounds/#the-background-origin",
    animation_value_type="discrete",
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
)}

${helpers.predefined_type(
    "background-size",
    "BackgroundSize",
    initial_value="computed::BackgroundSize::auto()",
    initial_specified_value="specified::BackgroundSize::auto()",
    spec="https://drafts.csswg.org/css-backgrounds/#the-background-size",
    vector=True,
    vector_animation_type="repeatable_list",
    animation_value_type="BackgroundSizeList",
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
    extra_prefixes="webkit")}

// https://drafts.fxtf.org/compositing/#background-blend-mode
${helpers.single_keyword(
    "background-blend-mode",
    """normal multiply screen overlay darken lighten color-dodge
    color-burn hard-light soft-light difference exclusion hue
    saturation color luminosity""",
    gecko_constant_prefix="NS_STYLE_BLEND",
    gecko_pref="layout.css.background-blend-mode.enabled",
    vector=True, products="gecko", animation_value_type="discrete",
    spec="https://drafts.fxtf.org/compositing/#background-blend-mode",
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}
<commit_msg>style: Drop layout.css.background-blend-mode.enabled pref.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("Background", inherited=False) %>

${helpers.predefined_type(
    "background-color",
    "Color",
    "computed_value::T::transparent()",
    initial_specified_value="SpecifiedValue::transparent()",
    spec="https://drafts.csswg.org/css-backgrounds/#background-color",
    animation_value_type="AnimatedColor",
    ignored_when_colors_disabled=True,
    allow_quirks=True,
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER \
           CAN_ANIMATE_ON_COMPOSITOR",
)}

${helpers.predefined_type(
    "background-image",
    "ImageLayer",
    initial_value="Either::First(None_)",
    initial_specified_value="Either::First(None_)",
    spec="https://drafts.csswg.org/css-backgrounds/#the-background-image",
    vector="True",
    animation_value_type="discrete",
    ignored_when_colors_disabled="True",
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}

% for (axis, direction, initial) in [("x", "Horizontal", "left"), ("y", "Vertical", "top")]:
    ${helpers.predefined_type(
        "background-position-" + axis,
        "position::" + direction + "Position",
        initial_value="computed::LengthOrPercentage::zero()",
        initial_specified_value="SpecifiedValue::initial_specified_value()",
        spec="https://drafts.csswg.org/css-backgrounds-4/#propdef-background-position-" + axis,
        animation_value_type="ComputedValue",
        vector=True,
        vector_animation_type="repeatable_list",
        flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
    )}
% endfor

${helpers.predefined_type(
    "background-repeat",
    "BackgroundRepeat",
    "computed::BackgroundRepeat::repeat()",
    initial_specified_value="specified::BackgroundRepeat::repeat()",
    animation_value_type="discrete",
    vector=True,
    spec="https://drafts.csswg.org/css-backgrounds/#the-background-repeat",
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}

${helpers.single_keyword(
    "background-attachment",
    "scroll fixed" + (" local" if product == "gecko" else ""),
    vector=True,
    gecko_enum_prefix="StyleImageLayerAttachment",
    spec="https://drafts.csswg.org/css-backgrounds/#the-background-attachment",
    animation_value_type="discrete",
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}

${helpers.single_keyword(
    "background-clip",
    "border-box padding-box content-box",
    extra_gecko_values="text",
    vector=True, extra_prefixes="webkit",
    gecko_enum_prefix="StyleGeometryBox",
    gecko_inexhaustive=True,
    spec="https://drafts.csswg.org/css-backgrounds/#the-background-clip",
    animation_value_type="discrete",
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}

${helpers.single_keyword(
    "background-origin",
    "padding-box border-box content-box",
    vector=True, extra_prefixes="webkit",
    gecko_enum_prefix="StyleGeometryBox",
    gecko_inexhaustive=True,
    spec="https://drafts.csswg.org/css-backgrounds/#the-background-origin",
    animation_value_type="discrete",
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
)}

${helpers.predefined_type(
    "background-size",
    "BackgroundSize",
    initial_value="computed::BackgroundSize::auto()",
    initial_specified_value="specified::BackgroundSize::auto()",
    spec="https://drafts.csswg.org/css-backgrounds/#the-background-size",
    vector=True,
    vector_animation_type="repeatable_list",
    animation_value_type="BackgroundSizeList",
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
    extra_prefixes="webkit")}

// https://drafts.fxtf.org/compositing/#background-blend-mode
${helpers.single_keyword(
    "background-blend-mode",
    """normal multiply screen overlay darken lighten color-dodge
    color-burn hard-light soft-light difference exclusion hue
    saturation color luminosity""",
    gecko_constant_prefix="NS_STYLE_BLEND",
    vector=True, products="gecko", animation_value_type="discrete",
    spec="https://drafts.fxtf.org/compositing/#background-blend-mode",
    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}
<|endoftext|>


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

// rust-lang/rust#45696: This test checks the compiler won't infinite
// loop when you declare a variable of type `struct A(Box<A>, ...);`
// (which is impossible to construct but *is* possible to declare; see
// also issues #4287, #44933, and #52852).
//
// We will explicitly test AST-borrowck, NLL, and migration modes;
// thus we will also skip the automated compare-mode=nll.

// revisions: ast nll migrate
// ignore-compare-mode-nll

#![cfg_attr(nll, feature(nll))]
//[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows

// run-pass

// This test has structs and functions that are by definiton unusable
// all over the place, so just go ahead and allow dead_code
#![allow(dead_code)]

// direct regular recursion with indirect ownership via box
struct C { field: Box<C> }

// direct non-regular recursion with indirect ownership via box
struct D { field: Box<(D, D)> }

// indirect regular recursion with indirect ownership via box.
struct E { field: F }
struct F { field: Box<E> }

// indirect non-regular recursion with indirect ownership via box.
struct G { field: (F, F) }
struct H { field: Box<E> }

// These enums are cases that are not currently hit by the
// `visit_terminator_drop` recursion down a type's structural
// definition.
//
// But it seems prudent to include them in this test as variants on
// the above, in that they are similarly non-constructable data types
// with destructors that would diverge.
enum I { One(Box<I>) }
enum J { One(Box<J>), Two(Box<J>) }

fn impossible_to_call_c(_c: C) { }
fn impossible_to_call_d(_d: D) { }
fn impossible_to_call_e(_e: E) { }
fn impossible_to_call_f(_f: F) { }
fn impossible_to_call_g(_g: G) { }
fn impossible_to_call_h(_h: H) { }
fn impossible_to_call_i(_i: I) { }
fn impossible_to_call_j(_j: J) { }

fn main() {

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

// rust-lang/rust#45696: This test checks the compiler won't infinite
// loop when you declare a variable of type `struct A(Box<A>, ...);`
// (which is impossible to construct but *is* possible to declare; see
// also issues #4287, #44933, and #52852).
//
// We will explicitly test AST-borrowck, NLL, and migration modes;
// thus we will also skip the automated compare-mode=nll.

// revisions: ast nll migrate
// ignore-compare-mode-nll

#![cfg_attr(nll, feature(nll))]
//[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows

// run-pass

// This test has structs and functions that are by definiton unusable
// all over the place, so just go ahead and allow dead_code
#![allow(dead_code)]

// direct regular recursion with indirect ownership via box
struct C { field: Box<C> }

// direct non-regular recursion with indirect ownership via box
struct D { field: Box<(D, D)> }

// indirect regular recursion with indirect ownership via box.
struct E { field: F }
struct F { field: Box<E> }

// indirect non-regular recursion with indirect ownership via box.
struct G { field: (H, H) }
struct H { field: Box<G> }

// These enums are cases that are not currently hit by the
// `visit_terminator_drop` recursion down a type's structural
// definition.
//
// But it seems prudent to include them in this test as variants on
// the above, in that they are similarly non-constructable data types
// with destructors that would diverge.
enum I { One(Box<I>) }
enum J { One(Box<J>), Two(Box<J>) }

fn impossible_to_call_c(_c: C) { }
fn impossible_to_call_d(_d: D) { }
fn impossible_to_call_e(_e: E) { }
fn impossible_to_call_f(_f: F) { }
fn impossible_to_call_g(_g: G) { }
fn impossible_to_call_h(_h: H) { }
fn impossible_to_call_i(_i: I) { }
fn impossible_to_call_j(_j: J) { }

fn main() {

}
<|endoftext|>


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

extern crate coatcheck;
extern crate test;

use coatcheck::*;

#[test]
fn two_cc() {
    let mut c1 = CoatCheck::new();
    let mut c2 = CoatCheck::new();

    let t1 = c1.check(1);
    let t2 = c1.check(2);
    assert_eq!(c1[t1], 1);
    assert_eq!(c1[t2], 2);
    assert_eq!(c1[t1], 1);
    assert_eq!(c1.claim(t1).unwrap(), 1);
    let t3 = c1.check(3);
    assert_eq!(c1.claim(t3).unwrap(), 3);

    let t4 = c2.check(4);
    let _ = c2.check(5);

    assert!(c2.claim(t2).is_err());
    assert!(c1.claim(t4).is_err());
}

#[test]
fn iter() {
    let mut cc = CoatCheck::new();
    cc.check_all(0..2).count();
    {
        let mut iter = cc.iter();
        assert_eq!(iter.next().cloned(), Some(0));
        assert_eq!(iter.next().cloned(), Some(1));
        assert_eq!(iter.next(), None);
    }

    {
        let mut iter = cc.iter_mut();
        assert_eq!(iter.next().cloned(), Some(0));
        let it = iter.next().unwrap();
        assert_eq!(it, &mut 1);
        *it = 2;
        assert_eq!(iter.next(), None);
    }

    {
        let mut iter = cc.into_iter();
        assert_eq!(iter.next(), Some(0));
        assert_eq!(iter.next(), Some(2));
        assert_eq!(iter.next(), None)
    }
}

#[test]
fn get() {
    let mut cc = CoatCheck::new();
    let tickets: Vec<Ticket> = cc.check_all(0us..10).collect();
    for (i, t) in tickets.iter().enumerate() {
        assert_eq!(cc[*t], i);
    }
    cc[tickets[2]] = 1;
    assert_eq!(cc[tickets[2]], 1);
}

#[test]
fn check_all() {
    let mut cc = CoatCheck::new();
    let mut v: Vec<Ticket> = cc.check_all(vec![1i32,2,3,4].into_iter()).collect();
    assert_eq!(cc.len(), 4);
    assert_eq!(cc.claim(v.pop().unwrap()).unwrap(), 4);
    assert_eq!(cc.claim(v.pop().unwrap()).unwrap(), 3);
    assert_eq!(cc.claim(v.pop().unwrap()).unwrap(), 2);
    assert_eq!(cc.claim(v.pop().unwrap()).unwrap(), 1);
    assert!(v.is_empty());
    assert!(cc.is_empty());
}
<commit_msg>update us->usize<commit_after>#![feature(test, core)]

extern crate coatcheck;
extern crate test;

use coatcheck::*;

#[test]
fn two_cc() {
    let mut c1 = CoatCheck::new();
    let mut c2 = CoatCheck::new();

    let t1 = c1.check(1);
    let t2 = c1.check(2);
    assert_eq!(c1[t1], 1);
    assert_eq!(c1[t2], 2);
    assert_eq!(c1[t1], 1);
    assert_eq!(c1.claim(t1).unwrap(), 1);
    let t3 = c1.check(3);
    assert_eq!(c1.claim(t3).unwrap(), 3);

    let t4 = c2.check(4);
    let _ = c2.check(5);

    assert!(c2.claim(t2).is_err());
    assert!(c1.claim(t4).is_err());
}

#[test]
fn iter() {
    let mut cc = CoatCheck::new();
    cc.check_all(0..2).count();
    {
        let mut iter = cc.iter();
        assert_eq!(iter.next().cloned(), Some(0));
        assert_eq!(iter.next().cloned(), Some(1));
        assert_eq!(iter.next(), None);
    }

    {
        let mut iter = cc.iter_mut();
        assert_eq!(iter.next().cloned(), Some(0));
        let it = iter.next().unwrap();
        assert_eq!(it, &mut 1);
        *it = 2;
        assert_eq!(iter.next(), None);
    }

    {
        let mut iter = cc.into_iter();
        assert_eq!(iter.next(), Some(0));
        assert_eq!(iter.next(), Some(2));
        assert_eq!(iter.next(), None)
    }
}

#[test]
fn get() {
    let mut cc = CoatCheck::new();
    let tickets: Vec<Ticket> = cc.check_all(0usize..10).collect();
    for (i, t) in tickets.iter().enumerate() {
        assert_eq!(cc[*t], i);
    }
    cc[tickets[2]] = 1;
    assert_eq!(cc[tickets[2]], 1);
}

#[test]
fn check_all() {
    let mut cc = CoatCheck::new();
    let mut v: Vec<Ticket> = cc.check_all(vec![1i32,2,3,4].into_iter()).collect();
    assert_eq!(cc.len(), 4);
    assert_eq!(cc.claim(v.pop().unwrap()).unwrap(), 4);
    assert_eq!(cc.claim(v.pop().unwrap()).unwrap(), 3);
    assert_eq!(cc.claim(v.pop().unwrap()).unwrap(), 2);
    assert_eq!(cc.claim(v.pop().unwrap()).unwrap(), 1);
    assert!(v.is_empty());
    assert!(cc.is_empty());
}
<|endoftext|>


<commit_before>/*

  This struct essentially encapsulates the "instance variables"

*/
#[derive(Debug)]
pub struct SimpleHdrHistogram {
    pub leading_zeros_count_base: usize,
    pub sub_bucket_mask: u64,
    pub unit_magnitude: u32,
    pub sub_bucket_count: usize,
    pub sub_bucket_half_count: usize,
    pub sub_bucket_half_count_magnitude: u32,
    pub counts: Vec<u64>,
    pub counts_array_length: usize,
    pub normalizing_index_offset: usize,
    pub max_value: u64,
    pub min_non_zero_value: u64,
    pub unit_magnitude_mask: u64,
}

/*

  Implementing this trait (Default) for our struct gives us a nice way to
  initialize an instance using default args instead of having to provide all of them

 */
impl Default for SimpleHdrHistogram {
    fn default () -> SimpleHdrHistogram {
        SimpleHdrHistogram {
            leading_zeros_count_base: 0,
            sub_bucket_mask: 0,
            unit_magnitude: 0,
            sub_bucket_count: 0,
            sub_bucket_half_count: 0,
            sub_bucket_half_count_magnitude: 0,
            counts: Vec::new(),
            counts_array_length: 0,
            normalizing_index_offset: 0,
            max_value: 0,
            min_non_zero_value: u64::max_value(),
            unit_magnitude_mask: 0,
        }
    }
}

pub trait HistogramBase {

    //FIXME this stuff could be mostly unsigned

    //TODO this block should be default impl of this trait
    fn record_single_value(&mut self, value: u64) -> Result<(), String>;
    fn counts_array_index(&self, value: u64) -> Result<usize, String>;
    fn counts_array_index_sub(&self, bucket_index: usize, sub_bucket_index: usize) -> usize;
    fn get_bucket_index(&self, value: u64) -> usize;
    fn get_sub_bucket_index(&self, value: u64, bucket_index: usize) -> usize;
    fn update_min_and_max(&mut self, value: u64);
    fn update_max_value(&mut self, value: u64);
    fn update_min_non_zero_value(&mut self, value: u64);
    // end TODO

    fn increment_count_at_index(&mut self, index: usize) -> Result<(), String>;
    fn normalize_index(&self, index: usize, normalizing_index_offset: usize, array_length: usize) ->
        Result<usize, String>;

}

impl HistogramBase for SimpleHdrHistogram {

    fn update_max_value(&mut self, value: u64) {
        let mut internal_value = value | self.unit_magnitude_mask;
        self.max_value = internal_value;
    }

    fn update_min_non_zero_value(&mut self, value: u64) {
        if value <= self.unit_magnitude_mask {
            return
        }
        let internal_value = value & !self.unit_magnitude_mask;
        self.min_non_zero_value = internal_value;
    }

    fn update_min_and_max(&mut self, value: u64) {
        if value > self.max_value {
            self.update_max_value(value);
        }
        if ((value < self.min_non_zero_value) && (value != 0)) {
            self.update_min_non_zero_value(value);
        }
    }

    fn normalize_index(&self, index: usize, normalizing_index_offset: usize, array_length: usize) ->
Result<usize, String> {
        match normalizing_index_offset {
            0 => Ok(index),
            _ =>
                if ((index > array_length) || (index < 0)) {
                    Err(String::from("index out of covered range"))
                } else {
                    let mut normalized_index: usize = index - normalizing_index_offset;
                    if (normalized_index < 0) {
                        normalized_index += array_length;
                    } else if (normalized_index >= array_length) {
                        normalized_index -=array_length;
                    }
                    Ok(normalized_index)
                }
        }
    }

    fn increment_count_at_index(&mut self, index: usize) -> Result<(), String> {
        let normalized_index =
            self.normalize_index(index, self.normalizing_index_offset, self.counts_array_length);
        match normalized_index {
            Ok(the_index) => {
                self.counts[the_index] += 1;
                Ok(())
            }
            Err(err) =>
                Err(err)
        }
    }

    fn get_sub_bucket_index(&self, value: u64, bucket_index: usize) -> usize {
        let sum = bucket_index + self.unit_magnitude as usize;
        value.rotate_right(sum as u32) as usize
    }

    fn get_bucket_index(&self, value: u64) -> usize {
        let valueOrred = value | self.sub_bucket_mask;
        self.leading_zeros_count_base - (valueOrred.leading_zeros() as usize)
    }

    fn record_single_value(&mut self, value: u64) -> Result<(), String> {

        match self.counts_array_index(value) {
            Ok(counts_index) => {
                match self.increment_count_at_index(counts_index) {
                    Ok(_) => {
                        self.update_min_and_max(value);
                        //incrementTotalCount()

                        Err(String::from("Could not record single value"))
                    }
                    Err(err) => { Err(String::from("Could not increment stuff")) }
                }}
            Err(err) => Err(String::from("Could not get index"))
        }

    }

    fn counts_array_index(&self, value: u64) -> Result<usize, String> {
        if value < 0 {
            Err(String::from("Histogram recorded values cannot be negative."))
        } else {
            let bucket_index = self.get_bucket_index(value);
            let sub_bucket_index = self.get_sub_bucket_index(value, bucket_index);
            let result = self.counts_array_index_sub(bucket_index, sub_bucket_index);
            Ok(result)
        }
    }

    fn counts_array_index_sub(&self, bucket_index: usize, sub_bucket_index: usize) -> usize {
        assert!(sub_bucket_index < self.sub_bucket_count);
        assert!(bucket_index == 0 || (sub_bucket_index >= self.sub_bucket_half_count));

        let bucket_base_index = (bucket_index + 1) << self.sub_bucket_half_count_magnitude;
        let offset_in_bucket = sub_bucket_index - self.sub_bucket_half_count;

        bucket_base_index + offset_in_bucket
    }
}

#[test]
fn can_record_single_value() {
    let mut the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.record_single_value(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not add single record to histogram because error: {}", err))
    }
}

#[test]
fn can_compute_counts_array_index() {
    let mut the_hist = init_histo(1, 1000, 5);
    let result = the_hist.counts_array_index(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not compute counts array index because error: {}", err))
    }
}

#[test]
fn can_get_bucket_index() {
    let mut the_hist = init_histo(1, 1000, 5);
    let result = the_hist.get_bucket_index(99);
    assert_eq!(result, 0)
}

#[test]
fn can_get_sub_bucket_index() {
    let mut the_hist = init_histo(1, 1000, 5);
    let result = the_hist.get_sub_bucket_index(99, 1);
    assert_eq!(result, 0)
}

/// lowest_discernible_value: must be >= 1
/// highest_trackable_value: must be >= 2 * lowest_discernible_value
/// num_significant_digits: must be <= 5
fn init_histo(lowest_discernible_value: u64, highest_trackable_value: u64, num_significant_digits: u32) -> SimpleHdrHistogram {

    assert!(lowest_discernible_value >= 1);
    assert!(highest_trackable_value >= 2 * lowest_discernible_value);
    assert!(num_significant_digits <= 5);

    let mut hist =  SimpleHdrHistogram { ..Default::default() };

    let largest_value_with_single_unit_resolution = 2_u64 * 10_u64.pow(num_significant_digits);

    let unit_magnitude = ((lowest_discernible_value as f64).ln() / 2_f64.ln()) as u32;
    let unit_magnitude_mask: u64  = 1_u64.rotate_left(unit_magnitude) - 1;

    // find nearest power of 2 to largest_value_with_single_unit_resolution
    let sub_bucket_count_magnitude: u32 =
        ((largest_value_with_single_unit_resolution as f64).ln() / 2_f64.ln()).ceil() as u32;

    // ugly looking... how should ternaries be done?
    let sub_bucket_half_count_magnitude: u32 = (if sub_bucket_count_magnitude > 1 { sub_bucket_count_magnitude } else { 1 }) - 1;
    let sub_bucket_count: usize = 2_usize.pow(sub_bucket_half_count_magnitude + 1);
    let sub_bucket_half_count: usize = sub_bucket_count / 2;
    // TODO is this cast OK?
    let sub_bucket_mask = (sub_bucket_count - 1).rotate_left(unit_magnitude) as u64;

    let counts_arr_len = counts_arr_len(highest_trackable_value, sub_bucket_count, unit_magnitude);
    let bucket_count = buckets_needed_for_value(highest_trackable_value, sub_bucket_count, unit_magnitude);

    let leading_zero_count_base: usize = (64_u32 - unit_magnitude - sub_bucket_half_count_magnitude - 1) as usize;

    hist.leading_zeros_count_base = leading_zero_count_base;
    hist.sub_bucket_mask = sub_bucket_mask;
    hist.unit_magnitude = unit_magnitude;
    hist.sub_bucket_count = sub_bucket_count;
    hist.sub_bucket_half_count = sub_bucket_half_count;
    hist.sub_bucket_half_count_magnitude = sub_bucket_half_count_magnitude;
    hist.counts = Vec::with_capacity(counts_arr_len);
    hist.counts_array_length = counts_arr_len;
    hist.normalizing_index_offset = 0_usize; // 0 for normal Histogram ctor in Java impl

    println!("hist: {:?}", hist);

    hist
}

fn buckets_needed_for_value(value: u64, sub_bucket_count: usize, unit_magnitude: u32) -> usize {

    // is this cast ok?
    let mut smallest_untrackable_value: u64 = sub_bucket_count.rotate_left(unit_magnitude) as u64;
    let mut buckets_needed: usize = 1;

    while smallest_untrackable_value <= value {
        if (smallest_untrackable_value > u64::max_value() / 2) {
            return buckets_needed + 1;
        }

        smallest_untrackable_value = smallest_untrackable_value.rotate_left(1);
        buckets_needed += 1;
    }

    return buckets_needed;
}

fn counts_arr_len_for_buckets(buckets: usize, sub_bucket_count: usize) -> usize {
    (buckets + 1) * (sub_bucket_count / 2)
}

fn counts_arr_len(value: u64, sub_bucket_count: usize, unit_magnitude: u32) -> usize {
    counts_arr_len_for_buckets(buckets_needed_for_value(value, sub_bucket_count, unit_magnitude), sub_bucket_count)
}<commit_msg>increment total count<commit_after>/*

  This struct essentially encapsulates the "instance variables"

*/
#[derive(Debug)]
pub struct SimpleHdrHistogram {
    pub leading_zeros_count_base: usize,
    pub sub_bucket_mask: u64,
    pub unit_magnitude: u32,
    pub sub_bucket_count: usize,
    pub sub_bucket_half_count: usize,
    pub sub_bucket_half_count_magnitude: u32,
    pub counts: Vec<u64>,
    pub counts_array_length: usize,
    pub normalizing_index_offset: usize,
    pub max_value: u64,
    pub min_non_zero_value: u64,
    pub unit_magnitude_mask: u64,
    pub total_count: u64,
}

/*

  Implementing this trait (Default) for our struct gives us a nice way to
  initialize an instance using default args instead of having to provide all of them

 */
impl Default for SimpleHdrHistogram {
    fn default () -> SimpleHdrHistogram {
        SimpleHdrHistogram {
            leading_zeros_count_base: 0,
            sub_bucket_mask: 0,
            unit_magnitude: 0,
            sub_bucket_count: 0,
            sub_bucket_half_count: 0,
            sub_bucket_half_count_magnitude: 0,
            counts: Vec::new(),
            counts_array_length: 0,
            normalizing_index_offset: 0,
            max_value: 0,
            min_non_zero_value: u64::max_value(),
            unit_magnitude_mask: 0,
            total_count: 0,
        }
    }
}

pub trait HistogramBase {

    //FIXME this stuff could be mostly unsigned

    //TODO this block should be default impl of this trait
    fn record_single_value(&mut self, value: u64) -> Result<(), String>;
    fn counts_array_index(&self, value: u64) -> Result<usize, String>;
    fn counts_array_index_sub(&self, bucket_index: usize, sub_bucket_index: usize) -> usize;
    fn get_bucket_index(&self, value: u64) -> usize;
    fn get_sub_bucket_index(&self, value: u64, bucket_index: usize) -> usize;
    fn update_min_and_max(&mut self, value: u64);
    fn update_max_value(&mut self, value: u64);
    fn update_min_non_zero_value(&mut self, value: u64);
    // end TODO

    fn increment_count_at_index(&mut self, index: usize) -> Result<(), String>;
    fn normalize_index(&self, index: usize, normalizing_index_offset: usize, array_length: usize) ->
        Result<usize, String>;
    fn increment_total_count(&mut self);

}

impl HistogramBase for SimpleHdrHistogram {

    fn increment_total_count(&mut self) {
        self.total_count += 1;
    }

    fn update_max_value(&mut self, value: u64) {
        let mut internal_value = value | self.unit_magnitude_mask;
        self.max_value = internal_value;
    }

    fn update_min_non_zero_value(&mut self, value: u64) {
        if value <= self.unit_magnitude_mask {
            return
        }
        let internal_value = value & !self.unit_magnitude_mask;
        self.min_non_zero_value = internal_value;
    }

    fn update_min_and_max(&mut self, value: u64) {
        if value > self.max_value {
            self.update_max_value(value);
        }
        if ((value < self.min_non_zero_value) && (value != 0)) {
            self.update_min_non_zero_value(value);
        }
    }

    fn normalize_index(&self, index: usize, normalizing_index_offset: usize, array_length: usize) ->
Result<usize, String> {
        match normalizing_index_offset {
            0 => Ok(index),
            _ =>
                if ((index > array_length) || (index < 0)) {
                    Err(String::from("index out of covered range"))
                } else {
                    let mut normalized_index: usize = index - normalizing_index_offset;
                    if (normalized_index < 0) {
                        normalized_index += array_length;
                    } else if (normalized_index >= array_length) {
                        normalized_index -=array_length;
                    }
                    Ok(normalized_index)
                }
        }
    }

    fn increment_count_at_index(&mut self, index: usize) -> Result<(), String> {
        let normalized_index =
            self.normalize_index(index, self.normalizing_index_offset, self.counts_array_length);
        match normalized_index {
            Ok(the_index) => {
                self.counts[the_index] += 1;
                Ok(())
            }
            Err(err) =>
                Err(err)
        }
    }

    fn get_sub_bucket_index(&self, value: u64, bucket_index: usize) -> usize {
        let sum = bucket_index + self.unit_magnitude as usize;
        value.rotate_right(sum as u32) as usize
    }

    fn get_bucket_index(&self, value: u64) -> usize {
        let valueOrred = value | self.sub_bucket_mask;
        self.leading_zeros_count_base - (valueOrred.leading_zeros() as usize)
    }

    fn record_single_value(&mut self, value: u64) -> Result<(), String> {
        match self.counts_array_index(value) {
            Ok(counts_index) => {
                match self.increment_count_at_index(counts_index) {
                    Ok(_) => {
                        self.update_min_and_max(value);
                        self.increment_total_count();
                        Ok(())
                    }
                    Err(err) => {
                        Err(String::from(format!("Could not increment count at index due to: {}", err))) }
                }}
            Err(err) => Err(String::from(format!("Could not get index due to: {}", err)))
        }
    }

    fn counts_array_index(&self, value: u64) -> Result<usize, String> {
        if value < 0 {
            Err(String::from("Histogram recorded values cannot be negative."))
        } else {
            let bucket_index = self.get_bucket_index(value);
            let sub_bucket_index = self.get_sub_bucket_index(value, bucket_index);
            let result = self.counts_array_index_sub(bucket_index, sub_bucket_index);
            Ok(result)
        }
    }

    fn counts_array_index_sub(&self, bucket_index: usize, sub_bucket_index: usize) -> usize {
        assert!(sub_bucket_index < self.sub_bucket_count);
        assert!(bucket_index == 0 || (sub_bucket_index >= self.sub_bucket_half_count));

        let bucket_base_index = (bucket_index + 1) << self.sub_bucket_half_count_magnitude;
        let offset_in_bucket = sub_bucket_index - self.sub_bucket_half_count;

        bucket_base_index + offset_in_bucket
    }
}

#[test]
fn can_record_single_value() {
    let mut the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.record_single_value(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not add single record to histogram because error: {}", err))
    }
}

#[test]
fn can_compute_counts_array_index() {
    let mut the_hist = init_histo(1, 1000, 5);
    let result = the_hist.counts_array_index(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not compute counts array index because error: {}", err))
    }
}

#[test]
fn can_get_bucket_index() {
    let mut the_hist = init_histo(1, 1000, 5);
    let result = the_hist.get_bucket_index(99);
    assert_eq!(result, 0)
}

#[test]
fn can_get_sub_bucket_index() {
    let mut the_hist = init_histo(1, 1000, 5);
    let result = the_hist.get_sub_bucket_index(99, 1);
    assert_eq!(result, 0)
}

/// lowest_discernible_value: must be >= 1
/// highest_trackable_value: must be >= 2 * lowest_discernible_value
/// num_significant_digits: must be <= 5
fn init_histo(lowest_discernible_value: u64, highest_trackable_value: u64, num_significant_digits: u32) -> SimpleHdrHistogram {

    assert!(lowest_discernible_value >= 1);
    assert!(highest_trackable_value >= 2 * lowest_discernible_value);
    assert!(num_significant_digits <= 5);

    let mut hist =  SimpleHdrHistogram { ..Default::default() };

    let largest_value_with_single_unit_resolution = 2_u64 * 10_u64.pow(num_significant_digits);

    let unit_magnitude = ((lowest_discernible_value as f64).ln() / 2_f64.ln()) as u32;
    let unit_magnitude_mask: u64  = 1_u64.rotate_left(unit_magnitude) - 1;

    // find nearest power of 2 to largest_value_with_single_unit_resolution
    let sub_bucket_count_magnitude: u32 =
        ((largest_value_with_single_unit_resolution as f64).ln() / 2_f64.ln()).ceil() as u32;

    // ugly looking... how should ternaries be done?
    let sub_bucket_half_count_magnitude: u32 = (if sub_bucket_count_magnitude > 1 { sub_bucket_count_magnitude } else { 1 }) - 1;
    let sub_bucket_count: usize = 2_usize.pow(sub_bucket_half_count_magnitude + 1);
    let sub_bucket_half_count: usize = sub_bucket_count / 2;
    // TODO is this cast OK?
    let sub_bucket_mask = (sub_bucket_count - 1).rotate_left(unit_magnitude) as u64;

    let counts_arr_len = counts_arr_len(highest_trackable_value, sub_bucket_count, unit_magnitude);
    let bucket_count = buckets_needed_for_value(highest_trackable_value, sub_bucket_count, unit_magnitude);

    let leading_zero_count_base: usize = (64_u32 - unit_magnitude - sub_bucket_half_count_magnitude - 1) as usize;

    hist.leading_zeros_count_base = leading_zero_count_base;
    hist.sub_bucket_mask = sub_bucket_mask;
    hist.unit_magnitude = unit_magnitude;
    hist.sub_bucket_count = sub_bucket_count;
    hist.sub_bucket_half_count = sub_bucket_half_count;
    hist.sub_bucket_half_count_magnitude = sub_bucket_half_count_magnitude;
    hist.counts = Vec::with_capacity(counts_arr_len);
    hist.counts_array_length = counts_arr_len;
    hist.normalizing_index_offset = 0_usize; // 0 for normal Histogram ctor in Java impl

    println!("hist: {:?}", hist);

    hist
}

fn buckets_needed_for_value(value: u64, sub_bucket_count: usize, unit_magnitude: u32) -> usize {

    // is this cast ok?
    let mut smallest_untrackable_value: u64 = sub_bucket_count.rotate_left(unit_magnitude) as u64;
    let mut buckets_needed: usize = 1;

    while smallest_untrackable_value <= value {
        if (smallest_untrackable_value > u64::max_value() / 2) {
            return buckets_needed + 1;
        }

        smallest_untrackable_value = smallest_untrackable_value.rotate_left(1);
        buckets_needed += 1;
    }

    return buckets_needed;
}

fn counts_arr_len_for_buckets(buckets: usize, sub_bucket_count: usize) -> usize {
    (buckets + 1) * (sub_bucket_count / 2)
}

fn counts_arr_len(value: u64, sub_bucket_count: usize, unit_magnitude: u32) -> usize {
    counts_arr_len_for_buckets(buckets_needed_for_value(value, sub_bucket_count, unit_magnitude), sub_bucket_count)
}<|endoftext|>


<commit_before>// Copyright (C) 2019 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

pub(crate) mod definitions;
pub(crate) mod fs;
pub(crate) mod io;
pub(crate) mod mtd;

use derive_more::{Display, Error, From};

pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug, Display, Error, From)]
pub enum Error {
    Io(std::io::Error),
    Nix(nix::Error),
    Uncompress(compress_tools::Error),
    Process(easy_process::Error),
    StripPrefix(std::path::StripPrefixError),

    #[display(fmt = "{:?} target device does not exists", _0)]
    #[from(ignore)]
    DeviceDoesNotExist(#[error(not(source))] std::path::PathBuf),

    #[display(fmt = "user doesn't have write permission on target device: {:?}", _0)]
    #[from(ignore)]
    MissingWritePermission(#[error(not(source))] std::path::PathBuf),

    #[display(
        fmt = "{} is not enough storage space for installation, at least {} is required",
        available,
        required
    )]
    #[from(ignore)]
    NotEnoughSpace {
        available: u64,
        required: u64,
    },

    #[display(fmt = "'{}' not found on PATH", _0)]
    #[from(ignore)]
    ExecutableNotInPath(#[error(not(source))] String),
    #[display(fmt = "unable to find Ubi Volume: {}" _0)]
    #[from(ignore)]
    NoUbiVolume(#[error(not(source))] String),
    #[display(fmt = "unable to find match for mtd device: {}", _0)]
    #[from(ignore)]
    NoMtdDevice(#[error(not(source))] String),
}

/// Encode a bytes stream in hex
pub(crate) fn hex_encode(data: &[u8]) -> String {
    data.iter().map(|c| format!("{:02x}", c)).collect()
}

/// Get sha256sum hash from a byte stream
pub(crate) fn sha256sum(data: &[u8]) -> String {
    hex_encode(&openssl::sha::sha256(data))
}
<commit_msg>updatehub: utils: Inline hex_encode and sha256sum methods<commit_after>// Copyright (C) 2019 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

pub(crate) mod definitions;
pub(crate) mod fs;
pub(crate) mod io;
pub(crate) mod mtd;

use derive_more::{Display, Error, From};

pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug, Display, Error, From)]
pub enum Error {
    Io(std::io::Error),
    Nix(nix::Error),
    Uncompress(compress_tools::Error),
    Process(easy_process::Error),
    StripPrefix(std::path::StripPrefixError),

    #[display(fmt = "{:?} target device does not exists", _0)]
    #[from(ignore)]
    DeviceDoesNotExist(#[error(not(source))] std::path::PathBuf),

    #[display(fmt = "user doesn't have write permission on target device: {:?}", _0)]
    #[from(ignore)]
    MissingWritePermission(#[error(not(source))] std::path::PathBuf),

    #[display(
        fmt = "{} is not enough storage space for installation, at least {} is required",
        available,
        required
    )]
    #[from(ignore)]
    NotEnoughSpace {
        available: u64,
        required: u64,
    },

    #[display(fmt = "'{}' not found on PATH", _0)]
    #[from(ignore)]
    ExecutableNotInPath(#[error(not(source))] String),
    #[display(fmt = "unable to find Ubi Volume: {}" _0)]
    #[from(ignore)]
    NoUbiVolume(#[error(not(source))] String),
    #[display(fmt = "unable to find match for mtd device: {}", _0)]
    #[from(ignore)]
    NoMtdDevice(#[error(not(source))] String),
}

/// Encode a bytes stream in hex
#[inline]
pub(crate) fn hex_encode(data: &[u8]) -> String {
    data.iter().map(|c| format!("{:02x}", c)).collect()
}

/// Get sha256sum hash from a byte stream
#[inline]
pub(crate) fn sha256sum(data: &[u8]) -> String {
    hex_encode(&openssl::sha::sha256(data))
}
<|endoftext|>


<commit_before>use probability::distribution::{Categorical, Sample};

use workload::{Pattern, Workload};
use {Config, Result, Source};

/// A workload model choosing workload patterns randomly.
pub struct Random {
    patterns: Vec<Pattern>,
    source: Source,
    distribution: Categorical,
}

impl Random {
    /// Create a model.
    pub fn new(config: &Config, source: &Source) -> Result<Random> {
        let mut patterns = vec![];
        if let Some(ref configs) = config.forest("patterns") {
            for config in configs {
                patterns.push(try!(Pattern::new(config)));
            }
        }
        let count = patterns.len();
        if count == 0 {
            raise!("at least one workload pattern is required");
        }
        Ok(Random {
            patterns: patterns,
            source: source.clone(),
            distribution: Categorical::new(&vec![1.0 / count as f64; count]),
        })
    }
}

impl Workload for Random {
    fn next(&mut self, _: f64) -> Option<Pattern> {
        Some(self.patterns[self.distribution.sample(&mut self.source)].clone())
    }
}
<commit_msg>Workload: adjust the description of Random<commit_after>use probability::distribution::{Categorical, Sample};

use workload::{Pattern, Workload};
use {Config, Result, Source};

/// A workload model that chooses workload patterns randomly.
pub struct Random {
    patterns: Vec<Pattern>,
    source: Source,
    distribution: Categorical,
}

impl Random {
    /// Create a model.
    pub fn new(config: &Config, source: &Source) -> Result<Random> {
        let mut patterns = vec![];
        if let Some(ref configs) = config.forest("patterns") {
            for config in configs {
                patterns.push(try!(Pattern::new(config)));
            }
        }
        let count = patterns.len();
        if count == 0 {
            raise!("at least one workload pattern is required");
        }
        Ok(Random {
            patterns: patterns,
            source: source.clone(),
            distribution: Categorical::new(&vec![1.0 / count as f64; count]),
        })
    }
}

impl Workload for Random {
    fn next(&mut self, _: f64) -> Option<Pattern> {
        Some(self.patterns[self.distribution.sample(&mut self.source)].clone())
    }
}
<|endoftext|>


<commit_before>use common::util::*;

#[test]
fn test_uname_compatible() {
    let (_, mut ucmd) = at_and_ucmd!();

    let result = ucmd.arg("-a").run();
    assert!(result.success);
}

#[test]
fn test_uname_name() {
    let (_, mut ucmd) = at_and_ucmd!();

    let result = ucmd.arg("-n").run();
    assert!(result.success);
}
<commit_msg>test(uname): Add a test for the -o/--operating-system flag<commit_after>use common::util::*;

#[test]
fn test_uname_compatible() {
    let (_, mut ucmd) = at_and_ucmd!();

    let result = ucmd.arg("-a").run();
    assert!(result.success);
}

#[test]
fn test_uname_name() {
    let (_, mut ucmd) = at_and_ucmd!();

    let result = ucmd.arg("-n").run();
    assert!(result.success);
}

#[test]
fn test_uname_kernel() {
    let (_, mut ucmd) = at_and_ucmd!();

    let result = ucmd.arg("-o").run();
    assert!(result.success);
    #[cfg(target_os = "linux")]
    assert!(result.stdout.to_lowercase().contains("linux"));
}
<|endoftext|>


<commit_before>extern crate cgmath;
extern crate winit;

#[cfg(windows)]
use winit::os::windows::WindowExt;

#[macro_use]
extern crate vulkano;

#[path = "support/teapot.rs"]
mod teapot;

use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::mem;
use std::ptr;
use std::sync::Arc;

mod vs { include!{concat!(env!("OUT_DIR"), "/shaders/examples/teapot_vs.glsl")} }
mod fs { include!{concat!(env!("OUT_DIR"), "/shaders/examples/teapot_fs.glsl")} }

fn main() {
    // The start of this example is exactly the same as `triangle`. You should read the
    // `triangle` example if you haven't done so yet.

    // TODO: for the moment the AMD driver crashes if you don't pass an ApplicationInfo, but in theory it's optional
    let app = vulkano::instance::ApplicationInfo { application_name: "test", application_version: 1, engine_name: "test", engine_version: 1 };
    let extensions = vulkano::instance::InstanceExtensions {
        khr_surface: true,
        khr_win32_surface: true,
        .. vulkano::instance::InstanceExtensions::none()
    };
    let instance = vulkano::instance::Instance::new(Some(&app), &extensions, None).expect("failed to create instance");

    let physical = vulkano::instance::PhysicalDevice::enumerate(&instance)
                            .next().expect("no device available");
    println!("Using device: {} (type: {:?})", physical.name(), physical.ty());

    let window = winit::WindowBuilder::new().build().unwrap();
    let surface = unsafe { vulkano::swapchain::Surface::from_hwnd(&instance, ptr::null() as *const () /* FIXME */, window.get_hwnd()).unwrap() };

    let queue = physical.queue_families().find(|q| q.supports_graphics() &&
                                                   surface.is_supported(q).unwrap_or(false))
                                                .expect("couldn't find a graphical queue family");

    let device_ext = vulkano::device::DeviceExtensions {
        khr_swapchain: true,
    };

    let (device, queues) = vulkano::device::Device::new(&physical, physical.supported_features(),
                                                        &device_ext, None, [(queue, 0.5)].iter().cloned())
                                                                .expect("failed to create device");
    let queue = queues.into_iter().next().unwrap();

    let (swapchain, images) = {
        let caps = surface.get_capabilities(&physical).expect("failed to get surface capabilities");

        let dimensions = caps.current_extent.unwrap_or([1280, 1024]);
        let present = caps.present_modes[0];
        let usage = caps.supported_usage_flags;

        vulkano::swapchain::Swapchain::new(&device, &surface, 3,
                                           vulkano::format::B8G8R8A8Srgb, dimensions, 1,
                                           &usage, &queue, vulkano::swapchain::SurfaceTransform::Identity,
                                           vulkano::swapchain::CompositeAlpha::Opaque,
                                           present, true).expect("failed to create swapchain")
    };

    let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.family())
                                                  .expect("failed to create command buffer pool");

    let depth_buffer = vulkano::image::attachment::AttachmentImage::new(&device, images[0].dimensions().width_height(), vulkano::format::D16Unorm).unwrap();

    let vertex_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer
                               ::array(&device, teapot::VERTICES.len(),
                                       &vulkano::buffer::Usage::all(), Some(queue.family()))
                                       .expect("failed to create buffer");

    {
        let mut mapping = vertex_buffer.try_write().unwrap();
        for (o, i) in mapping.iter_mut().zip(teapot::VERTICES.iter()) {
            *o = *i;
        }
    }

    let normals_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer
                                ::array(&device, teapot::NORMALS.len(),
                                        &vulkano::buffer::Usage::all(), Some(queue.family()))
                                        .expect("failed to create buffer");

    {
        let mut mapping = normals_buffer.try_write().unwrap();
        for (o, i) in mapping.iter_mut().zip(teapot::NORMALS.iter()) {
            *o = *i;
        }
    }

    let index_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer
                              ::array(&device, teapot::INDICES.len(),
                                      &vulkano::buffer::Usage::all(), Some(queue.family()))
                                      .expect("failed to create buffer");

    {
        let mut mapping = index_buffer.try_write().unwrap();
        for (o, i) in mapping.iter_mut().zip(teapot::INDICES.iter()) {
            *o = *i;
        }
    }

    // note: this teapot was meant for OpenGL where the origin is at the lower left
    //       instead the origin is at the upper left in vulkan, so we reverse the Y axis
    let proj = cgmath::perspective(cgmath::rad(3.141592 / 2.0), { let d = images[0].dimensions(); d.width() as f32 / d.height() as f32 }, 0.01, 100.0);
    let view = cgmath::Matrix4::look_at(cgmath::Point3::new(0.3, 0.3, 1.0), cgmath::Point3::new(0.0, 0.0, 0.0), cgmath::Vector3::new(0.0, -1.0, 0.0));
    let scale = cgmath::Matrix4::from_scale(0.01);

    let uniform_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer::<vs::ty::Data>
                               ::new(&device, &vulkano::buffer::Usage::all(), Some(queue.family()))
                               .expect("failed to create buffer");
    {
        let mut mapping = uniform_buffer.try_write().unwrap();
        mapping.worldview = (view * scale).into();
        mapping.proj = proj.into();
    }

    let vs = vs::Shader::load(&device).expect("failed to create shader module");
    let fs = fs::Shader::load(&device).expect("failed to create shader module");

    mod renderpass {
        single_pass_renderpass!{
            attachments: {
                color: {
                    load: Clear,
                    store: Store,
                    format: B8G8R8A8Srgb,
                },
                depth: {
                    load: Clear,
                    store: DontCare,
                    format: D16Unorm,
                }
            },
            pass: {
                color: [color],
                depth_stencil: {depth}
            }
        }
    }

    let renderpass = renderpass::CustomRenderPass::new(&device).unwrap();

    let descriptor_pool = vulkano::descriptor_set::DescriptorPool::new(&device).unwrap();
    let descriptor_set_layout = vulkano::descriptor_set::DescriptorSetLayout::new(&device, vs::Set0).unwrap();

    mod pipeline_layout { pipeline_from_sets!(::vs::Set0); }
    let pipeline_layout = vulkano::descriptor_set::PipelineLayout::new(&device, pipeline_layout::Layout, (descriptor_set_layout.clone(),)).unwrap();
    let set = vulkano::descriptor_set::DescriptorSet::new(&descriptor_pool, &descriptor_set_layout,
                                                          uniform_buffer.clone() as std::sync::Arc<_>).unwrap();

    let pipeline = {
        let ia = vulkano::pipeline::input_assembly::InputAssembly::triangle_list();
        let raster = Default::default();
        let ms = vulkano::pipeline::multisample::Multisample::disabled();
        let blend = vulkano::pipeline::blend::Blend {
            logic_op: None,
            blend_constants: Some([0.0; 4]),
        };

        let viewports = vulkano::pipeline::viewport::ViewportsState::Fixed {
            data: vec![(
                vulkano::pipeline::viewport::Viewport {
                    origin: [0.0, 0.0],
                    dimensions: [1244.0, 699.0],
                    depth_range: 0.0 .. 1.0
                },
                vulkano::pipeline::viewport::Scissor {
                    origin: [0, 0],
                    dimensions: [1244, 699],
                }
            )],
        };

        vulkano::pipeline::GraphicsPipeline::new(&device, vulkano::pipeline::vertex::TwoBuffersDefinition::new(), &vs.main_entry_point(), &ia, &viewports,
                                                 &raster, &ms, &blend, &fs.main_entry_point(),
                                                 &pipeline_layout, vulkano::framebuffer::Subpass::from(&renderpass, 0).unwrap())
                                                 .unwrap()
    };

    let framebuffers = images.iter().map(|image| {
        vulkano::framebuffer::Framebuffer::new(&renderpass, (1244, 699, 1), vec![image.clone() as std::sync::Arc<_>, depth_buffer.clone() as std::sync::Arc<_>]).unwrap()
    }).collect::<Vec<_>>();

    let command_buffers = framebuffers.iter().map(|framebuffer| {
        vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool).unwrap()
            .draw_inline(&renderpass, &framebuffer, renderpass::ClearValues {
                 color: [0.0, 0.0, 1.0, 1.0],
                 depth: 1.0,
             })
            .draw_indexed(&pipeline, (&vertex_buffer, &normals_buffer), &index_buffer, &vulkano::command_buffer::DynamicState::none(), set.clone())
            .draw_end()
            .build().unwrap()
    }).collect::<Vec<_>>();

    let mut submissions: Vec<Arc<vulkano::command_buffer::Submission>> = Vec::new();

    loop {
        submissions.retain(|s| !s.destroying_would_block());

        let image_num = swapchain.acquire_next_image(1000000).unwrap();
        submissions.push(vulkano::command_buffer::submit(&command_buffers[image_num], &queue).unwrap());
        swapchain.present(&queue, image_num).unwrap();

        for ev in window.poll_events() {
            match ev {
                winit::Event::Closed => break,
                _ => ()
            }
        }
    }
}
<commit_msg>Fix teapot viewport<commit_after>extern crate cgmath;
extern crate winit;

#[cfg(windows)]
use winit::os::windows::WindowExt;

#[macro_use]
extern crate vulkano;

#[path = "support/teapot.rs"]
mod teapot;

use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::mem;
use std::ptr;
use std::sync::Arc;

mod vs { include!{concat!(env!("OUT_DIR"), "/shaders/examples/teapot_vs.glsl")} }
mod fs { include!{concat!(env!("OUT_DIR"), "/shaders/examples/teapot_fs.glsl")} }

fn main() {
    // The start of this example is exactly the same as `triangle`. You should read the
    // `triangle` example if you haven't done so yet.

    // TODO: for the moment the AMD driver crashes if you don't pass an ApplicationInfo, but in theory it's optional
    let app = vulkano::instance::ApplicationInfo { application_name: "test", application_version: 1, engine_name: "test", engine_version: 1 };
    let extensions = vulkano::instance::InstanceExtensions {
        khr_surface: true,
        khr_win32_surface: true,
        .. vulkano::instance::InstanceExtensions::none()
    };
    let instance = vulkano::instance::Instance::new(Some(&app), &extensions, None).expect("failed to create instance");

    let physical = vulkano::instance::PhysicalDevice::enumerate(&instance)
                            .next().expect("no device available");
    println!("Using device: {} (type: {:?})", physical.name(), physical.ty());

    let window = winit::WindowBuilder::new().build().unwrap();
    let surface = unsafe { vulkano::swapchain::Surface::from_hwnd(&instance, ptr::null() as *const () /* FIXME */, window.get_hwnd()).unwrap() };

    let queue = physical.queue_families().find(|q| q.supports_graphics() &&
                                                   surface.is_supported(q).unwrap_or(false))
                                                .expect("couldn't find a graphical queue family");

    let device_ext = vulkano::device::DeviceExtensions {
        khr_swapchain: true,
    };

    let (device, queues) = vulkano::device::Device::new(&physical, physical.supported_features(),
                                                        &device_ext, None, [(queue, 0.5)].iter().cloned())
                                                                .expect("failed to create device");
    let queue = queues.into_iter().next().unwrap();

    let (swapchain, images) = {
        let caps = surface.get_capabilities(&physical).expect("failed to get surface capabilities");

        let dimensions = caps.current_extent.unwrap_or([1280, 1024]);
        let present = caps.present_modes[0];
        let usage = caps.supported_usage_flags;

        vulkano::swapchain::Swapchain::new(&device, &surface, 3,
                                           vulkano::format::B8G8R8A8Srgb, dimensions, 1,
                                           &usage, &queue, vulkano::swapchain::SurfaceTransform::Identity,
                                           vulkano::swapchain::CompositeAlpha::Opaque,
                                           present, true).expect("failed to create swapchain")
    };

    let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.family())
                                                  .expect("failed to create command buffer pool");

    let depth_buffer = vulkano::image::attachment::AttachmentImage::new(&device, images[0].dimensions().width_height(), vulkano::format::D16Unorm).unwrap();

    let vertex_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer
                               ::array(&device, teapot::VERTICES.len(),
                                       &vulkano::buffer::Usage::all(), Some(queue.family()))
                                       .expect("failed to create buffer");

    {
        let mut mapping = vertex_buffer.try_write().unwrap();
        for (o, i) in mapping.iter_mut().zip(teapot::VERTICES.iter()) {
            *o = *i;
        }
    }

    let normals_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer
                                ::array(&device, teapot::NORMALS.len(),
                                        &vulkano::buffer::Usage::all(), Some(queue.family()))
                                        .expect("failed to create buffer");

    {
        let mut mapping = normals_buffer.try_write().unwrap();
        for (o, i) in mapping.iter_mut().zip(teapot::NORMALS.iter()) {
            *o = *i;
        }
    }

    let index_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer
                              ::array(&device, teapot::INDICES.len(),
                                      &vulkano::buffer::Usage::all(), Some(queue.family()))
                                      .expect("failed to create buffer");

    {
        let mut mapping = index_buffer.try_write().unwrap();
        for (o, i) in mapping.iter_mut().zip(teapot::INDICES.iter()) {
            *o = *i;
        }
    }

    // note: this teapot was meant for OpenGL where the origin is at the lower left
    //       instead the origin is at the upper left in vulkan, so we reverse the Y axis
    let proj = cgmath::perspective(cgmath::rad(3.141592 / 2.0), { let d = images[0].dimensions(); d.width() as f32 / d.height() as f32 }, 0.01, 100.0);
    let view = cgmath::Matrix4::look_at(cgmath::Point3::new(0.3, 0.3, 1.0), cgmath::Point3::new(0.0, 0.0, 0.0), cgmath::Vector3::new(0.0, -1.0, 0.0));
    let scale = cgmath::Matrix4::from_scale(0.01);

    let uniform_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer::<vs::ty::Data>
                               ::new(&device, &vulkano::buffer::Usage::all(), Some(queue.family()))
                               .expect("failed to create buffer");
    {
        let mut mapping = uniform_buffer.try_write().unwrap();
        mapping.worldview = (view * scale).into();
        mapping.proj = proj.into();
    }

    let vs = vs::Shader::load(&device).expect("failed to create shader module");
    let fs = fs::Shader::load(&device).expect("failed to create shader module");

    mod renderpass {
        single_pass_renderpass!{
            attachments: {
                color: {
                    load: Clear,
                    store: Store,
                    format: B8G8R8A8Srgb,
                },
                depth: {
                    load: Clear,
                    store: DontCare,
                    format: D16Unorm,
                }
            },
            pass: {
                color: [color],
                depth_stencil: {depth}
            }
        }
    }

    let renderpass = renderpass::CustomRenderPass::new(&device).unwrap();

    let descriptor_pool = vulkano::descriptor_set::DescriptorPool::new(&device).unwrap();
    let descriptor_set_layout = vulkano::descriptor_set::DescriptorSetLayout::new(&device, vs::Set0).unwrap();

    mod pipeline_layout { pipeline_from_sets!(::vs::Set0); }
    let pipeline_layout = vulkano::descriptor_set::PipelineLayout::new(&device, pipeline_layout::Layout, (descriptor_set_layout.clone(),)).unwrap();
    let set = vulkano::descriptor_set::DescriptorSet::new(&descriptor_pool, &descriptor_set_layout,
                                                          uniform_buffer.clone() as std::sync::Arc<_>).unwrap();

    let pipeline = {
        let ia = vulkano::pipeline::input_assembly::InputAssembly::triangle_list();
        let raster = Default::default();
        let ms = vulkano::pipeline::multisample::Multisample::disabled();
        let blend = vulkano::pipeline::blend::Blend {
            logic_op: None,
            blend_constants: Some([0.0; 4]),
        };

        let viewports = vulkano::pipeline::viewport::ViewportsState::Fixed {
            data: vec![(
                vulkano::pipeline::viewport::Viewport {
                    origin: [0.0, 0.0],
                    dimensions: [images[0].dimensions().width() as f32, images[0].dimensions().height() as f32],
                    depth_range: 0.0 .. 1.0
                },
                vulkano::pipeline::viewport::Scissor::irrelevant()
            )],
        };

        vulkano::pipeline::GraphicsPipeline::new(&device, vulkano::pipeline::vertex::TwoBuffersDefinition::new(), &vs.main_entry_point(), &ia, &viewports,
                                                 &raster, &ms, &blend, &fs.main_entry_point(),
                                                 &pipeline_layout, vulkano::framebuffer::Subpass::from(&renderpass, 0).unwrap())
                                                 .unwrap()
    };

    let framebuffers = images.iter().map(|image| {
        vulkano::framebuffer::Framebuffer::new(&renderpass, (1244, 699, 1), vec![image.clone() as std::sync::Arc<_>, depth_buffer.clone() as std::sync::Arc<_>]).unwrap()
    }).collect::<Vec<_>>();

    let command_buffers = framebuffers.iter().map(|framebuffer| {
        vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool).unwrap()
            .draw_inline(&renderpass, &framebuffer, renderpass::ClearValues {
                 color: [0.0, 0.0, 1.0, 1.0],
                 depth: 1.0,
             })
            .draw_indexed(&pipeline, (&vertex_buffer, &normals_buffer), &index_buffer, &vulkano::command_buffer::DynamicState::none(), set.clone())
            .draw_end()
            .build().unwrap()
    }).collect::<Vec<_>>();

    let mut submissions: Vec<Arc<vulkano::command_buffer::Submission>> = Vec::new();

    loop {
        submissions.retain(|s| !s.destroying_would_block());

        let image_num = swapchain.acquire_next_image(1000000).unwrap();
        submissions.push(vulkano::command_buffer::submit(&command_buffers[image_num], &queue).unwrap());
        swapchain.present(&queue, image_num).unwrap();

        for ev in window.poll_events() {
            match ev {
                winit::Event::Closed => break,
                _ => ()
            }
        }
    }
}
<|endoftext|>


<commit_before>// compile-flags: -Zmiri-seed=0000000000000000

use std::collections::{self, HashMap};
use std::hash::{BuildHasherDefault, BuildHasher};

fn test_map<S: BuildHasher>(mut map: HashMap<i32, i32, S>) {
    map.insert(0, 0);
    assert_eq!(map.values().fold(0, |x, y| x+y), 0);

    let table_base = map.get(&0).unwrap() as *const _;

    let num = 22; // large enough to trigger a resize
    for i in 1..num {
        map.insert(i, i);
    }
    assert!(table_base != map.get(&0).unwrap() as *const _); // make sure relocation happened
    assert_eq!(map.values().fold(0, |x, y| x+y), num*(num-1)/2); // check the right things are in the table now

    // Inserting again replaces the existing entries
    for i in 0..num {
        map.insert(i, num-1-i);
    }
    assert_eq!(map.values().fold(0, |x, y| x+y), num*(num-1)/2);

    // TODO: Test Entry API, Iterators, ...

}

fn main() {
    let map : HashMap<i32, i32, BuildHasherDefault<collections::hash_map::DefaultHasher>> = Default::default();
    let map_normal: HashMap<i32, i32> = HashMap::new();

    test_map(map);
    test_map(map_normal);
}
<commit_msg>Only run test with default hasher<commit_after>// compile-flags: -Zmiri-seed=0000000000000000

use std::collections::{self, HashMap};
use std::hash::{BuildHasherDefault, BuildHasher};

fn test_map<S: BuildHasher>(mut map: HashMap<i32, i32, S>) {
    map.insert(0, 0);
    assert_eq!(map.values().fold(0, |x, y| x+y), 0);

    let table_base = map.get(&0).unwrap() as *const _;

    let num = 22; // large enough to trigger a resize
    for i in 1..num {
        map.insert(i, i);
    }
    assert!(table_base != map.get(&0).unwrap() as *const _); // make sure relocation happened
    assert_eq!(map.values().fold(0, |x, y| x+y), num*(num-1)/2); // check the right things are in the table now

    // Inserting again replaces the existing entries
    for i in 0..num {
        map.insert(i, num-1-i);
    }
    assert_eq!(map.values().fold(0, |x, y| x+y), num*(num-1)/2);

    // TODO: Test Entry API, Iterators, ...

}

fn main() {
    let _map : HashMap<i32, i32, BuildHasherDefault<collections::hash_map::DefaultHasher>> = Default::default();
    let map_normal: HashMap<i32, i32> = HashMap::new();

    test_map(map_normal);
}
<|endoftext|>


<commit_before>// compile-flags: -Zmiri-seed=0000000000000000

use std::collections::{self, HashMap};
use std::hash::{BuildHasherDefault, BuildHasher};

fn test_map<S: BuildHasher>(mut map: HashMap<i32, i32, S>) {
    map.insert(0, 0);
    assert_eq!(map.values().fold(0, |x, y| x+y), 0);

    let table_base = map.get(&0).unwrap() as *const _;

    let num = 22; // large enough to trigger a resize
    for i in 1..num {
        map.insert(i, i);
    }
    assert!(table_base != map.get(&0).unwrap() as *const _); // make sure relocation happened
    assert_eq!(map.values().fold(0, |x, y| x+y), num*(num-1)/2); // check the right things are in the table now

    // Inserting again replaces the existing entries
    for i in 0..num {
        map.insert(i, num-1-i);
    }
    assert_eq!(map.values().fold(0, |x, y| x+y), num*(num-1)/2);

    // TODO: Test Entry API, Iterators, ...

}

fn main() {
    let _map : HashMap<i32, i32, BuildHasherDefault<collections::hash_map::DefaultHasher>> = Default::default();

    // TODO: Implement random number generation on OS X
    if cfg!(not(target_os = "macos")) {
        let map_normal: HashMap<i32, i32> = HashMap::new();
        test_map(map_normal);
    } else {
        test_map(_map);
    }
}
<commit_msg>Don't create HashMap<K, V> when not needed<commit_after>// compile-flags: -Zmiri-seed=0000000000000000

use std::collections::{self, HashMap};
use std::hash::{BuildHasherDefault, BuildHasher};

fn test_map<S: BuildHasher>(mut map: HashMap<i32, i32, S>) {
    map.insert(0, 0);
    assert_eq!(map.values().fold(0, |x, y| x+y), 0);

    let table_base = map.get(&0).unwrap() as *const _;

    let num = 22; // large enough to trigger a resize
    for i in 1..num {
        map.insert(i, i);
    }
    assert!(table_base != map.get(&0).unwrap() as *const _); // make sure relocation happened
    assert_eq!(map.values().fold(0, |x, y| x+y), num*(num-1)/2); // check the right things are in the table now

    // Inserting again replaces the existing entries
    for i in 0..num {
        map.insert(i, num-1-i);
    }
    assert_eq!(map.values().fold(0, |x, y| x+y), num*(num-1)/2);

    // TODO: Test Entry API, Iterators, ...

}

fn main() {
    // TODO: Implement random number generation on OS X
    if cfg!(not(target_os = "macos")) {
        let map_normal: HashMap<i32, i32> = HashMap::new();
        test_map(map_normal);
    } else {
        let map : HashMap<i32, i32, BuildHasherDefault<collections::hash_map::DefaultHasher>> = Default::default();
        test_map(map);
    }
}
<|endoftext|>