<NME> mod.rs
<BEF> //! SHM handling helpers
//!
//! This module provides helpers to handle SHM-based buffers from wayland clients.
//!
//! SHM (Shared Memory) is the most basic way wayland clients can send content to
//! the compositor: by sending a file descriptor to some (likely RAM-backed) storage
//! containing the actual data. This helper handles for you most of the logic for
//! handling these file descriptor and accessing their contents as simple `&[u8]` slices.
//!
//! This module is heavily inspired from
//! [the similar helpers](https://cgit.freedesktop.org/wayland/wayland/tree/src/wayland-shm.c)
//! of the wayland C libraries.
//!
//! To use it, first add a `ShmGlobal` to your display, specifying the formats
//! you want to support (ARGB8888 and XRGB8888 are always considered as supported,
//! as specified by the wayland protocol).
//!
//! ```
//! extern crate wayland_server;
//! extern crate smithay;
//!
//! use smithay::wayland::buffer::BufferHandler;
//! use wayland_server::protocol::wl_shm::Format;
//!
//! # fn main() {
//! # let (display, mut event_loop) = wayland_server::create_display();
//! // Insert the ShmGlobal into your event loop
//! // Here, we specify that Yuyv and C8 format are supported
//! // additionnaly to the standart Argb8888 and Xrgb8888.
//! let shm_global = init_shm_global(
//!     &mut event_loop,
//!     vec![Format::Yuyv, Format::C8],
//!     None // we don't provide a logger here
//! );
//! );
//!
//! // insert the shmstate into your compositor state.
//! // ..
//!
//! // provide the necessary trait implementations
//! impl BufferHandler for State {
//! # extern crate wayland_server;
//! # extern crate smithay;
//! # use wayland_server::protocol::wl_buffer::WlBuffer;
//! # fn wrap(buffer: &WlBuffer) {
//! use smithay::wayland::shm::{with_buffer_contents, BufferData};
//!
//! with_buffer_contents(&buffer,
//!     }
//! }
//! delegate_shm!(State);
//! ```
//!
//! Then, when you have a [`WlBuffer`](wayland_server::protocol::wl_buffer::WlBuffer)
//! and need to retrieve its contents, use the
//! [`with_buffer_contents`] function to do it:
//!
//! ```
//! # extern crate wayland_server;
//! # extern crate smithay;
//! # fn wrap(buffer: &wayland_server::protocol::wl_buffer::WlBuffer) {
//! use smithay::wayland::shm::{with_buffer_contents, BufferData, BufferAccessError};
//!
use self::pool::{Pool, ResizeError};
use std::rc::Rc;
use std::sync::Arc;
use wayland_server::{resource_is_registered, Client, EventLoopHandle, Global, Resource};
use wayland_server::protocol::{wl_buffer, wl_shm, wl_shm_pool};

mod pool;
//!         /* `something` is the value you returned from the closure */
//!     },
//!     Err(BufferAccessError::NotManaged) => {
//!         /* This buffer is not managed by the SHM global, but by something else */
//!     },
//!     Err(BufferAccessError::BadMap) => {
pub struct ShmGlobalData {
    formats: Rc<Vec<wl_shm::Format>>,
    log: ::slog::Logger,
}

/// Create a new SHM global advertizing given supported formats.
//!     Err(BufferAccessError::NotWritable) => unreachable!("cannot be triggered by with_buffer_contents"),
//! }
/// as they are required by the protocol. Formats given as argument
/// as additionnaly advertized.
///
/// The global is directly registered into the eventloop, and this function
/// returns the global handle, in case you whish to remove this global in
/// the future.
pub fn init_shm_global<L>(
    evlh: &mut EventLoopHandle, mut formats: Vec<wl_shm::Format>, logger: L
) -> Global<wl_shm::WlShm, ShmGlobalData>
where
    L: Into<Option<::slog::Logger>>,
{
        wl_buffer,
        wl_shm::{self, WlShm},
        wl_shm_pool::WlShmPool,
    },
    Dispatch, DisplayHandle, GlobalDispatch, Resource,
    let data = ShmGlobalData {
        formats: Rc::new(formats),
        log: log.new(o!("smithay_module" => "shm_handler")),
    };

    evlh.register_global::<wl_shm::WlShm, _>(1, shm_global_bind, data)
}

/// Error that can occur when accessing an SHM buffer
    log: ::slog::Logger,
}

impl ShmState {
    /// Create a new SHM global advertizing the given formats.
    ///
    /// This global will always advertize `ARGB8888` and `XRGB8888` since these formats are required by the
    /// protocol. Formats given as an argument are also advertized.
    ///
    /// The global is directly created on the provided [`Display`](wayland_server::Display),
    /// and this function returns the a delegate type. The id provided by [`ShmState::global`] may be used to
    /// remove this global in the future.
    pub fn new<D, L>(display: &DisplayHandle, mut formats: Vec<wl_shm::Format>, logger: L) -> ShmState
    where
        D: GlobalDispatch<WlShm, ()>
            + Dispatch<WlShm, ()>
            + Dispatch<WlShmPool, ShmPoolUserData>
            + BufferHandler
            + ShmHandler
            + 'static,
///
/// If the buffer is not managed by the provided `ShmGlobal`, the closure is not called
/// and this method will return `Err(())` (this will be the case for an EGL buffer for example).
pub fn with_buffer_contents<F>(buffer: &wl_buffer::WlBuffer, f: F) -> Result<(), BufferAccessError>
where
    F: FnOnce(&[u8], BufferData),
{
    if !resource_is_registered(buffer, &buffer_implementation()) {
        return Err(BufferAccessError::NotManaged);
    }
    let data = unsafe { &*(buffer.get_user_data() as *mut InternalBufferData) };
            formats,
            shm,
            log: log.new(slog::o!("smithay_module" => "shm_handler")),
        }
    }

    /// Returns the id of the [`WlShm`] global.
    pub fn global(&self) -> GlobalId {
        self.shm.clone()
    Ok(())
}

fn shm_global_bind(evlh: &mut EventLoopHandle, data: &mut ShmGlobalData, _: &Client, global: wl_shm::WlShm) {
    // register an handler for this shm
    evlh.register(&global, shm_implementation(), data.clone(), None);
    // and then the custom formats
    for f in &data.formats[..] {
        global.format(*f);
    }
}

fn shm_implementation() -> wl_shm::Implementation<ShmGlobalData> {
    wl_shm::Implementation {
        create_pool: |evlh, data, _, shm, pool, fd, size| {
            if size <= 0 {
                shm.post_error(
                    wl_shm::Error::InvalidFd as u32,
                    "Invalid size for a new wl_shm_pool.".into(),
                );
                return;
            }
            let mmap_pool = match Pool::new(fd, size as usize, data.log.clone()) {
                Ok(p) => p,
                Err(()) => {
                    shm.post_error(
                        wl_shm::Error::InvalidFd as u32,
                        format!("Failed mmap of fd {}.", fd),
                    );
                    return;
                }
            };
            let arc_pool = Box::new(Arc::new(mmap_pool));
            evlh.register(
                &pool,
                shm_pool_implementation(),
                data.clone(),
                Some(destroy_shm_pool),
            );
            pool.set_user_data(Box::into_raw(arc_pool) as *mut ());
        },
    }
}

fn destroy_shm_pool(pool: &wl_shm_pool::WlShmPool) {
    let arc_pool = unsafe { Box::from_raw(pool.get_user_data() as *mut Arc<Pool>) };
    drop(arc_pool)
}

/// Details of the contents of a buffer relative to its pool
#[derive(Copy, Clone, Debug)]
pub struct BufferData {
/// extracted and the closure is extracted with them:
///
/// - The first argument is a data slice of the contents of the pool
/// - The second argument is the specification of this buffer is this pool
///
/// If the buffer is not managed by the provided `ShmGlobal`, the closure is not called
/// and this method will return `Err(BufferAccessError::NotManaged)` (this will be the case for an
/// EGL buffer for example).
pub fn with_buffer_contents<F, T>(buffer: &wl_buffer::WlBuffer, f: F) -> Result<T, BufferAccessError>
where
    F: FnOnce(&[u8], BufferData) -> T,
{
    let data = buffer
        .data::<ShmBufferUserData>()
    data: BufferData,
}

fn shm_pool_implementation() -> wl_shm_pool::Implementation<ShmGlobalData> {
    wl_shm_pool::Implementation {
        create_buffer: |evlh, data, _, pool, buffer, offset, width, height, stride, format| {
            if !data.formats.contains(&format) {
                buffer.post_error(wl_shm::Error::InvalidFormat as u32, String::new());
                return;
            }
            let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
            let data = Box::into_raw(Box::new(InternalBufferData {
                pool: arc_pool.clone(),
                data: BufferData {
                    offset: offset,
                    width: width,
                    height: height,
                    stride: stride,
                    format: format,
                },
            }));
            evlh.register(&buffer, buffer_implementation(), (), Some(destroy_buffer));
            buffer.set_user_data(data as *mut ());
        },
        resize: |_, _, _, pool, size| {
            let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
            match arc_pool.resize(size) {
                Ok(()) => {}
                Err(ResizeError::InvalidSize) => {
                    pool.post_error(
        wl_shm::Format::Xrgb8888
            | wl_shm::Format::C8
            | wl_shm::Format::Rgb332
            | wl_shm::Format::Bgr233
                Err(ResizeError::MremapFailed) => {
                    pool.post_error(wl_shm::Error::InvalidFd as u32, "mremap failed.".into());
                }
            }
        },
        destroy: |_, _, _, _| {},
    }
}

fn destroy_buffer(buffer: &wl_buffer::WlBuffer) {
    let buffer_data = unsafe { Box::from_raw(buffer.get_user_data() as *mut InternalBufferData) };
    drop(buffer_data)
}

fn buffer_implementation() -> wl_buffer::Implementation<()> {
    wl_buffer::Implementation {
        destroy: |_, _, _, _| {},
    }
}
            | wl_shm::Format::Xrgb2101010
            | wl_shm::Format::Xbgr2101010
            | wl_shm::Format::Rgbx1010102
            | wl_shm::Format::Bgrx1010102
            | wl_shm::Format::Yuyv
            | wl_shm::Format::Yvyu
            | wl_shm::Format::Uyvy
            | wl_shm::Format::Vyuy
            | wl_shm::Format::Ayuv
            | wl_shm::Format::Nv12
            | wl_shm::Format::Nv21
            | wl_shm::Format::Nv16
            | wl_shm::Format::Nv61
            | wl_shm::Format::Yuv410
            | wl_shm::Format::Yvu410
            | wl_shm::Format::Yuv411
            | wl_shm::Format::Yvu411
            | wl_shm::Format::Yuv420
            | wl_shm::Format::Yvu420
            | wl_shm::Format::Yuv422
            | wl_shm::Format::Yvu422
            | wl_shm::Format::Yuv444
            | wl_shm::Format::Yvu444
            | wl_shm::Format::R8
            | wl_shm::Format::R16
            | wl_shm::Format::Rg88
            | wl_shm::Format::Gr88
            | wl_shm::Format::Rg1616
            | wl_shm::Format::Gr1616
            | wl_shm::Format::Xrgb16161616f
            | wl_shm::Format::Xbgr16161616f
            | wl_shm::Format::Xyuv8888
            | wl_shm::Format::Vuy888
            | wl_shm::Format::Vuy101010
            | wl_shm::Format::Y210
            | wl_shm::Format::Y212
            | wl_shm::Format::Y216
            | wl_shm::Format::Y410
            | wl_shm::Format::Y412
            | wl_shm::Format::Y416
            | wl_shm::Format::Xvyu2101010
            | wl_shm::Format::Xvyu1216161616
            | wl_shm::Format::Xvyu16161616
            | wl_shm::Format::Y0l0
            | wl_shm::Format::X0l0
            | wl_shm::Format::Y0l2
            | wl_shm::Format::X0l2
            | wl_shm::Format::Yuv4208bit
            | wl_shm::Format::Yuv42010bit
            | wl_shm::Format::Xrgb8888A8
            | wl_shm::Format::Xbgr8888A8
            | wl_shm::Format::Rgbx8888A8
            | wl_shm::Format::Bgrx8888A8
            | wl_shm::Format::Rgb888A8
            | wl_shm::Format::Bgr888A8
            | wl_shm::Format::Rgb565A8
            | wl_shm::Format::Bgr565A8
            | wl_shm::Format::Nv24
            | wl_shm::Format::Nv42
            | wl_shm::Format::P210
            | wl_shm::Format::P010
            | wl_shm::Format::P012
            | wl_shm::Format::P016
            | wl_shm::Format::Nv15
            | wl_shm::Format::Q410
            | wl_shm::Format::Q401
            | wl_shm::Format::Xrgb16161616
            | wl_shm::Format::Xbgr16161616
    )
}

/// Details of the contents of a buffer relative to its pool
#[derive(Copy, Clone, Debug)]
pub struct BufferData {
    /// Offset of the start of the buffer relative to the beginning of the pool in bytes
    pub offset: i32,
    /// Width of the buffer in bytes
    pub width: i32,
    /// Height of the buffer in bytes
    pub height: i32,
    /// Stride of the buffer in bytes
    pub stride: i32,
    /// Format used by this buffer
    pub format: wl_shm::Format,
}

/// User data of WlShmPool
#[derive(Debug)]
pub struct ShmPoolUserData {
    inner: Arc<Pool>,
}

/// User data of shm WlBuffer
#[derive(Debug)]
pub struct ShmBufferUserData {
    pub(crate) pool: Arc<Pool>,
    pub(crate) data: BufferData,
}

#[allow(missing_docs)] // TODO
#[macro_export]
macro_rules! delegate_shm {
    ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
        $crate::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            $crate::reexports::wayland_server::protocol::wl_shm::WlShm: ()
        ] => $crate::wayland::shm::ShmState);

        $crate::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            $crate::reexports::wayland_server::protocol::wl_shm::WlShm: ()
        ] => $crate::wayland::shm::ShmState);
        $crate::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            $crate::reexports::wayland_server::protocol::wl_shm_pool::WlShmPool: $crate::wayland::shm::ShmPoolUserData
        ] => $crate::wayland::shm::ShmState);
        $crate::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            $crate::reexports::wayland_server::protocol::wl_buffer::WlBuffer: $crate::wayland::shm::ShmBufferUserData
        ] => $crate::wayland::shm::ShmState);
    };
}

<MSG> wayland.shm: migrate to wayland_rs-0.20

<DFF> @@ -23,12 +23,13 @@
 //! use wayland_server::protocol::wl_shm::Format;
 //!
 //! # fn main() {
-//! # let (display, mut event_loop) = wayland_server::create_display();
+//! # let (mut display, mut event_loop) = wayland_server::Display::new();
 //! // Insert the ShmGlobal into your event loop
 //! // Here, we specify that Yuyv and C8 format are supported
 //! // additionnaly to the standart Argb8888 and Xrgb8888.
 //! let shm_global = init_shm_global(
-//!     &mut event_loop,
+//!     &mut display,
+//!     event_loop.token(),
 //!     vec![Format::Yuyv, Format::C8],
 //!     None // we don't provide a logger here
 //! );
@@ -42,7 +43,8 @@
 //! # extern crate wayland_server;
 //! # extern crate smithay;
 //! # use wayland_server::protocol::wl_buffer::WlBuffer;
-//! # fn wrap(buffer: &WlBuffer) {
+//! # use wayland_server::Resource;
+//! # fn wrap(buffer: &Resource<WlBuffer>) {
 //! use smithay::wayland::shm::{with_buffer_contents, BufferData};
 //!
 //! with_buffer_contents(&buffer,
@@ -64,7 +66,8 @@
 use self::pool::{Pool, ResizeError};
 use std::rc::Rc;
 use std::sync::Arc;
-use wayland_server::{resource_is_registered, Client, EventLoopHandle, Global, Resource};
+use wayland_server::{Display, Global, LoopToken, NewResource, Resource};
+use wayland_server::commons::Implementation;
 use wayland_server::protocol::{wl_buffer, wl_shm, wl_shm_pool};
 
 mod pool;
@@ -77,6 +80,7 @@ mod pool;
 pub struct ShmGlobalData {
     formats: Rc<Vec<wl_shm::Format>>,
     log: ::slog::Logger,
+    token: LoopToken,
 }
 
 /// Create a new SHM global advertizing given supported formats.
@@ -85,12 +89,15 @@ pub struct ShmGlobalData {
 /// as they are required by the protocol. Formats given as argument
 /// as additionnaly advertized.
 ///
-/// The global is directly registered into the eventloop, and this function
+/// The global is directly created on the provided `Display`, and this function
 /// returns the global handle, in case you whish to remove this global in
 /// the future.
 pub fn init_shm_global<L>(
-    evlh: &mut EventLoopHandle, mut formats: Vec<wl_shm::Format>, logger: L
-) -> Global<wl_shm::WlShm, ShmGlobalData>
+    display: &mut Display,
+    token: LoopToken,
+    mut formats: Vec<wl_shm::Format>,
+    logger: L,
+) -> Global<wl_shm::WlShm>
 where
     L: Into<Option<::slog::Logger>>,
 {
@@ -102,9 +109,16 @@ where
     let data = ShmGlobalData {
         formats: Rc::new(formats),
         log: log.new(o!("smithay_module" => "shm_handler")),
+        token: token.clone(),
     };
 
-    evlh.register_global::<wl_shm::WlShm, _>(1, shm_global_bind, data)
+    display.create_global::<wl_shm::WlShm, _>(&token, 1, move |_version, shm_new: NewResource<_>| {
+        let shm = shm_new.implement_nonsend(data.clone(), None::<fn(_, _)>, &data.token);
+        // send the formats
+        for f in &data.formats[..] {
+            shm.send(wl_shm::Event::Format { format: *f });
+        }
+    })
 }
 
 /// Error that can occur when accessing an SHM buffer
@@ -131,11 +145,11 @@ pub enum BufferAccessError {
 ///
 /// If the buffer is not managed by the provided `ShmGlobal`, the closure is not called
 /// and this method will return `Err(())` (this will be the case for an EGL buffer for example).
-pub fn with_buffer_contents<F>(buffer: &wl_buffer::WlBuffer, f: F) -> Result<(), BufferAccessError>
+pub fn with_buffer_contents<F>(buffer: &Resource<wl_buffer::WlBuffer>, f: F) -> Result<(), BufferAccessError>
 where
     F: FnOnce(&[u8], BufferData),
 {
-    if !resource_is_registered(buffer, &buffer_implementation()) {
+    if !buffer.is_implemented_with::<ShmGlobalData>() {
         return Err(BufferAccessError::NotManaged);
     }
     let data = unsafe { &*(buffer.get_user_data() as *mut InternalBufferData) };
@@ -151,52 +165,43 @@ where
     Ok(())
 }
 
-fn shm_global_bind(evlh: &mut EventLoopHandle, data: &mut ShmGlobalData, _: &Client, global: wl_shm::WlShm) {
-    // register an handler for this shm
-    evlh.register(&global, shm_implementation(), data.clone(), None);
-    // and then the custom formats
-    for f in &data.formats[..] {
-        global.format(*f);
-    }
-}
+impl Implementation<Resource<wl_shm::WlShm>, wl_shm::Request> for ShmGlobalData {
+    fn receive(&mut self, request: wl_shm::Request, shm: Resource<wl_shm::WlShm>) {
+        use self::wl_shm::{Error, Request};
 
-fn shm_implementation() -> wl_shm::Implementation<ShmGlobalData> {
-    wl_shm::Implementation {
-        create_pool: |evlh, data, _, shm, pool, fd, size| {
-            if size <= 0 {
-                shm.post_error(
-                    wl_shm::Error::InvalidFd as u32,
-                    "Invalid size for a new wl_shm_pool.".into(),
-                );
-                return;
-            }
-            let mmap_pool = match Pool::new(fd, size as usize, data.log.clone()) {
-                Ok(p) => p,
-                Err(()) => {
+        match request {
+            Request::CreatePool { id: pool, fd, size } => {
+                if size <= 0 {
                     shm.post_error(
-                        wl_shm::Error::InvalidFd as u32,
-                        format!("Failed mmap of fd {}.", fd),
+                        Error::InvalidFd as u32,
+                        "Invalid size for a new wl_shm_pool.".into(),
                     );
                     return;
                 }
-            };
-            let arc_pool = Box::new(Arc::new(mmap_pool));
-            evlh.register(
-                &pool,
-                shm_pool_implementation(),
-                data.clone(),
-                Some(destroy_shm_pool),
-            );
-            pool.set_user_data(Box::into_raw(arc_pool) as *mut ());
-        },
+                let mmap_pool = match Pool::new(fd, size as usize, self.log.clone()) {
+                    Ok(p) => p,
+                    Err(()) => {
+                        shm.post_error(
+                            wl_shm::Error::InvalidFd as u32,
+                            format!("Failed mmap of fd {}.", fd),
+                        );
+                        return;
+                    }
+                };
+                let arc_pool = Box::new(Arc::new(mmap_pool));
+                let pool = pool.implement_nonsend(
+                    self.clone(),
+                    Some(|pool: Resource<_>, _| {
+                        drop(unsafe { Box::from_raw(pool.get_user_data() as *mut Arc<Pool>) })
+                    }),
+                    &self.token,
+                );
+                pool.set_user_data(Box::into_raw(arc_pool) as *mut ());
+            }
+        }
     }
 }
 
-fn destroy_shm_pool(pool: &wl_shm_pool::WlShmPool) {
-    let arc_pool = unsafe { Box::from_raw(pool.get_user_data() as *mut Arc<Pool>) };
-    drop(arc_pool)
-}
-
 /// Details of the contents of a buffer relative to its pool
 #[derive(Copy, Clone, Debug)]
 pub struct BufferData {
@@ -217,30 +222,48 @@ struct InternalBufferData {
     data: BufferData,
 }
 
-fn shm_pool_implementation() -> wl_shm_pool::Implementation<ShmGlobalData> {
-    wl_shm_pool::Implementation {
-        create_buffer: |evlh, data, _, pool, buffer, offset, width, height, stride, format| {
-            if !data.formats.contains(&format) {
-                buffer.post_error(wl_shm::Error::InvalidFormat as u32, String::new());
-                return;
+impl Implementation<Resource<wl_shm_pool::WlShmPool>, wl_shm_pool::Request> for ShmGlobalData {
+    fn receive(&mut self, request: wl_shm_pool::Request, pool: Resource<wl_shm_pool::WlShmPool>) {
+        use self::wl_shm_pool::Request;
+
+        let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
+
+        match request {
+            Request::CreateBuffer {
+                id: buffer,
+                offset,
+                width,
+                height,
+                stride,
+                format,
+            } => {
+                if !self.formats.contains(&format) {
+                    pool.post_error(
+                        wl_shm::Error::InvalidFormat as u32,
+                        format!("SHM format {:?} is not supported.", format),
+                    );
+                    return;
+                }
+                let data = Box::into_raw(Box::new(InternalBufferData {
+                    pool: arc_pool.clone(),
+                    data: BufferData {
+                        offset: offset,
+                        width: width,
+                        height: height,
+                        stride: stride,
+                        format: format,
+                    },
+                }));
+                let buffer = buffer.implement_nonsend(
+                    self.clone(),
+                    Some(|buffer: Resource<_>, _| {
+                        drop(unsafe { Box::from_raw(buffer.get_user_data() as *mut InternalBufferData) })
+                    }),
+                    &self.token,
+                );
+                buffer.set_user_data(data as *mut ());
             }
-            let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
-            let data = Box::into_raw(Box::new(InternalBufferData {
-                pool: arc_pool.clone(),
-                data: BufferData {
-                    offset: offset,
-                    width: width,
-                    height: height,
-                    stride: stride,
-                    format: format,
-                },
-            }));
-            evlh.register(&buffer, buffer_implementation(), (), Some(destroy_buffer));
-            buffer.set_user_data(data as *mut ());
-        },
-        resize: |_, _, _, pool, size| {
-            let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
-            match arc_pool.resize(size) {
+            Request::Resize { size } => match arc_pool.resize(size) {
                 Ok(()) => {}
                 Err(ResizeError::InvalidSize) => {
                     pool.post_error(
@@ -251,19 +274,15 @@ fn shm_pool_implementation() -> wl_shm_pool::Implementation<ShmGlobalData> {
                 Err(ResizeError::MremapFailed) => {
                     pool.post_error(wl_shm::Error::InvalidFd as u32, "mremap failed.".into());
                 }
-            }
-        },
-        destroy: |_, _, _, _| {},
+            },
+            Request::Destroy => {}
+        }
     }
 }
 
-fn destroy_buffer(buffer: &wl_buffer::WlBuffer) {
-    let buffer_data = unsafe { Box::from_raw(buffer.get_user_data() as *mut InternalBufferData) };
-    drop(buffer_data)
-}
-
-fn buffer_implementation() -> wl_buffer::Implementation<()> {
-    wl_buffer::Implementation {
-        destroy: |_, _, _, _| {},
+impl Implementation<Resource<wl_buffer::WlBuffer>, wl_buffer::Request> for ShmGlobalData {
+    fn receive(&mut self, request: wl_buffer::Request, _pool: Resource<wl_buffer::WlBuffer>) {
+        // this will break if new requests are added to buffer =)
+        let wl_buffer::Request::Destroy = request;
     }
 }

wayland.shm: migrate to wayland_rs-0.20