facet_core/impls_core/
array.rs

1use crate::*;
2use core::{cmp::Ordering, iter::zip};
3
4unsafe impl<'a, T, const L: usize> Facet<'a> for [T; L]
5where
6    T: Facet<'a>,
7{
8    const VTABLE: &'static ValueVTable = &const {
9        let mut builder = ValueVTable::builder::<Self>()
10            .marker_traits(T::SHAPE.vtable.marker_traits)
11            .type_name(|f, opts| {
12                if let Some(opts) = opts.for_children() {
13                    write!(f, "[")?;
14                    (T::SHAPE.vtable.type_name)(f, opts)?;
15                    write!(f, "; {L}]")
16                } else {
17                    write!(f, "[⋯; {L}]")
18                }
19            });
20        if T::SHAPE.vtable.display.is_some() {
21            builder = builder.display(|value, f| {
22                write!(f, "[")?;
23
24                for (idx, value) in value.iter().enumerate() {
25                    (<VTableView<T>>::of().display().unwrap())(value, f)?;
26                    if idx != L - 1 {
27                        write!(f, ", ")?;
28                    }
29                }
30                write!(f, "]")
31            });
32        }
33        if T::SHAPE.vtable.debug.is_some() {
34            builder = builder.debug(|value, f| {
35                write!(f, "[")?;
36
37                for (idx, value) in value.iter().enumerate() {
38                    (<VTableView<T>>::of().debug().unwrap())(value, f)?;
39                    if idx != L - 1 {
40                        write!(f, ", ")?;
41                    }
42                }
43                write!(f, "]")
44            });
45        }
46        if T::SHAPE.vtable.eq.is_some() {
47            builder = builder
48                .eq(|a, b| zip(a, b).all(|(a, b)| (<VTableView<T>>::of().eq().unwrap())(a, b)));
49        }
50        if L == 0 {
51            // Zero-length arrays implement `Default` irrespective of the element type
52            builder = builder.default_in_place(|target| unsafe { target.assume_init() });
53        } else if L <= 32 && T::SHAPE.vtable.default_in_place.is_some() {
54            builder = builder.default_in_place(|mut target| unsafe {
55                let t_dip = <VTableView<T>>::of().default_in_place().unwrap();
56                let stride = T::SHAPE
57                    .layout
58                    .sized_layout()
59                    .unwrap()
60                    .pad_to_align()
61                    .size();
62                for idx in 0..L {
63                    t_dip(target.field_uninit_at(idx * stride));
64                }
65                target.assume_init()
66            });
67        } else {
68            // arrays do not yet implement `Default` for > 32 elements due to
69            // specializing the `0` len case
70        }
71        if T::SHAPE.vtable.clone_into.is_some() {
72            builder = builder.clone_into(|src, mut dst| unsafe {
73                let t_cip = <VTableView<T>>::of().clone_into().unwrap();
74                let stride = T::SHAPE
75                    .layout
76                    .sized_layout()
77                    .unwrap()
78                    .pad_to_align()
79                    .size();
80                for (idx, src) in src.iter().enumerate() {
81                    (t_cip)(src, dst.field_uninit_at(idx * stride));
82                }
83                dst.assume_init()
84            });
85        }
86        if T::SHAPE.vtable.partial_ord.is_some() {
87            builder = builder.partial_ord(|a, b| {
88                zip(a, b)
89                    .find_map(
90                        |(a, b)| match (<VTableView<T>>::of().partial_ord().unwrap())(a, b) {
91                            Some(Ordering::Equal) => None,
92                            c => Some(c),
93                        },
94                    )
95                    .unwrap_or(Some(Ordering::Equal))
96            });
97        }
98        if T::SHAPE.vtable.ord.is_some() {
99            builder = builder.ord(|a, b| {
100                zip(a, b)
101                    .find_map(
102                        |(a, b)| match (<VTableView<T>>::of().ord().unwrap())(a, b) {
103                            Ordering::Equal => None,
104                            c => Some(c),
105                        },
106                    )
107                    .unwrap_or(Ordering::Equal)
108            });
109        }
110        if T::SHAPE.vtable.hash.is_some() {
111            builder = builder.hash(|value, state, hasher| {
112                for value in value {
113                    (<VTableView<T>>::of().hash().unwrap())(value, state, hasher)
114                }
115            });
116        }
117        builder.build()
118    };
119
120    const SHAPE: &'static Shape = &const {
121        Shape::builder_for_sized::<Self>()
122            .type_params(&[TypeParam {
123                name: "T",
124                shape: || T::SHAPE,
125            }])
126            .ty(Type::Sequence(SequenceType::Array(ArrayType {
127                t: T::SHAPE,
128                n: L,
129            })))
130            .def(Def::Array(
131                ArrayDef::builder()
132                    .vtable(
133                        &const {
134                            ArrayVTable::builder()
135                                .as_ptr(|ptr| unsafe {
136                                    let array = ptr.get::<[T; L]>();
137                                    PtrConst::new(array.as_ptr())
138                                })
139                                .as_mut_ptr(|ptr| unsafe {
140                                    let array = ptr.as_mut::<[T; L]>();
141                                    PtrMut::new(array.as_mut_ptr())
142                                })
143                                .build()
144                        },
145                    )
146                    .t(T::SHAPE)
147                    .n(L)
148                    .build(),
149            ))
150            .build()
151    };
152}