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)* :
49 ::serde::Serialize,
50 ::serde::de::DeserializeOwned,
51 );
52 ::static_assertions::assert_impl_all!(
53 $b $(::$b_sub)* :
54 ::serde::Serialize,
55 ::serde::de::DeserializeOwned,
56 );
57
58 unsafe impl $crate::durable::upgrade::json_compatible
62 ::JsonCompatible< $b $(::$b_sub)* >
63 for $a $(::$a_sub)* {}
64 unsafe impl $crate::durable::upgrade::json_compatible
65 ::JsonCompatible< $a $(::$a_sub)* >
66 for $b $(::$b_sub)* {}
67
68 #[cfg(test)]
69 ::static_assertions::assert_impl_all!(
70 $a $(::$a_sub)* :
71 ::proptest::arbitrary::Arbitrary,
72 );
73 #[cfg(test)]
74 ::static_assertions::assert_impl_all!(
75 $b $(::$b_sub)* :
76 ::proptest::arbitrary::Arbitrary,
77 );
78
79 #[cfg(test)]
80 ::paste::paste! {
81 ::proptest::proptest! {
82 #![proptest_config(::proptest::test_runner::Config {
83 cases: 64,
84 ..Default::default()
85 })]
86
87 #[mz_ore::test]
88 #[cfg_attr(miri, ignore)] fn [<proptest_json_compat_
90 $a:snake $(_$a_sub:snake)* _to_
91 $b:snake $(_$b_sub:snake)*
92 >](a: $a $(::$a_sub)* ) {
93 let a_bytes = ::serde_json::to_vec(&a)
94 .expect("JSON serializable");
95 let b_decoded = ::serde_json::from_slice
96 ::<$b $(::$b_sub)*>(&a_bytes);
97 ::proptest::prelude::prop_assert!(
98 b_decoded.is_ok(),
99 );
100
101 let b_decoded = b_decoded.expect("asserted Ok");
104 use $crate::durable::upgrade::json_compatible
105 ::JsonCompatible;
106 let b_converted: $b $(::$b_sub)* =
107 JsonCompatible::convert(&a);
108 assert_eq!(b_decoded, b_converted);
109
110 let b_bytes = ::serde_json::to_vec(&b_decoded)
111 .expect("JSON serializable");
112 ::proptest::prelude::prop_assert_eq!(
113 a_bytes, b_bytes,
114 "a and b serialize differently",
115 );
116 }
117
118 #[mz_ore::test]
119 #[cfg_attr(miri, ignore)] fn [<proptest_json_compat_
121 $b:snake $(_$b_sub:snake)* _to_
122 $a:snake $(_$a_sub:snake)*
123 >](b: $b $(::$b_sub)* ) {
124 let b_bytes = ::serde_json::to_vec(&b)
125 .expect("JSON serializable");
126 let a_decoded = ::serde_json::from_slice
127 ::<$a $(::$a_sub)*>(&b_bytes);
128 ::proptest::prelude::prop_assert!(
129 a_decoded.is_ok(),
130 );
131
132 let a_decoded = a_decoded.expect("asserted Ok");
135 use $crate::durable::upgrade::json_compatible
136 ::JsonCompatible;
137 let a_converted: $a $(::$a_sub)* =
138 JsonCompatible::convert(&b);
139 assert_eq!(a_decoded, a_converted);
140
141 let a_bytes = ::serde_json::to_vec(&a_decoded)
142 .expect("JSON serializable");
143 ::proptest::prelude::prop_assert_eq!(
144 a_bytes, b_bytes,
145 "a and b serialize differently",
146 );
147 }
148 }
149 }
150 };
151}
152pub use json_compatible;