Skip to main content

topsoil_core/
generate_genesis_config.rs

1// This file is part of Soil.
2
3// Copyright (C) Soil contributors.
4// Copyright (C) Parity Technologies (UK) Ltd.
5// SPDX-License-Identifier: Apache-2.0 OR GPL-3.0-or-later WITH Classpath-exception-2.0
6
7//! Helper macro allowing to construct JSON representation of partially initialized structs.
8
9use serde_json::Value;
10extern crate alloc;
11use alloc::{borrow::Cow, format, string::String};
12
13/// Represents the initialization method of a field within a struct.
14///
15/// This enum provides information about how it was initialized.
16///
17/// Intended to be used in `build_struct_json_patch` macro.
18#[derive(Debug)]
19pub enum InitilizationType {
20	/// The field was partially initialized (e.g., specific fields within the struct were set
21	/// manually).
22	Partial,
23	/// The field was fully initialized (e.g., using `new()` or `default()` like methods
24	Full,
25}
26
27/// This struct provides information about how the struct field was initialized and the field name
28/// (as a `&str`).
29///
30/// Intended to be used in `build_struct_json_patch` macro.
31#[derive(Debug)]
32pub struct InitializedField<'a>(InitilizationType, Cow<'a, str>);
33
34impl<'a> InitializedField<'a> {
35	/// Returns a name of the field.
36	pub fn get_name(&'a self) -> &'a str {
37		&self.1
38	}
39
40	/// Injects a prefix to the field name.
41	pub fn add_prefix(&mut self, prefix: &str) {
42		self.1 = format!("{prefix}.{}", self.1).into()
43	}
44
45	/// Creates new partial field instiance.
46	pub fn partial(s: &'a str) -> Self {
47		Self(InitilizationType::Partial, s.into())
48	}
49
50	/// Creates new full field instiance.
51	pub fn full(s: &'a str) -> Self {
52		Self(InitilizationType::Full, s.into())
53	}
54}
55
56impl PartialEq<String> for InitializedField<'_> {
57	fn eq(&self, other: &String) -> bool {
58		#[inline]
59		/// We need to respect the `camelCase` naming for field names. This means that
60		/// `"camelCaseKey"` should be considered equal to `"camel_case_key"`. This
61		/// function implements this comparison.
62		fn compare_keys(ident_chars: core::str::Chars, camel_chars: core::str::Chars) -> bool {
63			ident_chars
64				.filter(|c| *c != '_')
65				.map(|c| c.to_ascii_uppercase())
66				.eq(camel_chars.map(|c| c.to_ascii_uppercase()))
67		}
68		*self.1 == *other || compare_keys(self.1.chars(), other.chars())
69	}
70}
71
72impl<'a> From<(InitilizationType, &'a str)> for InitializedField<'a> {
73	fn from(value: (InitilizationType, &'a str)) -> Self {
74		match value.0 {
75			InitilizationType::Full => InitializedField::full(value.1),
76			InitilizationType::Partial => InitializedField::partial(value.1),
77		}
78	}
79}
80
81/// Recursively removes keys from provided `json_value` object, retaining only specified keys.
82///
83/// This function modifies the provided `json_value` in-place, keeping only the keys listed in
84/// `keys_to_retain`. The keys are matched recursively by combining the current key with
85/// the `current_root`, allowing for nested field retention.
86///
87/// Keys marked as `Full`, are retained as-is. For keys marked as `Partial`, the
88/// function recurses into nested objects to retain matching subfields.
89///
90/// Function respects the `camelCase` serde_json attribute for structures. This means that
91/// `"camelCaseKey"` key will be retained in JSON blob if `"camel_case_key"` exists in
92/// `keys_to_retain`.
93///
94/// Intended to be used from `build_struct_json_patch` macro.
95pub fn retain_initialized_fields(
96	json_value: &mut Value,
97	keys_to_retain: &[InitializedField],
98	current_root: String,
99) {
100	if let serde_json::Value::Object(ref mut map) = json_value {
101		map.retain(|key, value| {
102			let current_key =
103				if current_root.is_empty() { key.clone() } else { format!("{current_root}.{key}") };
104			match keys_to_retain.iter().find(|key| **key == current_key) {
105				Some(InitializedField(InitilizationType::Full, _)) => true,
106				Some(InitializedField(InitilizationType::Partial, _)) => {
107					retain_initialized_fields(value, keys_to_retain, current_key.clone());
108					true
109				},
110				None => false,
111			}
112		})
113	}
114}
115
116/// Creates a JSON patch for given `struct_type`, supporting recursive field initialization.
117///
118/// This macro creates a default `struct_type`, initializing specified fields (which can be nested)
119/// with the provided values. Any fields not explicitly given are initialized with their default
120/// values. The macro then serializes the fully initialized structure into a JSON blob, retaining
121/// only the fields that were explicitly provided, either partially or fully initialized.
122///
123/// Using this macro prevents errors from manually creating JSON objects, such as typos or
124/// inconsistencies with the `struct_type` structure, by relying on the actual
125/// struct definition. This ensures the generated JSON is valid and reflects any future changes
126/// to the structure.
127///
128/// # Example
129///
130/// ```rust
131/// use topsoil_core::build_struct_json_patch;
132/// #[derive(Default, serde::Serialize, serde::Deserialize)]
133/// #[serde(rename_all = "camelCase")]
134/// struct RuntimeGenesisConfig {
135///     a_field: u32,
136///     b_field: B,
137///     c_field: u32,
138/// }
139///
140/// #[derive(Default, serde::Serialize, serde::Deserialize)]
141/// #[serde(rename_all = "camelCase")]
142/// struct B {
143/// 	i_field: u32,
144/// 	j_field: u32,
145/// }
146/// impl B {
147/// 	fn new() -> Self {
148/// 		Self { i_field: 0, j_field: 2 }
149/// 	}
150/// }
151///
152/// assert_eq!(
153/// 	build_struct_json_patch! ( RuntimeGenesisConfig {
154/// 		a_field: 66,
155/// 	}),
156/// 	serde_json::json!({
157/// 			"aField": 66,
158/// 	})
159/// );
160///
161/// assert_eq!(
162/// 	build_struct_json_patch! ( RuntimeGenesisConfig {
163/// 		//"partial" initialization of `b_field`
164/// 		b_field: B {
165/// 			i_field: 2,
166/// 		}
167/// 	}),
168/// 	serde_json::json!({
169/// 		"bField": {"iField": 2}
170/// 	})
171/// );
172///
173/// assert_eq!(
174/// 	build_struct_json_patch! ( RuntimeGenesisConfig {
175/// 		a_field: 66,
176/// 		//"full" initialization of `b_field`
177/// 		b_field: B::new()
178/// 	}),
179/// 	serde_json::json!({
180/// 		"aField": 66,
181/// 		"bField": {"iField": 0, "jField": 2}
182/// 	})
183/// );
184/// ```
185///
186/// In this example:
187/// ```ignore
188/// 	build_struct_json_patch! ( RuntimeGenesisConfig {
189/// 		b_field: B {
190/// 			i_field: 2,
191/// 		}
192/// 	}),
193/// ```
194/// `b_field` is partially initialized, it will be expanded to:
195/// ```ignore
196/// RuntimeGenesisConfig {
197/// 		b_field {
198/// 			i_field: 2,
199/// 			..Default::default()
200/// 		},
201/// 		..Default::default()
202/// }
203/// ```
204/// While all other fields are initialized with default values. The macro serializes this, retaining
205/// only the provided fields.
206#[macro_export]
207macro_rules! build_struct_json_patch {
208	(
209		$($struct_type:ident)::+ { $($body:tt)* }
210	) => {
211		{
212			let mut __keys = $crate::__private::Vec::<$crate::generate_genesis_config::InitializedField>::default();
213			#[allow(clippy::needless_update)]
214			let __struct_instance = $crate::build_struct_json_patch!($($struct_type)::+, __keys @  { $($body)* }).0;
215			let mut __json_value =
216				$crate::__private::serde_json::to_value(__struct_instance).expect("serialization to json should work. qed");
217			$crate::generate_genesis_config::retain_initialized_fields(&mut __json_value, &__keys, Default::default());
218			__json_value
219		}
220	};
221	($($struct_type:ident)::+, $all_keys:ident @ { $($body:tt)* }) => {
222		{
223			let __value = $crate::build_struct_json_patch!($($struct_type)::+, $all_keys @ $($body)*);
224			(
225				$($struct_type)::+ { ..__value.0 },
226				__value.1
227			)
228		}
229	};
230	($($struct_type:ident)::+, $all_keys:ident @ $key:ident:  $($type:ident)::+ { $($body:tt)* } ) => {
231		(
232			$($struct_type)::+ {
233				$key: {
234					let mut __inner_keys =
235						$crate::__private::Vec::<$crate::generate_genesis_config::InitializedField>::default();
236					let __value = $crate::build_struct_json_patch!($($type)::+, __inner_keys @ { $($body)* });
237					for i in __inner_keys.iter_mut() {
238						i.add_prefix(stringify!($key));
239					};
240					$all_keys.push((__value.1,stringify!($key)).into());
241					$all_keys.extend(__inner_keys);
242					__value.0
243				},
244				..Default::default()
245			},
246			$crate::generate_genesis_config::InitilizationType::Partial
247		)
248	};
249	($($struct_type:ident)::+, $all_keys:ident @ $key:ident:  $($type:ident)::+ { $($body:tt)* },  $($tail:tt)*) => {
250		{
251			let mut __initialization_type;
252			(
253				$($struct_type)::+ {
254					$key : {
255						let mut __inner_keys =
256							$crate::__private::Vec::<$crate::generate_genesis_config::InitializedField>::default();
257						let __value = $crate::build_struct_json_patch!($($type)::+, __inner_keys @ { $($body)* });
258						$all_keys.push((__value.1,stringify!($key)).into());
259
260						for i in __inner_keys.iter_mut() {
261							i.add_prefix(stringify!($key));
262						};
263						$all_keys.extend(__inner_keys);
264						__value.0
265					},
266					.. {
267						let (__value, __tmp) =
268							$crate::build_struct_json_patch!($($struct_type)::+, $all_keys @ $($tail)*);
269						__initialization_type = __tmp;
270						__value
271					}
272				},
273				__initialization_type
274			)
275		}
276	};
277	($($struct_type:ident)::+, $all_keys:ident @ $key:ident: $value:expr, $($tail:tt)* ) => {
278		{
279			let mut __initialization_type;
280			(
281				$($struct_type)::+ {
282					$key: {
283						$all_keys.push($crate::generate_genesis_config::InitializedField::full(
284							stringify!($key))
285						);
286						$value
287					},
288					.. {
289						let (__value, __tmp) =
290							$crate::build_struct_json_patch!($($struct_type)::+, $all_keys @ $($tail)*);
291						__initialization_type = __tmp;
292						__value
293					}
294				},
295				__initialization_type
296			)
297		}
298	};
299	($($struct_type:ident)::+, $all_keys:ident @ $key:ident: $value:expr ) => {
300		(
301			$($struct_type)::+ {
302				$key: {
303					$all_keys.push($crate::generate_genesis_config::InitializedField::full(stringify!($key)));
304					$value
305				},
306				..Default::default()
307			},
308			$crate::generate_genesis_config::InitilizationType::Partial
309		)
310	};
311	// field init shorthand
312	($($struct_type:ident)::+, $all_keys:ident @ $key:ident, $($tail:tt)* ) => {
313		{
314			let __update = $crate::build_struct_json_patch!($($struct_type)::+, $all_keys @ $($tail)*);
315			(
316				$($struct_type)::+ {
317					$key: {
318						$all_keys.push($crate::generate_genesis_config::InitializedField::full(
319							stringify!($key))
320						);
321						$key
322					},
323					..__update.0
324				},
325				__update.1
326			)
327		}
328	};
329	($($struct_type:ident)::+, $all_keys:ident @ $key:ident ) => {
330		(
331			$($struct_type)::+ {
332				$key: {
333					$all_keys.push($crate::generate_genesis_config::InitializedField::full(stringify!($key)));
334					$key
335				},
336				..Default::default()
337			},
338			$crate::generate_genesis_config::InitilizationType::Partial
339		)
340	};
341	// update struct
342	($($struct_type:ident)::+, $all_keys:ident @ ..$update:expr ) => {
343		(
344			$($struct_type)::+ {
345				..$update
346			},
347			$crate::generate_genesis_config::InitilizationType::Full
348		)
349	};
350	($($struct_type:ident)::+, $all_keys:ident  @ $(,)?) => {
351		(
352			$($struct_type)::+ {
353				..Default::default()
354			},
355			$crate::generate_genesis_config::InitilizationType::Partial
356		)
357	};
358}
359
360#[cfg(test)]
361mod test {
362	mod nested_mod {
363		#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
364		pub struct InsideMod {
365			pub a: u32,
366			pub b: u32,
367		}
368
369		pub mod nested_mod2 {
370			pub mod nested_mod3 {
371				#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
372				pub struct InsideMod3 {
373					pub a: u32,
374					pub b: u32,
375					pub s: super::super::InsideMod,
376				}
377			}
378		}
379	}
380
381	#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
382	struct TestStruct {
383		a: u32,
384		b: u32,
385		s: S,
386		s3: S3,
387		t3: S3,
388		i: Nested1,
389		e: E,
390		t: nested_mod::InsideMod,
391		u: nested_mod::nested_mod2::nested_mod3::InsideMod3,
392	}
393
394	#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
395	struct S {
396		x: u32,
397	}
398
399	impl S {
400		fn new(c: u32) -> Self {
401			Self { x: c }
402		}
403	}
404
405	#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
406	struct E(u8);
407
408	#[derive(Default, Debug, serde::Serialize, serde::Deserialize)]
409	enum SomeEnum<T> {
410		#[default]
411		A,
412		B(T),
413	}
414
415	#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
416	struct S3 {
417		x: u32,
418		y: u32,
419		z: u32,
420	}
421
422	impl S3 {
423		fn new(c: u32) -> Self {
424			Self { x: c, y: c, z: c }
425		}
426
427		fn new_from_s(s: S) -> Self {
428			Self { x: s.x, ..Default::default() }
429		}
430	}
431
432	#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
433	struct Nested3 {
434		a: u32,
435		b: u32,
436		s: S,
437		v: Vec<(u32, u32, u32, SomeEnum<u32>)>,
438	}
439
440	#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
441	struct Nested2 {
442		a: u32,
443		iii: Nested3,
444		v: Vec<u32>,
445		s3: S3,
446	}
447
448	impl Nested2 {
449		fn new(a: u32) -> Self {
450			Nested2 {
451				a,
452				v: vec![a, a, a],
453				iii: Nested3 { a, b: a, ..Default::default() },
454				s3: S3 { x: a, ..Default::default() },
455			}
456		}
457	}
458
459	#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
460	struct Nested1 {
461		a: u32,
462		ii: Nested2,
463	}
464
465	macro_rules! test {
466		($($struct:ident)::+ { $($v:tt)* }, { $($j:tt)* } ) => {{
467			let expected = serde_json::json!({ $($j)* });
468			let value = build_struct_json_patch!($($struct)::+ { $($v)* });
469			assert_eq!(value, expected);
470		}};
471	}
472
473	#[test]
474	fn test_generate_config_macro() {
475		let t = 5;
476		const C: u32 = 5;
477		test!(TestStruct { b: 5 }, { "b": 5 });
478		test!(TestStruct { b: 5, }, { "b": 5 });
479		#[allow(unused_braces)]
480		{
481			test!(TestStruct { b: { 4 + 34 } } , { "b": 38 });
482		}
483		test!(TestStruct { s: S { x: 5 } }, { "s": { "x": 5 } });
484		test!(
485			TestStruct { s: S::new(C) },
486			{
487				"s": { "x": 5 }
488			}
489		);
490		test!(
491			TestStruct { s: S { x: t } },
492			{
493				"s": { "x": t }
494			}
495		);
496		test!(
497			TestStruct {
498				b: 5,
499				s: S { x: t }
500			},
501			{
502				"b": 5,
503				"s": { "x": 5 }
504			}
505		);
506		test!(
507			TestStruct { s: S::new(C), b: 5 },
508			{
509				"s": { "x": 5 }, "b": 5
510			}
511		);
512		test!(
513			TestStruct { s3: S3 { x: t } },
514			{
515				"s3": { "x": 5 }
516			}
517		);
518		test!(
519			TestStruct {
520				s3: S3 { x: t, y: 2 }
521			},
522			{
523				"s3": { "x": 5, "y": 2 }
524			}
525		);
526		// //
527		test!(
528			TestStruct {
529				s3: S3 { x: t, y: 2 },
530				t3: S3 { x: 2 }
531			},
532			{
533				"s3": { "x": t, "y": 2 },
534				"t3": { "x": 2 }
535			}
536
537		);
538		test!(
539			TestStruct {
540				i: Nested1 {
541					ii: Nested2 { iii: Nested3 { a: 2 } }
542				}
543			}
544			,
545			{
546				"i":  {
547					"ii": { "iii": { "a": 2 } }
548				}
549			}
550
551		);
552		test!(
553			TestStruct {
554				i: Nested1 {
555					ii: Nested2 {
556						iii: Nested3 { a: 2, s: S::new(C) }
557					}
558				}
559			},
560			{
561				"i": {
562					"ii": {
563						"iii": { "a": 2, "s": { "x": 5} }
564					}
565				}
566			}
567		);
568		test!(
569			TestStruct {
570				i: Nested1 {
571					ii: Nested2 {
572						iii: Nested3 { s: S::new(C), a: 2 }
573					},
574					a: 44
575				},
576				a: 3,
577				s3: S3 { x: 5 },
578				b: 4
579			},
580			{
581				"i": {
582					"ii": {
583						"iii": { "a": 2, "s": { "x": 5} }
584					},
585					"a": 44
586				},
587				"a": 3,
588				"s3": { "x": 5 },
589				"b": 4
590			}
591		);
592		test!(
593			TestStruct {
594				i: Nested1 {
595					ii: Nested2::new(66),
596					a: 44,
597				},
598				a: 3,
599				s3: S3 { x: 5 },
600				b: 4
601			},
602			{
603				"i": {
604					"ii": {
605						"a": 66,
606						"s3": { "x":66, "y": 0, "z": 0 },
607						"iii": { "a": 66,"b":66, "s": { "x": 0 }, "v": Vec::<u32>::default() },
608						"v": vec![66,66,66]
609					},
610					"a": 44
611				},
612				"a": 3,
613				"s3": { "x": 5 },
614				"b": 4
615			}
616		);
617
618		test!(
619			TestStruct {
620				i: Nested1 {
621					ii: Nested2 {
622						a: 66,
623						s3: S3 { x: 66 },
624						iii: Nested3 {
625							a: 66,b:66
626						},
627						v: vec![66,66,66]
628					},
629					a: 44,
630				},
631				a: 3,
632				s3: S3 { x: 5 },
633				b: 4
634			},
635			{
636				"i": {
637					"ii": {
638						"a": 66,
639						"s3": { "x":66,  },
640						"iii": { "a": 66,"b":66, },
641						"v": vec![66,66,66]
642					},
643					"a": 44
644				},
645				"a": 3,
646				"s3": { "x": 5 },
647				"b": 4
648			}
649		);
650
651		test!(
652			TestStruct {
653				i: Nested1 {
654					ii: Nested2 {
655						iii: Nested3 { a: 2, s: S::new(C) },
656					},
657					a: 44,
658				},
659				a: 3,
660				s3: S3 { x: 5 },
661				b: 4,
662			},
663			{
664				"i": {
665					"ii": {
666						"iii": { "a": 2, "s": { "x": 5 } },
667					},
668					"a" : 44,
669				},
670				"a": 3,
671				"s3": { "x": 5 },
672				"b": 4
673			}
674		);
675		test!(
676			TestStruct {
677				i: Nested1 {
678					ii: Nested2 {
679						s3: S3::new(5),
680						iii: Nested3 { a: 2, s: S::new(C) },
681					},
682					a: 44,
683				},
684				a: 3,
685				s3: S3 { x: 5 },
686				b: 4,
687			},
688			{
689				"i": {
690					"ii": {
691						"iii": { "a": 2, "s": { "x": 5 } },
692						"s3": {"x": 5, "y": 5, "z": 5 }
693					},
694					"a" : 44,
695				},
696				"a": 3,
697				"s3": { "x": 5 },
698				"b": 4
699			}
700		);
701		test!(
702			TestStruct {
703				a: 3,
704				s3: S3 { x: 5 },
705				b: 4,
706				i: Nested1 {
707					ii: Nested2 {
708						iii: Nested3 { a: 2, s: S::new(C) },
709						s3: S3::new_from_s(S { x: 4 })
710					},
711					a: 44,
712				}
713			},
714			{
715				"i": {
716					"ii": {
717						"iii": { "a": 2, "s": { "x": 5 } },
718						"s3": {"x": 4, "y": 0, "z": 0 }
719					},
720					"a" : 44,
721				},
722				"a": 3,
723				"s3": { "x": 5 },
724				"b": 4
725			}
726		);
727		let i = [0u32, 1u32, 2u32];
728		test!(
729			TestStruct {
730				i: Nested1 {
731					ii: Nested2 {
732						iii: Nested3 {
733							a: 2,
734							s: S::new(C),
735							v: i.iter()
736								.map(|x| (*x, 2 * x, 100 + x, SomeEnum::<u32>::A))
737								.collect::<Vec<_>>(),
738						},
739						s3: S3::new_from_s(S { x: 4 })
740					},
741					a: 44,
742				},
743				a: 3,
744				s3: S3 { x: 5 },
745				b: 4,
746			},
747
748			{
749				"i": {
750					"ii": {
751						"iii": {
752							"a": 2,
753							"s": { "x": 5 },
754							"v": i.iter()
755								.map(|x| (*x, 2 * x, 100 + x, SomeEnum::<u32>::A))
756								.collect::<Vec<_>>(),
757						},
758						"s3": {"x": 4, "y": 0, "z": 0 }
759					},
760					"a" : 44,
761				},
762				"a": 3,
763				"s3": { "x": 5 },
764				"b": 4
765			}
766		);
767	}
768
769	#[test]
770	fn test_generate_config_macro_field_init_shorthand() {
771		{
772			let x = 5;
773			test!(TestStruct { s: S { x } }, { "s": { "x": 5 } });
774		}
775		{
776			let s = nested_mod::InsideMod { a: 34, b: 8 };
777			test!(
778				TestStruct {
779					t: nested_mod::InsideMod { a: 32 },
780					u: nested_mod::nested_mod2::nested_mod3::InsideMod3 {
781						s,
782						a: 32,
783					}
784				},
785				{
786					"t" : { "a": 32 },
787					"u" : { "a": 32, "s": { "a": 34, "b": 8} }
788				}
789			);
790		}
791		{
792			let s = nested_mod::InsideMod { a: 34, b: 8 };
793			test!(
794				TestStruct {
795					t: nested_mod::InsideMod { a: 32 },
796					u: nested_mod::nested_mod2::nested_mod3::InsideMod3 {
797						a: 32,
798						s,
799					}
800				},
801				{
802					"t" : { "a": 32 },
803					"u" : { "a": 32, "s": { "a": 34, "b": 8} }
804				}
805			);
806		}
807	}
808
809	#[test]
810	fn test_generate_config_macro_struct_update() {
811		{
812			let s = S { x: 5 };
813			test!(TestStruct { s: S { ..s } }, { "s": { "x": 5 } });
814		}
815		{
816			mod nested {
817				use super::*;
818				pub fn function() -> S {
819					S { x: 5 }
820				}
821			}
822			test!(TestStruct { s: S { ..nested::function() } }, { "s": { "x": 5 } });
823		}
824		{
825			let s = nested_mod::InsideMod { a: 34, b: 8 };
826			let s1 = nested_mod::InsideMod { a: 34, b: 8 };
827			test!(
828				TestStruct {
829					t: nested_mod::InsideMod { ..s1 },
830					u: nested_mod::nested_mod2::nested_mod3::InsideMod3 {
831						s,
832						a: 32,
833					}
834				},
835				{
836					"t" : { "a": 34, "b": 8 },
837					"u" : { "a": 32, "s": { "a": 34, "b": 8} }
838				}
839			);
840		}
841		{
842			let i3 = nested_mod::nested_mod2::nested_mod3::InsideMod3 {
843				a: 1,
844				b: 2,
845				s: nested_mod::InsideMod { a: 55, b: 88 },
846			};
847			test!(
848				TestStruct {
849					t: nested_mod::InsideMod { a: 32 },
850					u: nested_mod::nested_mod2::nested_mod3::InsideMod3 {
851						a: 32,
852						..i3
853					}
854				},
855				{
856					"t" : { "a": 32 },
857					"u" : { "a": 32, "b": 2, "s": { "a": 55, "b": 88} }
858				}
859			);
860		}
861		{
862			let s = nested_mod::InsideMod { a: 34, b: 8 };
863			test!(
864				TestStruct {
865					t: nested_mod::InsideMod { a: 32 },
866					u: nested_mod::nested_mod2::nested_mod3::InsideMod3 {
867						a: 32,
868						s: nested_mod::InsideMod  {
869							b: 66,
870							..s
871						}
872					}
873				},
874				{
875					"t" : { "a": 32 },
876					"u" : { "a": 32, "s": { "a": 34, "b": 66} }
877				}
878			);
879		}
880		{
881			let s = nested_mod::InsideMod { a: 34, b: 8 };
882			test!(
883				TestStruct {
884					t: nested_mod::InsideMod { a: 32 },
885					u: nested_mod::nested_mod2::nested_mod3::InsideMod3 {
886						s: nested_mod::InsideMod  {
887							b: 66,
888							..s
889						},
890						a: 32
891					}
892				},
893				{
894					"t" : { "a": 32 },
895					"u" : { "a": 32, "s": { "a": 34, "b": 66} }
896				}
897			);
898		}
899	}
900
901	#[test]
902	fn test_generate_config_macro_with_execution_order() {
903		#[derive(Debug, Default, serde::Serialize, serde::Deserialize, PartialEq)]
904		struct X {
905			x: Vec<u32>,
906			x2: Vec<u32>,
907			y2: Y,
908		}
909		#[derive(Debug, Default, serde::Serialize, serde::Deserialize, PartialEq)]
910		struct Y {
911			y: Vec<u32>,
912		}
913		#[derive(Debug, Default, serde::Serialize, serde::Deserialize, PartialEq)]
914		struct Z {
915			a: u32,
916			x: X,
917			y: Y,
918		}
919		{
920			let v = vec![1, 2, 3];
921			test!(Z { a: 0, x: X { x: v },  }, {
922				"a": 0, "x": { "x": [1,2,3] }
923			});
924		}
925		{
926			let v = vec![1, 2, 3];
927			test!(Z { a: 3, x: X { x: v.clone() }, y: Y { y: v } }, {
928				"a": 3, "x": { "x": [1,2,3] }, "y": { "y": [1,2,3] }
929			});
930		}
931		{
932			let v = vec![1, 2, 3];
933			test!(Z { a: 3, x: X { y2: Y { y: v.clone() }, x: v.clone() }, y: Y { y: v } }, {
934				"a": 3, "x": { "x": [1,2,3], "y2":{ "y":[1,2,3] } }, "y": { "y": [1,2,3] }
935			});
936		}
937		{
938			let v = vec![1, 2, 3];
939			test!(Z { a: 3, y: Y { y: v.clone() }, x: X { y2: Y { y: v.clone() }, x: v },  }, {
940				"a": 3, "x": { "x": [1,2,3], "y2":{ "y":[1,2,3] } }, "y": { "y": [1,2,3] }
941			});
942		}
943		{
944			let v = vec![1, 2, 3];
945			test!(
946				Z {
947					y: Y {
948						y: v.clone()
949					},
950					x: X {
951						y2: Y {
952							y: v.clone()
953						},
954						x: v.clone(),
955						x2: v.clone()
956					},
957				},
958				{
959					"x": {
960						"x": [1,2,3],
961						"x2": [1,2,3],
962						"y2": {
963							"y":[1,2,3]
964						}
965					},
966					"y": {
967						"y": [1,2,3]
968					}
969			});
970		}
971		{
972			let v = vec![1, 2, 3];
973			test!(
974				Z {
975					y: Y {
976						y: v.clone()
977					},
978					x: X {
979						y2: Y {
980							y: v.clone()
981						},
982						x: v
983					},
984				},
985				{
986					"x": {
987						"x": [1,2,3],
988						"y2": {
989							"y":[1,2,3]
990						}
991					},
992					"y": {
993						"y": [1,2,3]
994					}
995			});
996		}
997		{
998			let mut v = vec![0, 1, 2];
999			let f = |vec: &mut Vec<u32>| -> Vec<u32> {
1000				vec.iter_mut().for_each(|x| *x += 1);
1001				vec.clone()
1002			};
1003			let z = Z {
1004				a: 0,
1005				y: Y { y: f(&mut v) },
1006				x: X { y2: Y { y: f(&mut v) }, x: f(&mut v), x2: vec![] },
1007			};
1008			let z_expected = Z {
1009				a: 0,
1010				y: Y { y: vec![1, 2, 3] },
1011				x: X { y2: Y { y: vec![2, 3, 4] }, x: vec![3, 4, 5], x2: vec![] },
1012			};
1013			assert_eq!(z, z_expected);
1014			v = vec![0, 1, 2];
1015			println!("{z:?}");
1016			test!(
1017				Z {
1018					y: Y {
1019						y: f(&mut v)
1020					},
1021					x: X {
1022						y2: Y {
1023							y: f(&mut v)
1024						},
1025						x: f(&mut v)
1026					},
1027				},
1028				{
1029					"y": {
1030						"y": [1,2,3]
1031					},
1032					"x": {
1033						"y2": {
1034							"y":[2,3,4]
1035						},
1036						"x": [3,4,5],
1037					},
1038			});
1039		}
1040		{
1041			let mut v = vec![0, 1, 2];
1042			let f = |vec: &mut Vec<u32>| -> Vec<u32> {
1043				vec.iter_mut().for_each(|x| *x += 1);
1044				vec.clone()
1045			};
1046			let z = Z {
1047				a: 0,
1048				y: Y { y: f(&mut v) },
1049				x: X { y2: Y { y: f(&mut v) }, x: f(&mut v), x2: f(&mut v) },
1050			};
1051			let z_expected = Z {
1052				a: 0,
1053				y: Y { y: vec![1, 2, 3] },
1054				x: X { y2: Y { y: vec![2, 3, 4] }, x: vec![3, 4, 5], x2: vec![4, 5, 6] },
1055			};
1056			assert_eq!(z, z_expected);
1057			v = vec![0, 1, 2];
1058			println!("{z:?}");
1059			test!(
1060				Z {
1061					y: Y {
1062						y: f(&mut v)
1063					},
1064					x: X {
1065						y2: Y {
1066							y: f(&mut v)
1067						},
1068						x: f(&mut v),
1069						x2: f(&mut v)
1070					},
1071				},
1072				{
1073					"y": {
1074						"y": [1,2,3]
1075					},
1076					"x": {
1077						"y2": {
1078							"y":[2,3,4]
1079						},
1080						"x": [3,4,5],
1081						"x2": [4,5,6],
1082					},
1083			});
1084		}
1085	}
1086
1087	#[test]
1088	fn test_generate_config_macro_with_nested_mods() {
1089		test!(
1090			TestStruct { t: nested_mod::InsideMod { a: 32 } },
1091			{
1092				"t" : { "a": 32 }
1093			}
1094		);
1095		test!(
1096			TestStruct {
1097				t: nested_mod::InsideMod { a: 32 },
1098				u: nested_mod::nested_mod2::nested_mod3::InsideMod3 { a: 32 }
1099			},
1100			{
1101				"t" : { "a": 32 },
1102				"u" : { "a": 32 }
1103			}
1104		);
1105		test!(
1106			TestStruct {
1107				t: nested_mod::InsideMod { a: 32 },
1108				u: nested_mod::nested_mod2::nested_mod3::InsideMod3 {
1109					a: 32,
1110					s: nested_mod::InsideMod { a: 34 },
1111				}
1112			},
1113			{
1114				"t" : { "a": 32 },
1115				"u" : { "a": 32, "s": { "a": 34 } }
1116			}
1117		);
1118		test!(
1119			TestStruct {
1120				t: nested_mod::InsideMod { a: 32 },
1121				u: nested_mod::nested_mod2::nested_mod3::InsideMod3::default()
1122			},
1123			{
1124				"t" : { "a": 32 },
1125				"u" : { "a": 0, "b": 0,  "s": { "a": 0, "b": 0} }
1126			}
1127		);
1128
1129		let i = [0u32, 1u32, 2u32];
1130		const C: u32 = 5;
1131		test!(
1132			TestStruct {
1133				t: nested_mod::InsideMod { a: 32 },
1134				u: nested_mod::nested_mod2::nested_mod3::InsideMod3::default(),
1135				i: Nested1 {
1136					ii: Nested2 {
1137						iii: Nested3 {
1138							a: 2,
1139							s: S::new(C),
1140							v: i.iter()
1141								.map(|x| (*x, 2 * x, 100 + x, SomeEnum::<u32>::A))
1142								.collect::<Vec<_>>(),
1143						},
1144						s3: S3::new_from_s(S { x: 4 })
1145					},
1146					a: 44,
1147				},
1148			},
1149			{
1150				"t" : { "a": 32 },
1151				"u" : { "a": 0, "b": 0,  "s": { "a": 0, "b": 0} } ,
1152				"i": {
1153					"ii": {
1154						"iii": {
1155							"a": 2,
1156							"s": { "x": 5 },
1157							"v": i.iter()
1158								.map(|x| (*x, 2 * x, 100 + x, SomeEnum::<u32>::A))
1159								.collect::<Vec<_>>(),
1160						},
1161						"s3": {"x": 4, "y": 0, "z": 0 }
1162					},
1163					"a" : 44,
1164				},
1165			}
1166		);
1167	}
1168}
1169
1170#[cfg(test)]
1171mod retain_keys_test {
1172	use super::*;
1173	use serde_json::json;
1174
1175	macro_rules! check_initialized_field_eq_cc(
1176		( $s:literal ) => {
1177			let field = InitializedField::full($s);
1178			let cc = inflector::cases::camelcase::to_camel_case($s);
1179			assert_eq!(field,cc);
1180		} ;
1181		( &[ $f:literal $(, $r:literal)* ]) => {
1182			let field = InitializedField::full(
1183				concat!( $f $(,".",$r)+ )
1184			);
1185			let cc = [ $f $(,$r)+  ].into_iter()
1186				.map(|s| inflector::cases::camelcase::to_camel_case(s))
1187				.collect::<Vec<_>>()
1188				.join(".");
1189			assert_eq!(field,cc);
1190		} ;
1191	);
1192
1193	#[test]
1194	fn test_initialized_field_eq_cc_string() {
1195		check_initialized_field_eq_cc!("a_");
1196		check_initialized_field_eq_cc!("abc");
1197		check_initialized_field_eq_cc!("aBc");
1198		check_initialized_field_eq_cc!("aBC");
1199		check_initialized_field_eq_cc!("ABC");
1200		check_initialized_field_eq_cc!("2abs");
1201		check_initialized_field_eq_cc!("2Abs");
1202		check_initialized_field_eq_cc!("2ABs");
1203		check_initialized_field_eq_cc!("2aBs");
1204		check_initialized_field_eq_cc!("AlreadyCamelCase");
1205		check_initialized_field_eq_cc!("alreadyCamelCase");
1206		check_initialized_field_eq_cc!("C");
1207		check_initialized_field_eq_cc!("1a");
1208		check_initialized_field_eq_cc!("_1a");
1209		check_initialized_field_eq_cc!("a_b");
1210		check_initialized_field_eq_cc!("_a_b");
1211		check_initialized_field_eq_cc!("a___b");
1212		check_initialized_field_eq_cc!("__a_b");
1213		check_initialized_field_eq_cc!("_a___b_C");
1214		check_initialized_field_eq_cc!("__A___B_C");
1215		check_initialized_field_eq_cc!(&["a_b", "b_c"]);
1216		check_initialized_field_eq_cc!(&["al_pha", "_a___b_C"]);
1217		check_initialized_field_eq_cc!(&["al_pha_", "_a___b_C"]);
1218		check_initialized_field_eq_cc!(&["first_field", "al_pha_", "_a___b_C"]);
1219		check_initialized_field_eq_cc!(&["al_pha_", "__2nd_field", "_a___b_C"]);
1220		check_initialized_field_eq_cc!(&["al_pha_", "__2nd3and_field", "_a___b_C"]);
1221		check_initialized_field_eq_cc!(&["_a1", "_a2", "_a3_"]);
1222	}
1223
1224	#[test]
1225	fn test01() {
1226		let mut v = json!({
1227			"a":1
1228		});
1229		let e = v.clone();
1230		retain_initialized_fields(&mut v, &[InitializedField::full("a")], String::default());
1231		assert_eq!(e, v);
1232	}
1233
1234	#[test]
1235	fn test02() {
1236		let mut v = json!({
1237			"a":1
1238		});
1239		retain_initialized_fields(&mut v, &[InitializedField::full("b")], String::default());
1240		assert_eq!(Value::Object(Default::default()), v);
1241	}
1242
1243	#[test]
1244	fn test03() {
1245		let mut v = json!({});
1246		retain_initialized_fields(&mut v, &[], String::default());
1247		assert_eq!(Value::Object(Default::default()), v);
1248	}
1249
1250	#[test]
1251	fn test04() {
1252		let mut v = json!({});
1253		retain_initialized_fields(&mut v, &[InitializedField::full("b")], String::default());
1254		assert_eq!(Value::Object(Default::default()), v);
1255	}
1256
1257	#[test]
1258	fn test05() {
1259		let mut v = json!({
1260			"a":1
1261		});
1262		retain_initialized_fields(&mut v, &[], String::default());
1263		assert_eq!(Value::Object(Default::default()), v);
1264	}
1265
1266	#[test]
1267	fn test06() {
1268		let mut v = json!({
1269			"a": {
1270				"b":1,
1271				"c":2
1272			}
1273		});
1274		retain_initialized_fields(&mut v, &[], String::default());
1275		assert_eq!(Value::Object(Default::default()), v);
1276	}
1277
1278	#[test]
1279	fn test07() {
1280		let mut v = json!({
1281			"a": {
1282				"b":1,
1283				"c":2
1284			}
1285		});
1286		retain_initialized_fields(&mut v, &[InitializedField::full("a.b")], String::default());
1287		assert_eq!(Value::Object(Default::default()), v);
1288	}
1289
1290	#[test]
1291	fn test08() {
1292		let mut v = json!({
1293			"a": {
1294				"b":1,
1295				"c":2
1296			}
1297		});
1298		let e = json!({
1299			"a": {
1300				"b":1,
1301			}
1302		});
1303		retain_initialized_fields(
1304			&mut v,
1305			&[InitializedField::partial("a"), InitializedField::full("a.b")],
1306			String::default(),
1307		);
1308		assert_eq!(e, v);
1309	}
1310
1311	#[test]
1312	fn test09() {
1313		let mut v = json!({
1314			"a": {
1315				"b":1,
1316				"c":2
1317			}
1318		});
1319		let e = json!({
1320			"a": {
1321				"b":1,
1322				"c":2,
1323			}
1324		});
1325		retain_initialized_fields(&mut v, &[InitializedField::full("a")], String::default());
1326		assert_eq!(e, v);
1327	}
1328}