reactive_mutiny/ogre_std/ogre_alloc/
ogre_unique.rs1use crate::ogre_std::ogre_alloc::{
4 ogre_arc::OgreArc,
5 BoundedOgreAllocator,
6 };
7use std::{
8 ops::Deref,
9 fmt::{Debug, Display, Formatter},
10};
11use std::borrow::Borrow;
12
13
14pub struct OgreUnique<DataType: Debug + Send + Sync + 'static,
17 OgreAllocatorType: BoundedOgreAllocator<DataType> + Send + Sync + 'static> {
18 allocator: &'static OgreAllocatorType,
19 data_ref: &'static DataType,
20}
21
22
23impl<DataType: Debug + Send + Sync + 'static,
24 OgreAllocatorType: BoundedOgreAllocator<DataType> + Send + Sync>
25OgreUnique<DataType, OgreAllocatorType> {
26
27 #[inline(always)]
28 pub fn new<F: FnOnce(&mut DataType)>(setter: F, allocator: &OgreAllocatorType) -> Option<Self> {
29 allocator.alloc_ref()
30 .map(|(slot_ref, _slot_id)| {
31 setter(slot_ref);
32 Self::from_allocated_ref(slot_ref, allocator)
33 })
34 }
35
36 #[inline(always)]
37 pub fn from_allocated_id(data_id: u32, allocator: &OgreAllocatorType) -> Self {
38 let data_ref = allocator.ref_from_id(data_id);
39 Self::from_allocated_ref(data_ref, allocator)
40 }
41
42 #[inline(always)]
43 pub fn from_allocated_ref(data_ref: &DataType, allocator: &OgreAllocatorType) -> Self {
44 Self {
45 allocator: unsafe { &*(allocator as *const OgreAllocatorType) },
46 data_ref: unsafe { &*(data_ref as *const DataType) },
47 }
48 }
49
50 #[inline(always)]
51 pub fn into_ogre_arc(self) -> OgreArc<DataType, OgreAllocatorType> {
52 let undroppable_self = std::mem::ManuallyDrop::new(self);
53 OgreArc::from_allocated(undroppable_self.allocator.id_from_ref(undroppable_self.data_ref), undroppable_self.allocator)
54 }
55
56}
57
58
59impl<DataType: Debug + Send + Sync,
60 OgreAllocatorType: BoundedOgreAllocator<DataType> + Send + Sync>
61Deref for
62OgreUnique<DataType, OgreAllocatorType> {
63
64 type Target = DataType;
65
66 #[inline(always)]
67 fn deref(&self) -> &Self::Target {
68 self.data_ref
69 }
70}
71
72
73impl<DataType: Debug + Send + Sync,
74 OgreAllocatorType: BoundedOgreAllocator<DataType> + Send + Sync>
75AsRef<DataType> for
76OgreUnique<DataType, OgreAllocatorType> {
77
78 #[inline(always)]
79 fn as_ref(&self) -> &DataType {
80 self.data_ref
81 }
82
83}
84
85impl<DataType: Debug + Send + Sync,
86 OgreAllocatorType: BoundedOgreAllocator<DataType> + Send + Sync>
87Borrow<DataType> for
88OgreUnique<DataType, OgreAllocatorType> {
89
90 #[inline(always)]
91 fn borrow(&self) -> &DataType {
92 self.data_ref
93 }
94}
95
96impl<DataType: Debug + Send + Sync + Display,
97 OgreAllocatorType: BoundedOgreAllocator<DataType> + Send + Sync>
98Display for
99OgreUnique<DataType, OgreAllocatorType> {
100
101 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
102 std::fmt::Display::fmt(&self.deref(), f)
103 }
104}
105
106
107impl<DataType: Debug + Send + Sync,
108 OgreAllocatorType: BoundedOgreAllocator<DataType> + Send + Sync>
109Debug for
110OgreUnique<DataType, OgreAllocatorType> {
111
112 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
113 write!(f, "OgreUnique {{allocator: {:?}, data: #{}:{:?}}}",
114 self.allocator, self.allocator.id_from_ref(self.data_ref), self.data_ref)
115 }
116}
117
118
119impl<DataType: Debug + Send + Sync,
120 OgreAllocatorType: BoundedOgreAllocator<DataType> + Send + Sync>
121PartialEq<DataType> for
122OgreUnique<DataType, OgreAllocatorType>
123where DataType: PartialEq {
124
125 #[inline(always)]
126 fn eq(&self, other: &DataType) -> bool {
127 self.deref().eq(other)
128 }
129}
130
131
132impl<DataType: Debug + Send + Sync,
133 OgreAllocatorType: BoundedOgreAllocator<DataType> + Send + Sync>
134From<OgreUnique<DataType, OgreAllocatorType>> for
135OgreArc<DataType, OgreAllocatorType> {
136
137 #[inline(always)]
138 fn from(ogre_unique: OgreUnique<DataType, OgreAllocatorType>) -> OgreArc<DataType, OgreAllocatorType> {
139 ogre_unique.into_ogre_arc()
140 }
141}
142
143
144impl<DataType: Debug + Send + Sync,
145 OgreAllocatorType: BoundedOgreAllocator<DataType> + Send + Sync>
146Drop for
147OgreUnique<DataType, OgreAllocatorType> {
148
149 #[inline(always)]
150 fn drop(&mut self) {
151 self.allocator.dealloc_ref(self.data_ref);
152 }
153}
154
155
156unsafe impl<DataType: Debug + Send + Sync,
157 OgreAllocatorType: BoundedOgreAllocator<DataType> + Send + Sync>
158Send for
159OgreUnique<DataType, OgreAllocatorType> {}
160
161unsafe impl<DataType: Debug + Send + Sync,
162 OgreAllocatorType: BoundedOgreAllocator<DataType> + Send + Sync>
163Sync for
164OgreUnique<DataType, OgreAllocatorType> {}
165
166
167#[cfg(any(test,doc))]
168mod tests {
169 use super::*;
172 use crate::prelude::advanced::AllocatorAtomicArray;
173
174
175 #[cfg_attr(not(doc),test)]
176 pub fn happy_path_usage() {
177 let allocator = AllocatorAtomicArray::<u128, 128>::new();
178 let unique = OgreUnique::new(|slot| *slot = 128, &allocator).expect("Allocation should have been done");
179 println!("unique is {unique} -- {:?}", unique);
180 assert_eq!(*unique.deref(), 128, "Value doesn't match");
181 drop(unique);
182 println!("all is free:");
184 println!("{:?}", allocator);
185 }
186
187 #[cfg_attr(not(doc),test)]
188 pub fn into_ogrearc() {
189 let allocator = AllocatorAtomicArray::<u128, 128>::new();
190 let unique = OgreUnique::new(|slot| *slot = 128, &allocator).expect("Allocation should have been done");
191 let ogre_arc = unique.into_ogre_arc();
192 println!("arc is {ogre_arc} -- {:?}", ogre_arc);
193 assert_eq!((*ogre_arc.deref(), ogre_arc.references_count()), (128, 1), "Starting Value and Reference Counts don't match for the converted `ogre_arc`");
194 drop(ogre_arc);
195 println!("all is free:");
197 println!("{:?}", allocator);
198 }
199
200 #[cfg_attr(not(doc),test)]
201 pub fn comparisons() {
202 let expected: &str = "&str to compare";
204 let allocator = AllocatorAtomicArray::<&str, 128>::new();
205 let observed = OgreUnique::new(|slot| *slot = expected, &allocator).expect("Allocation should have been done");
206 assert_eq!(observed, expected, "Comparison of pristine types failed for `&str`");
207 assert_eq!(&observed, &expected, "Comparison of references failed for `&str`");
208 assert_eq!(*observed, expected, "Comparison of `Deref` failed for `&str`");
209
210 let expected: String = String::from("String to compare");
212 let allocator = AllocatorAtomicArray::<String, 128>::new();
213 let observed = OgreUnique::new(|slot| unsafe { std::ptr::write(slot, expected.clone()); }, &allocator).expect("Allocation should have been done");
214 assert_eq!(observed, expected, "Comparison of pristine types failed for `String`");
215 assert_eq!(&observed, &expected, "Comparison of references failed for `String`");
216 assert_eq!(*observed, expected, "Comparison of `Deref` failed for `String`");
217
218 }
229
230}