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 pub fn as_u32(self) -> u32 {
45 self.0.get()
46 }
47
48 pub fn created_by_server(self) -> bool {
50 self >= Self::MIN_SERVER
51 }
52
53 pub fn created_by_client(self) -> bool {
55 self <= Self::MAX_CLIENT
56 }
57}
58
59#[derive(Debug, Clone, Copy)]
61pub struct MessageHeader {
62 pub object_id: ObjectId,
64 pub size: u16,
66 pub opcode: u16,
68}
69
70impl MessageHeader {
71 pub const SIZE: usize = 8;
73}
74
75#[derive(Debug)]
77pub struct Message {
78 pub header: MessageHeader,
79 pub args: Vec<ArgValue>,
80}
81
82#[derive(Debug, PartialEq, Eq)]
83pub enum ArgType {
84 Int,
85 Uint,
86 Fixed,
87 Object,
88 OptObject,
89 NewId(&'static Interface),
90 AnyNewId,
91 String,
92 OptString,
93 Array,
94 Fd,
95}
96
97#[derive(Debug)]
98pub enum ArgValue {
99 Int(i32),
100 Uint(u32),
101 Fixed(Fixed),
102 Object(ObjectId),
103 OptObject(Option<ObjectId>),
104 NewId(ObjectId),
105 AnyNewId(Cow<'static, CStr>, u32, ObjectId),
106 String(CString),
107 OptString(Option<CString>),
108 Array(Vec<u8>),
109 Fd(OwnedFd),
110}
111
112impl ArgValue {
113 pub fn size(&self) -> usize {
115 fn len_with_padding(len: usize) -> usize {
116 let padding = (4 - (len % 4)) % 4;
117 4 + len + padding
118 }
119
120 match self {
121 Self::Int(_)
122 | Self::Uint(_)
123 | Self::Fixed(_)
124 | Self::Object(_)
125 | Self::OptObject(_)
126 | Self::NewId(_)
127 | Self::OptString(None) => 4,
128 Self::AnyNewId(iface, _version, _id) => {
129 len_with_padding(iface.to_bytes_with_nul().len()) + 8
130 }
131 Self::String(string) | Self::OptString(Some(string)) => {
132 len_with_padding(string.to_bytes_with_nul().len())
133 }
134 Self::Array(array) => len_with_padding(array.len()),
135 Self::Fd(_) => 0,
136 }
137 }
138}
139
140#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
142pub struct Fixed(pub i32);
143
144impl From<i32> for Fixed {
145 fn from(value: i32) -> Self {
146 Self(value * 256)
147 }
148}
149
150impl From<u32> for Fixed {
151 fn from(value: u32) -> Self {
152 Self(value as i32 * 256)
153 }
154}
155
156impl From<f32> for Fixed {
157 fn from(value: f32) -> Self {
158 Self((value * 256.0) as i32)
159 }
160}
161
162impl From<f64> for Fixed {
163 fn from(value: f64) -> Self {
164 Self((value * 256.0) as i32)
165 }
166}
167
168impl Fixed {
169 pub const ZERO: Self = Self(0);
170 pub const ONE: Self = Self(256);
171 pub const MINUS_ONE: Self = Self(-256);
172
173 pub fn as_f64(self) -> f64 {
174 self.0 as f64 / 256.0
175 }
176
177 pub fn as_f32(self) -> f32 {
178 self.0 as f32 / 256.0
179 }
180
181 pub fn as_int(self) -> i32 {
182 self.0 / 256
183 }
184
185 pub fn is_int(self) -> bool {
186 self.0 & 255 == 0
187 }
188}
189
190impl fmt::Debug for Fixed {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 self.as_f64().fmt(f)
193 }
194}
195
196pub struct Interface {
200 pub name: &'static CStr,
201 pub version: u32,
202 pub events: &'static [MessageDesc],
203 pub requests: &'static [MessageDesc],
204}
205
206#[derive(Debug, Clone, Copy)]
208pub struct MessageDesc {
209 pub name: &'static str,
210 pub is_destructor: bool,
211 pub signature: &'static [ArgType],
212}
213
214impl PartialEq for &'static Interface {
215 fn eq(&self, other: &Self) -> bool {
216 self.name == other.name
217 }
218}
219
220impl Eq for &'static Interface {}
221
222impl Hash for &'static Interface {
223 fn hash<H: Hasher>(&self, state: &mut H) {
224 self.name.hash(state);
225 }
226}
227
228impl fmt::Debug for Interface {
229 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
230 f.debug_tuple("Interface").field(&self.name).finish()
231 }
232}
233
234#[derive(Default)]
236pub struct MessageBuffersPool {
237 pool: Vec<Vec<ArgValue>>,
238}
239
240impl MessageBuffersPool {
241 pub fn reuse_args(&mut self, mut buf: Vec<ArgValue>) {
242 buf.clear();
243 self.pool.push(buf);
244 }
245
246 pub fn get_args(&mut self) -> Vec<ArgValue> {
247 self.pool.pop().unwrap_or_default()
248 }
249}