facet_core/impls_core/
array.rs

1use crate::*;
2
3unsafe impl<'a, T, const L: usize> Facet<'a> for [T; L]
4where
5    T: Facet<'a>,
6{
7    const VTABLE: &'static ValueVTable = &const {
8        ValueVTable::builder::<Self>()
9            .marker_traits(|| T::SHAPE.vtable.marker_traits())
10            .type_name(|f, opts| {
11                if let Some(opts) = opts.for_children() {
12                    write!(f, "[")?;
13                    (T::SHAPE.vtable.type_name())(f, opts)?;
14                    write!(f, "; {L}]")
15                } else {
16                    write!(f, "[⋯; {L}]")
17                }
18            })
19            .default_in_place(|| {
20                if L == 0 {
21                    // Zero-length arrays implement `Default` irrespective of the element type
22                    Some(|target| unsafe { target.assume_init() })
23                } else if L <= 32 && T::SHAPE.vtable.has_default_in_place() {
24                    Some(|mut target| unsafe {
25                        let t_dip = <VTableView<T>>::of().default_in_place().unwrap();
26                        let stride = T::SHAPE
27                            .layout
28                            .sized_layout()
29                            .unwrap()
30                            .pad_to_align()
31                            .size();
32                        for idx in 0..L {
33                            t_dip(target.field_uninit_at(idx * stride));
34                        }
35                        target.assume_init()
36                    })
37                } else {
38                    // arrays do not yet implement `Default` for > 32 elements due
39                    // to specializing the `0` len case
40                    None
41                }
42            })
43            .clone_into(|| {
44                if T::SHAPE.vtable.has_clone_into() {
45                    Some(|src, mut dst| unsafe {
46                        let t_cip = <VTableView<T>>::of().clone_into().unwrap();
47                        let stride = T::SHAPE
48                            .layout
49                            .sized_layout()
50                            .unwrap()
51                            .pad_to_align()
52                            .size();
53                        for (idx, src) in src.iter().enumerate() {
54                            (t_cip)(src, dst.field_uninit_at(idx * stride));
55                        }
56                        dst.assume_init()
57                    })
58                } else {
59                    None
60                }
61            })
62            .build()
63    };
64
65    const SHAPE: &'static Shape = &const {
66        Shape::builder_for_sized::<Self>()
67            .type_identifier("&[_; _]")
68            .type_params(&[TypeParam {
69                name: "T",
70                shape: || T::SHAPE,
71            }])
72            .ty(Type::Sequence(SequenceType::Array(ArrayType {
73                t: T::SHAPE,
74                n: L,
75            })))
76            .def(Def::Array(
77                ArrayDef::builder()
78                    .vtable(
79                        &const {
80                            ArrayVTable::builder()
81                                .as_ptr(|ptr| unsafe {
82                                    let array = ptr.get::<[T; L]>();
83                                    PtrConst::new(array.as_ptr())
84                                })
85                                .as_mut_ptr(|ptr| unsafe {
86                                    let array = ptr.as_mut::<[T; L]>();
87                                    PtrMut::new(array.as_mut_ptr())
88                                })
89                                .build()
90                        },
91                    )
92                    .t(T::SHAPE)
93                    .n(L)
94                    .build(),
95            ))
96            .build()
97    };
98}