facet_core/_trait/impls/
vec_impl.rs

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