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}