sbor/schema/schema_comparison/
comparable_schema.rs1use super::*;
2
3pub struct NamedSchemaVersions<S: CustomSchema, C: ComparableSchema<S>> {
6 ordered_versions: IndexMap<String, C>,
7 custom_schema: PhantomData<S>,
8}
9
10impl<S: CustomSchema, C: ComparableSchema<S>> Default for NamedSchemaVersions<S, C> {
11 fn default() -> Self {
12 Self::new()
13 }
14}
15
16impl<S: CustomSchema, C: ComparableSchema<S>> NamedSchemaVersions<S, C> {
17 pub fn new() -> Self {
18 Self {
19 ordered_versions: Default::default(),
20 custom_schema: Default::default(),
21 }
22 }
23
24 pub fn from<F: IntoIterator<Item = (K, V)>, K: AsRef<str>, V: IntoComparableSchema<C, S>>(
25 from: F,
26 ) -> Self {
27 Self {
28 ordered_versions: from
29 .into_iter()
30 .map(|(name, version)| (name.as_ref().to_string(), version.into_schema()))
31 .collect(),
32 custom_schema: Default::default(),
33 }
34 }
35
36 pub fn register_version(
37 mut self,
38 name: impl AsRef<str>,
39 version: impl IntoComparableSchema<C, S>,
40 ) -> Self {
41 self.ordered_versions
42 .insert(name.as_ref().to_string(), version.into_schema());
43 self
44 }
45
46 pub fn get_versions(&self) -> &IndexMap<String, C> {
47 &self.ordered_versions
48 }
49}
50
51pub trait ComparableSchema<S: CustomSchema>: Clone + VecSbor<S::DefaultCustomExtension> {
55 fn encode_to_bytes(&self) -> Vec<u8> {
56 vec_encode::<S::DefaultCustomExtension, Self>(self, BASIC_SBOR_V1_MAX_DEPTH).unwrap()
57 }
58
59 fn encode_to_hex(&self) -> String {
60 hex::encode(self.encode_to_bytes())
61 }
62
63 fn decode_from_bytes(bytes: &[u8]) -> Self {
64 vec_decode_with_nice_error::<S::DefaultCustomExtension, Self>(
65 bytes,
66 BASIC_SBOR_V1_MAX_DEPTH,
67 )
68 .unwrap_or_else(|err| {
69 panic!(
70 "Could not SBOR decode bytes into {} with {}: {:?}",
71 core::any::type_name::<Self>(),
72 core::any::type_name::<S::DefaultCustomExtension>(),
73 err,
74 )
75 })
76 }
77
78 fn decode_from_hex(hex: &str) -> Self {
79 let bytes = hex::decode(hex)
80 .unwrap_or_else(|err| panic!("Provided string was not valid hex: {err}"));
81 Self::decode_from_bytes(&bytes)
82 }
83
84 fn compare_with<'s>(
85 &'s self,
86 compared: &'s Self,
87 settings: &SchemaComparisonSettings,
88 ) -> SchemaComparisonResult<'s, S>;
89}
90
91impl<S: CustomSchema> ComparableSchema<S> for SingleTypeSchema<S> {
92 fn compare_with<'s>(
93 &'s self,
94 compared: &'s Self,
95 settings: &SchemaComparisonSettings,
96 ) -> SchemaComparisonResult<'s, S> {
97 SchemaComparisonKernel::new(
98 self.schema.as_unique_version(),
99 compared.schema.as_unique_version(),
100 settings,
101 )
102 .compare_using_fixed_type_roots(&[ComparisonTypeRoot {
103 name: "root".to_string(),
104 base_type_id: self.type_id,
105 compared_type_id: compared.type_id,
106 }])
107 }
108}
109
110impl<S: CustomSchema> ComparableSchema<S> for TypeCollectionSchema<S> {
111 fn compare_with<'s>(
112 &'s self,
113 compared: &'s Self,
114 settings: &SchemaComparisonSettings,
115 ) -> SchemaComparisonResult<'s, S> {
116 SchemaComparisonKernel::new(
117 self.schema.as_unique_version(),
118 compared.schema.as_unique_version(),
119 settings,
120 )
121 .compare_using_named_type_roots(&self.type_ids, &compared.type_ids)
122 }
123}
124
125pub trait IntoComparableSchema<C: ComparableSchema<S>, S: CustomSchema> {
126 #[allow(clippy::wrong_self_convention)]
127 fn into_schema(&self) -> C;
128}
129
130impl<S: CustomSchema> IntoComparableSchema<Self, S> for SingleTypeSchema<S> {
131 fn into_schema(&self) -> Self {
132 self.clone()
133 }
134}
135
136impl<S: CustomSchema> IntoComparableSchema<Self, S> for TypeCollectionSchema<S> {
137 fn into_schema(&self) -> Self {
138 self.clone()
139 }
140}
141
142impl<C: ComparableSchema<S>, S: CustomSchema, T: IntoComparableSchema<C, S> + ?Sized>
143 IntoComparableSchema<C, S> for &T
144{
145 fn into_schema(&self) -> C {
146 <T as IntoComparableSchema<C, S>>::into_schema(*self)
147 }
148}
149
150impl<C: ComparableSchema<S>, S: CustomSchema> IntoComparableSchema<C, S> for [u8] {
151 fn into_schema(&self) -> C {
152 C::decode_from_bytes(self)
153 }
154}
155
156impl<C: ComparableSchema<S>, S: CustomSchema, const N: usize> IntoComparableSchema<C, S>
157 for [u8; N]
158{
159 fn into_schema(&self) -> C {
160 C::decode_from_bytes(self.as_slice())
161 }
162}
163
164impl<C: ComparableSchema<S>, S: CustomSchema> IntoComparableSchema<C, S> for Vec<u8> {
165 fn into_schema(&self) -> C {
166 C::decode_from_bytes(self)
167 }
168}
169
170impl<C: ComparableSchema<S>, S: CustomSchema> IntoComparableSchema<C, S> for String {
171 fn into_schema(&self) -> C {
172 C::decode_from_hex(self)
173 }
174}
175
176impl<C: ComparableSchema<S>, S: CustomSchema> IntoComparableSchema<C, S> for str {
177 fn into_schema(&self) -> C {
178 C::decode_from_hex(self)
179 }
180}