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