any_container/boxed.rs
1use std::any::{Any, TypeId, type_name};
2use std::ops::{Deref, DerefMut};
3
4use crate::multimap::AnyMultiMap;
5
6/// A type-erased cloneable box that stores any `Clone + Send + Sync` type.
7///
8/// `AnyCloneBox` enables runtime type-erased storage of values while maintaining
9/// the ability to clone and downcast them to their original types. It is the
10/// fundamental building block for type-erased containers in the crate.
11///
12/// # Examples
13///
14/// ```
15/// use any_container::AnyCloneBox;
16///
17/// // Create an AnyCloneBox with an i32
18/// let boxed = AnyCloneBox::new(42i32);
19///
20/// // Downcast to get the original value
21/// assert_eq!(*boxed.downcast_ref::<i32>().unwrap(), 42);
22///
23/// // Downcasting to a wrong type returns None
24/// assert!(boxed.downcast_ref::<String>().is_none());
25///
26/// // Clone the boxed value
27/// let _clone = boxed.clone();
28/// ```
29pub struct AnyCloneBox {
30 inner: Box<dyn AnyClone>,
31 type_id: TypeId,
32 type_name: &'static str,
33}
34
35impl AnyCloneBox {
36 /// Creates a new `AnyCloneBox` containing the given value.
37 pub fn new<T: Clone + Send + Sync + 'static>(value: T) -> Self {
38 AnyCloneBox {
39 inner: Box::new(value),
40 type_id: TypeId::of::<T>(),
41 type_name: type_name::<T>(),
42 }
43 }
44
45 /// Returns the `TypeId` of the value contained in this `AnyCloneBox`.
46 pub fn type_id(&self) -> TypeId {
47 self.type_id
48 }
49
50 /// Returns the type name of the value contained in this `AnyCloneBox`.
51 pub fn type_name(&self) -> &'static str {
52 self.type_name
53 }
54
55 /// Attempts to downcast the `AnyCloneBox` to an immutable reference of type `T`.
56 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
57 if self.type_id == TypeId::of::<T>() {
58 Some(unsafe {
59 // SAFETY: The type has been checked to match, so this is safe.
60 self.downcast_ref_unchecked::<T>()
61 })
62 } else {
63 None
64 }
65 }
66
67 /// Unsafely downcasts the `AnyCloneBox` to an immutable reference of type `T` without checking the type.
68 ///
69 /// # Safety
70 /// The caller must ensure that the type `T` is the same as the type of the value contained in
71 /// this `AnyCloneBox`. If the types do not match, this will result in undefined behaviour.
72 pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
73 unsafe { &*(self.inner.deref() as *const dyn Any as *const T) }
74 }
75
76 /// Attempts to downcast the `AnyCloneBox` to a mutable reference of type `T`.
77 ///
78 /// This method allows mutation of the contained value through a type-safe interface.
79 /// Returns `None` if the contained type doesn't match `T`.
80 pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
81 if self.type_id == TypeId::of::<T>() {
82 Some(unsafe {
83 // SAFETY: The type has been checked to match, so this is safe.
84 self.downcast_mut_unchecked::<T>()
85 })
86 } else {
87 None
88 }
89 }
90
91 /// Unsafely downcasts the `AnyCloneBox` to a mutable reference of type `T` without checking the type.
92 ///
93 /// # Safety
94 /// The caller must ensure that the type `T` is the same as the type of the value contained in
95 /// this `AnyCloneBox`. If the types do not match, this will result in undefined behaviour.
96 pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
97 unsafe { &mut *(self.inner.deref_mut() as *mut dyn Any as *mut T) }
98 }
99
100 /// Consumes the `AnyCloneBox` and attempts to downcast it to a boxed value of type `T`.
101 pub fn downcast<T: Any>(self) -> Result<Box<T>, Self> {
102 if self.type_id == TypeId::of::<T>() {
103 Ok(unsafe {
104 // SAFETY: The type has been checked to match, so this is safe.
105 self.downcast_unchecked::<T>()
106 })
107 } else {
108 Err(self)
109 }
110 }
111
112 /// Unsafely downcasts the `AnyCloneBox` to a boxed value of type `T` without checking the type.
113 ///
114 /// # Safety
115 /// The caller must ensure that the type `T` is the same as the type of the value contained in
116 /// this `AnyCloneBox`. If the types do not match, this will result in undefined behaviour.
117 pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T> {
118 unsafe {
119 let raw = Box::into_raw(self.inner);
120 Box::from_raw(raw as *mut T)
121 }
122 }
123}
124
125impl AnyCloneBox {
126 pub(super) fn insert_into_multimap(self, multimap: &mut AnyMultiMap) {
127 self.inner.insert_into_multimap(multimap);
128 }
129}
130
131impl Clone for AnyCloneBox {
132 fn clone(&self) -> Self {
133 AnyCloneBox {
134 inner: self.inner.clone_box(),
135 type_id: self.type_id,
136 type_name: self.type_name,
137 }
138 }
139}
140
141trait AnyClone: Any + Send + Sync {
142 fn clone_box(&self) -> Box<dyn AnyClone>;
143 fn insert_into_multimap(self: Box<Self>, multimap: &mut AnyMultiMap);
144}
145
146impl<T: Clone + Send + Sync + 'static> AnyClone for T {
147 fn clone_box(&self) -> Box<dyn AnyClone> {
148 Box::new(self.clone())
149 }
150 fn insert_into_multimap(self: Box<Self>, multimap: &mut AnyMultiMap) {
151 multimap.insert(*self);
152 }
153}