1use crate::parser::utils::ReadError;
4use std::{
5 collections::HashMap,
6 error::Error,
7 fmt::{Debug, Display, Formatter},
8};
9
10pub struct Schema {
11 pub hosts: Hosts,
12 pub versioning: Versioning,
13 pub types: TypeDeclResults,
14 pub interfaces: InterfaceDeclResults,
15}
16
17impl Display for Schema {
18 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
19 let mut result = "Schema {\n".to_string();
20 result.push_str(&format!(" hosts = {:?}\n", self.hosts));
21 result.push_str(&format!(" versioning = {:?}\n", self.versioning));
22 result.push_str(&format!(
23 " types = {}\n",
24 self.types
25 .iter()
26 .map(|t| {
27 match t {
28 Ok(val) => format!("{}\n", val),
29 Err(err) => format!("{}\n", err),
30 }
31 })
32 .collect::<String>()
33 ));
34 result.push_str(&format!(
35 " interfaces = {}\n",
36 self.interfaces
37 .iter()
38 .map(|t| {
39 match t {
40 Ok(val) => format!("{}\n", val),
41 Err(err) => format!("{}\n", err),
42 }
43 })
44 .collect::<String>()
45 ));
46 f.write_str(&result)
47 }
48}
49
50#[derive(Debug)]
51pub struct Host {
52 pub env: String,
53 pub address: String,
54}
55
56pub type Hosts = Vec<Host>;
57
58#[derive(Debug)]
59pub enum VersioningFormat {
60 Headers,
61}
62
63#[derive(Debug)]
64pub struct Versioning {
65 pub format: VersioningFormat,
66 pub header: Option<String>,
67}
68
69pub type TypeDeclResults = Vec<Result<TypeDecl, TypeDeclError>>;
70
71#[derive(PartialEq, Clone, Debug)]
72pub struct TypeDecl {
73 pub name: String,
74 pub property_decls: Vec<PropertyDecl>,
75}
76
77impl Display for TypeDecl {
78 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
79 let mut result = format!("type `{}` {{ ", self.name);
80 for property_decl in &self.property_decls {
81 match &property_decl.data_type_decl {
82 Ok(data_type_decl) => {
83 result.push_str(&format!("{}: {}; ", property_decl.name, data_type_decl));
84 }
85 Err(err) => {
86 result.push_str(&format!("{}: {}; ", property_decl.name, err));
87 }
88 }
89 }
90 result.push_str(" }");
91 f.write_str(&result)
92 }
93}
94
95#[derive(Debug, PartialEq, Clone)]
96pub struct PropertyDecl {
97 pub name: String,
98 pub data_type_decl: Result<DataTypeDecl, TypeDeclError>,
99}
100
101#[derive(Debug, PartialEq, Clone)]
102pub enum TypeDeclError {
103 ImportFailure(ImportError),
104 UnsupportedTypeDeclaration,
105 UnsupportedKeyType,
106 EmptyTypeDeclaration,
107 SubtypeValuesEmptyDeclaration,
108 UnsupportedPrimitive(String),
109}
110
111impl TypeDeclError {
112 fn default_fmt(&self, f: &mut Formatter) -> std::fmt::Result {
113 match self {
114 TypeDeclError::ImportFailure(import_error) => {
115 write!(f, "Import failed: {}", import_error.to_string())
116 }
117 TypeDeclError::UnsupportedTypeDeclaration => {
118 write!(f, "This type declaration format is not supported.")
119 }
120 TypeDeclError::UnsupportedKeyType => write!(f, "Key type must be string."),
121 TypeDeclError::EmptyTypeDeclaration => write!(f, "Type declaration cannot be empty."),
122 TypeDeclError::SubtypeValuesEmptyDeclaration => {
123 write!(f, "Subtype declaration cannot be empty.")
124 }
125 TypeDeclError::UnsupportedPrimitive(value) => {
126 write!(f, "Primitive {} not supported.", value)
127 }
128 }
129 }
130}
131
132impl Error for TypeDeclError {}
133
134impl Display for TypeDeclError {
135 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
136 self.default_fmt(f)
137 }
138}
139
140#[derive(PartialEq, Clone, Debug)]
141pub struct DataTypeDecl {
142 pub data_type: DataType,
143 pub is_required: bool,
144}
145
146impl Display for DataTypeDecl {
147 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
148 let mut result = format!("{}", self.data_type);
149 if !self.is_required {
150 result.push_str("?");
151 }
152 f.write_str(&result)
153 }
154}
155
156#[derive(PartialEq, Clone, Debug)]
157pub enum DataType {
158 Primitive(Primitive),
159 Array(Box<DataType>),
160 Dict(Primitive, Box<DataType>),
161 Object(String),
162 ObjectDecl(TypeDecl),
163}
164
165impl Display for DataType {
166 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
167 match self {
168 DataType::Primitive(primitive) => f.write_str(&format!("{}", primitive)),
169 DataType::Array(data_type) => f.write_str(&format!("array[{}]", data_type)),
170 DataType::Dict(key, value) => f.write_str(&format!("dict{{ {}: {} }}", key, value)),
171 DataType::Object(ident) => f.write_str(&format!("{}", ident)),
172 DataType::ObjectDecl(type_decl) => f.write_str(&format!("{}", type_decl)),
173 }
174 }
175}
176
177#[derive(Debug, PartialEq, Clone)]
178pub enum Primitive {
179 Int,
180 Double,
181 Bool,
182 Str,
183}
184
185impl Display for Primitive {
186 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
187 match self {
188 Primitive::Int => f.write_str("int"),
189 Primitive::Double => f.write_str("double"),
190 Primitive::Bool => f.write_str("bool"),
191 Primitive::Str => f.write_str("str"),
192 }
193 }
194}
195
196#[derive(Clone)]
197pub enum ImportError {
198 IOError(ReadError),
199 InvalidInputSource,
200 InvalidImportValue,
201}
202
203impl PartialEq for ImportError {
204 fn eq(&self, other: &Self) -> bool {
205 match (self, other) {
206 (ImportError::IOError(lhs), ImportError::IOError(rhs)) => lhs == rhs,
207 (ImportError::InvalidInputSource, ImportError::InvalidInputSource) => true,
208 (ImportError::InvalidImportValue, ImportError::InvalidImportValue) => true,
209 _ => false,
210 }
211 }
212}
213
214pub type InterfaceDeclResults = Vec<Result<InterfaceDecl, InterfaceDeclError>>;
217
218#[derive(PartialEq, Debug)]
219pub struct InterfaceDecl {
220 pub ident: String,
221 pub params: Vec<String>,
222 pub spec: InterfaceSpec,
223}
224
225impl Display for InterfaceDecl {
226 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
227 let InterfaceSpec::Api(api) = &self.spec;
228 let mut result = format!("{:?} /{}\n", api.method, self.ident);
229 if let Some(payload) = &api.payload {
230 match payload {
231 HttpPayload::Body(body) => {
232 result.push_str(&format!("Body: {:?}\n", body));
233 }
234 HttpPayload::Query(query) => {
235 result.push_str(&format!("Query: {:?}\n", query));
236 }
237 }
238 }
239 if let Some(responses) = &api.responses {
240 result.push_str(&format!(
241 "Responses: {}",
242 responses
243 .iter()
244 .map(|(k, v)| { format!("{}: {}\n", k, v) })
245 .collect::<String>()
246 ));
247 }
248 f.write_str(&result)
249 }
250}
251
252#[derive(PartialEq)]
253pub enum InterfaceSpec {
254 Api(ApiSpec),
255}
256
257impl Debug for InterfaceSpec {
258 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
259 match self {
260 InterfaceSpec::Api(api_spec) => f.write_str(&format!("{}", api_spec)),
261 }
262 }
263}
264
265#[derive(PartialEq, Debug)]
266pub struct ApiSpec {
267 pub method: HttpMethod,
268 pub payload: Option<HttpPayload>,
269 pub responses: HttpResponses,
270}
271
272impl Display for ApiSpec {
273 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
274 let mut result = format!("method: {}\n", self.method);
275 if let Some(payload) = &self.payload {
276 result.push_str(&format!("\t{}\n", payload));
277 }
278 if let Some(responses) = &self.responses {
279 result.push_str(&format!("\t{:?}", responses));
280 }
281 f.write_str(&result)
282 }
283}
284
285pub type HttpResponses = Option<HashMap<StatusCode, TypeDecl>>;
286
287#[derive(Eq, Hash, PartialEq, Clone, Debug)]
288pub enum StatusCode {
289 Fixed(u16),
290 Prefix(u16),
291}
292
293impl StatusCode {
294 pub fn as_key(&self) -> String {
295 match self {
296 StatusCode::Fixed(val) => val.to_string(),
297 StatusCode::Prefix(val) => val.to_string() + "xx",
298 }
299 }
300}
301
302impl Display for StatusCode {
303 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
304 match self {
305 StatusCode::Fixed(val) => f.write_str(&val.to_string()),
306 StatusCode::Prefix(val) => f.write_str(&(val.to_string() + "xx")),
307 }
308 }
309}
310
311#[derive(Debug, PartialEq)]
312pub enum HttpMethod {
313 Get,
314 Post,
315 Put,
316 Delete,
317 Patch,
318 Head,
319}
320
321impl Display for HttpMethod {
322 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
323 match self {
324 HttpMethod::Get => f.write_str("GET"),
325 HttpMethod::Post => f.write_str("POST"),
326 HttpMethod::Put => f.write_str("PUT"),
327 HttpMethod::Delete => f.write_str("DELETE"),
328 HttpMethod::Patch => f.write_str("PATCH"),
329 HttpMethod::Head => f.write_str("HEAD"),
330 }
331 }
332}
333
334#[derive(Debug, PartialEq)]
335pub enum HttpPayload {
336 Query(Vec<PropertyDecl>),
337 Body(Vec<PropertyDecl>),
338}
339
340impl Display for HttpPayload {
341 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
342 match self {
343 HttpPayload::Query(query) => {
344 let mut result = "Query: {\n".to_string();
345 for property_decl in query {
346 result.push_str(&format!(
347 " {}: {:?}\n",
348 property_decl.name, property_decl.data_type_decl
349 ));
350 }
351 result.push_str("}\n");
352 f.write_str(&result)
353 }
354 HttpPayload::Body(body) => {
355 let mut result = "Body: {\n".to_string();
356 for property_decl in body {
357 result.push_str(&format!(
358 " {}: {:?}\n",
359 property_decl.name, property_decl.data_type_decl
360 ));
361 }
362 result.push_str("}\n");
363 f.write_str(&result)
364 }
365 }
366 }
367}
368
369#[derive(Debug, PartialEq)]
370pub enum InterfaceDeclError {
371 ImportFailure(ImportError),
372 BodyNotAllowed,
373 QueryNotAllowed,
374 InvalidKey,
375 InvalidStatusCode,
376 TypeNotFound(String),
377 InvalidResponseDeclaration,
378 InvalidInterfaceDeclaration,
379 InvalidIdent,
380 EmptyParam,
381 InvalidMethod,
382 InvalidQuery,
383 InvalidBody,
384 InvalidResponseTypeDeclaration,
385}
386
387impl Error for InterfaceDeclError {}
388
389impl Display for InterfaceDeclError {
390 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
391 match self {
392 _ => f.write_str("InterfaceDeclError"),
393 }
394 }
395}
396
397pub type TypeUsageMeta = Option<Vec<UnknownType>>;
398
399#[derive(Debug, PartialEq, Clone)]
400pub enum UnknownType {
401 InTypeDeclaration(usize, usize),
402 InPayload(usize, usize),
403 InResponse(usize, StatusCode, usize)
404}
405