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