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 {
13 name: stringify!($field),
14 shape: $crate::shape_of(&|s: $struct| s.$field),
15 offset: ::std::mem::offset_of!($struct, $field),
16 flags: $crate::FieldFlags::EMPTY,
17 }
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 &$crate::ValueVTable {
167 type_name: $type_name_fn,
168 display: if $crate::facet_spez::impls!($type_name: std::fmt::Display) {
169 Some(|data, f| {
170 use $crate::facet_spez::*;
171 (&&Spez(unsafe { data.as_ref::<$type_name>() })).spez_display(f)
172 })
173 } else {
174 None
175 },
176 debug: if $crate::facet_spez::impls!($type_name: std::fmt::Debug) {
177 Some(|data, f| {
178 use $crate::facet_spez::*;
179 (&&Spez(unsafe { data.as_ref::<$type_name>() })).spez_debug(f)
180 })
181 } else {
182 None
183 },
184 default_in_place: if $crate::facet_spez::impls!($type_name: std::default::Default) {
185 Some(|target| {
186 use $crate::facet_spez::*;
187 (&&Spez(<$type_name as $crate::Facet>::DUMMY)).spez_default_in_place(target)
188 })
189 } else {
190 None
191 },
192 clone_into: if $crate::facet_spez::impls!($type_name: std::clone::Clone) {
193 Some(|src, dst| {
194 use $crate::facet_spez::*;
195 (&&Spez(unsafe { src.as_ref::<$type_name>() })).spez_clone_into(dst)
196 })
197 } else {
198 None
199 },
200 marker_traits: {
201 const fn combine_traits() -> $crate::MarkerTraits {
202 let mut traits = $crate::MarkerTraits::empty();
203 if $crate::facet_spez::impls!($type_name: std::cmp::Eq) {
204 traits = traits.union($crate::MarkerTraits::EQ);
205 }
206 if $crate::facet_spez::impls!($type_name: std::marker::Send) {
207 traits = traits.union($crate::MarkerTraits::SEND);
208 }
209 if $crate::facet_spez::impls!($type_name: std::marker::Sync) {
210 traits = traits.union($crate::MarkerTraits::SYNC);
211 }
212 if $crate::facet_spez::impls!($type_name: std::marker::Copy) {
213 traits = traits.union($crate::MarkerTraits::COPY);
214 }
215 traits
216 }
217 combine_traits()
218 },
219 eq: if $crate::facet_spez::impls!($type_name: std::cmp::PartialEq) {
220 Some(|left, right| {
221 use $crate::facet_spez::*;
222 (&&Spez(unsafe { left.as_ref::<$type_name>() }))
223 .spez_eq(&&Spez(unsafe { right.as_ref::<$type_name>() }))
224 })
225 } else {
226 None
227 },
228 partial_ord: if $crate::facet_spez::impls!($type_name: std::cmp::PartialOrd) {
229 Some(|left, right| {
230 use $crate::facet_spez::*;
231 (&&Spez(unsafe { left.as_ref::<$type_name>() }))
232 .spez_partial_cmp(&&Spez(unsafe { right.as_ref::<$type_name>() }))
233 })
234 } else {
235 None
236 },
237 ord: if $crate::facet_spez::impls!($type_name: std::cmp::Ord) {
238 Some(|left, right| {
239 use $crate::facet_spez::*;
240 (&&Spez(unsafe { left.as_ref::<$type_name>() }))
241 .spez_cmp(&&Spez(unsafe { right.as_ref::<$type_name>() }))
242 })
243 } else {
244 None
245 },
246 hash: if $crate::facet_spez::impls!($type_name: std::hash::Hash) {
247 Some(|value, hasher_this, hasher_write_fn| {
248 use $crate::facet_spez::*;
249 use $crate::HasherProxy;
250 (&&Spez(unsafe { value.as_ref::<$type_name>() }))
251 .spez_hash(&mut unsafe { HasherProxy::new(hasher_this, hasher_write_fn) })
252 })
253 } else {
254 None
255 },
256 drop_in_place: Some(|data| unsafe { data.drop_in_place::<$type_name>() }),
257 parse: None,
258 try_from: None,
259 }
260 };
261}