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