scarab_plugin_api/object_model/
registry.rs1use crate::object_model::{ObjectError, ObjectHandle};
8
9#[derive(Debug, Clone)]
18pub struct RegistryEntry<T> {
19 pub handle: ObjectHandle,
21 pub object: T,
23}
24
25impl<T> RegistryEntry<T> {
26 pub fn new(handle: ObjectHandle, object: T) -> Self {
33 Self { handle, object }
34 }
35
36 #[inline]
38 pub fn handle(&self) -> ObjectHandle {
39 self.handle
40 }
41
42 #[inline]
44 pub fn object(&self) -> &T {
45 &self.object
46 }
47
48 #[inline]
50 pub fn object_mut(&mut self) -> &mut T {
51 &mut self.object
52 }
53
54 #[inline]
56 pub fn into_object(self) -> T {
57 self.object
58 }
59
60 #[inline]
62 pub fn is_valid(&self, current_generation: u32) -> bool {
63 self.handle.is_valid(current_generation)
64 }
65}
66
67pub trait ObjectRegistry<T> {
98 fn register(&mut self, object: T) -> ObjectHandle;
111
112 fn unregister(&mut self, handle: ObjectHandle) -> Result<T, ObjectError>;
126
127 fn get(&self, handle: ObjectHandle) -> Result<&T, ObjectError>;
138
139 fn get_mut(&mut self, handle: ObjectHandle) -> Result<&mut T, ObjectError>;
150
151 fn get_by_id(&self, id: u64) -> Option<&T>;
165
166 fn next_id(&mut self) -> u64;
175
176 fn increment_generation(&mut self, id: u64);
185
186 fn current_generation(&self, id: u64) -> u32;
196
197 fn is_valid(&self, handle: ObjectHandle) -> bool {
207 let current_gen = self.current_generation(handle.id());
208 handle.is_valid(current_gen) && self.get_by_id(handle.id()).is_some()
209 }
210
211 fn all_ids(&self) -> Vec<u64>;
217
218 fn len(&self) -> usize;
224
225 fn is_empty(&self) -> bool {
231 self.len() == 0
232 }
233
234 fn get_parent(&self, handle: &ObjectHandle) -> Result<Option<ObjectHandle>, ObjectError>;
248
249 fn get_children(&self, handle: &ObjectHandle) -> Result<Vec<ObjectHandle>, ObjectError>;
262}
263
264#[cfg(test)]
265mod tests {
266 use super::*;
267 use crate::object_model::handle::ObjectType;
268 use std::collections::HashMap;
269
270 #[derive(Debug, Clone, PartialEq)]
272 struct TestObject {
273 name: String,
274 value: i32,
275 }
276
277 struct TestRegistry {
279 objects: HashMap<u64, RegistryEntry<TestObject>>,
280 next_id_counter: u64,
281 generations: HashMap<u64, u32>,
282 parents: HashMap<u64, ObjectHandle>,
283 children: HashMap<u64, Vec<ObjectHandle>>,
284 }
285
286 impl TestRegistry {
287 fn new() -> Self {
288 Self {
289 objects: HashMap::new(),
290 next_id_counter: 1,
291 generations: HashMap::new(),
292 parents: HashMap::new(),
293 children: HashMap::new(),
294 }
295 }
296
297 fn set_parent(&mut self, child: ObjectHandle, parent: ObjectHandle) {
298 self.parents.insert(child.id(), parent);
299 self.children
300 .entry(parent.id())
301 .or_insert_with(Vec::new)
302 .push(child);
303 }
304 }
305
306 impl ObjectRegistry<TestObject> for TestRegistry {
307 fn register(&mut self, object: TestObject) -> ObjectHandle {
308 let id = self.next_id();
309 let generation = self.current_generation(id);
310 let handle = ObjectHandle::new(ObjectType::Window, id, generation);
311 self.objects.insert(id, RegistryEntry::new(handle, object));
312 handle
313 }
314
315 fn unregister(&mut self, handle: ObjectHandle) -> Result<TestObject, ObjectError> {
316 let current_gen = self.current_generation(handle.id());
317 if !handle.is_valid(current_gen) {
318 return Err(ObjectError::stale_handle(handle, current_gen));
319 }
320
321 self.increment_generation(handle.id());
322 self.objects
323 .remove(&handle.id())
324 .map(|entry| entry.into_object())
325 .ok_or_else(|| ObjectError::not_found(handle))
326 }
327
328 fn get(&self, handle: ObjectHandle) -> Result<&TestObject, ObjectError> {
329 let current_gen = self.current_generation(handle.id());
330 if !handle.is_valid(current_gen) {
331 return Err(ObjectError::stale_handle(handle, current_gen));
332 }
333
334 self.objects
335 .get(&handle.id())
336 .map(|entry| entry.object())
337 .ok_or_else(|| ObjectError::not_found(handle))
338 }
339
340 fn get_mut(&mut self, handle: ObjectHandle) -> Result<&mut TestObject, ObjectError> {
341 let current_gen = self.current_generation(handle.id());
342 if !handle.is_valid(current_gen) {
343 return Err(ObjectError::stale_handle(handle, current_gen));
344 }
345
346 self.objects
347 .get_mut(&handle.id())
348 .map(|entry| entry.object_mut())
349 .ok_or_else(|| ObjectError::not_found(handle))
350 }
351
352 fn get_by_id(&self, id: u64) -> Option<&TestObject> {
353 self.objects.get(&id).map(|entry| entry.object())
354 }
355
356 fn next_id(&mut self) -> u64 {
357 let id = self.next_id_counter;
358 self.next_id_counter += 1;
359 id
360 }
361
362 fn increment_generation(&mut self, id: u64) {
363 let gen = self.generations.entry(id).or_insert(0);
364 *gen = gen.wrapping_add(1);
365 }
366
367 fn current_generation(&self, id: u64) -> u32 {
368 self.generations.get(&id).copied().unwrap_or(0)
369 }
370
371 fn all_ids(&self) -> Vec<u64> {
372 self.objects.keys().copied().collect()
373 }
374
375 fn len(&self) -> usize {
376 self.objects.len()
377 }
378
379 fn get_parent(&self, handle: &ObjectHandle) -> Result<Option<ObjectHandle>, ObjectError> {
380 let current_gen = self.current_generation(handle.id());
381 if !handle.is_valid(current_gen) {
382 return Err(ObjectError::stale_handle(*handle, current_gen));
383 }
384
385 if !self.objects.contains_key(&handle.id()) {
386 return Err(ObjectError::not_found(*handle));
387 }
388
389 Ok(self.parents.get(&handle.id()).copied())
390 }
391
392 fn get_children(&self, handle: &ObjectHandle) -> Result<Vec<ObjectHandle>, ObjectError> {
393 let current_gen = self.current_generation(handle.id());
394 if !handle.is_valid(current_gen) {
395 return Err(ObjectError::stale_handle(*handle, current_gen));
396 }
397
398 if !self.objects.contains_key(&handle.id()) {
399 return Err(ObjectError::not_found(*handle));
400 }
401
402 Ok(self
403 .children
404 .get(&handle.id())
405 .cloned()
406 .unwrap_or_else(Vec::new))
407 }
408 }
409
410 #[test]
411 fn test_registry_entry_creation() {
412 let handle = ObjectHandle::new(ObjectType::Window, 1, 0);
413 let obj = TestObject {
414 name: "test".to_string(),
415 value: 42,
416 };
417 let entry = RegistryEntry::new(handle, obj.clone());
418
419 assert_eq!(entry.handle(), handle);
420 assert_eq!(entry.object(), &obj);
421 }
422
423 #[test]
424 fn test_registry_entry_mutability() {
425 let handle = ObjectHandle::new(ObjectType::Window, 1, 0);
426 let obj = TestObject {
427 name: "test".to_string(),
428 value: 42,
429 };
430 let mut entry = RegistryEntry::new(handle, obj);
431
432 entry.object_mut().value = 100;
433 assert_eq!(entry.object().value, 100);
434 }
435
436 #[test]
437 fn test_register_and_get() {
438 let mut registry = TestRegistry::new();
439 let obj = TestObject {
440 name: "test".to_string(),
441 value: 42,
442 };
443
444 let handle = registry.register(obj.clone());
445 let retrieved = registry.get(handle).unwrap();
446
447 assert_eq!(retrieved, &obj);
448 }
449
450 #[test]
451 fn test_unregister() {
452 let mut registry = TestRegistry::new();
453 let obj = TestObject {
454 name: "test".to_string(),
455 value: 42,
456 };
457
458 let handle = registry.register(obj.clone());
459 assert_eq!(registry.len(), 1);
460
461 let removed = registry.unregister(handle).unwrap();
462 assert_eq!(removed, obj);
463 assert_eq!(registry.len(), 0);
464 }
465
466 #[test]
467 fn test_stale_handle_after_unregister() {
468 let mut registry = TestRegistry::new();
469 let obj = TestObject {
470 name: "test".to_string(),
471 value: 42,
472 };
473
474 let handle = registry.register(obj.clone());
475 registry.unregister(handle).unwrap();
476
477 let result = registry.get(handle);
479 assert!(matches!(result, Err(ObjectError::StaleHandle { .. })));
480 }
481
482 #[test]
483 fn test_generation_increment() {
484 let mut registry = TestRegistry::new();
485
486 let obj1 = TestObject {
487 name: "first".to_string(),
488 value: 1,
489 };
490 let obj2 = TestObject {
491 name: "second".to_string(),
492 value: 2,
493 };
494
495 let handle1 = registry.register(obj1);
496 let id = handle1.id();
497
498 registry.unregister(handle1).unwrap();
499
500 assert_eq!(registry.current_generation(id), 1);
502
503 let handle2 = registry.register(obj2);
505 assert_ne!(handle2.id(), id);
506 assert_eq!(handle2.generation(), 0); }
508
509 #[test]
510 fn test_get_by_id() {
511 let mut registry = TestRegistry::new();
512 let obj = TestObject {
513 name: "test".to_string(),
514 value: 42,
515 };
516
517 let handle = registry.register(obj.clone());
518 let retrieved = registry.get_by_id(handle.id()).unwrap();
519
520 assert_eq!(retrieved, &obj);
521 }
522
523 #[test]
524 fn test_is_valid() {
525 let mut registry = TestRegistry::new();
526 let obj = TestObject {
527 name: "test".to_string(),
528 value: 42,
529 };
530
531 let handle = registry.register(obj);
532 assert!(registry.is_valid(handle));
533
534 registry.unregister(handle).unwrap();
535 assert!(!registry.is_valid(handle));
536 }
537
538 #[test]
539 fn test_all_ids() {
540 let mut registry = TestRegistry::new();
541
542 let h1 = registry.register(TestObject {
543 name: "one".to_string(),
544 value: 1,
545 });
546 let h2 = registry.register(TestObject {
547 name: "two".to_string(),
548 value: 2,
549 });
550
551 let mut ids = registry.all_ids();
552 ids.sort();
553
554 assert_eq!(ids.len(), 2);
555 assert!(ids.contains(&h1.id()));
556 assert!(ids.contains(&h2.id()));
557 }
558
559 #[test]
560 fn test_len_and_is_empty() {
561 let mut registry = TestRegistry::new();
562 assert!(registry.is_empty());
563 assert_eq!(registry.len(), 0);
564
565 let handle = registry.register(TestObject {
566 name: "test".to_string(),
567 value: 42,
568 });
569 assert!(!registry.is_empty());
570 assert_eq!(registry.len(), 1);
571
572 registry.unregister(handle).unwrap();
573 assert!(registry.is_empty());
574 assert_eq!(registry.len(), 0);
575 }
576
577 #[test]
578 fn test_get_mut() {
579 let mut registry = TestRegistry::new();
580 let obj = TestObject {
581 name: "test".to_string(),
582 value: 42,
583 };
584
585 let handle = registry.register(obj);
586
587 {
588 let obj_mut = registry.get_mut(handle).unwrap();
589 obj_mut.value = 100;
590 }
591
592 let obj = registry.get(handle).unwrap();
593 assert_eq!(obj.value, 100);
594 }
595
596 #[test]
597 fn test_get_parent_none() {
598 let mut registry = TestRegistry::new();
599 let obj = TestObject {
600 name: "root".to_string(),
601 value: 1,
602 };
603
604 let handle = registry.register(obj);
605 let parent = registry.get_parent(&handle).unwrap();
606 assert!(parent.is_none());
607 }
608
609 #[test]
610 fn test_get_parent_some() {
611 let mut registry = TestRegistry::new();
612
613 let parent_obj = TestObject {
614 name: "parent".to_string(),
615 value: 1,
616 };
617 let child_obj = TestObject {
618 name: "child".to_string(),
619 value: 2,
620 };
621
622 let parent_handle = registry.register(parent_obj);
623 let child_handle = registry.register(child_obj);
624
625 registry.set_parent(child_handle, parent_handle);
626
627 let retrieved_parent = registry.get_parent(&child_handle).unwrap();
628 assert_eq!(retrieved_parent, Some(parent_handle));
629 }
630
631 #[test]
632 fn test_get_parent_stale_handle() {
633 let mut registry = TestRegistry::new();
634 let obj = TestObject {
635 name: "test".to_string(),
636 value: 42,
637 };
638
639 let handle = registry.register(obj);
640 registry.unregister(handle).unwrap();
641
642 let result = registry.get_parent(&handle);
643 assert!(matches!(result, Err(ObjectError::StaleHandle { .. })));
644 }
645
646 #[test]
647 fn test_get_children_empty() {
648 let mut registry = TestRegistry::new();
649 let obj = TestObject {
650 name: "leaf".to_string(),
651 value: 1,
652 };
653
654 let handle = registry.register(obj);
655 let children = registry.get_children(&handle).unwrap();
656 assert!(children.is_empty());
657 }
658
659 #[test]
660 fn test_get_children_multiple() {
661 let mut registry = TestRegistry::new();
662
663 let parent_obj = TestObject {
664 name: "parent".to_string(),
665 value: 1,
666 };
667 let child1_obj = TestObject {
668 name: "child1".to_string(),
669 value: 2,
670 };
671 let child2_obj = TestObject {
672 name: "child2".to_string(),
673 value: 3,
674 };
675
676 let parent_handle = registry.register(parent_obj);
677 let child1_handle = registry.register(child1_obj);
678 let child2_handle = registry.register(child2_obj);
679
680 registry.set_parent(child1_handle, parent_handle);
681 registry.set_parent(child2_handle, parent_handle);
682
683 let children = registry.get_children(&parent_handle).unwrap();
684 assert_eq!(children.len(), 2);
685 assert!(children.contains(&child1_handle));
686 assert!(children.contains(&child2_handle));
687 }
688
689 #[test]
690 fn test_get_children_stale_handle() {
691 let mut registry = TestRegistry::new();
692 let obj = TestObject {
693 name: "test".to_string(),
694 value: 42,
695 };
696
697 let handle = registry.register(obj);
698 registry.unregister(handle).unwrap();
699
700 let result = registry.get_children(&handle);
701 assert!(matches!(result, Err(ObjectError::StaleHandle { .. })));
702 }
703
704 #[test]
705 fn test_navigation_hierarchy() {
706 let mut registry = TestRegistry::new();
707
708 let window_handle = registry.register(TestObject {
710 name: "window".to_string(),
711 value: 1,
712 });
713 let tab_handle = registry.register(TestObject {
714 name: "tab".to_string(),
715 value: 2,
716 });
717 let pane_handle = registry.register(TestObject {
718 name: "pane".to_string(),
719 value: 3,
720 });
721
722 registry.set_parent(tab_handle, window_handle);
723 registry.set_parent(pane_handle, tab_handle);
724
725 let pane_parent = registry.get_parent(&pane_handle).unwrap().unwrap();
727 assert_eq!(pane_parent, tab_handle);
728
729 let tab_parent = registry.get_parent(&tab_handle).unwrap().unwrap();
731 assert_eq!(tab_parent, window_handle);
732
733 let window_parent = registry.get_parent(&window_handle).unwrap();
735 assert!(window_parent.is_none());
736
737 let window_children = registry.get_children(&window_handle).unwrap();
739 assert_eq!(window_children.len(), 1);
740 assert_eq!(window_children[0], tab_handle);
741
742 let tab_children = registry.get_children(&tab_handle).unwrap();
744 assert_eq!(tab_children.len(), 1);
745 assert_eq!(tab_children[0], pane_handle);
746 }
747}