Skip to main content

ave_common/
schematype.rs

1use std::fmt::Display;
2
3use borsh::{BorshDeserialize, BorshSerialize};
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5
6#[derive(
7    Default,
8    Debug,
9    Clone,
10    Hash,
11    PartialEq,
12    Eq,
13    Ord,
14    PartialOrd,
15    BorshSerialize,
16    BorshDeserialize,
17)]
18pub enum SchemaType {
19    #[default]
20    Governance,
21    Type(String),
22    AllSchemas,
23}
24
25pub enum ReservedWords {
26    AllSchemas,
27    Governance,
28    Any,
29    Witnesses,
30    Owner,
31}
32
33impl Display for ReservedWords {
34    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35        match self {
36            ReservedWords::AllSchemas => write!(f, "all_schemas"),
37            ReservedWords::Governance => write!(f, "governance"),
38            ReservedWords::Any => write!(f, "Any"),
39            ReservedWords::Witnesses => write!(f, "Witnesses"),
40            ReservedWords::Owner => write!(f, "Owner"),
41        }
42    }
43}
44
45impl std::str::FromStr for SchemaType {
46    type Err = String;
47
48    fn from_str(s: &str) -> Result<Self, Self::Err> {
49        // Special case: empty string deserializes to default (empty) digest
50        if s.is_empty() {
51            return Err("Schema_id can not be empty".to_string());
52        }
53
54        match s {
55            "governance" => Ok(SchemaType::Governance),
56            "all_schemas" => Ok(SchemaType::AllSchemas),
57            _ => Ok(SchemaType::Type(s.to_string())),
58        }
59    }
60}
61
62impl SchemaType {
63    pub fn len(&self) -> usize {
64        match self {
65            SchemaType::Governance => "governance".len(),
66            SchemaType::Type(schema_id) => schema_id.len(),
67            SchemaType::AllSchemas => "all_schemas".len(),
68        }
69    }
70
71    pub fn is_empty(&self) -> bool {
72        match self {
73            SchemaType::Governance => false,
74            SchemaType::Type(schschema_id) => schschema_id.is_empty(),
75            SchemaType::AllSchemas => false,
76        }
77    }
78
79    pub fn is_valid(&self) -> bool {
80        match self {
81            SchemaType::Governance => true,
82            SchemaType::AllSchemas => true,
83            SchemaType::Type(schema_id) => {
84                !schema_id.is_empty()
85                    && schema_id != &ReservedWords::Governance.to_string()
86                    && schema_id != &ReservedWords::AllSchemas.to_string()
87                    && schema_id.trim().len() == schema_id.len()
88            }
89        }
90    }
91}
92
93impl Display for SchemaType {
94    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95        match self {
96            SchemaType::AllSchemas => write!(f, "all_schemas"),
97            SchemaType::Governance => write!(f, "governance"),
98            SchemaType::Type(schema_id) => write!(f, "{}", schema_id),
99        }
100    }
101}
102
103impl SchemaType {
104    pub fn is_gov(&self) -> bool {
105        matches!(self, SchemaType::Governance)
106    }
107}
108
109impl<'de> Deserialize<'de> for SchemaType {
110    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
111    where
112        D: Deserializer<'de>,
113    {
114        let s = <String as serde::Deserialize>::deserialize(deserializer)?;
115        if s.is_empty() {
116            return Err(serde::de::Error::custom(
117                "Schema can not be empty".to_string(),
118            ));
119        }
120
121        Ok(match s.as_str() {
122            "governance" => SchemaType::Governance,
123            "all_schemas" => SchemaType::AllSchemas,
124            _ => SchemaType::Type(s),
125        })
126    }
127}
128
129impl Serialize for SchemaType {
130    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
131    where
132        S: Serializer,
133    {
134        match self {
135            SchemaType::AllSchemas => serializer.serialize_str("all_schemas"),
136            SchemaType::Governance => serializer.serialize_str("governance"),
137            SchemaType::Type(schema) => serializer.serialize_str(schema),
138        }
139    }
140}