facet_trait/impls/
vec_impl.rs

1use crate::*;
2use core::{alloc::Layout, hash::Hash as _};
3
4unsafe impl<T> Facet for Vec<T>
5where
6    T: Facet,
7{
8    const ARCHETYPE: Self = Vec::new(); // oh this is const, fantastic
9    const SHAPE: &'static Shape = &const {
10        Shape::builder()
11            .layout(Layout::new::<Vec<T>>())
12            .vtable(
13                &const {
14                    let mut builder = ValueVTable::builder()
15                        .type_name(|f, opts| {
16                            if let Some(opts) = opts.for_children() {
17                                write!(f, "Vec<")?;
18                                (T::SHAPE.vtable.type_name)(f, opts)?;
19                                write!(f, ">")
20                            } else {
21                                write!(f, "Vec<⋯>")
22                            }
23                        })
24                        .drop_in_place(|value| unsafe {
25                            core::ptr::drop_in_place(value.as_mut::<Vec<T>>());
26                        })
27                        .default_in_place(|target| unsafe { target.write(Self::default()) })
28                        .clone_into(|src, dst| unsafe { dst.write(src.as_ref::<Vec<T>>()) });
29
30                    if T::SHAPE.vtable.debug.is_some() {
31                        builder = builder.debug(|value, f| {
32                            let value = unsafe { value.as_ref::<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                                        OpaqueConst::from_ref(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.as_ref::<Vec<T>>();
52                            let b = b.as_ref::<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                                    OpaqueConst::from_ref(item_a),
59                                    OpaqueConst::from_ref(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.as_ref::<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)(OpaqueConst::from_ref(item), hasher_this, hasher_write_fn);
77                            }
78                        });
79                    }
80
81                    let mut traits = MarkerTraits::empty();
82                    if T::SHAPE.vtable.marker_traits.contains(MarkerTraits::SEND) {
83                        traits = traits.union(MarkerTraits::SEND);
84                    }
85                    if T::SHAPE.vtable.marker_traits.contains(MarkerTraits::SYNC) {
86                        traits = traits.union(MarkerTraits::SYNC);
87                    }
88                    if T::SHAPE.vtable.marker_traits.contains(MarkerTraits::EQ) {
89                        traits = traits.union(MarkerTraits::EQ);
90                    }
91                    builder = builder.marker_traits(traits);
92
93                    builder.build()
94                },
95            )
96            .def(Def::List(
97                ListDef::builder()
98                    .vtable(
99                        &const {
100                            ListVTable::builder()
101                        .init_in_place_with_capacity(|data, capacity| unsafe {
102                            Ok(data.write(Self::with_capacity(capacity)))
103                        })
104                        .push(|ptr, item| unsafe {
105                            let vec = ptr.as_mut::<Vec<T>>();
106                            let item = item.read::<T>();
107                            (*vec).push(item);
108                        })
109                        .len(|ptr| unsafe {
110                            let vec = ptr.as_ref::<Vec<T>>();
111                            vec.len()
112                        })
113                        .get_item_ptr(|ptr, index| unsafe {
114                            let vec = ptr.as_ref::<Vec<T>>();
115                            let len = vec.len();
116                            if index >= len {
117                                panic!(
118                                    "Index out of bounds: the len is {len} but the index is {index}"
119                                );
120                            }
121                            OpaqueConst::new_unchecked(vec.as_ptr().add(index))
122                        })
123                        .build()
124                        },
125                    )
126                    .t(T::SHAPE)
127                    .build(),
128            ))
129            .build()
130    };
131}