sbor/schema/type_data/
type_metadata.rs

1use borrow::Borrow;
2
3use crate::rust::prelude::*;
4use crate::*;
5
6/// This is the struct used in the Schema
7#[derive(Debug, Clone, PartialEq, Eq, Sbor)]
8pub struct NovelTypeMetadata {
9    pub type_hash: TypeHash,
10    pub type_metadata: TypeMetadata,
11}
12
13/// This enables the type to be represented as eg JSON
14/// Also used to facilitate type reconstruction
15#[derive(Debug, Clone, PartialEq, Eq, Sbor)]
16pub struct TypeMetadata {
17    pub type_name: Option<Cow<'static, str>>,
18    pub child_names: Option<ChildNames>,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq, Sbor)]
22pub enum ChildNames {
23    NamedFields(Vec<Cow<'static, str>>),
24    EnumVariants(IndexMap<u8, TypeMetadata>),
25}
26
27impl TypeMetadata {
28    pub fn unnamed() -> Self {
29        Self {
30            type_name: None,
31            child_names: None,
32        }
33    }
34
35    pub fn no_child_names(name: &'static str) -> Self {
36        Self {
37            type_name: Some(Cow::Borrowed(name)),
38            child_names: None,
39        }
40    }
41
42    pub fn struct_fields(name: &'static str, field_names: &[&'static str]) -> Self {
43        let field_names = field_names
44            .iter()
45            .map(|field_name| Cow::Borrowed(*field_name))
46            .collect();
47        Self {
48            type_name: Some(Cow::Borrowed(name)),
49            child_names: Some(ChildNames::NamedFields(field_names)),
50        }
51    }
52
53    pub fn enum_variants(name: &'static str, variant_naming: IndexMap<u8, TypeMetadata>) -> Self {
54        Self {
55            type_name: Some(Cow::Borrowed(name)),
56            child_names: Some(ChildNames::EnumVariants(variant_naming)),
57        }
58    }
59
60    pub fn with_name(mut self, name: Option<Cow<'static, str>>) -> Self {
61        self.type_name = name;
62        self
63    }
64
65    pub fn with_type_hash(self, type_hash: TypeHash) -> NovelTypeMetadata {
66        NovelTypeMetadata {
67            type_hash,
68            type_metadata: self,
69        }
70    }
71
72    pub fn get_name(&self) -> Option<&str> {
73        self.type_name.as_ref().map(|c| c.as_ref())
74    }
75
76    pub fn get_name_string(&self) -> Option<String> {
77        self.type_name.as_ref().map(|c| c.to_string())
78    }
79
80    pub fn get_field_names<'a>(&'a self) -> Option<&'a [Cow<'static, str>]> {
81        match &self.child_names {
82            Some(ChildNames::NamedFields(field_names)) => Some(field_names.as_slice()),
83            _ => None,
84        }
85    }
86
87    pub fn get_field_name<'a>(&'a self, field_index: usize) -> Option<&'a str> {
88        match &self.child_names {
89            Some(ChildNames::NamedFields(field_names)) => {
90                Some(field_names.get(field_index)?.borrow())
91            }
92            _ => None,
93        }
94    }
95
96    pub fn get_enum_variant_data<'a>(&'a self, discriminator: u8) -> Option<&'a TypeMetadata> {
97        match &self.child_names {
98            Some(ChildNames::EnumVariants(variants)) => variants.get(&discriminator),
99            _ => None,
100        }
101    }
102
103    pub fn get_matching_tuple_data(&self, fields_length: usize) -> TupleData {
104        TupleData {
105            name: self.get_name(),
106            field_names: self
107                .get_field_names()
108                .filter(|field_names| field_names.len() == fields_length),
109        }
110    }
111
112    pub fn get_matching_enum_variant_data(
113        &self,
114        variant_id: u8,
115        fields_length: usize,
116    ) -> EnumVariantData {
117        let enum_name = self.get_name();
118        let Some(ChildNames::EnumVariants(variants)) = &self.child_names else {
119            return EnumVariantData {
120                enum_name,
121                variant_name: None,
122                field_names: None,
123            };
124        };
125        let Some(variant_metadata) = variants.get(&variant_id) else {
126            return EnumVariantData {
127                enum_name,
128                variant_name: None,
129                field_names: None,
130            };
131        };
132        EnumVariantData {
133            enum_name,
134            variant_name: variant_metadata.get_name(),
135            field_names: variant_metadata
136                .get_field_names()
137                .filter(|field_names| field_names.len() == fields_length),
138        }
139    }
140}
141
142#[derive(Debug, Default)]
143pub struct TupleData<'s> {
144    pub name: Option<&'s str>,
145    pub field_names: Option<&'s [Cow<'static, str>]>,
146}
147
148#[derive(Debug, Default)]
149pub struct EnumVariantData<'s> {
150    pub enum_name: Option<&'s str>,
151    pub variant_name: Option<&'s str>,
152    pub field_names: Option<&'s [Cow<'static, str>]>,
153}