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 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}