scarab_plugin_api/object_model/
handle.rs1use std::fmt;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11#[repr(u8)]
12pub enum ObjectType {
13 Window = 0,
15 Tab = 1,
17 Pane = 2,
19 MuxWindow = 3,
21 MuxTab = 4,
23 MuxPane = 5,
25}
26
27impl fmt::Display for ObjectType {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 match self {
30 ObjectType::Window => write!(f, "Window"),
31 ObjectType::Tab => write!(f, "Tab"),
32 ObjectType::Pane => write!(f, "Pane"),
33 ObjectType::MuxWindow => write!(f, "MuxWindow"),
34 ObjectType::MuxTab => write!(f, "MuxTab"),
35 ObjectType::MuxPane => write!(f, "MuxPane"),
36 }
37 }
38}
39
40#[derive(Clone, Copy, PartialEq, Eq, Hash)]
61pub struct ObjectHandle {
62 object_type: ObjectType,
63 id: u64,
64 generation: u32,
65}
66
67impl ObjectHandle {
68 pub const fn new(object_type: ObjectType, id: u64, generation: u32) -> Self {
76 Self {
77 object_type,
78 id,
79 generation,
80 }
81 }
82
83 #[inline]
85 pub const fn object_type(&self) -> ObjectType {
86 self.object_type
87 }
88
89 #[inline]
91 pub const fn id(&self) -> u64 {
92 self.id
93 }
94
95 #[inline]
97 pub const fn generation(&self) -> u32 {
98 self.generation
99 }
100
101 #[inline]
117 pub const fn is_valid(&self, current_generation: u32) -> bool {
118 self.generation == current_generation
119 }
120
121 #[inline]
125 pub const fn next_generation(&self) -> Self {
126 Self {
127 object_type: self.object_type,
128 id: self.id,
129 generation: self.generation.wrapping_add(1),
130 }
131 }
132}
133
134impl fmt::Debug for ObjectHandle {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 write!(
137 f,
138 "ObjectHandle({}, id={}, gen={})",
139 self.object_type, self.id, self.generation
140 )
141 }
142}
143
144impl fmt::Display for ObjectHandle {
145 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146 write!(f, "{}#{}", self.object_type, self.id)
147 }
148}
149
150unsafe impl Send for ObjectHandle {}
152unsafe impl Sync for ObjectHandle {}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157
158 #[test]
159 fn test_handle_creation() {
160 let handle = ObjectHandle::new(ObjectType::Window, 42, 1);
161 assert_eq!(handle.object_type(), ObjectType::Window);
162 assert_eq!(handle.id(), 42);
163 assert_eq!(handle.generation(), 1);
164 }
165
166 #[test]
167 fn test_handle_equality() {
168 let h1 = ObjectHandle::new(ObjectType::Tab, 10, 1);
169 let h2 = ObjectHandle::new(ObjectType::Tab, 10, 1);
170 let h3 = ObjectHandle::new(ObjectType::Tab, 10, 2);
171 let h4 = ObjectHandle::new(ObjectType::Pane, 10, 1);
172
173 assert_eq!(h1, h2);
174 assert_ne!(h1, h3); assert_ne!(h1, h4); }
177
178 #[test]
179 fn test_handle_validation() {
180 let handle = ObjectHandle::new(ObjectType::Window, 1, 5);
181 assert!(handle.is_valid(5));
182 assert!(!handle.is_valid(4));
183 assert!(!handle.is_valid(6));
184 }
185
186 #[test]
187 fn test_next_generation() {
188 let h1 = ObjectHandle::new(ObjectType::Pane, 100, 1);
189 let h2 = h1.next_generation();
190
191 assert_eq!(h2.id(), 100);
192 assert_eq!(h2.object_type(), ObjectType::Pane);
193 assert_eq!(h2.generation(), 2);
194 assert!(!h1.is_valid(2));
195 assert!(h2.is_valid(2));
196 }
197
198 #[test]
199 fn test_generation_wrapping() {
200 let handle = ObjectHandle::new(ObjectType::Window, 1, u32::MAX);
201 let next = handle.next_generation();
202 assert_eq!(next.generation(), 0); }
204
205 #[test]
206 fn test_handle_copy() {
207 let h1 = ObjectHandle::new(ObjectType::Tab, 5, 3);
208 let h2 = h1; assert_eq!(h1, h2);
210 assert_eq!(h1.id(), h2.id()); }
212
213 #[test]
214 fn test_object_type_display() {
215 assert_eq!(ObjectType::Window.to_string(), "Window");
216 assert_eq!(ObjectType::Tab.to_string(), "Tab");
217 assert_eq!(ObjectType::Pane.to_string(), "Pane");
218 assert_eq!(ObjectType::MuxWindow.to_string(), "MuxWindow");
219 assert_eq!(ObjectType::MuxTab.to_string(), "MuxTab");
220 assert_eq!(ObjectType::MuxPane.to_string(), "MuxPane");
221 }
222
223 #[test]
224 fn test_handle_display() {
225 let handle = ObjectHandle::new(ObjectType::Window, 42, 1);
226 assert_eq!(handle.to_string(), "Window#42");
227 }
228
229 #[test]
230 fn test_handle_debug() {
231 let handle = ObjectHandle::new(ObjectType::Pane, 7, 3);
232 let debug_str = format!("{:?}", handle);
233 assert!(debug_str.contains("Pane"));
234 assert!(debug_str.contains("id=7"));
235 assert!(debug_str.contains("gen=3"));
236 }
237}