1use crate::{Facet, Shape};
2
3#[doc(hidden)]
4pub const fn shape_of<TStruct, TField: Facet>(_f: &dyn Fn(TStruct) -> TField) -> &'static Shape {
5 TField::SHAPE
6}
7
8#[doc(hidden)]
9#[macro_export]
10macro_rules! struct_field {
11 ($struct:ty, $field:tt) => {
12 $crate::Field::builder()
13 .name(stringify!($field))
14 .shape($crate::shape_of(&|s: $struct| s.$field))
15 .offset(::core::mem::offset_of!($struct, $field))
16 .flags($crate::FieldFlags::EMPTY)
17 .build()
18 };
19}
20
21#[doc(hidden)]
22#[macro_export]
23macro_rules! struct_fields {
24 ($struct:ty, ($($field:tt),*)) => {{
25 static FIELDS: &[$crate::Field] = &[ $($crate::struct_field!($struct, $field)),* ];
26 FIELDS
27 }};
28}
29
30#[doc(hidden)]
31#[macro_export]
32macro_rules! enum_unit_variant {
33 ($enum:ty, $variant:ident) => {
34 $crate::Variant {
35 name: stringify!($variant),
36 discriminant: None,
37 kind: $crate::VariantKind::Unit,
38 }
39 };
40 ($enum:ty, $variant:ident, $discriminant:expr) => {
41 $crate::Variant {
42 name: stringify!($variant),
43 discriminant: Some($discriminant),
44 kind: $crate::VariantKind::Unit,
45 }
46 };
47}
48
49#[doc(hidden)]
50#[macro_export]
51macro_rules! enum_tuple_variant {
52 ($enum:ty, $variant:ident, [$($field_type:ty),*]) => {{
53 static FIELDS: &[$crate::Field] = &[
54 $(
55 $crate::Field {
56 name: concat!("_", stringify!($field_type)),
57 shape_fn: <$field_type>::shape,
58 offset: 0, flags: $crate::FieldFlags::EMPTY,
60 }
61 ),*
62 ];
63
64 $crate::Variant {
65 name: stringify!($variant),
66 discriminant: None,
67 kind: $crate::VariantKind::Tuple { fields: FIELDS },
68 }
69 }};
70 ($enum:ty, $variant:ident, [$($field_type:ty),*], $discriminant:expr) => {{
71 static FIELDS: &[$crate::Field] = &[
72 $(
73 $crate::Field {
74 name: concat!("_", stringify!($field_type)),
75 shape_fn: <$field_type>::shape,
76 offset: 0, flags: $crate::FieldFlags::EMPTY,
78 }
79 ),*
80 ];
81
82 $crate::Variant {
83 name: stringify!($variant),
84 discriminant: Some($discriminant),
85 kind: $crate::VariantKind::Tuple { fields: FIELDS },
86 }
87 }};
88}
89
90#[doc(hidden)]
91#[macro_export]
92macro_rules! enum_struct_variant {
93 ($enum:ty, $variant:ident, {$($field:ident: $field_type:ty),*}) => {{
94 static FIELDS: &[$crate::Field] = &[
95 $(
96 $crate::Field {
97 name: stringify!($field),
98 shape_fn: <$field_type>::shape,
99 offset: 0, flags: $crate::FieldFlags::EMPTY,
101 }
102 ),*
103 ];
104
105 $crate::Variant {
106 name: stringify!($variant),
107 discriminant: None,
108 kind: $crate::VariantKind::Struct { fields: FIELDS },
109 }
110 }};
111 ($enum:ty, $variant:ident, {$($field:ident: $field_type:ty),*}, $discriminant:expr) => {{
112 static FIELDS: &[$crate::Field] = &[
113 $(
114 $crate::Field {
115 name: stringify!($field),
116 shape_fn: <$field_type>::shape,
117 offset: 0, flags: $crate::FieldFlags::EMPTY,
119 }
120 ),*
121 ];
122
123 $crate::Variant {
124 name: stringify!($variant),
125 discriminant: Some($discriminant),
126 kind: $crate::VariantKind::Struct { fields: FIELDS },
127 }
128 }};
129}
130
131#[doc(hidden)]
132#[macro_export]
133macro_rules! enum_variants {
134 ($enum:ty, [$($variant:expr),*]) => {{
135 static VARIANTS: &[$crate::Variant] = &[ $($variant),* ];
136 VARIANTS
137 }};
138}
139
140#[macro_export]
164macro_rules! value_vtable {
165 ($type_name:ty, $type_name_fn:expr) => {
166 &const {
167 let mut builder = $crate::ValueVTable::builder()
168 .type_name($type_name_fn)
169 .drop_in_place(|data| unsafe { data.drop_in_place::<$type_name>() });
170
171 if $crate::facet_spez::impls!($type_name: core::fmt::Display) {
172 builder = builder.display(|data, f| {
173 use $crate::facet_spez::*;
174 (&&Spez(unsafe { data.as_ref::<$type_name>() })).spez_display(f)
175 });
176 }
177
178 if $crate::facet_spez::impls!($type_name: core::fmt::Debug) {
179 builder = builder.debug(|data, f| {
180 use $crate::facet_spez::*;
181 (&&Spez(unsafe { data.as_ref::<$type_name>() })).spez_debug(f)
182 });
183 }
184
185 if $crate::facet_spez::impls!($type_name: core::default::Default) {
186 builder = builder.default_in_place(|target| {
187 use $crate::facet_spez::*;
188 (&&Spez(<$type_name as $crate::Facet>::ARCHETYPE)).spez_default_in_place(target)
189 });
190 }
191
192 if $crate::facet_spez::impls!($type_name: core::clone::Clone) {
193 builder = builder.clone_into(|src, dst| {
194 use $crate::facet_spez::*;
195 (&&Spez(unsafe { src.as_ref::<$type_name>() })).spez_clone_into(dst)
196 });
197 }
198
199 {
200 let mut traits = $crate::MarkerTraits::empty();
201 if $crate::facet_spez::impls!($type_name: core::cmp::Eq) {
202 traits = traits.union($crate::MarkerTraits::EQ);
203 }
204 if $crate::facet_spez::impls!($type_name: core::marker::Send) {
205 traits = traits.union($crate::MarkerTraits::SEND);
206 }
207 if $crate::facet_spez::impls!($type_name: core::marker::Sync) {
208 traits = traits.union($crate::MarkerTraits::SYNC);
209 }
210 if $crate::facet_spez::impls!($type_name: core::marker::Copy) {
211 traits = traits.union($crate::MarkerTraits::COPY);
212 }
213 builder = builder.marker_traits(traits);
214 }
215
216 if $crate::facet_spez::impls!($type_name: core::cmp::PartialEq) {
217 builder = builder.eq(|left, right| {
218 use $crate::facet_spez::*;
219 (&&Spez(unsafe { left.as_ref::<$type_name>() }))
220 .spez_eq(&&Spez(unsafe { right.as_ref::<$type_name>() }))
221 });
222 }
223
224 if $crate::facet_spez::impls!($type_name: core::cmp::PartialOrd) {
225 builder = builder.partial_ord(|left, right| {
226 use $crate::facet_spez::*;
227 (&&Spez(unsafe { left.as_ref::<$type_name>() }))
228 .spez_partial_cmp(&&Spez(unsafe { right.as_ref::<$type_name>() }))
229 });
230 }
231
232 if $crate::facet_spez::impls!($type_name: core::cmp::Ord) {
233 builder = builder.ord(|left, right| {
234 use $crate::facet_spez::*;
235 (&&Spez(unsafe { left.as_ref::<$type_name>() }))
236 .spez_cmp(&&Spez(unsafe { right.as_ref::<$type_name>() }))
237 });
238 }
239
240 if $crate::facet_spez::impls!($type_name: core::hash::Hash) {
241 builder = builder.hash(|value, hasher_this, hasher_write_fn| {
242 use $crate::facet_spez::*;
243 use $crate::HasherProxy;
244 (&&Spez(unsafe { value.as_ref::<$type_name>() }))
245 .spez_hash(&mut unsafe { HasherProxy::new(hasher_this, hasher_write_fn) })
246 });
247 }
248
249 if $crate::facet_spez::impls!($type_name: core::str::FromStr) {
250 builder = builder.parse(|s, target| {
251 use $crate::facet_spez::*;
252 let res = (&&Spez(<$type_name as $crate::Facet>::ARCHETYPE)).spez_parse(s, target);
253 res.map(|_| unsafe { target.assume_init() })
254 });
255 }
256
257 builder.build()
258 }
259 };
260}