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        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            .display(|| {
21                if (T::SHAPE.vtable.display)().is_some() {
22                    Some(|value, f| {
23                        write!(f, "[")?;
24
25                        for (idx, value) in value.iter().enumerate() {
26                            (<VTableView<T>>::of().display().unwrap())(value, f)?;
27                            if idx != L - 1 {
28                                write!(f, ", ")?;
29                            }
30                        }
31                        write!(f, "]")
32                    })
33                } else {
34                    None
35                }
36            })
37            .debug(|| {
38                if (T::SHAPE.vtable.debug)().is_some() {
39                    Some(|value, f| {
40                        write!(f, "[")?;
41
42                        for (idx, value) in value.iter().enumerate() {
43                            (<VTableView<T>>::of().debug().unwrap())(value, f)?;
44                            if idx != L - 1 {
45                                write!(f, ", ")?;
46                            }
47                        }
48                        write!(f, "]")
49                    })
50                } else {
51                    None
52                }
53            })
54            .partial_eq(|| {
55                if (T::SHAPE.vtable.partial_eq)().is_some() {
56                    Some(|a, b| {
57                        zip(a, b).all(|(a, b)| (<VTableView<T>>::of().partial_eq().unwrap())(a, b))
58                    })
59                } else {
60                    None
61                }
62            })
63            .default_in_place(|| {
64                if L == 0 {
65                    // Zero-length arrays implement `Default` irrespective of the element type
66                    Some(|target| unsafe { target.assume_init() })
67                } else if L <= 32 && (T::SHAPE.vtable.default_in_place)().is_some() {
68                    Some(|mut target| unsafe {
69                        let t_dip = <VTableView<T>>::of().default_in_place().unwrap();
70                        let stride = T::SHAPE
71                            .layout
72                            .sized_layout()
73                            .unwrap()
74                            .pad_to_align()
75                            .size();
76                        for idx in 0..L {
77                            t_dip(target.field_uninit_at(idx * stride));
78                        }
79                        target.assume_init()
80                    })
81                } else {
82                    // arrays do not yet implement `Default` for > 32 elements due
83                    // to specializing the `0` len case
84                    None
85                }
86            })
87            .clone_into(|| {
88                if (T::SHAPE.vtable.clone_into)().is_some() {
89                    Some(|src, mut dst| unsafe {
90                        let t_cip = <VTableView<T>>::of().clone_into().unwrap();
91                        let stride = T::SHAPE
92                            .layout
93                            .sized_layout()
94                            .unwrap()
95                            .pad_to_align()
96                            .size();
97                        for (idx, src) in src.iter().enumerate() {
98                            (t_cip)(src, dst.field_uninit_at(idx * stride));
99                        }
100                        dst.assume_init()
101                    })
102                } else {
103                    None
104                }
105            })
106            .partial_ord(|| {
107                if (T::SHAPE.vtable.partial_ord)().is_some() {
108                    Some(|a, b| {
109                        zip(a, b)
110                            .find_map(|(a, b)| {
111                                match (<VTableView<T>>::of().partial_ord().unwrap())(a, b) {
112                                    Some(Ordering::Equal) => None,
113                                    c => Some(c),
114                                }
115                            })
116                            .unwrap_or(Some(Ordering::Equal))
117                    })
118                } else {
119                    // arrays do not yet implement `Default` for > 32 elements due
120                    // to specializing the `0` len case
121                    None
122                }
123            })
124            .ord(|| {
125                if (T::SHAPE.vtable.ord)().is_some() {
126                    Some(|a, b| {
127                        zip(a, b)
128                            .find_map(
129                                |(a, b)| match (<VTableView<T>>::of().ord().unwrap())(a, b) {
130                                    Ordering::Equal => None,
131                                    c => Some(c),
132                                },
133                            )
134                            .unwrap_or(Ordering::Equal)
135                    })
136                } else {
137                    // arrays do not yet implement `Default` for > 32 elements due
138                    // to specializing the `0` len case
139                    None
140                }
141            })
142            .hash(|| {
143                if (T::SHAPE.vtable.hash)().is_some() {
144                    Some(|value, state, hasher| {
145                        for value in value {
146                            (<VTableView<T>>::of().hash().unwrap())(value, state, hasher)
147                        }
148                    })
149                } else {
150                    // arrays do not yet implement `Default` for > 32 elements due
151                    // to specializing the `0` len case
152                    None
153                }
154            })
155            .build()
156    };
157
158    const SHAPE: &'static Shape<'static> = &const {
159        Shape::builder_for_sized::<Self>()
160            .type_identifier("&[_; _]")
161            .type_params(&[TypeParam {
162                name: "T",
163                shape: || T::SHAPE,
164            }])
165            .ty(Type::Sequence(SequenceType::Array(ArrayType {
166                t: T::SHAPE,
167                n: L,
168            })))
169            .def(Def::Array(
170                ArrayDef::builder()
171                    .vtable(
172                        &const {
173                            ArrayVTable::builder()
174                                .as_ptr(|ptr| unsafe {
175                                    let array = ptr.get::<[T; L]>();
176                                    PtrConst::new(array.as_ptr())
177                                })
178                                .as_mut_ptr(|ptr| unsafe {
179                                    let array = ptr.as_mut::<[T; L]>();
180                                    PtrMut::new(array.as_mut_ptr())
181                                })
182                                .build()
183                        },
184                    )
185                    .t(T::SHAPE)
186                    .n(L)
187                    .build(),
188            ))
189            .build()
190    };
191}