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}