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> {}