torn_api_codegen/model/
mod.rs1use indexmap::IndexMap;
2use newtype::Newtype;
3use object::Object;
4use proc_macro2::TokenStream;
5use r#enum::Enum;
6
7use crate::openapi::r#type::OpenApiType;
8
9pub mod r#enum;
10pub mod newtype;
11pub mod object;
12pub mod parameter;
13pub mod path;
14pub mod scope;
15pub mod union;
16
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub enum Model {
19 Newtype(Newtype),
20 Enum(Enum),
21 Object(Object),
22 Unresolved,
23}
24
25pub fn resolve(r#type: &OpenApiType, name: &str, schemas: &IndexMap<&str, OpenApiType>) -> Model {
26 match r#type {
27 OpenApiType {
28 r#enum: Some(_), ..
29 } => Enum::from_schema(name, r#type).map_or(Model::Unresolved, Model::Enum),
30 OpenApiType {
31 r#type: Some("object"),
32 ..
33 } => Object::from_schema_object(name, r#type, schemas)
34 .map_or(Model::Unresolved, Model::Object),
35 OpenApiType {
36 r#type: Some(_), ..
37 } => Newtype::from_schema(name, r#type).map_or(Model::Unresolved, Model::Newtype),
38 OpenApiType {
39 one_of: Some(types),
40 ..
41 } => Enum::from_one_of(name, types).map_or(Model::Unresolved, Model::Enum),
42 OpenApiType {
43 all_of: Some(types),
44 ..
45 } => Object::from_all_of(name, types, schemas).map_or(Model::Unresolved, Model::Object),
46 _ => Model::Unresolved,
47 }
48}
49
50impl Model {
51 pub fn codegen(&self) -> Option<TokenStream> {
52 match self {
53 Self::Newtype(newtype) => newtype.codegen(),
54 Self::Enum(r#enum) => r#enum.codegen(),
55 Self::Object(object) => object.codegen(),
56 Self::Unresolved => None,
57 }
58 }
59}
60
61#[cfg(test)]
62mod test {
63 use super::*;
64 use crate::openapi::schema::OpenApiSchema;
65
66 #[test]
67 fn resolve_newtypes() {
68 let schema = OpenApiSchema::read().unwrap();
69
70 let user_id_schema = schema.components.schemas.get("UserId").unwrap();
71
72 let user_id = resolve(user_id_schema, "UserId", &schema.components.schemas);
73
74 assert_eq!(
75 user_id,
76 Model::Newtype(Newtype {
77 name: "UserId".to_owned(),
78 description: None,
79 inner: newtype::NewtypeInner::I32,
80 copy: true,
81 ord: true
82 })
83 );
84
85 let attack_code_schema = schema.components.schemas.get("AttackCode").unwrap();
86
87 let attack_code = resolve(attack_code_schema, "AttackCode", &schema.components.schemas);
88
89 assert_eq!(
90 attack_code,
91 Model::Newtype(Newtype {
92 name: "AttackCode".to_owned(),
93 description: None,
94 inner: newtype::NewtypeInner::Str,
95 copy: false,
96 ord: false
97 })
98 );
99 }
100
101 #[test]
102 fn resolve_all() {
103 let schema = OpenApiSchema::read().unwrap();
104
105 let mut unresolved = vec![];
106 let total = schema.components.schemas.len();
107
108 for (name, desc) in &schema.components.schemas {
109 if resolve(desc, name, &schema.components.schemas) == Model::Unresolved {
110 unresolved.push(name);
111 }
112 }
113
114 if !unresolved.is_empty() {
115 panic!(
116 "Failed to resolve {}/{} types. Could not resolve [{}]",
117 unresolved.len(),
118 total,
119 unresolved
120 .into_iter()
121 .map(|u| format!("`{u}`"))
122 .collect::<Vec<_>>()
123 .join(", ")
124 )
125 }
126 }
127}