facet_core/impls_core/tuple.rs
1use core::{cmp::Ordering, fmt, mem};
2
3use crate::{
4 Characteristic, Facet, MarkerTraits, Repr, Shape, StructKind, StructType, Type, TypeNameOpts,
5 UserType, VTableView, ValueVTable, types::field_in_type,
6};
7
8#[inline(always)]
9pub fn write_type_name_list(
10 f: &mut fmt::Formatter<'_>,
11 opts: TypeNameOpts,
12 open: &'static str,
13 delimiter: &'static str,
14 close: &'static str,
15 shapes: &'static [&'static Shape],
16) -> fmt::Result {
17 f.pad(open)?;
18 if let Some(opts) = opts.for_children() {
19 for (index, shape) in shapes.iter().enumerate() {
20 if index > 0 {
21 f.pad(delimiter)?;
22 }
23 shape.write_type_name(f, opts)?;
24 }
25 } else {
26 write!(f, "⋯")?;
27 }
28 f.pad(close)?;
29 Ok(())
30}
31
32macro_rules! impl_facet_for_tuple {
33 // Used to implement the next bigger tuple type, by taking the next typename & associated index
34 // out of `remaining`, if it exists.
35 {
36 continue from ($($elems:ident.$idx:tt,)+),
37 remaining ()
38 } => {};
39 {
40 continue from ($($elems:ident.$idx:tt,)+),
41 remaining ($next:ident.$nextidx:tt, $($remaining:ident.$remainingidx:tt,)*)
42 } => {
43 impl_facet_for_tuple! {
44 impl ($($elems.$idx,)+ $next.$nextidx,),
45 remaining ($($remaining.$remainingidx,)*)
46 }
47 };
48 // Handle commas correctly for the debug implementation
49 { debug on $f:ident { $first:stmt; } } => {
50 write!($f, "(")?;
51 $first
52 write!($f, ",)")
53 };
54 { debug on $f:ident { $first:stmt; $($stmt:stmt;)+ } } => {
55 write!($f, "(")?;
56 $first
57 $(
58 write!($f, ", ")?;
59 $stmt
60 )+
61 write!($f, ")")
62 };
63 // Common structure of eq, partial_ord & ord
64 { ord on ($($elems:ident.$idx:tt,)+), $cmp:ident($a:ident, $b:ident), eq = $eq:expr } => {{
65 $(
66 unsafe {
67 let ordering = (<VTableView<$elems>>::of().$cmp().unwrap_unchecked())(
68 &$a.$idx,
69 &$b.$idx,
70 );
71
72 if ordering != $eq {
73 return ordering;
74 }
75 }
76 )+
77
78 $eq
79 }};
80 // Actually generate the trait implementation, and keep the remaining possible elements around
81 {
82 impl ($($elems:ident.$idx:tt,)+),
83 remaining ($($remaining:ident.$remainingidx:tt,)*)
84 } => {
85 unsafe impl<'a $(, $elems)+> Facet<'a> for ($($elems,)+)
86 where
87 $($elems: Facet<'a>,)+
88 {
89 const VTABLE: &'static ValueVTable = &const {
90 ValueVTable::builder::<Self>()
91 .type_name(|f, opts| {
92 write_type_name_list(f, opts, "(", ", ", ")", &[$($elems::SHAPE),+])
93 })
94 .drop_in_place(|| Some(|data| unsafe { data.drop_in_place::<Self>() }))
95 .marker_traits(||
96 MarkerTraits::all()
97 $(.intersection($elems::SHAPE.vtable.marker_traits()))+
98 )
99 .debug(|| {
100 let elem_shapes = const { &[$($elems::SHAPE),+] };
101 if Characteristic::Debug.all(elem_shapes) {
102 Some(|value, f| {
103 impl_facet_for_tuple! {
104 debug on f {
105 $(
106 (<VTableView<$elems>>::of().debug().unwrap())(
107 &value.$idx,
108 f,
109 )?;
110 )+
111 }
112 }
113 })
114 } else {
115 None
116 }
117 })
118 .default_in_place(|| {
119 let elem_shapes = const { &[$($elems::SHAPE),+] };
120 if Characteristic::all_default(elem_shapes) {
121 Some(|mut dst| {
122 $(
123 unsafe {
124 (<VTableView<$elems>>::of().default_in_place().unwrap())(
125 dst.field_uninit_at(mem::offset_of!(Self, $idx))
126 );
127 }
128 )+
129
130 unsafe { dst.assume_init() }
131 })
132 } else {
133 None
134 }
135 })
136 // .clone_into(|| {
137 // let elem_shapes = const { &[$($elems::SHAPE),+] };
138 // if Characteristic::Clone.all(elem_shapes) {
139 // Some(|src, dst| {
140 // $({
141 // let offset = mem::offset_of!(Self, $idx);
142 // unsafe {
143 // (<VTableView<$elems>>::of().clone_into().unwrap())(
144 // src.field(offset),
145 // dst.field_uninit_at(offset),
146 // );
147 // }
148 // })+
149
150 // unsafe { dst.assume_init() }
151 // })
152 // } else {
153 // None
154 // }
155 // })
156 .partial_eq(|| {
157 let elem_shapes = const { &[$($elems::SHAPE),+] };
158 if Characteristic::all_partial_eq(elem_shapes) {
159 Some(|a, b| impl_facet_for_tuple! {
160 ord on ($($elems.$idx,)+),
161 partial_eq(a, b),
162 eq = true
163 })
164 } else {
165 None
166 }
167 })
168 .partial_ord(|| {
169 let elem_shapes = const { &[$($elems::SHAPE),+] };
170 if Characteristic::all_partial_ord(elem_shapes) {
171 Some(|a, b| impl_facet_for_tuple! {
172 ord on ($($elems.$idx,)+),
173 partial_ord(a, b),
174 eq = Some(Ordering::Equal)
175 })
176 } else {
177 None
178 }
179 })
180 .ord(|| {
181 let elem_shapes = const { &[$($elems::SHAPE),+] };
182 if Characteristic::all_ord(elem_shapes) {
183 Some(|a, b| impl_facet_for_tuple! {
184 ord on ($($elems.$idx,)+),
185 ord(a, b),
186 eq = Ordering::Equal
187 })
188 } else {
189 None
190 }
191 })
192 .hash(|| {
193 let elem_shapes = const { &[$($elems::SHAPE),+] };
194 if Characteristic::all_hash(elem_shapes) {
195 Some(|value, hasher_this, hasher_write_fn| {
196 $(
197 (<VTableView<$elems>>::of().hash().unwrap())(
198 &value.$idx,
199 hasher_this,
200 hasher_write_fn,
201 );
202 )+
203 })
204 } else {
205 None
206 }
207 })
208 .build()
209 };
210
211 const SHAPE: &'static Shape<'static> = &const {
212 Shape::builder_for_sized::<Self>()
213 .type_identifier(const {
214 let fields = [
215 $(field_in_type!(Self, $idx),)+
216 ];
217 if fields.len() == 1 {
218 "(_)"
219 } else {
220 "(⋯)"
221 }
222 })
223 .ty(Type::User(UserType::Struct(StructType {
224 repr: Repr::default(),
225 kind: StructKind::Tuple,
226 fields: &const {[
227 $(field_in_type!(Self, $idx),)+
228 ]}
229 })))
230 .build()
231 };
232 }
233
234 impl_facet_for_tuple! {
235 continue from ($($elems.$idx,)+),
236 remaining ($($remaining.$remainingidx,)*)
237 }
238 };
239 // The entry point into this macro, all smaller tuple types get implemented as well.
240 { ($first:ident.$firstidx:tt $(, $remaining:ident.$remainingidx:tt)* $(,)?) } => {
241 impl_facet_for_tuple! {
242 impl ($first.$firstidx,),
243 remaining ($($remaining.$remainingidx,)*)
244 }
245 };
246}
247
248#[cfg(feature = "tuples-12")]
249impl_facet_for_tuple! {
250 (T0.0, T1.1, T2.2, T3.3, T4.4, T5.5, T6.6, T7.7, T8.8, T9.9, T10.10, T11.11)
251}
252
253#[cfg(not(feature = "tuples-12"))]
254impl_facet_for_tuple! {
255 (T0.0, T1.1, T2.2, T3.3)
256}