bullet_exchange_interface/
schema.rs1use std::collections::HashMap;
2
3pub use sov_universal_wallet::schema::Schema;
5use sov_universal_wallet::schema::{IndexLinking, Link};
6use sov_universal_wallet::ty::{NamedField, Ty, UnnamedField};
7
8#[derive(serde::Deserialize)]
9pub struct SchemaFile {
10 pub chain_hash: String,
11 pub schema: Schema,
12}
13
14pub fn trim(input: &Schema, filter_variants: &dyn Fn(&str, &str) -> bool) -> Vec<Ty<IndexLinking>> {
16 let types = input.types();
17 let mut res = vec![];
18 let mut map = HashMap::new();
19 trim_internal(0, types, filter_variants, &mut map, &mut res);
20 res
21}
22
23fn trim_internal(
24 index: usize,
25 types: &[Ty<IndexLinking>],
26 filter_variants: &dyn Fn(&str, &str) -> bool,
27 map: &mut HashMap<usize, usize>,
28 res: &mut Vec<Ty<IndexLinking>>,
29) {
30 if map.contains_key(&index) {
31 return;
32 }
33 let ofs = res.len();
34 map.insert(index, ofs);
35 let mut elem = types.get(index).expect("type not found").clone();
36 res.push(elem.clone());
37
38 match elem {
39 Ty::Enum(ref mut value) => {
40 let type_name = value.type_name.as_str();
41 value.variants.retain(|x| filter_variants(type_name, x.name.as_str()));
42 for v in &mut value.variants {
43 if let Some(x) = &mut v.value {
44 replace_link(x, types, filter_variants, map, res);
45 }
46 }
47 }
48 Ty::Tuple(ref mut value) => {
49 for f in &mut value.fields {
50 let UnnamedField::<IndexLinking> { value, silent: _, doc: _ } = f;
51 replace_link(value, types, filter_variants, map, res);
52 }
53 }
54 Ty::Struct(ref mut value) => {
55 for f in &mut value.fields {
56 let NamedField::<IndexLinking> { value, silent: _, doc: _, display_name: _ } = f;
57 replace_link(value, types, filter_variants, map, res);
58 }
59 }
60 Ty::Option { ref mut value }
61 | Ty::Vec { ref mut value }
62 | Ty::Array { ref mut value, len: _ } => {
63 replace_link(value, types, filter_variants, map, res);
64 }
65 Ty::Map { ref mut key, ref mut value } => {
66 replace_link(key, types, filter_variants, map, res);
67 replace_link(value, types, filter_variants, map, res);
68 }
69 Ty::String
70 | Ty::Boolean
71 | Ty::Float32
72 | Ty::Float64
73 | Ty::ByteVec { .. }
74 | Ty::Integer { .. }
75 | Ty::ByteArray { .. }
76 | Ty::Skip { .. } => {}
77 }
78 res[ofs] = elem;
80}
81
82fn replace_link(
83 v: &mut Link,
84 types: &[Ty<IndexLinking>],
85 filter_variants: &dyn Fn(&str, &str) -> bool,
86 map: &mut HashMap<usize, usize>,
87 res: &mut Vec<Ty<IndexLinking>>,
88) {
89 match v {
90 Link::ByIndex(index) => {
91 let old = *index;
92 *index = map.get(&old).copied().unwrap_or(res.len());
93 if *index == res.len() {
94 trim_internal(old, types, filter_variants, map, res);
95 }
96 }
97 Link::Immediate(_) => {}
98 Link::Placeholder | Link::IndexedPlaceholder(_) => {
99 panic!("constructed schemas must not contain placeholders");
100 }
101 }
102}