1use core::{alloc::Layout, cmp::Ordering, fmt, mem};
2
3use crate::{
4 Characteristic, ConstTypeId, Def, Facet, Field, FieldFlags, MarkerTraits, PtrConst, Shape,
5 StructDef, TypeNameOpts, ValueVTable, shape_of,
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 {
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 { 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 { ord on ($($elems:ident.$idx:tt,)+), $cmp:ident($a:ident, $b:ident), eq = $eq:expr } => {{
65 let a = unsafe { $a.get::<Self>() };
66 let b = unsafe { $b.get::<Self>() };
67
68 $(
69 unsafe {
70 let a_ptr = &a.$idx as *const $elems;
71 let b_ptr = &b.$idx as *const $elems;
72
73 let ordering = ($elems::SHAPE.vtable.$cmp.unwrap_unchecked())(
74 PtrConst::new(a_ptr),
75 PtrConst::new(b_ptr),
76 );
77
78 if ordering != $eq {
79 return ordering;
80 }
81 }
82 )+
83
84 $eq
85 }};
86 {
88 impl ($($elems:ident.$idx:tt,)+),
89 remaining ($($remaining:ident.$remainingidx:tt,)*)
90 } => {
91 unsafe impl<'a $(, $elems)+> Facet<'a> for ($($elems,)+)
92 where
93 $($elems: Facet<'a>,)+
94 {
95 const SHAPE: &'static Shape = &const {
96 Shape::builder()
97 .id(ConstTypeId::of::<Self>())
98 .layout(Layout::new::<Self>())
99 .vtable(&const {
100 let mut builder = ValueVTable::builder()
101 .type_name(|f, opts| {
102 write_type_name_list(f, opts, "(", ", ", ")", &[$($elems::SHAPE),+])
103 })
104 .drop_in_place(|data| unsafe { data.drop_in_place::<Self>() })
105 .marker_traits(
106 MarkerTraits::all()
107 $(.intersection($elems::SHAPE.vtable.marker_traits))+
108 );
109
110 let elem_shapes = const { &[$($elems::SHAPE),+] };
111 if Characteristic::Debug.all(elem_shapes) {
112 builder = builder.debug(|value, f| {
113 let value = unsafe { value.get::<Self>() };
114
115 impl_facet_for_tuple! {
116 debug on f {
117 $(
118 unsafe {
119 let ptr = &value.$idx as *const $elems;
120 ($elems::SHAPE.vtable.debug.unwrap_unchecked())(
121 PtrConst::new(ptr),
122 f,
123 )
124 }?;
125 )+
126 }
127 }
128 });
129 }
130
131 if Characteristic::Default.all(elem_shapes) {
132 builder = builder.default_in_place(|dst| {
133 $(
134 unsafe {
135 ($elems::SHAPE.vtable.default_in_place.unwrap_unchecked())(
136 dst.field_uninit_at(mem::offset_of!(Self, $idx))
137 );
138 }
139 )+
140
141 unsafe { dst.assume_init() }
142 });
143 }
144
145 if Characteristic::Clone.all(elem_shapes) {
146 builder = builder.clone_into(|src, dst| {
147 $({
148 let offset = mem::offset_of!(Self, $idx);
149 unsafe {
150 ($elems::SHAPE.vtable.clone_into.unwrap_unchecked())(
151 src.field(offset),
152 dst.field_uninit_at(offset),
153 );
154 }
155 })+
156
157 unsafe { dst.assume_init() }
158 });
159 }
160
161 if Characteristic::PartialEq.all(elem_shapes) {
162 builder = builder.eq(|a, b| impl_facet_for_tuple! {
163 ord on ($($elems.$idx,)+),
164 eq(a, b),
165 eq = true
166 });
167 }
168
169 if Characteristic::PartialOrd.all(elem_shapes) {
170 builder = builder.partial_ord(|a, b| impl_facet_for_tuple! {
171 ord on ($($elems.$idx,)+),
172 partial_ord(a, b),
173 eq = Some(Ordering::Equal)
174 });
175 }
176
177 if Characteristic::Ord.all(elem_shapes) {
178 builder = builder.ord(|a, b| impl_facet_for_tuple! {
179 ord on ($($elems.$idx,)+),
180 ord(a, b),
181 eq = Ordering::Equal
182 });
183 }
184
185 if Characteristic::Hash.all(elem_shapes) {
186 builder = builder.hash(|value, hasher_this, hasher_write_fn| {
187 let value = unsafe { value.get::<Self>() };
188
189 $(
190 unsafe {
191 let ptr = &value.$idx as *const $elems;
192
193 ($elems::SHAPE.vtable.hash.unwrap_unchecked())(
194 PtrConst::new(ptr),
195 hasher_this,
196 hasher_write_fn,
197 );
198 }
199 )+
200 });
201 }
202
203 builder.build()
204 })
205 .def(Def::Struct({
206 StructDef::builder()
207 .tuple()
208 .fields(
209 &const {[
210 $(
211 Field::builder()
212 .name(stringify!($idx))
213 .shape(|| shape_of(&|t: &Self| &t.$idx))
214 .offset(mem::offset_of!(Self, $idx))
215 .flags(FieldFlags::EMPTY)
216 .build(),
217 )+
218 ]}
219 )
220 .build()
221 }))
222 .build()
223 };
224 }
225
226 impl_facet_for_tuple! {
227 continue from ($($elems.$idx,)+),
228 remaining ($($remaining.$remainingidx,)*)
229 }
230 };
231 { ($first:ident.$firstidx:tt $(, $remaining:ident.$remainingidx:tt)* $(,)?) } => {
233 impl_facet_for_tuple! {
234 impl ($first.$firstidx,),
235 remaining ($($remaining.$remainingidx,)*)
236 }
237 };
238}
239
240impl_facet_for_tuple! {
241 (T0.0, T1.1, T2.2, T3.3, T4.4, T5.5, T6.6, T7.7, T8.8, T9.9, T10.10, T11.11)
242}