1use serde::{Deserialize, Serialize};
2use std::{
3 collections::{HashMap, HashSet},
4 hash::{Hash, Hasher},
5};
6
7fn is_false(value: &bool) -> bool {
8 !value
9}
10
11#[derive(Debug, Serialize, Deserialize)]
12pub struct IgniteTypeDefinition {
13 #[serde(default, skip_serializing_if = "String::is_empty")]
14 pub namespace: String,
15 #[serde(default, skip_serializing_if = "Vec::is_empty")]
16 pub generic_args: Vec<String>,
17 pub variant: IgniteTypeVariant,
18 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
19 pub meta: HashMap<String, IgniteAttribMeta>,
20 #[serde(default, skip_serializing_if = "is_false")]
21 pub is_proxy: bool,
22}
23
24impl IgniteTypeDefinition {
25 pub fn name(&self) -> String {
26 self.variant.name()
27 }
28
29 pub fn referenced(&self) -> HashSet<String> {
30 self.variant.referenced()
31 }
32}
33
34impl Hash for IgniteTypeDefinition {
35 fn hash<H>(&self, state: &mut H)
36 where
37 H: Hasher,
38 {
39 self.namespace.hash(state);
40 self.generic_args.hash(state);
41 self.variant.hash(state);
42 }
43}
44
45#[derive(Debug, Serialize, Deserialize, Hash)]
46pub enum IgniteTypeVariant {
47 StructUnit(String),
48 StructNamed(IgniteNamed),
49 StructUnnamed(IgniteUnnamed),
50 Enum(IgniteEnum),
51}
52
53impl IgniteTypeVariant {
54 pub fn name(&self) -> String {
55 match self {
56 Self::StructUnit(name) => name.clone(),
57 Self::StructNamed(value) => value.name.clone(),
58 Self::StructUnnamed(value) => value.name.clone(),
59 Self::Enum(value) => value.name.clone(),
60 }
61 }
62
63 pub fn referenced(&self) -> HashSet<String> {
64 match self {
65 Self::StructUnit(_) => HashSet::new(),
66 Self::StructNamed(value) => value.referenced(),
67 Self::StructUnnamed(value) => value.referenced(),
68 Self::Enum(value) => value.referenced(),
69 }
70 }
71}
72
73#[derive(Debug, Serialize, Deserialize, Hash)]
74pub struct IgniteNamed {
75 pub name: String,
76 #[serde(default, skip_serializing_if = "Vec::is_empty")]
77 pub fields: Vec<IgniteNamedField>,
78}
79
80impl IgniteNamed {
81 pub fn referenced(&self) -> HashSet<String> {
82 self.fields
83 .iter()
84 .flat_map(|field| field.referenced())
85 .collect()
86 }
87}
88
89#[derive(Debug, Serialize, Deserialize, Hash)]
90pub struct IgniteUnnamed {
91 pub name: String,
92 #[serde(default, skip_serializing_if = "Vec::is_empty")]
93 pub fields: Vec<IgniteUnnamedField>,
94}
95
96impl IgniteUnnamed {
97 pub fn referenced(&self) -> HashSet<String> {
98 self.fields
99 .iter()
100 .flat_map(|field| field.referenced())
101 .collect()
102 }
103}
104
105#[derive(Debug, Serialize, Deserialize)]
106pub struct IgniteNamedField {
107 pub name: String,
108 pub typename: IgniteType,
109 #[serde(default, skip_serializing_if = "Option::is_none")]
110 pub mapping: Option<String>,
111 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
112 pub meta: HashMap<String, IgniteAttribMeta>,
113}
114
115impl IgniteNamedField {
116 pub fn referenced(&self) -> HashSet<String> {
117 if let Some(mapping) = &self.mapping {
118 let mut result = HashSet::new();
119 if let Some(mapping) = mapping.split('.').last() {
120 result.insert(mapping.to_owned());
121 }
122 result
123 } else {
124 self.typename.referenced()
125 }
126 }
127}
128
129impl Hash for IgniteNamedField {
130 fn hash<H>(&self, state: &mut H)
131 where
132 H: Hasher,
133 {
134 self.name.hash(state);
135 self.typename.hash(state);
136 }
137}
138
139#[derive(Debug, Serialize, Deserialize)]
140pub struct IgniteUnnamedField {
141 pub typename: IgniteType,
142 #[serde(default, skip_serializing_if = "Option::is_none")]
143 pub mapping: Option<String>,
144 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
145 pub meta: HashMap<String, IgniteAttribMeta>,
146}
147
148impl IgniteUnnamedField {
149 pub fn referenced(&self) -> HashSet<String> {
150 if let Some(mapping) = &self.mapping {
151 let mut result = HashSet::new();
152 if let Some(mapping) = mapping.split('.').last() {
153 result.insert(mapping.to_owned());
154 }
155 result
156 } else {
157 self.typename.referenced()
158 }
159 }
160}
161
162impl Hash for IgniteUnnamedField {
163 fn hash<H>(&self, state: &mut H)
164 where
165 H: Hasher,
166 {
167 self.typename.hash(state);
168 }
169}
170
171#[derive(Debug, Serialize, Deserialize, Hash)]
172pub struct IgniteEnum {
173 pub name: String,
174 #[serde(default, skip_serializing_if = "Vec::is_empty")]
175 pub variants: Vec<IgniteVariant>,
176}
177
178impl IgniteEnum {
179 pub fn referenced(&self) -> HashSet<String> {
180 self.variants
181 .iter()
182 .flat_map(|variant| variant.referenced())
183 .collect()
184 }
185}
186
187#[derive(Debug, Serialize, Deserialize, Hash)]
188pub enum IgniteVariant {
189 Unit(String),
190 Named(IgniteNamed),
191 Unnamed(IgniteUnnamed),
192}
193
194impl IgniteVariant {
195 pub fn referenced(&self) -> HashSet<String> {
196 match self {
197 Self::Unit(_) => HashSet::new(),
198 Self::Named(value) => value.referenced(),
199 Self::Unnamed(value) => value.referenced(),
200 }
201 }
202}
203
204#[derive(Debug, Serialize, Deserialize, Hash)]
205pub enum IgniteType {
206 Unit,
207 Atom(String),
208 Tuple(Vec<IgniteType>),
209 Array(IgniteTypeArray),
210 Generic(IgniteTypeGeneric),
211}
212
213impl IgniteType {
214 pub fn referenced(&self) -> HashSet<String> {
215 match self {
216 Self::Unit => HashSet::new(),
217 Self::Atom(name) => {
218 let mut result = HashSet::new();
219 result.insert(name.clone());
220 result
221 }
222 Self::Tuple(value) => value.iter().flat_map(|item| item.referenced()).collect(),
223 Self::Array(value) => value.referenced(),
224 Self::Generic(value) => value.referenced(),
225 }
226 }
227}
228
229#[derive(Debug, Serialize, Deserialize, Hash)]
230pub struct IgniteTypeArray {
231 pub typename: Box<IgniteType>,
232 pub size: usize,
233}
234
235impl IgniteTypeArray {
236 pub fn referenced(&self) -> HashSet<String> {
237 self.typename.referenced()
238 }
239}
240
241#[derive(Debug, Serialize, Deserialize, Hash)]
242pub struct IgniteTypeGeneric {
243 pub name: String,
244 #[serde(default, skip_serializing_if = "Vec::is_empty")]
245 pub arguments: Vec<IgniteType>,
246}
247
248impl IgniteTypeGeneric {
249 pub fn referenced(&self) -> HashSet<String> {
250 std::iter::once(self.name.clone())
251 .chain(self.arguments.iter().flat_map(|arg| arg.referenced()))
252 .collect()
253 }
254}
255
256#[derive(Debug, Serialize, Deserialize)]
257pub enum IgniteAttribMeta {
258 None,
259 Bool(bool),
260 String(String),
261 Integer(i64),
262 Float(f64),
263}
264
265impl Default for IgniteAttribMeta {
266 fn default() -> Self {
267 Self::None
268 }
269}
270
271pub trait Ignite {
272 fn generate_type_definition() -> IgniteTypeDefinition;
273}