Skip to main content

ploidy_codegen_rust/
lib.rs

1use std::{collections::BTreeMap, path::Path};
2
3use itertools::Itertools;
4use proc_macro2::TokenStream;
5use quote::quote;
6
7use ploidy_core::codegen::{IntoCode, WrittenFile, write_to_disk};
8
9mod cargo;
10mod cfg;
11mod client;
12mod config;
13mod derives;
14mod enum_;
15mod ext;
16mod graph;
17mod inlines;
18mod naming;
19mod operation;
20mod primitive;
21mod query;
22mod ref_;
23mod resource;
24mod schema;
25mod statics;
26mod struct_;
27mod tagged;
28mod types;
29mod untagged;
30
31#[cfg(test)]
32mod tests;
33
34pub use cargo::*;
35pub use cfg::*;
36pub use client::*;
37pub use config::*;
38pub use graph::*;
39pub use naming::*;
40pub use operation::*;
41pub use primitive::*;
42pub use query::*;
43pub use resource::*;
44pub use schema::*;
45pub use statics::*;
46pub use types::*;
47
48pub fn write_types_to_disk(
49    output: &Path,
50    graph: &CodegenGraph<'_>,
51) -> miette::Result<Vec<WrittenFile>> {
52    let mut written = Vec::new();
53
54    for schema in graph.schemas() {
55        let code = CodegenSchemaType::new(graph, &schema).into_code();
56        written.push(write_to_disk(output, code)?);
57    }
58
59    written.push(write_to_disk(output, CodegenTypesModule::new(graph))?);
60
61    Ok(written)
62}
63
64pub fn write_client_to_disk(
65    output: &Path,
66    graph: &CodegenGraph<'_>,
67) -> miette::Result<Vec<WrittenFile>> {
68    // Group operations by resource name.
69    let ops_by_resource: BTreeMap<_, Vec<_>> =
70        graph.operations().fold(BTreeMap::default(), |mut map, op| {
71            let resource = graph.resource_for(&op);
72            map.entry(resource).or_default().push(op);
73            map
74        });
75
76    let mut written = Vec::new();
77
78    // Write a module per resource.
79    for (ident, ops) in &ops_by_resource {
80        written.push(write_to_disk(
81            output,
82            CodegenResource::new(graph, *ident, ops),
83        )?);
84    }
85
86    // Write the top-level client module.
87    let idents = ops_by_resource.keys().copied().collect_vec();
88    written.push(write_to_disk(
89        output,
90        CodegenClientModule::new(graph, &idents),
91    )?);
92
93    Ok(written)
94}
95
96/// Generates one or more `#[doc]` attributes for a schema description,
97/// wrapping at 80 characters for readability.
98pub fn doc_attrs(description: &str) -> TokenStream {
99    use textwrap::{Options, dedent, wrap};
100    let dedented = dedent(description);
101    let lines = wrap(
102        &dedented,
103        Options::new(80)
104            .initial_indent(" ")
105            .subsequent_indent(" ")
106            .break_words(false),
107    )
108    .into_iter()
109    .map(|line| quote!(#[doc = #line]));
110    quote! { #(#lines)* }
111}