ploidy_codegen_rust/
schema.rs1use ploidy_core::{
2 codegen::IntoCode,
3 ir::{InlineIrTypeView, SchemaIrTypeView, View},
4};
5use proc_macro2::TokenStream;
6use quote::{ToTokens, TokenStreamExt, quote};
7
8use super::{
9 enum_::CodegenEnum, naming::CodegenTypeName, struct_::CodegenStruct, tagged::CodegenTagged,
10 untagged::CodegenUntagged,
11};
12
13#[derive(Debug)]
15pub struct CodegenSchemaType<'a> {
16 name: CodegenTypeName<'a>,
17 ty: &'a SchemaIrTypeView<'a>,
18}
19
20impl<'a> CodegenSchemaType<'a> {
21 pub fn new(name: CodegenTypeName<'a>, ty: &'a SchemaIrTypeView<'a>) -> Self {
22 Self { name, ty }
23 }
24}
25
26impl ToTokens for CodegenSchemaType<'_> {
27 fn to_tokens(&self, tokens: &mut TokenStream) {
28 let name = self.name;
29 let code = match self.ty {
30 SchemaIrTypeView::Struct(_, view) => CodegenStruct::new(name, view).into_token_stream(),
31 SchemaIrTypeView::Enum(_, view) => CodegenEnum::new(name, view).into_token_stream(),
32 SchemaIrTypeView::Tagged(_, view) => CodegenTagged::new(name, view).into_token_stream(),
33 SchemaIrTypeView::Untagged(_, view) => {
34 CodegenUntagged::new(name, view).into_token_stream()
35 }
36 };
37 let mut inlines = self.ty.inlines().map(|view| match view {
38 InlineIrTypeView::Enum(path, view) => {
39 CodegenEnum::new(CodegenTypeName::Inline(path), &view).into_token_stream()
40 }
41 InlineIrTypeView::Struct(path, view) => {
42 CodegenStruct::new(CodegenTypeName::Inline(path), &view).into_token_stream()
43 }
44 InlineIrTypeView::Untagged(path, view) => {
45 CodegenUntagged::new(CodegenTypeName::Inline(path), &view).into_token_stream()
46 }
47 });
48 let fields_module = inlines.next().map(|head| {
49 quote! {
50 pub mod types {
51 #head
52 #(#inlines)*
53 }
54 }
55 });
56 tokens.append_all(quote! {
57 #code
58 #fields_module
59 });
60 }
61}
62
63impl IntoCode for CodegenSchemaType<'_> {
64 type Code = (String, TokenStream);
65
66 fn into_code(self) -> Self::Code {
67 let name = match self.name {
68 CodegenTypeName::Schema(_, ident) => {
69 format!("src/types/{}.rs", ident.module().to_token_stream())
70 }
71 CodegenTypeName::Inline(..) => {
72 unreachable!("inline types shouldn't be written to disk")
73 }
74 };
75 (name, self.into_token_stream())
76 }
77}