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