1use crate::*;
2
3use alloc::boxed::Box;
4use alloc::vec::Vec;
5
6struct DebugViaShape(&'static Shape, PtrConst);
8
9impl core::fmt::Debug for DebugViaShape {
10 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
11 match unsafe { self.0.call_debug(self.1, f) } {
12 Some(result) => result,
13 None => write!(f, "???"),
14 }
15 }
16}
17
18#[repr(C)]
25struct VecLayout {
26 #[allow(dead_code)]
27 cap: usize,
28 ptr: *mut u8,
29 len: usize,
30}
31
32const _: () = {
34 let v: Vec<u8> = Vec::new();
36 let fields: [usize; 3] = unsafe { core::mem::transmute(v) };
37
38 assert!(
42 core::mem::size_of::<Vec<u8>>() == core::mem::size_of::<VecLayout>(),
43 "VecLayout size mismatch"
44 );
45 assert!(
46 core::mem::align_of::<Vec<u8>>() == core::mem::align_of::<VecLayout>(),
47 "VecLayout align mismatch"
48 );
49
50 assert!(fields[0] == 0, "expected cap=0 at offset 0");
55 assert!(fields[1] != 0, "expected non-null ptr at offset 1");
56 assert!(fields[2] == 0, "expected len=0 at offset 2");
57};
58
59unsafe fn vec_len_erased(ptr: PtrConst) -> usize {
61 unsafe {
62 let layout = ptr.as_byte_ptr() as *const VecLayout;
63 (*layout).len
64 }
65}
66
67unsafe fn vec_get_erased(ptr: PtrConst, index: usize, shape: &'static Shape) -> Option<PtrConst> {
69 unsafe {
70 let layout = ptr.as_byte_ptr() as *const VecLayout;
71 let len = (*layout).len;
72 if index >= len {
73 return None;
74 }
75 let elem_size = shape
76 .type_params
77 .first()?
78 .shape
79 .layout
80 .sized_layout()
81 .ok()?
82 .size();
83 let data_ptr = (*layout).ptr;
84 Some(PtrConst::new(data_ptr.add(index * elem_size)))
85 }
86}
87
88unsafe fn vec_get_mut_erased(ptr: PtrMut, index: usize, shape: &'static Shape) -> Option<PtrMut> {
90 unsafe {
91 let layout = ptr.as_byte_ptr() as *const VecLayout;
92 let len = (*layout).len;
93 if index >= len {
94 return None;
95 }
96 let elem_size = shape
97 .type_params
98 .first()?
99 .shape
100 .layout
101 .sized_layout()
102 .ok()?
103 .size();
104 let data_ptr = (*layout).ptr;
105 Some(PtrMut::new(data_ptr.add(index * elem_size)))
106 }
107}
108
109static VEC_LIST_VTABLE: ListVTable = ListVTable {
115 len: vec_len_erased,
116 get: vec_get_erased,
117 get_mut: Some(vec_get_mut_erased),
118 as_ptr: Some(vec_as_ptr_erased),
119 as_mut_ptr: Some(vec_as_mut_ptr_erased),
120};
121
122unsafe fn vec_as_ptr_erased(ptr: PtrConst) -> PtrConst {
124 unsafe {
125 let layout = ptr.as_byte_ptr() as *const VecLayout;
126 PtrConst::new((*layout).ptr)
127 }
128}
129
130unsafe fn vec_as_mut_ptr_erased(ptr: PtrMut) -> PtrMut {
132 unsafe {
133 let layout = ptr.as_byte_ptr() as *const VecLayout;
134 PtrMut::new((*layout).ptr)
135 }
136}
137
138fn vec_type_name(
140 shape: &'static Shape,
141 f: &mut core::fmt::Formatter<'_>,
142 opts: TypeNameOpts,
143) -> core::fmt::Result {
144 write!(f, "Vec")?;
145 if let Some(opts) = opts.for_children() {
146 write!(f, "<")?;
147 if let Some(tp) = shape.type_params.first() {
148 tp.shape.write_type_name(f, opts)?;
149 }
150 write!(f, ">")?;
151 } else {
152 write!(f, "<…>")?;
153 }
154 Ok(())
155}
156
157#[inline]
159fn get_list_def(shape: &'static Shape) -> &'static ListDef {
160 match &shape.def {
161 Def::List(list_def) => list_def,
162 _ => panic!("expected List def"),
163 }
164}
165
166unsafe fn vec_debug_erased(
168 ox: OxPtrConst,
169 f: &mut core::fmt::Formatter<'_>,
170) -> Option<core::fmt::Result> {
171 let shape = ox.shape();
172 let elem_shape = shape.type_params.first().map(|tp| tp.shape)?;
173 if !elem_shape.vtable.has_debug() {
174 return None;
175 }
176
177 let list_def = get_list_def(shape);
178 let ptr = ox.ptr();
179 let len = unsafe { (list_def.vtable.len)(ptr) };
180
181 let mut list = f.debug_list();
182 for i in 0..len {
183 if let Some(item_ptr) = unsafe { (list_def.vtable.get)(ptr, i, shape) } {
184 list.entry(&DebugViaShape(elem_shape, item_ptr));
185 }
186 }
187 Some(list.finish())
188}
189
190unsafe fn vec_partial_eq_erased(ox_a: OxPtrConst, ox_b: OxPtrConst) -> Option<bool> {
192 let shape = ox_a.shape();
193 let elem_shape = shape.type_params.first().map(|tp| tp.shape)?;
194 if !elem_shape.vtable.has_partial_eq() {
195 return None;
196 }
197
198 let list_def = get_list_def(shape);
199 let ptr_a = ox_a.ptr();
200 let ptr_b = ox_b.ptr();
201 let len_a = unsafe { (list_def.vtable.len)(ptr_a) };
202 let len_b = unsafe { (list_def.vtable.len)(ptr_b) };
203
204 if len_a != len_b {
205 return Some(false);
206 }
207
208 for i in 0..len_a {
209 let item_a = unsafe { (list_def.vtable.get)(ptr_a, i, shape) }?;
210 let item_b = unsafe { (list_def.vtable.get)(ptr_b, i, shape) }?;
211 match unsafe { elem_shape.call_partial_eq(item_a, item_b) } {
212 Some(true) => continue,
213 Some(false) => return Some(false),
214 None => return None,
215 }
216 }
217 Some(true)
218}
219
220unsafe fn vec_partial_cmp_erased(
222 ox_a: OxPtrConst,
223 ox_b: OxPtrConst,
224) -> Option<Option<core::cmp::Ordering>> {
225 let shape = ox_a.shape();
226 let elem_shape = shape.type_params.first().map(|tp| tp.shape)?;
227 if !elem_shape.vtable.has_partial_ord() {
228 return None;
229 }
230
231 let list_def = get_list_def(shape);
232 let ptr_a = ox_a.ptr();
233 let ptr_b = ox_b.ptr();
234 let len_a = unsafe { (list_def.vtable.len)(ptr_a) };
235 let len_b = unsafe { (list_def.vtable.len)(ptr_b) };
236
237 let min_len = len_a.min(len_b);
238
239 for i in 0..min_len {
240 let item_a = unsafe { (list_def.vtable.get)(ptr_a, i, shape) }?;
241 let item_b = unsafe { (list_def.vtable.get)(ptr_b, i, shape) }?;
242 match unsafe { elem_shape.call_partial_cmp(item_a, item_b) } {
243 Some(Some(core::cmp::Ordering::Equal)) => continue,
244 Some(ord) => return Some(ord),
245 None => return None,
246 }
247 }
248 Some(Some(len_a.cmp(&len_b)))
249}
250
251unsafe fn vec_cmp_erased(ox_a: OxPtrConst, ox_b: OxPtrConst) -> Option<core::cmp::Ordering> {
253 let shape = ox_a.shape();
254 let elem_shape = shape.type_params.first().map(|tp| tp.shape)?;
255 if !elem_shape.vtable.has_ord() {
256 return None;
257 }
258
259 let list_def = get_list_def(shape);
260 let ptr_a = ox_a.ptr();
261 let ptr_b = ox_b.ptr();
262 let len_a = unsafe { (list_def.vtable.len)(ptr_a) };
263 let len_b = unsafe { (list_def.vtable.len)(ptr_b) };
264
265 let min_len = len_a.min(len_b);
266
267 for i in 0..min_len {
268 let item_a = unsafe { (list_def.vtable.get)(ptr_a, i, shape) }?;
269 let item_b = unsafe { (list_def.vtable.get)(ptr_b, i, shape) }?;
270 match unsafe { elem_shape.call_cmp(item_a, item_b) } {
271 Some(core::cmp::Ordering::Equal) => continue,
272 Some(ord) => return Some(ord),
273 None => return None,
274 }
275 }
276 Some(len_a.cmp(&len_b))
277}
278
279type VecIterator<'mem, T> = core::slice::Iter<'mem, T>;
284
285unsafe fn vec_init_in_place_with_capacity<T>(uninit: PtrUninit, capacity: usize) -> PtrMut {
286 unsafe { uninit.put(Vec::<T>::with_capacity(capacity)) }
287}
288
289unsafe fn vec_push<T: 'static>(ptr: PtrMut, item: PtrMut) {
290 unsafe {
291 let vec = ptr.as_mut::<Vec<T>>();
292 let item = item.read::<T>();
293 vec.push(item);
294 }
295}
296
297unsafe fn vec_set_len<T: 'static>(ptr: PtrMut, len: usize) {
304 unsafe {
305 let vec = ptr.as_mut::<Vec<T>>();
306 vec.set_len(len);
307 }
308}
309
310unsafe fn vec_as_mut_ptr_typed<T: 'static>(ptr: PtrMut) -> *mut u8 {
315 unsafe {
316 let vec = ptr.as_mut::<Vec<T>>();
317 vec.as_mut_ptr() as *mut u8
318 }
319}
320
321unsafe fn vec_reserve<T: 'static>(ptr: PtrMut, additional: usize) {
326 unsafe {
327 let vec = ptr.as_mut::<Vec<T>>();
328 vec.reserve(additional);
329 }
330}
331
332unsafe fn vec_capacity<T: 'static>(ptr: PtrConst) -> usize {
337 unsafe {
338 let vec = ptr.get::<Vec<T>>();
339 vec.capacity()
340 }
341}
342
343unsafe fn vec_iter_init<T: 'static>(ptr: PtrConst) -> PtrMut {
344 unsafe {
345 let vec = ptr.get::<Vec<T>>();
346 let iter: VecIterator<T> = vec.iter();
347 let iter_state = Box::new(iter);
348 PtrMut::new(Box::into_raw(iter_state) as *mut u8)
349 }
350}
351
352unsafe fn vec_iter_next<T: 'static>(iter_ptr: PtrMut) -> Option<PtrConst> {
353 unsafe {
354 let state = iter_ptr.as_mut::<VecIterator<'static, T>>();
355 state.next().map(|value| PtrConst::new(value as *const T))
356 }
357}
358
359unsafe fn vec_iter_next_back<T: 'static>(iter_ptr: PtrMut) -> Option<PtrConst> {
360 unsafe {
361 let state = iter_ptr.as_mut::<VecIterator<'static, T>>();
362 state
363 .next_back()
364 .map(|value| PtrConst::new(value as *const T))
365 }
366}
367
368unsafe fn vec_iter_dealloc<T>(iter_ptr: PtrMut) {
369 unsafe {
370 drop(Box::from_raw(
371 iter_ptr.as_ptr::<VecIterator<'_, T>>() as *mut VecIterator<'_, T>
372 ))
373 }
374}
375
376unsafe impl<'a, T> Facet<'a> for Vec<T>
377where
378 T: Facet<'a> + 'static,
379{
380 const SHAPE: &'static Shape =
381 &const {
382 const fn build_list_type_ops<T: 'static>() -> ListTypeOps {
384 ListTypeOps::builder()
385 .init_in_place_with_capacity(vec_init_in_place_with_capacity::<T>)
386 .push(vec_push::<T>)
387 .set_len(vec_set_len::<T>)
388 .as_mut_ptr_typed(vec_as_mut_ptr_typed::<T>)
389 .reserve(vec_reserve::<T>)
390 .capacity(vec_capacity::<T>)
391 .iter_vtable(IterVTable {
392 init_with_value: Some(vec_iter_init::<T>),
393 next: vec_iter_next::<T>,
394 next_back: Some(vec_iter_next_back::<T>),
395 size_hint: None,
396 dealloc: vec_iter_dealloc::<T>,
397 })
398 .build()
399 }
400
401 ShapeBuilder::for_sized::<Self>("Vec")
402 .type_name(vec_type_name)
403 .ty(Type::User(UserType::Opaque))
404 .def(Def::List(ListDef::with_type_ops(
405 &VEC_LIST_VTABLE,
407 &const { build_list_type_ops::<T>() },
408 T::SHAPE,
409 )))
410 .type_params(&[TypeParam {
411 name: "T",
412 shape: T::SHAPE,
413 }])
414 .inner(T::SHAPE)
415 .variance(Shape::computed_variance)
417 .vtable_indirect(&const {
418 VTableIndirect {
419 debug: Some(vec_debug_erased),
420 partial_eq: Some(vec_partial_eq_erased),
421 partial_cmp: Some(vec_partial_cmp_erased),
422 cmp: Some(vec_cmp_erased),
423 display: None,
424 hash: None,
425 invariants: None,
426 parse: None,
427 parse_bytes: None,
428 try_from: None,
429 try_into_inner: None,
430 try_borrow_inner: None,
431 }
432 })
433 .type_ops_indirect(&const {
434 unsafe fn drop_in_place<T>(ox: OxPtrMut) {
435 unsafe {
436 core::ptr::drop_in_place(ox.ptr().as_ptr::<Vec<T>>() as *mut Vec<T>);
437 }
438 }
439
440 unsafe fn default_in_place<T>(ox: OxPtrMut) {
441 unsafe { ox.ptr().as_uninit().put(Vec::<T>::new()) };
442 }
443
444 unsafe fn truthy<T>(ptr: PtrConst) -> bool {
445 !unsafe { ptr.get::<Vec<T>>() }.is_empty()
446 }
447
448 TypeOpsIndirect {
449 drop_in_place: drop_in_place::<T>,
450 default_in_place: Some(default_in_place::<T>),
451 clone_into: None,
452 is_truthy: Some(truthy::<T>),
453 }
454 })
455 .build()
456 };
457}