1use std::borrow::Cow;
6use std::ffi::{CStr, CString};
7use std::fmt;
8use std::hash::{Hash, Hasher};
9use std::num::NonZeroU32;
10use std::os::fd::OwnedFd;
11
12mod ring_buffer;
13pub mod transport;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum IoMode {
18 Blocking,
23 NonBlocking,
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
36pub struct ObjectId(pub NonZeroU32);
37
38impl ObjectId {
39 pub const DISPLAY: Self = Self(unsafe { NonZeroU32::new_unchecked(1) });
40 pub const MAX_CLIENT: Self = Self(unsafe { NonZeroU32::new_unchecked(0xFEFFFFFF) });
41 pub const MIN_SERVER: Self = Self(unsafe { NonZeroU32::new_unchecked(0xFF000000) });
42
43 #[must_use]
45 pub fn as_u32(self) -> u32 {
46 self.0.get()
47 }
48
49 #[must_use]
51 pub fn created_by_server(self) -> bool {
52 self >= Self::MIN_SERVER
53 }
54
55 #[must_use]
57 pub fn created_by_client(self) -> bool {
58 self <= Self::MAX_CLIENT
59 }
60}
61
62#[derive(Debug, Clone, Copy)]
64pub struct MessageHeader {
65 pub object_id: ObjectId,
67 pub size: u16,
69 pub opcode: u16,
71}
72
73impl MessageHeader {
74 pub const SIZE: usize = 8;
76}
77
78#[derive(Debug)]
80pub struct Message {
81 pub header: MessageHeader,
82 pub args: Vec<ArgValue>,
83}
84
85#[derive(Debug, PartialEq, Eq)]
86pub enum ArgType {
87 Int,
88 Uint,
89 Fixed,
90 Object,
91 OptObject,
92 NewId(&'static Interface),
93 AnyNewId,
94 String,
95 OptString,
96 Array,
97 Fd,
98}
99
100#[derive(Debug)]
101pub enum ArgValue {
102 Int(i32),
103 Uint(u32),
104 Fixed(Fixed),
105 Object(ObjectId),
106 OptObject(Option<ObjectId>),
107 NewId(ObjectId),
108 AnyNewId(Cow<'static, CStr>, u32, ObjectId),
109 String(CString),
110 OptString(Option<CString>),
111 Array(Vec<u8>),
112 Fd(OwnedFd),
113}
114
115impl ArgValue {
116 #[must_use]
118 pub fn size(&self) -> usize {
119 match self {
120 Self::Int(_)
121 | Self::Uint(_)
122 | Self::Fixed(_)
123 | Self::Object(_)
124 | Self::OptObject(_)
125 | Self::NewId(_)
126 | Self::OptString(None) => 4,
127 Self::AnyNewId(iface, _version, _id) => {
128 iface.to_bytes_with_nul().len().next_multiple_of(4) + 12
129 }
130 Self::String(string) | Self::OptString(Some(string)) => {
131 string.to_bytes_with_nul().len().next_multiple_of(4) + 4
132 }
133 Self::Array(array) => array.len().next_multiple_of(4) + 4,
134 Self::Fd(_) => 0,
135 }
136 }
137}
138
139#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
141pub struct Fixed(pub i32);
142
143impl From<i32> for Fixed {
144 fn from(value: i32) -> Self {
145 Self(value * 256)
146 }
147}
148
149impl From<u32> for Fixed {
150 fn from(value: u32) -> Self {
151 Self(value as i32 * 256)
152 }
153}
154
155impl From<f32> for Fixed {
156 fn from(value: f32) -> Self {
157 Self((value * 256.0) as i32)
158 }
159}
160
161impl From<f64> for Fixed {
162 fn from(value: f64) -> Self {
163 Self((value * 256.0) as i32)
164 }
165}
166
167impl Fixed {
168 pub const ZERO: Self = Self(0);
169 pub const ONE: Self = Self(256);
170 pub const MINUS_ONE: Self = Self(-256);
171
172 #[must_use]
173 pub fn as_f64(self) -> f64 {
174 self.0 as f64 / 256.0
175 }
176
177 #[must_use]
178 pub fn as_f32(self) -> f32 {
179 self.0 as f32 / 256.0
180 }
181
182 #[must_use]
183 pub fn as_int(self) -> i32 {
184 self.0 / 256
185 }
186
187 #[must_use]
188 pub fn is_int(self) -> bool {
189 self.0 & 255 == 0
190 }
191}
192
193impl fmt::Debug for Fixed {
194 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195 self.as_f64().fmt(f)
196 }
197}
198
199pub struct Interface {
203 pub name: &'static CStr,
204 pub version: u32,
205 pub events: &'static [MessageDesc],
206 pub requests: &'static [MessageDesc],
207}
208
209#[derive(Debug, Clone, Copy)]
211pub struct MessageDesc {
212 pub name: &'static str,
213 pub is_destructor: bool,
214 pub signature: &'static [ArgType],
215}
216
217impl PartialEq for &'static Interface {
218 fn eq(&self, other: &Self) -> bool {
219 self.name == other.name
220 }
221}
222
223impl Eq for &'static Interface {}
224
225impl Hash for &'static Interface {
226 fn hash<H: Hasher>(&self, state: &mut H) {
227 self.name.hash(state);
228 }
229}
230
231impl fmt::Debug for Interface {
232 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
233 f.debug_tuple("Interface").field(&self.name).finish()
234 }
235}
236
237#[derive(Default)]
239pub struct MessageBuffersPool {
240 pool: Vec<Vec<ArgValue>>,
241}
242
243impl MessageBuffersPool {
244 pub fn reuse_args(&mut self, mut buf: Vec<ArgValue>) {
245 buf.clear();
246 self.pool.push(buf);
247 }
248
249 pub fn get_args(&mut self) -> Vec<ArgValue> {
250 self.pool.pop().unwrap_or_default()
251 }
252}