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