torn_api_codegen/model/
union.rs1use heck::ToSnakeCase;
2use proc_macro2::TokenStream;
3use quote::{format_ident, quote};
4
5use crate::openapi::path::OpenApiResponseBody;
6
7#[derive(Debug, Clone)]
8pub struct Union {
9 pub name: String,
10 pub members: Vec<String>,
11}
12
13impl Union {
14 pub fn from_schema(name: &str, schema: &OpenApiResponseBody) -> Option<Self> {
15 let members = match schema {
16 OpenApiResponseBody::Union { any_of } => {
17 any_of.iter().map(|l| l.ref_path.to_owned()).collect()
18 }
19 _ => return None,
20 };
21 let name = name.to_owned();
22
23 Some(Self { name, members })
24 }
25
26 pub fn codegen(&self) -> Option<TokenStream> {
27 let name = format_ident!("{}", self.name);
28 let mut variants = Vec::new();
29
30 for member in &self.members {
31 let variant_name = member.strip_prefix("#/components/schemas/")?;
32 let accessor_name = format_ident!("{}", variant_name.to_snake_case());
33 let ty_name = format_ident!("{}", variant_name);
34 variants.push(quote! {
35 pub fn #accessor_name(&self) -> Result<crate::models::#ty_name, serde_json::Error> {
36 <crate::models::#ty_name as serde::Deserialize>::deserialize(&self.0)
37 }
38 });
39 }
40
41 Some(quote! {
42 #[derive(Debug, Clone, serde::Deserialize)]
43 pub struct #name(serde_json::Value);
44
45 impl #name {
46 #(#variants)*
47 }
48 })
49 }
50}