mz_catalog/durable/upgrade/
json_compatible.rs1use serde::Serialize;
11use serde::de::DeserializeOwned;
12
13pub unsafe trait JsonCompatible<T>: Serialize + DeserializeOwned
17where
18 T: Serialize + DeserializeOwned,
19{
20 fn convert(old: &T) -> Self {
22 let bytes = serde_json::to_vec(old).expect("JSON serializable");
23 serde_json::from_slice(&bytes).expect("JSON compatible")
24 }
25}
26
27unsafe impl<T: Serialize + DeserializeOwned + Clone> JsonCompatible<T> for T {
29 fn convert(old: &Self) -> Self {
30 old.clone()
31 }
32}
33
34#[macro_export]
45macro_rules! json_compatible {
46 ($a:ident $(:: $a_sub:ident)* with $b:ident $(:: $b_sub:ident)*) => {
47 ::static_assertions::assert_impl_all!(
48 $a $(::$a_sub)* : ::proptest::arbitrary::Arbitrary, ::serde::Serialize, ::serde::de::DeserializeOwned,
49 );
50 ::static_assertions::assert_impl_all!(
51 $b $(::$b_sub)* : ::proptest::arbitrary::Arbitrary, ::serde::Serialize, ::serde::de::DeserializeOwned,
52 );
53
54 unsafe impl $crate::durable::upgrade::json_compatible::JsonCompatible< $b $(::$b_sub)* > for $a $(::$a_sub)* {}
57 unsafe impl $crate::durable::upgrade::json_compatible::JsonCompatible< $a $(::$a_sub)* > for $b $(::$b_sub)* {}
58
59 ::paste::paste! {
60 ::proptest::proptest! {
61 #![proptest_config(::proptest::test_runner::Config {
62 cases: 64,
63 ..Default::default()
64 })]
65
66 #[mz_ore::test]
67 #[cfg_attr(miri, ignore)] fn [<proptest_json_compat_ $a:snake $(_$a_sub:snake)* _to_ $b:snake $(_$b_sub:snake)* >](a: $a $(::$a_sub)* ) {
69 let a_bytes = ::serde_json::to_vec(&a).expect("JSON serializable");
70 let b_decoded = ::serde_json::from_slice::<$b $(::$b_sub)*>(&a_bytes);
71 ::proptest::prelude::prop_assert!(b_decoded.is_ok());
72
73 let b_decoded = b_decoded.expect("asserted Ok");
75 let b_converted: $b $(::$b_sub)* = $crate::durable::upgrade::json_compatible::JsonCompatible::convert(&a);
76 assert_eq!(b_decoded, b_converted);
77
78 let b_bytes = ::serde_json::to_vec(&b_decoded).expect("JSON serializable");
79 ::proptest::prelude::prop_assert_eq!(a_bytes, b_bytes, "a and b serialize differently");
80 }
81
82 #[mz_ore::test]
83 #[cfg_attr(miri, ignore)] fn [<proptest_json_compat_ $b:snake $(_$b_sub:snake)* _to_ $a:snake $(_$a_sub:snake)* >](b: $b $(::$b_sub)* ) {
85 let b_bytes = ::serde_json::to_vec(&b).expect("JSON serializable");
86 let a_decoded = ::serde_json::from_slice::<$a $(::$a_sub)*>(&b_bytes);
87 ::proptest::prelude::prop_assert!(a_decoded.is_ok());
88
89 let a_decoded = a_decoded.expect("asserted Ok");
91 let a_converted: $a $(::$a_sub)* = $crate::durable::upgrade::json_compatible::JsonCompatible::convert(&b);
92 assert_eq!(a_decoded, a_converted);
93
94 let a_bytes = ::serde_json::to_vec(&a_decoded).expect("JSON serializable");
95 ::proptest::prelude::prop_assert_eq!(a_bytes, b_bytes, "a and b serialize differently");
96 }
97 }
98 }
99 };
100}
101pub use json_compatible;