1use alloc::{boxed::Box, collections::BTreeMap};
2
3use crate::{
4 Def, Facet, IterVTable, MapDef, MapVTable, OxPtrMut, PtrConst, PtrMut, PtrUninit, Shape,
5 ShapeBuilder, TypeNameFn, TypeNameOpts, TypeOpsIndirect, TypeParam, VTableIndirect, Variance,
6 VarianceDep, VarianceDesc,
7};
8
9type BTreeMapIterator<'mem, K, V> = alloc::collections::btree_map::Iter<'mem, K, V>;
10
11unsafe fn btreemap_init_in_place_with_capacity<K, V>(
12 uninit: PtrUninit,
13 _capacity: usize,
14) -> PtrMut {
15 unsafe { uninit.put(BTreeMap::<K, V>::new()) }
16}
17
18unsafe fn btreemap_insert<K: Eq + Ord + 'static, V: 'static>(
19 ptr: PtrMut,
20 key: PtrMut,
21 value: PtrMut,
22) {
23 unsafe {
24 let map = ptr.as_mut::<BTreeMap<K, V>>();
25 let k = key.read::<K>();
26 let v = value.read::<V>();
27 map.insert(k, v);
28 }
29}
30
31unsafe fn btreemap_len<K: 'static, V: 'static>(ptr: PtrConst) -> usize {
32 unsafe { ptr.get::<BTreeMap<K, V>>().len() }
33}
34
35unsafe fn btreemap_contains_key<K: Eq + Ord + 'static, V: 'static>(
36 ptr: PtrConst,
37 key: PtrConst,
38) -> bool {
39 unsafe { ptr.get::<BTreeMap<K, V>>().contains_key(key.get()) }
40}
41
42unsafe fn btreemap_get_value_ptr<K: Eq + Ord + 'static, V: 'static>(
43 ptr: PtrConst,
44 key: PtrConst,
45) -> Option<PtrConst> {
46 unsafe {
47 ptr.get::<BTreeMap<K, V>>()
48 .get(key.get())
49 .map(|v| PtrConst::new(v as *const V))
50 }
51}
52
53unsafe fn btreemap_iter_init<K: 'static, V: 'static>(ptr: PtrConst) -> PtrMut {
54 unsafe {
55 let map = ptr.get::<BTreeMap<K, V>>();
56 let iter: BTreeMapIterator<'_, K, V> = map.iter();
57 let state = Box::new(iter);
58 PtrMut::new(Box::into_raw(state) as *mut u8)
59 }
60}
61
62unsafe fn btreemap_iter_next<K: 'static, V: 'static>(
63 iter_ptr: PtrMut,
64) -> Option<(PtrConst, PtrConst)> {
65 unsafe {
66 let state = iter_ptr.as_mut::<BTreeMapIterator<'static, K, V>>();
67 state.next().map(|(key, value)| {
68 (
69 PtrConst::new(key as *const K),
70 PtrConst::new(value as *const V),
71 )
72 })
73 }
74}
75
76unsafe fn btreemap_iter_next_back<K: 'static, V: 'static>(
77 iter_ptr: PtrMut,
78) -> Option<(PtrConst, PtrConst)> {
79 unsafe {
80 let state = iter_ptr.as_mut::<BTreeMapIterator<'static, K, V>>();
81 state.next_back().map(|(key, value)| {
82 (
83 PtrConst::new(key as *const K),
84 PtrConst::new(value as *const V),
85 )
86 })
87 }
88}
89
90unsafe fn btreemap_iter_dealloc<K, V>(iter_ptr: PtrMut) {
91 unsafe {
92 drop(Box::from_raw(
93 iter_ptr.as_ptr::<BTreeMapIterator<'_, K, V>>() as *mut BTreeMapIterator<'_, K, V>,
94 ))
95 }
96}
97
98unsafe fn btreemap_from_pair_slice<K: Eq + Ord + 'static, V: 'static>(
100 uninit: PtrUninit,
101 pairs_ptr: *mut u8,
102 count: usize,
103) -> PtrMut {
104 let pairs = pairs_ptr as *mut (K, V);
105 let iter = (0..count).map(|i| unsafe {
106 let pair_ptr = pairs.add(i);
107 core::ptr::read(pair_ptr)
108 });
109 let map: BTreeMap<K, V> = iter.collect();
110 unsafe { uninit.put(map) }
111}
112
113unsafe fn btreemap_drop<K: 'static, V: 'static>(ox: OxPtrMut) {
115 unsafe {
116 core::ptr::drop_in_place(ox.as_mut::<BTreeMap<K, V>>());
117 }
118}
119
120unsafe fn btreemap_default<K: 'static, V: 'static>(ox: OxPtrMut) {
122 unsafe { ox.ptr().as_uninit().put(BTreeMap::<K, V>::new()) };
123}
124
125unsafe impl<'a, K, V> Facet<'a> for BTreeMap<K, V>
127where
128 K: Facet<'a> + core::cmp::Eq + core::cmp::Ord + 'static,
129 V: Facet<'a> + 'static,
130{
131 const SHAPE: &'static crate::Shape = &const {
132 const fn build_map_vtable<K: Eq + Ord + 'static, V: 'static>() -> MapVTable {
133 MapVTable::builder()
134 .init_in_place_with_capacity(btreemap_init_in_place_with_capacity::<K, V>)
135 .insert(btreemap_insert::<K, V>)
136 .len(btreemap_len::<K, V>)
137 .contains_key(btreemap_contains_key::<K, V>)
138 .get_value_ptr(btreemap_get_value_ptr::<K, V>)
139 .iter_vtable(IterVTable {
140 init_with_value: Some(btreemap_iter_init::<K, V>),
141 next: btreemap_iter_next::<K, V>,
142 next_back: Some(btreemap_iter_next_back::<K, V>),
143 size_hint: None,
144 dealloc: btreemap_iter_dealloc::<K, V>,
145 })
146 .from_pair_slice(Some(btreemap_from_pair_slice::<K, V>))
147 .pair_stride(core::mem::size_of::<(K, V)>())
148 .value_offset_in_pair(core::mem::offset_of!((K, V), 1))
149 .build()
150 }
151
152 const VTABLE: VTableIndirect = VTableIndirect::EMPTY;
153
154 const fn build_type_name<'a, K: Facet<'a>, V: Facet<'a>>() -> TypeNameFn {
155 fn type_name_impl<'a, K: Facet<'a>, V: Facet<'a>>(
156 _shape: &'static Shape,
157 f: &mut core::fmt::Formatter<'_>,
158 opts: TypeNameOpts,
159 ) -> core::fmt::Result {
160 write!(f, "BTreeMap")?;
161 if let Some(opts) = opts.for_children() {
162 write!(f, "<")?;
163 K::SHAPE.write_type_name(f, opts)?;
164 write!(f, ", ")?;
165 V::SHAPE.write_type_name(f, opts)?;
166 write!(f, ">")?;
167 } else {
168 write!(f, "<…>")?;
169 }
170 Ok(())
171 }
172 type_name_impl::<K, V>
173 }
174
175 ShapeBuilder::for_sized::<Self>("BTreeMap")
176 .module_path("alloc::collections::btree_map")
177 .type_name(build_type_name::<K, V>())
178 .vtable_indirect(&VTABLE)
179 .def(Def::Map(MapDef::new(
180 &const { build_map_vtable::<K, V>() },
181 K::SHAPE,
182 V::SHAPE,
183 )))
184 .type_params(&[
185 TypeParam {
186 name: "K",
187 shape: K::SHAPE,
188 },
189 TypeParam {
190 name: "V",
191 shape: V::SHAPE,
192 },
193 ])
194 .variance(VarianceDesc {
196 base: Variance::Bivariant,
197 deps: &const {
198 [
199 VarianceDep::covariant(K::SHAPE),
200 VarianceDep::covariant(V::SHAPE),
201 ]
202 },
203 })
204 .type_ops_indirect(
205 &const {
206 TypeOpsIndirect {
207 drop_in_place: btreemap_drop::<K, V>,
208 default_in_place: Some(btreemap_default::<K, V>),
209 clone_into: None,
210 is_truthy: None,
211 }
212 },
213 )
214 .build()
215 };
216}