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