1#[macro_export]
2macro_rules! __define_person_property_common {
3 ($person_property:ident, $value:ty, $compute_fn:expr, $is_required:expr, $display_impl:expr) => {
4 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
5 pub struct $person_property;
6 impl $crate::people::PersonProperty for $person_property {
7 type Value = $value;
8 type CanonicalValue = $value;
9 fn compute(
10 _context: &$crate::context::Context,
11 _person: $crate::people::PersonId,
12 ) -> Self::CanonicalValue {
13 $compute_fn(_context, _person)
14 }
15 fn make_canonical(value: Self::Value) -> Self::CanonicalValue {
16 value
17 }
18 fn make_uncanonical(value: Self::CanonicalValue) -> Self::Value {
19 value
20 }
21 fn is_required() -> bool {
22 $is_required
23 }
24 fn get_instance() -> Self {
25 $person_property
26 }
27 fn name() -> &'static str {
28 stringify!($person_property)
29 }
30 fn get_display(value: &Self::CanonicalValue) -> String {
31 $display_impl(value)
32 }
33 }
34 };
35}
36
37#[macro_export]
44macro_rules! define_person_property {
45 ($person_property:ident, Option<$value:ty>, $initialize:expr) => {
47 $crate::__define_person_property_common!(
48 $person_property,
49 Option<$value>,
50 $initialize,
51 false,
52 |&value| {
53 match value {
54 Some(v) => format!("{:?}", v),
55 None => "None".to_string(),
56 }
57 }
58 );
59 };
60 ($person_property:ident, $value:ty, $initialize:expr) => {
62 $crate::__define_person_property_common!(
63 $person_property,
64 $value,
65 $initialize,
66 false,
67 |&value| format!("{:?}", value)
68 );
69 };
70 ($person_property:ident, Option<$value:ty>) => {
72 $crate::__define_person_property_common!(
73 $person_property,
74 Option<$value>,
75 |_, _| panic!("Property not initialized when person created."),
76 true,
77 |&value| {
78 match value {
79 Some(v) => format!("{:?}", v),
80 None => "None".to_string(),
81 }
82 }
83 );
84 };
85 ($person_property:ident, $value:ty) => {
87 $crate::__define_person_property_common!(
88 $person_property,
89 $value,
90 |_, _| panic!("Property not initialized when person created."),
91 true,
92 |&value| format!("{:?}", value)
93 );
94 };
95}
96pub use define_person_property;
97
98#[macro_export]
103macro_rules! define_person_property_with_default {
104 ($person_property:ident, Option<$value:ty>, $default:expr) => {
105 $crate::define_person_property!(
106 $person_property,
107 Option<$value>,
108 |_context, _person_id| { $default }
109 );
110 };
111 ($person_property:ident, $value:ty, $default:expr) => {
112 $crate::define_person_property!($person_property, $value, |_context, _person_id| {
113 $default
114 });
115 };
116}
117pub use define_person_property_with_default;
118
119#[macro_export]
128macro_rules! __define_derived_property_common {
129 (
130 $derived_property:ident,
131 $value:ty,
132 $canonical_value:ty,
133 $compute_canonical_impl:expr,
134 $compute_uncanonical_impl:expr,
135 $at_dependency_registration:expr,
136 [$($dependency:ident),*],
137 [$($global_dependency:ident),*],
138 |$($param:ident),+| $derive_fn:expr,
139 $display_impl:expr,
140 $hash_fn:expr,
141 $type_id_impl:expr
142 ) => {
143 #[derive(Debug, Copy, Clone)]
144 pub struct $derived_property;
145
146 impl $crate::people::PersonProperty for $derived_property {
147 type Value = $value;
148 type CanonicalValue = $canonical_value;
149
150 fn compute(context: &$crate::context::Context, person_id: $crate::people::PersonId) -> Self::Value {
151 #[allow(unused_imports)]
152 use $crate::global_properties::ContextGlobalPropertiesExt;
153 #[allow(unused_parens)]
154 let ($($param,)*) = (
155 $(context.get_person_property(person_id, $dependency)),*,
156 $(
157 context.get_global_property_value($global_dependency)
158 .expect(&format!("Global property {} not initialized", stringify!($global_dependency)))
159 ),*
160 );
161 #[allow(non_snake_case)]
162 (|$($param),+| $derive_fn)($($param),+)
163 }
164 fn make_canonical(value: Self::Value) -> Self::CanonicalValue {
165 ($compute_canonical_impl)(value)
166 }
167 fn make_uncanonical(value: Self::CanonicalValue) -> Self::Value {
168 ($compute_uncanonical_impl)(value)
169 }
170 fn is_derived() -> bool { true }
171 fn dependencies() -> Vec<Box<dyn $crate::people::PersonPropertyHolder>> {
172 vec![$(
173 Box::new($dependency) as Box<dyn $crate::people::PersonPropertyHolder>
174 ),*]
175 }
176 fn register_dependencies(context: &$crate::context::Context) {
177 $at_dependency_registration
178 $(context.register_property::<$dependency>();)+
179 }
180 fn get_instance() -> Self {
181 $derived_property
182 }
183 fn name() -> &'static str {
184 stringify!($derived_property)
185 }
186 fn get_display(value: &Self::CanonicalValue) -> String {
187 $display_impl(value)
188 }
189 fn hash_property_value(value: &Self::CanonicalValue) -> u128 {
190 ($hash_fn)(value)
191 }
192 fn type_id() -> std::any::TypeId {
193 $type_id_impl
194 }
195 }
196 };
197}
198
199#[macro_export]
206macro_rules! define_derived_property {
207 (
208 $derived_property:ident,
209 $value:ty,
210 [$($dependency:ident),*],
211 [$($global_dependency:ident),*],
212 |$($param:ident),+| $derive_fn:expr
213 ) => {
214 $crate::__define_derived_property_common!(
215 $derived_property,
216 $value,
217 $value,
218 |v| v,
219 |v| v,
220 {},
221 [$($dependency),*],
222 [$($global_dependency),*],
223 |$($param),+| $derive_fn,
224 |&value| format!("{:?}", value),
225 $crate::hashing::hash_serialized_128,
226 std::any::TypeId::of::<Self>()
227 );
228 };
229
230 (
232 $derived_property:ident,
233 $value:ty,
234 [$($dependency:ident),*],
235 |$($param:ident),+| $derive_fn:expr
236 ) => {
237 $crate::__define_derived_property_common!(
238 $derived_property,
239 $value,
240 $value,
241 |v| v,
242 |v| v,
243 {},
244 [$($dependency),*],
245 [],
246 |$($param),+| $derive_fn,
247 |&value| format!("{:?}", value),
248 $crate::hashing::hash_serialized_128,
249 std::any::TypeId::of::<Self>()
250 );
251 };
252}
253pub use define_derived_property;
254
255#[macro_export]
260macro_rules! define_multi_property {
261 (
262 $person_property:ident,
263 ( $($dependency:ident),+ )
264 ) => {
265 $crate::paste::paste! {
267 $crate::__define_derived_property_common!(
268 $person_property,
270
271 ( $(<$dependency as $crate::people::PersonProperty>::Value),+ ),
273
274 $crate::sorted_value_type!(( $($dependency),+ )),
276
277 $person_property::reorder_by_tag,
279
280 $person_property::unreorder_by_tag,
282
283 {
285 let type_ids = &mut [$($dependency::type_id()),+ ];
286 type_ids.sort();
287 $crate::people::register_type_ids_to_muli_property_id(type_ids, Self::type_id());
288 },
289
290 [$($dependency),+],
292
293 [],
295
296 |$( [<_ $dependency:lower>] ),+| {
298 ( $( [<_ $dependency:lower>] ),+ )
299 },
300
301 |values_tuple: &Self::CanonicalValue| {
303 let values_tuple: Self::Value = Self::unreorder_by_tag(*values_tuple);
305 let mut displayed = String::from("(");
306 let ( $( [<_ $dependency:lower>] ),+ ) = values_tuple;
307 $(
308 displayed.push_str(<$dependency as $crate::PersonProperty>::get_display(
309 & <$dependency as $crate::PersonProperty>::make_canonical([<_ $dependency:lower>])
310 ).as_str());
311 displayed.push_str(", ");
312 )+
313 displayed.truncate(displayed.len() - 2);
314 displayed.push_str(")");
315 displayed
316 },
317
318 $crate::hashing::hash_serialized_128,
320
321 std::any::TypeId::of::<$crate::sorted_tag!(( $($dependency),+ ))>()
326 );
327 $crate::impl_make_canonical!($person_property, ( $($dependency),+ ));
328 }
329 };
330}
331pub use define_multi_property;