facet_core/impls_alloc/
btreeset.rs1use core::hash::Hash;
2
3use alloc::boxed::Box;
4use alloc::collections::BTreeSet;
5
6use crate::ptr::{PtrConst, PtrMut};
7
8use crate::{
9 Def, Facet, MarkerTraits, SetDef, SetIterVTable, SetVTable, Shape, Type, TypeParam, UserType,
10 VTableView, ValueVTable,
11};
12
13struct BTreeSetIterator<'mem, T> {
14 set: &'mem BTreeSet<T>,
15 next_bound: core::ops::Bound<&'mem T>,
16}
17
18impl<'mem, T> BTreeSetIterator<'mem, T>
19where
20 T: Ord,
21{
22 fn next(&mut self) -> Option<&'mem T> {
23 let mut range = self
24 .set
25 .range((self.next_bound, core::ops::Bound::Unbounded));
26 let next = range.next();
27
28 if let Some(next) = next {
29 self.next_bound = core::ops::Bound::Excluded(next);
30 }
31
32 next
33 }
34}
35
36unsafe impl<'a, T> Facet<'a> for BTreeSet<T>
37where
38 T: Facet<'a> + core::cmp::Eq + core::cmp::Ord,
39{
40 const VTABLE: &'static ValueVTable = &const {
41 let mut builder = ValueVTable::builder::<Self>()
42 .marker_traits(
43 MarkerTraits::SEND
44 .union(MarkerTraits::SYNC)
45 .union(MarkerTraits::EQ)
46 .union(MarkerTraits::UNPIN)
47 .intersection(T::SHAPE.vtable.marker_traits),
48 )
49 .type_name(|f, opts| {
50 if let Some(opts) = opts.for_children() {
51 write!(f, "BTreeSet<")?;
52 (T::SHAPE.vtable.type_name)(f, opts)?;
53 write!(f, ">")
54 } else {
55 write!(f, "BTreeSet<⋯>")
56 }
57 })
58 .default_in_place(|target| unsafe { target.put(Self::default()) })
59 .eq(|a, b| a == b);
60
61 if T::SHAPE.vtable.debug.is_some() {
62 builder = builder.debug(|value, f| {
63 let t_debug = <VTableView<T>>::of().debug().unwrap();
64 write!(f, "{{")?;
65 for (i, item) in value.iter().enumerate() {
66 if i > 0 {
67 write!(f, ", ")?;
68 }
69 (t_debug)(item, f)?;
70 }
71 write!(f, "}}")
72 });
73 }
74
75 if T::SHAPE.vtable.clone_into.is_some() {
76 builder = builder.clone_into(|src, dst| unsafe {
77 let set = src;
78 let mut new_set = BTreeSet::new();
79
80 let t_clone_into = <VTableView<T>>::of().clone_into().unwrap();
81
82 for item in set {
83 use crate::TypedPtrUninit;
84 use core::mem::MaybeUninit;
85
86 let mut new_item = MaybeUninit::<T>::uninit();
87 let uninit_item = TypedPtrUninit::new(new_item.as_mut_ptr());
88
89 (t_clone_into)(item, uninit_item);
90
91 new_set.insert(new_item.assume_init());
92 }
93
94 dst.put(new_set)
95 });
96 }
97
98 if T::SHAPE.vtable.hash.is_some() {
99 builder = builder.hash(|set, hasher_this, hasher_write_fn| unsafe {
100 use crate::HasherProxy;
101 let t_hash = <VTableView<T>>::of().hash().unwrap();
102 let mut hasher = HasherProxy::new(hasher_this, hasher_write_fn);
103 set.len().hash(&mut hasher);
104 for item in set {
105 (t_hash)(item, hasher_this, hasher_write_fn);
106 }
107 });
108 }
109
110 builder.build()
111 };
112
113 const SHAPE: &'static Shape = &const {
114 Shape::builder_for_sized::<Self>()
115 .type_params(&[TypeParam {
116 name: "T",
117 shape: || T::SHAPE,
118 }])
119 .ty(Type::User(UserType::Opaque))
120 .def(Def::Set(
121 SetDef::builder()
122 .t(|| T::SHAPE)
123 .vtable(
124 &const {
125 SetVTable::builder()
126 .init_in_place_with_capacity(|uninit, _capacity| unsafe {
127 uninit.put(Self::new())
128 })
129 .insert(|ptr, item| unsafe {
130 let set = ptr.as_mut::<BTreeSet<T>>();
131 let item = item.read::<T>();
132 set.insert(item)
133 })
134 .len(|ptr| unsafe {
135 let set = ptr.get::<BTreeSet<T>>();
136 set.len()
137 })
138 .contains(|ptr, item| unsafe {
139 let set = ptr.get::<BTreeSet<T>>();
140 set.contains(item.get())
141 })
142 .iter(|ptr| {
143 let set = unsafe { ptr.get::<BTreeSet<T>>() };
144 let iter_state = Box::new(BTreeSetIterator {
145 set,
146 next_bound: core::ops::Bound::Unbounded,
147 });
148 PtrMut::new(Box::into_raw(iter_state) as *mut u8)
149 })
150 .iter_vtable(
151 SetIterVTable::builder()
152 .next(|iter_ptr| {
153 let state = unsafe {
154 iter_ptr.as_mut::<BTreeSetIterator<'_, T>>()
155 };
156 state
157 .next()
158 .map(|value| PtrConst::new(value as *const T))
159 })
160 .dealloc(|iter_ptr| unsafe {
161 drop(Box::from_raw(
162 iter_ptr.as_ptr::<BTreeSetIterator<'_, T>>()
163 as *mut BTreeSetIterator<'_, T>,
164 ));
165 })
166 .build(),
167 )
168 .build()
169 },
170 )
171 .build(),
172 ))
173 .build()
174 };
175}
176
177#[cfg(test)]
178mod tests {
179 use alloc::collections::BTreeSet;
180 use alloc::string::String;
181 use alloc::vec::Vec;
182
183 use super::*;
184
185 #[test]
186 fn test_btreesetset_type_params() {
187 let [type_param_1] = <BTreeSet<i32>>::SHAPE.type_params else {
188 panic!("BTreeSet<T> should have 1 type param")
189 };
190 assert_eq!(type_param_1.shape(), i32::SHAPE);
191 }
192
193 #[test]
194 fn test_btreeset_vtable_1_new_insert_iter_drop() -> eyre::Result<()> {
195 facet_testhelpers::setup();
196
197 let btreeset_shape = <BTreeSet<String>>::SHAPE;
198 let btreeset_def = btreeset_shape
199 .def
200 .into_set()
201 .expect("BTreeSet<T> should have a set definition");
202
203 let btreeset_uninit_ptr = btreeset_shape.allocate()?;
205
206 let btreeset_ptr =
208 unsafe { (btreeset_def.vtable.init_in_place_with_capacity_fn)(btreeset_uninit_ptr, 0) };
209
210 let btreeset_actual_length =
212 unsafe { (btreeset_def.vtable.len_fn)(btreeset_ptr.as_const()) };
213 assert_eq!(btreeset_actual_length, 0);
214
215 let strings = ["foo", "bar", "bazz", "fizzbuzz", "fifth thing"];
217
218 let mut btreeset_length = 0;
220 for string in strings {
221 let mut new_value = string.to_string();
223
224 let did_insert = unsafe {
226 (btreeset_def.vtable.insert_fn)(btreeset_ptr, PtrMut::new(&raw mut new_value))
227 };
228
229 core::mem::forget(new_value);
231
232 assert!(did_insert, "expected value to be inserted in the BTreeSet");
233
234 btreeset_length += 1;
236 let btreeset_actual_length =
237 unsafe { (btreeset_def.vtable.len_fn)(btreeset_ptr.as_const()) };
238 assert_eq!(btreeset_actual_length, btreeset_length);
239 }
240
241 for string in strings {
243 let mut new_value = string.to_string();
245
246 let did_insert = unsafe {
248 (btreeset_def.vtable.insert_fn)(btreeset_ptr, PtrMut::new(&raw mut new_value))
249 };
250
251 core::mem::forget(new_value);
253
254 assert!(
255 !did_insert,
256 "expected value to not be inserted in the BTreeSet"
257 );
258
259 let btreeset_actual_length =
261 unsafe { (btreeset_def.vtable.len_fn)(btreeset_ptr.as_const()) };
262 assert_eq!(btreeset_actual_length, btreeset_length);
263 }
264
265 let btreeset_iter_ptr = unsafe { (btreeset_def.vtable.iter_fn)(btreeset_ptr.as_const()) };
267
268 let mut iter_items = Vec::<&str>::new();
270 loop {
271 let item_ptr = unsafe { (btreeset_def.vtable.iter_vtable.next)(btreeset_iter_ptr) };
273 let Some(item_ptr) = item_ptr else {
274 break;
275 };
276
277 let item = unsafe { item_ptr.get::<String>() };
278
279 iter_items.push(&**item);
281 }
282
283 unsafe {
285 (btreeset_def.vtable.iter_vtable.dealloc)(btreeset_iter_ptr);
286 }
287
288 let mut strings_sorted = strings.to_vec();
291 strings_sorted.sort();
292 assert_eq!(iter_items, strings_sorted);
293
294 let drop_fn = btreeset_shape
296 .vtable
297 .drop_in_place
298 .expect("BTreeSet<T> should have drop_in_place");
299
300 unsafe { drop_fn(btreeset_ptr) };
302
303 unsafe { btreeset_shape.deallocate_mut(btreeset_ptr)? };
305
306 Ok(())
307 }
308}