| //! Common definitions for wayland |
| //! |
| //! This crate hosts common type and traits used to represent wayland messages |
| //! and routines in the `wayland-client` and `wayland-server` crates. |
| //! |
| //! This notably includes the `Interface` trait, which can exhaustively describe |
| //! any wayland interface. Its implementations are intended to be generated by the |
| //! `wayland-scanner` crate. |
| //! |
| //! The principal user-facing definition provided by this crate is the `Implementation` |
| //! trait, which as a user of `wayland-client` or `wayland-server` you will be using |
| //! to define objects able to handle the messages your program receives. Note that |
| //! this trait is auto-implemented for closures with appropriate signature, for |
| //! convenience. |
| |
| #![warn(missing_docs, missing_debug_implementations)] |
| |
| #[macro_use] |
| extern crate nix; |
| |
| use std::os::raw::c_void; |
| use wayland_sys::common as syscom; |
| |
| pub mod debug; |
| pub mod filter; |
| pub mod map; |
| pub mod socket; |
| pub mod user_data; |
| pub mod wire; |
| |
| pub use smallvec::smallvec; |
| |
| /// A group of messages |
| /// |
| /// This represents a group of message that can be serialized on the protocol wire. |
| /// Typically the set of events or requests of a single interface. |
| /// |
| /// Implementations of this trait are supposed to be |
| /// generated using the `wayland-scanner` crate. |
| pub trait MessageGroup: Sized { |
| /// Wire representation of this MessageGroup |
| const MESSAGES: &'static [wire::MessageDesc]; |
| /// The wrapper type for ObjectMap allowing the mapping of Object and |
| /// NewId arguments to the object map during parsing. |
| type Map; |
| /// The opcode of this message |
| fn opcode(&self) -> u16; |
| /// Whether this message is a destructor |
| /// |
| /// If it is, once send or receive the associated object cannot be used any more. |
| fn is_destructor(&self) -> bool; |
| /// The minimal object version for which this message exists |
| fn since(&self) -> u32; |
| /// Retrieve the child `Object` associated with this message if any |
| fn child<Meta: self::map::ObjectMetadata>( |
| opcode: u16, |
| version: u32, |
| meta: &Meta, |
| ) -> Option<crate::map::Object<Meta>>; |
| /// Construct a message from its raw representation |
| // -- The lint is allowed because fixing it would be a breaking change -- |
| #[allow(clippy::result_unit_err)] |
| fn from_raw(msg: wire::Message, map: &mut Self::Map) -> Result<Self, ()>; |
| /// Turn this message into its raw representation |
| fn into_raw(self, send_id: u32) -> wire::Message; |
| /// Construct a message of this group from its C representation |
| /// |
| /// # Safety |
| /// |
| /// The pointers provided to this function must all be valid pointers from |
| /// `libwayland-client` |
| // -- The lint is allowed because fixing it would be a breaking change -- |
| #[allow(clippy::result_unit_err)] |
| unsafe fn from_raw_c( |
| obj: *mut c_void, |
| opcode: u32, |
| args: *const syscom::wl_argument, |
| ) -> Result<Self, ()>; |
| /// Build a C representation of this message |
| /// |
| /// It can only be accessed from the provided closure, and this consumes |
| /// the message. |
| // -- The lint is allowed because fixing it would be a breaking change -- |
| #[allow(clippy::wrong_self_convention)] |
| fn as_raw_c_in<F, T>(self, f: F) -> T |
| where |
| F: FnOnce(u32, &mut [syscom::wl_argument]) -> T; |
| } |
| |
| /// The description of a wayland interface |
| /// |
| /// Implementations of this trait are supposed to be |
| /// generated using the `wayland-scanner` crate. |
| pub trait Interface: 'static { |
| /// Set of requests associated to this interface |
| /// |
| /// Requests are messages from the client to the server |
| type Request: MessageGroup + 'static; |
| /// Set of events associated to this interface |
| /// |
| /// Events are messages from the server to the client |
| type Event: MessageGroup + 'static; |
| /// Name of this interface |
| const NAME: &'static str; |
| /// Maximum supported version of this interface |
| /// |
| /// This is the maximum version supported by the protocol specification currently |
| /// used by this library, and should not be used as-is in your code, as a version |
| /// change can subtly change the behavior of some objects. |
| /// |
| /// Server are supposed to be able to handle all versions from 1 to the one they |
| /// advertise through the registry, and clients can choose any version among the |
| /// ones the server supports. |
| const VERSION: u32; |
| /// Pointer to the C representation of this interface |
| fn c_interface() -> *const syscom::wl_interface; |
| } |
| |
| /// An empty enum representing a MessageGroup with no messages |
| #[derive(Debug)] |
| pub enum NoMessage {} |
| |
| #[cfg(not(tarpaulin_include))] |
| impl MessageGroup for NoMessage { |
| const MESSAGES: &'static [wire::MessageDesc] = &[]; |
| type Map = (); |
| fn is_destructor(&self) -> bool { |
| match *self {} |
| } |
| fn opcode(&self) -> u16 { |
| match *self {} |
| } |
| fn since(&self) -> u32 { |
| match *self {} |
| } |
| fn child<M: self::map::ObjectMetadata>(_: u16, _: u32, _: &M) -> Option<crate::map::Object<M>> { |
| None |
| } |
| fn from_raw(_: wire::Message, _: &mut ()) -> Result<Self, ()> { |
| Err(()) |
| } |
| fn into_raw(self, _: u32) -> wire::Message { |
| match self {} |
| } |
| unsafe fn from_raw_c( |
| _obj: *mut c_void, |
| _opcode: u32, |
| _args: *const syscom::wl_argument, |
| ) -> Result<Self, ()> { |
| Err(()) |
| } |
| fn as_raw_c_in<F, T>(self, _f: F) -> T |
| where |
| F: FnOnce(u32, &mut [syscom::wl_argument]) -> T, |
| { |
| match self {} |
| } |
| } |
| |
| /// Stores a value in a threadafe container that |
| /// only lets you access it from its owning thread |
| /// |
| /// If the ThreadGuard is dropped from the wrong thread, |
| /// the underlying value will be leaked. |
| #[derive(Debug)] |
| pub struct ThreadGuard<T: ?Sized> { |
| thread: std::thread::ThreadId, |
| val: std::mem::ManuallyDrop<T>, |
| } |
| |
| impl<T> ThreadGuard<T> { |
| /// Create a new ThreadGuard wrapper |
| pub fn new(val: T) -> ThreadGuard<T> { |
| ThreadGuard { val: std::mem::ManuallyDrop::new(val), thread: std::thread::current().id() } |
| } |
| } |
| |
| impl<T: ?Sized> ThreadGuard<T> { |
| /// Access the underlying value |
| /// |
| /// Panics if done on the wrong thread |
| pub fn get(&self) -> &T { |
| self.try_get().expect("Attempted to access a ThreadGuard contents from the wrong thread.") |
| } |
| |
| /// Mutably access the underlying value |
| /// |
| /// Panics if done on the wrong thread |
| pub fn get_mut(&mut self) -> &mut T { |
| self.try_get_mut() |
| .expect("Attempted to access a ThreadGuard contents from the wrong thread.") |
| } |
| |
| /// Try to access the underlying value |
| /// |
| /// Returns `None` if done on the wrong thread |
| pub fn try_get(&self) -> Option<&T> { |
| if self.thread == ::std::thread::current().id() { |
| Some(&self.val) |
| } else { |
| None |
| } |
| } |
| |
| /// Try to mutably access the underlying value |
| /// |
| /// Returns `None` if done on the wrong thread |
| pub fn try_get_mut(&mut self) -> Option<&mut T> { |
| if self.thread == ::std::thread::current().id() { |
| Some(&mut self.val) |
| } else { |
| None |
| } |
| } |
| } |
| |
| impl<T: ?Sized> Drop for ThreadGuard<T> { |
| fn drop(&mut self) { |
| // We can only actually perform the drop if we are on the right thread |
| // otherwise it may be racy, so we just leak the value |
| if self.thread == ::std::thread::current().id() { |
| unsafe { std::mem::ManuallyDrop::drop(&mut self.val) } |
| } |
| } |
| } |
| |
| unsafe impl<T: ?Sized> Send for ThreadGuard<T> {} |
| unsafe impl<T: ?Sized> Sync for ThreadGuard<T> {} |