1use std::{ffi::CString, os::unix::io::AsRawFd};
4
5pub use wayland_sys::common::{wl_argument, wl_interface, wl_message};
6
7#[derive(Clone, Copy, PartialEq, Eq, Debug)]
9pub enum AllowNull {
10 Yes,
12 No,
14}
15
16#[derive(Copy, Clone, PartialEq, Eq, Debug)]
18pub enum ArgumentType {
19 Int,
21 Uint,
23 Fixed,
25 Str(AllowNull),
27 Object(AllowNull),
29 NewId,
31 Array,
33 Fd,
37}
38
39impl ArgumentType {
40 pub fn same_type(self, other: Self) -> bool {
42 std::mem::discriminant(&self) == std::mem::discriminant(&other)
43 }
44}
45
46#[derive(Debug, Clone)]
48#[allow(clippy::box_collection)]
49pub enum Argument<Id, Fd> {
50 Int(i32),
52 Uint(u32),
54 Fixed(i32),
56 Str(Option<Box<CString>>),
61 Object(Id),
63 NewId(Id),
65 Array(Box<Vec<u8>>),
70 Fd(Fd),
74}
75
76impl<Id, Fd> Argument<Id, Fd> {
77 pub fn get_type(&self) -> ArgumentType {
79 match *self {
80 Self::Int(_) => ArgumentType::Int,
81 Self::Uint(_) => ArgumentType::Uint,
82 Self::Fixed(_) => ArgumentType::Fixed,
83 Self::Str(_) => ArgumentType::Str(AllowNull::Yes),
84 Self::Object(_) => ArgumentType::Object(AllowNull::Yes),
85 Self::NewId(_) => ArgumentType::NewId,
86 Self::Array(_) => ArgumentType::Array,
87 Self::Fd(_) => ArgumentType::Fd,
88 }
89 }
90
91 fn map_fd<T>(self, f: &mut impl FnMut(Fd) -> T) -> Argument<Id, T> {
92 match self {
93 Self::Int(val) => Argument::Int(val),
94 Self::Uint(val) => Argument::Uint(val),
95 Self::Fixed(val) => Argument::Fixed(val),
96 Self::Str(val) => Argument::Str(val),
97 Self::Object(val) => Argument::Object(val),
98 Self::NewId(val) => Argument::NewId(val),
99 Self::Array(val) => Argument::Array(val),
100 Self::Fd(val) => Argument::Fd(f(val)),
101 }
102 }
103}
104
105impl<Id: PartialEq, Fd: AsRawFd> PartialEq for Argument<Id, Fd> {
106 fn eq(&self, other: &Self) -> bool {
107 match (self, other) {
108 (Self::Int(a), Self::Int(b)) => a == b,
109 (Self::Uint(a), Self::Uint(b)) => a == b,
110 (Self::Fixed(a), Self::Fixed(b)) => a == b,
111 (Self::Str(a), Self::Str(b)) => a == b,
112 (Self::Object(a), Self::Object(b)) => a == b,
113 (Self::NewId(a), Self::NewId(b)) => a == b,
114 (Self::Array(a), Self::Array(b)) => a == b,
115 (Self::Fd(a), Self::Fd(b)) => a.as_raw_fd() == b.as_raw_fd(),
116 _ => false,
117 }
118 }
119}
120
121impl<Id: Eq, Fd: AsRawFd> Eq for Argument<Id, Fd> {}
122
123impl<Id: std::fmt::Display, Fd: AsRawFd> std::fmt::Display for Argument<Id, Fd> {
124 #[cfg_attr(coverage, coverage(off))]
125 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126 match self {
127 Self::Int(value) => write!(f, "{}", value),
128 Self::Uint(value) => write!(f, "{}", value),
129 Self::Fixed(value) => write!(f, "{:.4}", *value as f64 / 256.0),
130 Self::Str(value) => write!(f, "{:?}", value),
131 Self::Object(value) => write!(f, "{}", value),
132 Self::NewId(value) => write!(f, "{}", value),
133 Self::Array(value) => write!(f, "{:?}", value),
134 Self::Fd(value) => write!(f, "{}", value.as_raw_fd()),
135 }
136 }
137}
138
139#[derive(Debug)]
144pub struct Interface {
145 pub name: &'static str,
147 pub version: u32,
149 pub requests: &'static [MessageDesc],
151 pub events: &'static [MessageDesc],
153 pub c_ptr: Option<&'static wayland_sys::common::wl_interface>,
155}
156
157impl std::fmt::Display for Interface {
158 #[cfg_attr(coverage, coverage(off))]
159 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
160 f.write_str(self.name)
161 }
162}
163
164#[derive(Copy, Clone, Debug)]
166pub struct MessageDesc {
167 pub name: &'static str,
169 pub signature: &'static [ArgumentType],
171 pub since: u32,
173 pub is_destructor: bool,
175 pub child_interface: Option<&'static Interface>,
179 pub arg_interfaces: &'static [&'static Interface],
181}
182
183pub static ANONYMOUS_INTERFACE: Interface =
185 Interface { name: "<anonymous>", version: 0, requests: &[], events: &[], c_ptr: None };
186
187#[derive(Copy, Clone, Debug)]
189pub struct ObjectInfo {
190 pub id: u32,
192 pub interface: &'static Interface,
194 pub version: u32,
196}
197
198#[derive(Clone, Debug)]
203pub struct ProtocolError {
204 pub code: u32,
209 pub object_id: u32,
211 pub object_interface: String,
213 pub message: String,
215}
216
217pub const INLINE_ARGS: usize = 4;
223
224#[derive(Clone, Debug)]
226pub struct Message<Id, Fd> {
227 pub sender_id: Id,
229 pub opcode: u16,
231 pub args: smallvec::SmallVec<[Argument<Id, Fd>; INLINE_ARGS]>,
233}
234
235impl<Id, Fd> Message<Id, Fd> {
236 pub fn map_fd<T>(self, mut f: impl FnMut(Fd) -> T) -> Message<Id, T> {
238 Message {
239 sender_id: self.sender_id,
240 opcode: self.opcode,
241 args: self.args.into_iter().map(move |arg| arg.map_fd(&mut f)).collect(),
242 }
243 }
244}
245
246impl<Id: PartialEq, Fd: AsRawFd> PartialEq for Message<Id, Fd> {
247 fn eq(&self, other: &Self) -> bool {
248 self.sender_id == other.sender_id && self.opcode == other.opcode && self.args == other.args
249 }
250}
251
252impl<Id: Eq, Fd: AsRawFd> Eq for Message<Id, Fd> {}
253
254impl std::error::Error for ProtocolError {}
255
256impl std::fmt::Display for ProtocolError {
257 #[cfg_attr(coverage, coverage(off))]
258 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
259 write!(
260 f,
261 "Protocol error {} on object {}@{}: {}",
262 self.code, self.object_interface, self.object_id, self.message
263 )
264 }
265}
266
267#[inline]
269pub fn same_interface(a: &'static Interface, b: &'static Interface) -> bool {
270 std::ptr::eq(a, b) || a.name == b.name
271}
272
273pub(crate) fn check_for_signature<Id, Fd>(
274 signature: &[ArgumentType],
275 args: &[Argument<Id, Fd>],
276) -> bool {
277 if signature.len() != args.len() {
278 return false;
279 }
280 for (typ, arg) in signature.iter().copied().zip(args.iter()) {
281 if !arg.get_type().same_type(typ) {
282 return false;
283 }
284 }
285 true
286}
287
288#[inline]
289#[allow(dead_code)]
290pub(crate) fn same_interface_or_anonymous(a: &'static Interface, b: &'static Interface) -> bool {
291 same_interface(a, b) || same_interface(a, &ANONYMOUS_INTERFACE)
292}
293
294#[derive(Debug, Clone, Copy, PartialEq, Eq)]
296pub enum WEnum<T> {
297 Value(T),
299 Unknown(u32),
301}
302
303#[derive(Debug, Copy, Clone)]
305pub struct WEnumError {
306 typ: &'static str,
307 value: u32,
308}
309
310impl std::error::Error for WEnumError {}
311
312impl std::fmt::Display for WEnumError {
313 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
314 write!(f, "Unknown numeric value {} for enum {}", self.value, self.typ)
315 }
316}
317
318impl<T> WEnum<T> {
319 #[inline]
326 pub fn into_result(self) -> Result<T, WEnumError> {
327 match self {
328 Self::Value(v) => Ok(v),
329 Self::Unknown(value) => Err(WEnumError { typ: std::any::type_name::<T>(), value }),
330 }
331 }
332}
333
334impl<T> From<WEnum<T>> for Result<T, WEnumError> {
335 fn from(me: WEnum<T>) -> Self {
336 me.into_result()
337 }
338}
339
340impl<T: TryFrom<u32>> From<u32> for WEnum<T> {
341 fn from(v: u32) -> Self {
343 match T::try_from(v) {
344 Ok(t) => Self::Value(t),
345 Err(_) => Self::Unknown(v),
346 }
347 }
348}
349
350impl<T: Into<u32>> From<WEnum<T>> for u32 {
351 fn from(enu: WEnum<T>) -> u32 {
353 match enu {
354 WEnum::Unknown(u) => u,
355 WEnum::Value(t) => t.into(),
356 }
357 }
358}