Skip to main content

ave_common/
schematype.rs

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