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