wayland_commons/
lib.rs

1//! Common definitions for wayland
2//!
3//! This crate hosts common type and traits used to represent wayland messages
4//! and routines in the `wayland-client` and `wayland-server` crates.
5//!
6//! This notably includes the `Interface` trait, which can exhaustively describe
7//! any wayland interface. Its implementations are intended to be generated by the
8//! `wayland-scanner` crate.
9//!
10//! The principal user-facing definition provided by this crate is the `Implementation`
11//! trait, which as a user of `wayland-client` or `wayland-server` you will be using
12//! to define objects able to handle the messages your program receives. Note that
13//! this trait is auto-implemented for closures with appropriate signature, for
14//! convenience.
15
16#![warn(missing_docs, missing_debug_implementations)]
17
18#[macro_use]
19extern crate nix;
20
21use std::os::raw::c_void;
22use wayland_sys::common as syscom;
23
24pub mod debug;
25pub mod filter;
26pub mod map;
27pub mod socket;
28pub mod user_data;
29pub mod wire;
30
31pub use smallvec::smallvec;
32
33/// A group of messages
34///
35/// This represents a group of message that can be serialized on the protocol wire.
36/// Typically the set of events or requests of a single interface.
37///
38/// Implementations of this trait are supposed to be
39/// generated using the `wayland-scanner` crate.
40pub trait MessageGroup: Sized {
41    /// Wire representation of this MessageGroup
42    const MESSAGES: &'static [wire::MessageDesc];
43    /// The wrapper type for ObjectMap allowing the mapping of Object and
44    /// NewId arguments to the object map during parsing.
45    type Map;
46    /// The opcode of this message
47    fn opcode(&self) -> u16;
48    /// Whether this message is a destructor
49    ///
50    /// If it is, once send or receive the associated object cannot be used any more.
51    fn is_destructor(&self) -> bool;
52    /// The minimal object version for which this message exists
53    fn since(&self) -> u32;
54    /// Retrieve the child `Object` associated with this message if any
55    fn child<Meta: self::map::ObjectMetadata>(
56        opcode: u16,
57        version: u32,
58        meta: &Meta,
59    ) -> Option<crate::map::Object<Meta>>;
60    /// Construct a message from its raw representation
61    // -- The lint is allowed because fixing it would be a breaking change --
62    #[allow(clippy::result_unit_err)]
63    fn from_raw(msg: wire::Message, map: &mut Self::Map) -> Result<Self, ()>;
64    /// Turn this message into its raw representation
65    fn into_raw(self, send_id: u32) -> wire::Message;
66    /// Construct a message of this group from its C representation
67    ///
68    /// # Safety
69    ///
70    /// The pointers provided to this function must all be valid pointers from
71    /// `libwayland-client`
72    // -- The lint is allowed because fixing it would be a breaking change --
73    #[allow(clippy::result_unit_err)]
74    unsafe fn from_raw_c(
75        obj: *mut c_void,
76        opcode: u32,
77        args: *const syscom::wl_argument,
78    ) -> Result<Self, ()>;
79    /// Build a C representation of this message
80    ///
81    /// It can only be accessed from the provided closure, and this consumes
82    /// the message.
83    // -- The lint is allowed because fixing it would be a breaking change --
84    #[allow(clippy::wrong_self_convention)]
85    fn as_raw_c_in<F, T>(self, f: F) -> T
86    where
87        F: FnOnce(u32, &mut [syscom::wl_argument]) -> T;
88}
89
90/// The description of a wayland interface
91///
92/// Implementations of this trait are supposed to be
93/// generated using the `wayland-scanner` crate.
94pub trait Interface: 'static {
95    /// Set of requests associated to this interface
96    ///
97    /// Requests are messages from the client to the server
98    type Request: MessageGroup + 'static;
99    /// Set of events associated to this interface
100    ///
101    /// Events are messages from the server to the client
102    type Event: MessageGroup + 'static;
103    /// Name of this interface
104    const NAME: &'static str;
105    /// Maximum supported version of this interface
106    ///
107    /// This is the maximum version supported by the protocol specification currently
108    /// used by this library, and should not be used as-is in your code, as a version
109    /// change can subtly change the behavior of some objects.
110    ///
111    /// Server are supposed to be able to handle all versions from 1 to the one they
112    /// advertise through the registry, and clients can choose any version among the
113    /// ones the server supports.
114    const VERSION: u32;
115    /// Pointer to the C representation of this interface
116    fn c_interface() -> *const syscom::wl_interface;
117}
118
119/// An empty enum representing a MessageGroup with no messages
120#[derive(Debug)]
121pub enum NoMessage {}
122
123#[cfg(not(tarpaulin_include))]
124impl MessageGroup for NoMessage {
125    const MESSAGES: &'static [wire::MessageDesc] = &[];
126    type Map = ();
127    fn is_destructor(&self) -> bool {
128        match *self {}
129    }
130    fn opcode(&self) -> u16 {
131        match *self {}
132    }
133    fn since(&self) -> u32 {
134        match *self {}
135    }
136    fn child<M: self::map::ObjectMetadata>(_: u16, _: u32, _: &M) -> Option<crate::map::Object<M>> {
137        None
138    }
139    fn from_raw(_: wire::Message, _: &mut ()) -> Result<Self, ()> {
140        Err(())
141    }
142    fn into_raw(self, _: u32) -> wire::Message {
143        match self {}
144    }
145    unsafe fn from_raw_c(
146        _obj: *mut c_void,
147        _opcode: u32,
148        _args: *const syscom::wl_argument,
149    ) -> Result<Self, ()> {
150        Err(())
151    }
152    fn as_raw_c_in<F, T>(self, _f: F) -> T
153    where
154        F: FnOnce(u32, &mut [syscom::wl_argument]) -> T,
155    {
156        match self {}
157    }
158}
159
160/// Stores a value in a threadafe container that
161/// only lets you access it from its owning thread
162///
163/// If the ThreadGuard is dropped from the wrong thread,
164/// the underlying value will be leaked.
165#[derive(Debug)]
166pub struct ThreadGuard<T: ?Sized> {
167    thread: std::thread::ThreadId,
168    val: std::mem::ManuallyDrop<T>,
169}
170
171impl<T> ThreadGuard<T> {
172    /// Create a new ThreadGuard wrapper
173    pub fn new(val: T) -> ThreadGuard<T> {
174        ThreadGuard { val: std::mem::ManuallyDrop::new(val), thread: std::thread::current().id() }
175    }
176}
177
178impl<T: ?Sized> ThreadGuard<T> {
179    /// Access the underlying value
180    ///
181    /// Panics if done on the wrong thread
182    pub fn get(&self) -> &T {
183        self.try_get().expect("Attempted to access a ThreadGuard contents from the wrong thread.")
184    }
185
186    /// Mutably access the underlying value
187    ///
188    /// Panics if done on the wrong thread
189    pub fn get_mut(&mut self) -> &mut T {
190        self.try_get_mut()
191            .expect("Attempted to access a ThreadGuard contents from the wrong thread.")
192    }
193
194    /// Try to access the underlying value
195    ///
196    /// Returns `None` if done on the wrong thread
197    pub fn try_get(&self) -> Option<&T> {
198        if self.thread == ::std::thread::current().id() {
199            Some(&self.val)
200        } else {
201            None
202        }
203    }
204
205    /// Try to mutably access the underlying value
206    ///
207    /// Returns `None` if done on the wrong thread
208    pub fn try_get_mut(&mut self) -> Option<&mut T> {
209        if self.thread == ::std::thread::current().id() {
210            Some(&mut self.val)
211        } else {
212            None
213        }
214    }
215}
216
217impl<T: ?Sized> Drop for ThreadGuard<T> {
218    fn drop(&mut self) {
219        // We can only actually perform the drop if we are on the right thread
220        // otherwise it may be racy, so we just leak the value
221        if self.thread == ::std::thread::current().id() {
222            unsafe { std::mem::ManuallyDrop::drop(&mut self.val) }
223        }
224    }
225}
226
227unsafe impl<T: ?Sized> Send for ThreadGuard<T> {}
228unsafe impl<T: ?Sized> Sync for ThreadGuard<T> {}