1use std::borrow::Borrow;
4use std::cmp;
5use std::fmt::{self, Debug};
6use std::hash::{Hash, Hasher};
7use std::num::NonZeroU32;
8
9use crate::connection::GenericCallback;
10use crate::protocol::WlDisplay;
11
12pub use wayrs_core::ObjectId;
13use wayrs_core::{Interface, Message, MessageBuffersPool};
14
15#[derive(Clone, Copy)]
23pub struct Object {
24 pub id: ObjectId,
25 pub interface: &'static Interface,
26 pub version: u32,
27}
28
29impl PartialEq for Object {
30 #[inline]
31 fn eq(&self, other: &Self) -> bool {
32 self.id == other.id
33 }
34}
35
36impl Eq for Object {}
37
38impl PartialEq<ObjectId> for Object {
39 #[inline]
40 fn eq(&self, other: &ObjectId) -> bool {
41 self.id == *other
42 }
43}
44
45impl PartialEq<Object> for ObjectId {
46 #[inline]
47 fn eq(&self, other: &Object) -> bool {
48 *self == other.id
49 }
50}
51
52impl PartialOrd for Object {
53 #[inline]
54 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
55 Some(self.cmp(other))
56 }
57}
58
59impl Ord for Object {
60 #[inline]
61 fn cmp(&self, other: &Self) -> cmp::Ordering {
62 self.id.cmp(&other.id)
63 }
64}
65
66impl Hash for Object {
67 #[inline]
68 fn hash<H: Hasher>(&self, state: &mut H) {
69 self.id.hash(state);
70 }
71}
72
73impl Borrow<ObjectId> for Object {
74 #[inline]
75 fn borrow(&self) -> &ObjectId {
76 &self.id
77 }
78}
79
80impl Debug for Object {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 write!(
83 f,
84 "{}@{}v{}",
85 self.interface.name.to_string_lossy(),
86 self.id.0,
87 self.version
88 )
89 }
90}
91
92pub(crate) struct ObjectManager<D> {
93 vacant_ids: Vec<ObjectId>,
94 client_objects: Vec<Option<ObjectState<D>>>,
95 server_objects: Vec<Option<ObjectState<D>>>,
96}
97
98pub(crate) struct ObjectState<D> {
99 pub object: Object,
100 pub is_alive: bool,
101 pub cb: Option<GenericCallback<D>>,
102}
103
104#[doc(hidden)]
105#[derive(Debug)]
106pub struct BadMessage;
107
108#[derive(Debug)]
110pub struct WrongObject;
111
112pub trait Proxy: TryFrom<Object, Error = WrongObject> + Copy {
116 type Event;
117
118 const INTERFACE: &'static Interface;
119
120 #[doc(hidden)]
121 fn new(id: ObjectId, version: u32) -> Self;
122
123 #[doc(hidden)]
124 fn parse_event(
125 event: Message,
126 version: u32,
127 pool: &mut MessageBuffersPool,
128 ) -> Result<Self::Event, BadMessage>;
129
130 fn id(&self) -> ObjectId;
131
132 fn version(&self) -> u32;
133}
134
135impl<P: Proxy> From<P> for Object {
136 fn from(value: P) -> Self {
137 Self {
138 id: value.id(),
139 interface: P::INTERFACE,
140 version: value.version(),
141 }
142 }
143}
144
145impl<D> ObjectManager<D> {
146 pub fn new() -> Self {
147 let mut this = Self {
148 vacant_ids: Vec::new(),
149 client_objects: Vec::with_capacity(16),
150 server_objects: Vec::new(),
151 };
152
153 this.client_objects.push(None);
155
156 this.client_objects.push(Some(ObjectState {
158 object: WlDisplay::INSTANCE.into(),
159 is_alive: true,
160 cb: None,
161 }));
162
163 this
164 }
165
166 pub fn clear_callbacks<D2>(self) -> ObjectManager<D2> {
167 let map = |x: ObjectState<D>| ObjectState {
168 object: x.object,
169 is_alive: x.is_alive,
170 cb: None,
171 };
172 ObjectManager {
173 vacant_ids: self.vacant_ids,
174 client_objects: self
175 .client_objects
176 .into_iter()
177 .map(|x| x.map(map))
178 .collect(),
179 server_objects: self
180 .server_objects
181 .into_iter()
182 .map(|x| x.map(map))
183 .collect(),
184 }
185 }
186
187 pub fn alloc_client_object(
188 &mut self,
189 interface: &'static Interface,
190 version: u32,
191 ) -> &mut ObjectState<D> {
192 let id = self.vacant_ids.pop().unwrap_or_else(|| {
193 let id = self.client_objects.len() as u32;
194 self.client_objects.push(None);
195 ObjectId(NonZeroU32::new(id).unwrap())
196 });
197
198 assert!(id.created_by_client());
199 let obj = self.client_objects.get_mut(id.0.get() as usize).unwrap();
200 assert!(obj.is_none());
201
202 obj.insert(ObjectState {
203 object: Object {
204 id,
205 interface,
206 version,
207 },
208 is_alive: true,
209 cb: None,
210 })
211 }
212
213 pub fn register_server_object(&mut self, object: Object) -> &mut ObjectState<D> {
214 assert!(object.id.created_by_server());
215
216 let index = (object.id.as_u32() - ObjectId::MIN_SERVER.as_u32()) as usize;
217
218 while index >= self.server_objects.len() {
219 self.server_objects.push(None);
220 }
221
222 self.server_objects[index].insert(ObjectState {
223 object,
224 is_alive: true,
225 cb: None,
226 })
227 }
228
229 pub fn get_object_mut(&mut self, id: ObjectId) -> Option<&mut ObjectState<D>> {
230 if id.created_by_client() {
231 self.client_objects
232 .get_mut(id.as_u32() as usize)
233 .and_then(Option::as_mut)
234 } else {
235 self.server_objects
236 .get_mut((id.as_u32() - ObjectId::MIN_SERVER.as_u32()) as usize)
237 .and_then(Option::as_mut)
238 }
239 }
240
241 pub fn delete_client_object(&mut self, id: ObjectId) {
243 assert!(id.created_by_client());
244 *self.client_objects.get_mut(id.as_u32() as usize).unwrap() = None;
245 self.vacant_ids.push(id);
246 }
247}