facet_core/impls_alloc/
vec.rs

1use crate::*;
2use core::{alloc::Layout, hash::Hash as _};
3
4use alloc::vec::Vec;
5
6unsafe impl<T> Facet for Vec<T>
7where
8    T: Facet,
9{
10    const SHAPE: &'static Shape = &const {
11        Shape::builder()
12            .id(ConstTypeId::of::<Vec<T>>())
13            .layout(Layout::new::<Vec<T>>())
14            .vtable(
15                &const {
16                    let mut builder = ValueVTable::builder()
17                        .type_name(|f, opts| {
18                            if let Some(opts) = opts.for_children() {
19                                write!(f, "Vec<")?;
20                                (T::SHAPE.vtable.type_name)(f, opts)?;
21                                write!(f, ">")
22                            } else {
23                                write!(f, "Vec<⋯>")
24                            }
25                        })
26                        .drop_in_place(|value| unsafe { value.drop_in_place::<Vec<T>>() })
27                        .default_in_place(|target| unsafe { target.put(Self::default()) })
28                        .clone_into(|src, dst| unsafe { dst.put(src.get::<Vec<T>>()) });
29
30                    if T::SHAPE.vtable.debug.is_some() {
31                        builder = builder.debug(|value, f| {
32                            let value = unsafe { value.get::<Vec<T>>() };
33                            write!(f, "[")?;
34                            for (i, item) in value.iter().enumerate() {
35                                if i > 0 {
36                                    write!(f, ", ")?;
37                                }
38                                unsafe {
39                                    (T::SHAPE.vtable.debug.unwrap_unchecked())(
40                                        PtrConst::new(item),
41                                        f,
42                                    )?;
43                                }
44                            }
45                            write!(f, "]")
46                        });
47                    }
48
49                    if T::SHAPE.vtable.eq.is_some() {
50                        builder = builder.eq(|a, b| unsafe {
51                            let a = a.get::<Vec<T>>();
52                            let b = b.get::<Vec<T>>();
53                            if a.len() != b.len() {
54                                return false;
55                            }
56                            for (item_a, item_b) in a.iter().zip(b.iter()) {
57                                if !(T::SHAPE.vtable.eq.unwrap_unchecked())(
58                                    PtrConst::new(item_a),
59                                    PtrConst::new(item_b),
60                                ) {
61                                    return false;
62                                }
63                            }
64                            true
65                        });
66                    }
67
68                    if T::SHAPE.vtable.hash.is_some() {
69                        builder = builder.hash(|value, hasher_this, hasher_write_fn| unsafe {
70                            use crate::HasherProxy;
71                            let vec = value.get::<Vec<T>>();
72                            let t_hash = T::SHAPE.vtable.hash.unwrap_unchecked();
73                            let mut hasher = HasherProxy::new(hasher_this, hasher_write_fn);
74                            vec.len().hash(&mut hasher);
75                            for item in vec {
76                                (t_hash)(PtrConst::new(item), hasher_this, hasher_write_fn);
77                            }
78                        });
79                    }
80
81                    let traits = MarkerTraits::SEND
82                        .union(MarkerTraits::SYNC)
83                        .union(MarkerTraits::EQ)
84                        .union(MarkerTraits::UNPIN)
85                        .intersection(T::SHAPE.vtable.marker_traits);
86                    builder = builder.marker_traits(traits);
87
88                    builder.build()
89                },
90            )
91            .def(Def::List(
92                ListDef::builder()
93                    .vtable(
94                        &const {
95                            ListVTable::builder()
96                                .init_in_place_with_capacity(|data, capacity| unsafe {
97                                    data.put(Self::with_capacity(capacity))
98                                })
99                                .push(|ptr, item| unsafe {
100                                    let vec = ptr.as_mut::<Vec<T>>();
101                                    let item = item.read::<T>();
102                                    (*vec).push(item);
103                                })
104                                .len(|ptr| unsafe {
105                                    let vec = ptr.get::<Vec<T>>();
106                                    vec.len()
107                                })
108                                .get_item_ptr(|ptr, index| unsafe {
109                                    let vec = ptr.get::<Vec<T>>();
110                                    let len = vec.len();
111                                    if index >= len {
112                                        panic!(
113                                            "Index out of bounds: the len is {len} but the index is {index}"
114                                        );
115                                    }
116                                    PtrConst::new(vec.as_ptr().add(index))
117                                })
118                                .build()
119                        },
120                    )
121                    .t(|| T::SHAPE)
122                    .build(),
123            ))
124            .build()
125    };
126}