1#![allow(dead_code)] use crate as borsh; use crate::maybestd::{
16 boxed::Box,
17 collections::{hash_map::Entry, HashMap},
18 format,
19 string::{String, ToString},
20 vec,
21 vec::Vec,
22};
23use crate::{BorshDeserialize, BorshSchema as BorshSchemaMacro, BorshSerialize};
24
25pub type Declaration = String;
27pub type VariantName = String;
29pub type FieldName = String;
31#[derive(PartialEq, Debug, BorshSerialize, BorshDeserialize, BorshSchemaMacro)]
33pub enum Definition {
34 Array { length: u32, elements: Declaration },
36 Sequence { elements: Declaration },
38 Tuple { elements: Vec<Declaration> },
41 Enum {
43 variants: Vec<(VariantName, Declaration)>,
44 },
45 Struct { fields: Fields },
47}
48
49#[derive(PartialEq, Debug, BorshSerialize, BorshDeserialize, BorshSchemaMacro)]
51pub enum Fields {
52 NamedFields(Vec<(FieldName, Declaration)>),
54 UnnamedFields(Vec<Declaration>),
56 Empty,
58}
59
60#[derive(PartialEq, Debug, BorshSerialize, BorshDeserialize, BorshSchemaMacro)]
62pub struct BorshSchemaContainer {
63 pub declaration: Declaration,
65 pub definitions: HashMap<Declaration, Definition>,
67}
68
69pub trait BorshSchema {
72 fn add_definitions_recursively(definitions: &mut HashMap<Declaration, Definition>);
75
76 fn add_definition(
78 declaration: Declaration,
79 definition: Definition,
80 definitions: &mut HashMap<Declaration, Definition>,
81 ) {
82 match definitions.entry(declaration) {
83 Entry::Occupied(occ) => {
84 let existing_def = occ.get();
85 assert_eq!(existing_def, &definition, "Redefining type schema for the same type name. Types with the same names are not supported.");
86 }
87 Entry::Vacant(vac) => {
88 vac.insert(definition);
89 }
90 }
91 }
92 fn declaration() -> Declaration;
94
95 fn schema_container() -> BorshSchemaContainer {
96 let mut definitions = HashMap::new();
97 Self::add_definitions_recursively(&mut definitions);
98 BorshSchemaContainer {
99 declaration: Self::declaration(),
100 definitions,
101 }
102 }
103}
104
105impl<T> BorshSchema for Box<T>
106where
107 T: BorshSchema,
108{
109 fn add_definitions_recursively(definitions: &mut HashMap<Declaration, Definition>) {
110 T::add_definitions_recursively(definitions);
111 }
112
113 fn declaration() -> Declaration {
114 T::declaration()
115 }
116}
117
118impl BorshSchema for () {
119 fn add_definitions_recursively(_definitions: &mut HashMap<Declaration, Definition>) {}
120
121 fn declaration() -> Declaration {
122 "nil".to_string()
123 }
124}
125
126macro_rules! impl_for_renamed_primitives {
127 ($($type: ident : $name: ident)+) => {
128 $(
129 impl BorshSchema for $type {
130 fn add_definitions_recursively(_definitions: &mut HashMap<Declaration, Definition>) {}
131 fn declaration() -> Declaration {
132 stringify!($name).to_string()
133 }
134 }
135 )+
136 };
137}
138
139macro_rules! impl_for_primitives {
140 ($($type: ident)+) => {
141 impl_for_renamed_primitives!{$($type : $type)+}
142 };
143}
144
145impl_for_primitives!(bool char f32 f64 i8 i16 i32 i64 i128 u8 u16 u32 u64 u128);
146impl_for_renamed_primitives!(String: string);
147
148macro_rules! impl_arrays {
149 ($($len:expr)+) => {
150 $(
151 impl<T> BorshSchema for [T; $len]
152 where
153 T: BorshSchema,
154 {
155 fn add_definitions_recursively(definitions: &mut HashMap<Declaration, Definition>) {
156 let definition = Definition::Array { length: $len, elements: T::declaration() };
157 Self::add_definition(Self::declaration(), definition, definitions);
158 T::add_definitions_recursively(definitions);
159 }
160 fn declaration() -> Declaration {
161 format!(r#"Array<{}, {}>"#, T::declaration(), $len)
162 }
163 }
164 )+
165 };
166}
167
168impl_arrays!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 32 64 65);
169
170impl<T> BorshSchema for Option<T>
171where
172 T: BorshSchema,
173{
174 fn add_definitions_recursively(definitions: &mut HashMap<Declaration, Definition>) {
175 let definition = Definition::Enum {
176 variants: vec![
177 ("None".to_string(), <()>::declaration()),
178 ("Some".to_string(), T::declaration()),
179 ],
180 };
181 Self::add_definition(Self::declaration(), definition, definitions);
182 T::add_definitions_recursively(definitions);
183 }
184
185 fn declaration() -> Declaration {
186 format!(r#"Option<{}>"#, T::declaration())
187 }
188}
189
190impl<T, E> BorshSchema for core::result::Result<T, E>
191where
192 T: BorshSchema,
193 E: BorshSchema,
194{
195 fn add_definitions_recursively(definitions: &mut HashMap<Declaration, Definition>) {
196 let definition = Definition::Enum {
197 variants: vec![
198 ("Ok".to_string(), T::declaration()),
199 ("Err".to_string(), E::declaration()),
200 ],
201 };
202 Self::add_definition(Self::declaration(), definition, definitions);
203 T::add_definitions_recursively(definitions);
204 }
205
206 fn declaration() -> Declaration {
207 format!(r#"Result<{}, {}>"#, T::declaration(), E::declaration())
208 }
209}
210
211impl<T> BorshSchema for Vec<T>
212where
213 T: BorshSchema,
214{
215 fn add_definitions_recursively(definitions: &mut HashMap<Declaration, Definition>) {
216 let definition = Definition::Sequence {
217 elements: T::declaration(),
218 };
219 Self::add_definition(Self::declaration(), definition, definitions);
220 T::add_definitions_recursively(definitions);
221 }
222
223 fn declaration() -> Declaration {
224 format!(r#"Vec<{}>"#, T::declaration())
225 }
226}
227
228impl<K, V> BorshSchema for HashMap<K, V>
229where
230 K: BorshSchema,
231 V: BorshSchema,
232{
233 fn add_definitions_recursively(definitions: &mut HashMap<Declaration, Definition>) {
234 let definition = Definition::Sequence {
235 elements: <(K, V)>::declaration(),
236 };
237 Self::add_definition(Self::declaration(), definition, definitions);
238 <(K, V)>::add_definitions_recursively(definitions);
239 }
240
241 fn declaration() -> Declaration {
242 format!(r#"HashMap<{}, {}>"#, K::declaration(), V::declaration())
243 }
244}
245
246macro_rules! impl_tuple {
247 ($($name:ident),+) => {
248 impl<$($name),+> BorshSchema for ($($name),+)
249 where
250 $($name: BorshSchema),+
251 {
252 fn add_definitions_recursively(definitions: &mut HashMap<Declaration, Definition>) {
253 let mut elements = vec![];
254 $(
255 elements.push($name::declaration());
256 )+
257
258 let definition = Definition::Tuple { elements };
259 Self::add_definition(Self::declaration(), definition, definitions);
260 $(
261 $name::add_definitions_recursively(definitions);
262 )+
263 }
264
265 fn declaration() -> Declaration {
266 let params = vec![$($name::declaration()),+];
267 format!(r#"Tuple<{}>"#, params.join(", "))
268 }
269 }
270 };
271}
272
273impl_tuple!(T0, T1);
274impl_tuple!(T0, T1, T2);
275impl_tuple!(T0, T1, T2, T3);
276impl_tuple!(T0, T1, T2, T3, T4);
277impl_tuple!(T0, T1, T2, T3, T4, T5);
278impl_tuple!(T0, T1, T2, T3, T4, T5, T6);
279impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7);
280impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8);
281impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
282impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
283impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
284impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
285impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
286impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
287impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
288impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);
289impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17);
290impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18);
291impl_tuple!(
292 T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19
293);
294impl_tuple!(
295 T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20
296);
297
298#[cfg(test)]
299mod tests {
300 use super::*;
301 use crate::maybestd::collections::HashMap;
302
303 macro_rules! map(
304 () => { HashMap::new() };
305 { $($key:expr => $value:expr),+ } => {
306 {
307 let mut m = HashMap::new();
308 $(
309 m.insert($key.to_string(), $value);
310 )+
311 m
312 }
313 };
314 );
315
316 #[test]
317 fn simple_option() {
318 let actual_name = Option::<u64>::declaration();
319 let mut actual_defs = map!();
320 Option::<u64>::add_definitions_recursively(&mut actual_defs);
321 assert_eq!("Option<u64>", actual_name);
322 assert_eq!(
323 map! {"Option<u64>" =>
324 Definition::Enum{ variants: vec![
325 ("None".to_string(), "nil".to_string()),
326 ("Some".to_string(), "u64".to_string()),
327 ]}
328 },
329 actual_defs
330 );
331 }
332
333 #[test]
334 fn nested_option() {
335 let actual_name = Option::<Option<u64>>::declaration();
336 let mut actual_defs = map!();
337 Option::<Option<u64>>::add_definitions_recursively(&mut actual_defs);
338 assert_eq!("Option<Option<u64>>", actual_name);
339 assert_eq!(
340 map! {
341 "Option<u64>" =>
342 Definition::Enum {variants: vec![
343 ("None".to_string(), "nil".to_string()),
344 ("Some".to_string(), "u64".to_string()),
345 ]},
346 "Option<Option<u64>>" =>
347 Definition::Enum {variants: vec![
348 ("None".to_string(), "nil".to_string()),
349 ("Some".to_string(), "Option<u64>".to_string()),
350 ]}
351 },
352 actual_defs
353 );
354 }
355
356 #[test]
357 fn simple_vec() {
358 let actual_name = Vec::<u64>::declaration();
359 let mut actual_defs = map!();
360 Vec::<u64>::add_definitions_recursively(&mut actual_defs);
361 assert_eq!("Vec<u64>", actual_name);
362 assert_eq!(
363 map! {
364 "Vec<u64>" => Definition::Sequence { elements: "u64".to_string() }
365 },
366 actual_defs
367 );
368 }
369
370 #[test]
371 fn nested_vec() {
372 let actual_name = Vec::<Vec<u64>>::declaration();
373 let mut actual_defs = map!();
374 Vec::<Vec<u64>>::add_definitions_recursively(&mut actual_defs);
375 assert_eq!("Vec<Vec<u64>>", actual_name);
376 assert_eq!(
377 map! {
378 "Vec<u64>" => Definition::Sequence { elements: "u64".to_string() },
379 "Vec<Vec<u64>>" => Definition::Sequence { elements: "Vec<u64>".to_string() }
380 },
381 actual_defs
382 );
383 }
384
385 #[test]
386 fn simple_tuple() {
387 let actual_name = <(u64, String)>::declaration();
388 let mut actual_defs = map!();
389 <(u64, String)>::add_definitions_recursively(&mut actual_defs);
390 assert_eq!("Tuple<u64, string>", actual_name);
391 assert_eq!(
392 map! {
393 "Tuple<u64, string>" => Definition::Tuple { elements: vec![ "u64".to_string(), "string".to_string()]}
394 },
395 actual_defs
396 );
397 }
398
399 #[test]
400 fn nested_tuple() {
401 let actual_name = <(u64, (u8, bool), String)>::declaration();
402 let mut actual_defs = map!();
403 <(u64, (u8, bool), String)>::add_definitions_recursively(&mut actual_defs);
404 assert_eq!("Tuple<u64, Tuple<u8, bool>, string>", actual_name);
405 assert_eq!(
406 map! {
407 "Tuple<u64, Tuple<u8, bool>, string>" => Definition::Tuple { elements: vec![
408 "u64".to_string(),
409 "Tuple<u8, bool>".to_string(),
410 "string".to_string(),
411 ]},
412 "Tuple<u8, bool>" => Definition::Tuple { elements: vec![ "u8".to_string(), "bool".to_string()]}
413 },
414 actual_defs
415 );
416 }
417
418 #[test]
419 fn simple_map() {
420 let actual_name = HashMap::<u64, String>::declaration();
421 let mut actual_defs = map!();
422 HashMap::<u64, String>::add_definitions_recursively(&mut actual_defs);
423 assert_eq!("HashMap<u64, string>", actual_name);
424 assert_eq!(
425 map! {
426 "HashMap<u64, string>" => Definition::Sequence { elements: "Tuple<u64, string>".to_string()} ,
427 "Tuple<u64, string>" => Definition::Tuple { elements: vec![ "u64".to_string(), "string".to_string()]}
428 },
429 actual_defs
430 );
431 }
432
433 #[test]
434 fn simple_array() {
435 let actual_name = <[u64; 32]>::declaration();
436 let mut actual_defs = map!();
437 <[u64; 32]>::add_definitions_recursively(&mut actual_defs);
438 assert_eq!("Array<u64, 32>", actual_name);
439 assert_eq!(
440 map! {"Array<u64, 32>" => Definition::Array { length: 32, elements: "u64".to_string()}},
441 actual_defs
442 );
443 }
444
445 #[test]
446 fn nested_array() {
447 let actual_name = <[[[u64; 9]; 10]; 32]>::declaration();
448 let mut actual_defs = map!();
449 <[[[u64; 9]; 10]; 32]>::add_definitions_recursively(&mut actual_defs);
450 assert_eq!("Array<Array<Array<u64, 9>, 10>, 32>", actual_name);
451 assert_eq!(
452 map! {
453 "Array<u64, 9>" =>
454 Definition::Array { length: 9, elements: "u64".to_string() },
455 "Array<Array<u64, 9>, 10>" =>
456 Definition::Array { length: 10, elements: "Array<u64, 9>".to_string() },
457 "Array<Array<Array<u64, 9>, 10>, 32>" =>
458 Definition::Array { length: 32, elements: "Array<Array<u64, 9>, 10>".to_string() }
459 },
460 actual_defs
461 );
462 }
463}