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, 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 inlines::*;
40pub use naming::*;
41pub use operation::*;
42pub use primitive::*;
43pub use query::*;
44pub use resource::*;
45pub use schema::*;
46pub use statics::*;
47pub use types::*;
48
49pub fn write_types_to_disk(output: &Path, graph: &CodegenGraph<'_>) -> miette::Result<()> {
50    for view in graph.schemas() {
51        let code = CodegenSchemaType::new(&view).into_code();
52        write_to_disk(output, code)?;
53    }
54
55    write_to_disk(output, CodegenTypesModule::new(graph))?;
56
57    Ok(())
58}
59
60pub fn write_client_to_disk(output: &Path, graph: &CodegenGraph<'_>) -> miette::Result<()> {
61    // Group operations by feature. All operations belong to a feature,
62    // or `default` for operations without a named resource.
63    let ops_by_feature = graph
64        .operations()
65        .fold(BTreeMap::<_, Vec<_>>::new(), |mut map, view| {
66            let feature = view
67                .resource()
68                .map(CargoFeature::from_name)
69                .unwrap_or_default();
70            map.entry(feature).or_default().push(view);
71            map
72        });
73
74    // Write all operations for each feature into separate modules.
75    for (feature, ops) in &ops_by_feature {
76        let code = CodegenResource::new(feature, ops);
77        write_to_disk(output, code)?;
78    }
79
80    // Write the top-level client module.
81    let features = ops_by_feature.keys().collect_vec();
82    let mod_code = CodegenClientModule::new(graph, &features);
83    write_to_disk(output, mod_code)?;
84
85    Ok(())
86}
87
88/// Generates one or more `#[doc]` attributes for a schema description,
89/// wrapping at 80 characters for readability.
90pub fn doc_attrs(description: &str) -> TokenStream {
91    let lines = textwrap::wrap(description, 80)
92        .into_iter()
93        .map(|line| quote!(#[doc = #line]));
94    quote! { #(#lines)* }
95}