1use serde::*;
2use std::collections::BTreeMap;
3use std::hash::{Hash, Hasher};
4
5#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
17#[serde(transparent)]
18pub struct MetaMap(pub BTreeMap<String, serde_json::Value>);
19
20impl MetaMap {
21 pub fn is_empty(&self) -> bool {
22 self.0.is_empty()
23 }
24
25 pub fn get(&self, key: &str) -> Option<&serde_json::Value> {
26 self.0.get(key)
27 }
28
29 pub fn insert(&mut self, key: impl Into<String>, value: serde_json::Value) {
30 self.0.insert(key.into(), value);
31 }
32}
33
34impl Hash for MetaMap {
37 fn hash<H: Hasher>(&self, state: &mut H) {
38 for (key, value) in &self.0 {
39 key.hash(state);
40 value.to_string().hash(state);
41 }
42 }
43}
44
45impl Ord for MetaMap {
46 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
47 self.0
48 .iter()
49 .map(|(k, v)| (k, v.to_string()))
50 .cmp(other.0.iter().map(|(k, v)| (k, v.to_string())))
51 }
52}
53
54impl PartialOrd for MetaMap {
55 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
56 Some(self.cmp(other))
57 }
58}
59
60#[derive(Clone, Debug, Hash, Serialize, Deserialize, Ord, PartialOrd, Eq, PartialEq)]
62#[non_exhaustive]
63pub struct Field {
64 pub name: String,
66
67 #[serde(skip)]
69 pub description: String,
70
71 pub ty: Type,
73
74 #[serde(default, skip_serializing_if = "MetaMap::is_empty")]
76 pub meta: MetaMap,
77}
78
79impl Field {
80 pub fn new(name: impl Into<String>, ty: Type) -> Self {
83 Self {
84 name: name.into(),
85 description: "".into(),
86 ty,
87 meta: MetaMap::default(),
88 }
89 }
90
91 pub fn new_with_description(
93 name: impl Into<String>,
94 description: impl Into<String>,
95 ty: Type,
96 ) -> Self {
97 Self {
98 name: name.into(),
99 description: description.into(),
100 ty,
101 meta: MetaMap::default(),
102 }
103 }
104
105 #[must_use]
107 pub fn with_meta(mut self, meta: MetaMap) -> Self {
108 self.meta = meta;
109 self
110 }
111}
112
113#[derive(Clone, Debug, Hash, Serialize, Deserialize, Ord, PartialOrd, Eq, PartialEq)]
115#[non_exhaustive]
116pub struct EnumVariant {
117 pub name: String,
119
120 pub description: String,
122
123 pub value: i64,
125}
126
127impl EnumVariant {
128 pub fn new(name: impl Into<String>, value: i64) -> Self {
131 Self {
132 name: name.into(),
133 description: "".into(),
134 value,
135 }
136 }
137
138 pub fn new_with_description(
140 name: impl Into<String>,
141 description: impl Into<String>,
142 value: i64,
143 ) -> Self {
144 Self {
145 name: name.into(),
146 description: description.into(),
147 value,
148 }
149 }
150}
151
152#[derive(Clone, Debug, Serialize, Deserialize, Hash, PartialEq, PartialOrd, Eq, Ord)]
154#[non_exhaustive]
155pub enum Type {
156 UInt32,
157 Int32,
158 Int64,
159 Float64,
160 Boolean,
161 String,
162 Bytea,
163 UUID,
164 NanoId {
165 len: usize,
166 },
167 IpAddr,
168 Struct {
169 name: String,
170 fields: Vec<Field>,
171 },
172 StructRef(String),
173 Object,
174 StructTable {
179 struct_ref: String,
180 },
181 Vec(Box<Type>),
182 Unit,
183 Optional(Box<Type>),
184 Enum {
185 name: String,
186 variants: Vec<EnumVariant>,
187 },
188 EnumRef {
189 name: String,
190 #[serde(default, skip_serializing)]
191 prefixed_name: bool,
192 },
193 TimeStampMs,
194 BlockchainDecimal,
195 BlockchainAddress,
196 BlockchainTransactionHash,
197}
198
199impl Type {
200 pub fn struct_(name: impl Into<String>, fields: Vec<Field>) -> Self {
202 Self::Struct {
203 name: name.into(),
204 fields,
205 }
206 }
207
208 pub fn struct_ref(name: impl Into<String>) -> Self {
210 Self::StructRef(name.into())
211 }
212
213 pub fn struct_table(struct_ref: impl Into<String>) -> Self {
223 Self::StructTable {
224 struct_ref: struct_ref.into(),
225 }
226 }
227
228 pub fn vec(ty: Type) -> Self {
230 Self::Vec(Box::new(ty))
231 }
232
233 pub fn optional(ty: Type) -> Self {
235 Self::Optional(Box::new(ty))
236 }
237
238 pub fn enum_ref(name: impl Into<String>, prefixed_name: bool) -> Self {
240 Self::EnumRef {
241 name: name.into(),
242 prefixed_name,
243 }
244 }
245
246 pub fn enum_(name: impl Into<String>, fields: Vec<EnumVariant>) -> Self {
248 Self::Enum {
249 name: name.into(),
250 variants: fields,
251 }
252 }
253 pub fn try_unwrap(self) -> Option<Self> {
254 match self {
255 Self::Vec(v) => Some(*v),
256 Self::StructTable { .. } => None,
258 _ => Some(self),
259 }
260 }
261
262 pub fn add_default_enum_derives(input: String) -> String {
263 format!(
264 r#"#[derive(Debug, Clone, Copy, Serialize, Deserialize, FromPrimitive, PartialEq, Eq, PartialOrd, Ord, EnumString, Display, Hash)]{input}"#
265 )
266 }
267
268 pub fn add_default_struct_derives(input: String) -> String {
269 format!(
270 r#" #[derive(Serialize, Deserialize, Debug, Clone)]
271 #[serde(rename_all = "camelCase")]
272 {input}
273 "#
274 )
275 }
276}