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::{
8    codegen::{IntoCode, write_to_disk},
9    ir::View,
10};
11
12mod cargo;
13mod client;
14mod derives;
15mod enum_;
16mod graph;
17mod naming;
18mod operation;
19mod ref_;
20mod resource;
21mod schema;
22mod statics;
23mod struct_;
24mod tagged;
25mod types;
26mod untagged;
27
28pub use cargo::*;
29pub use client::*;
30pub use graph::*;
31pub use naming::*;
32pub use operation::*;
33pub use resource::*;
34pub use schema::*;
35pub use statics::*;
36pub use types::*;
37
38pub fn write_types_to_disk(output: &Path, graph: &CodegenGraph<'_>) -> miette::Result<()> {
39    for view in graph.schemas() {
40        let ext = view.extensions();
41        let info = ext.get::<SchemaIdent>().unwrap();
42        let name = CodegenTypeName::Schema(view.name(), &info);
43        let code = CodegenSchemaType::new(name, &view).into_code();
44        write_to_disk(output, code)?;
45    }
46
47    write_to_disk(output, CodegenTypesModule::new(graph))?;
48
49    Ok(())
50}
51
52pub fn write_client_to_disk(output: &Path, graph: &CodegenGraph<'_>) -> miette::Result<()> {
53    let by_resource = graph
54        .operations()
55        .fold(BTreeMap::<_, Vec<_>>::new(), |mut map, view| {
56            let resource = view.resource();
57            map.entry(resource).or_default().push(view);
58            map
59        });
60
61    for (resource, operations) in &by_resource {
62        let code = CodegenResource::new(resource, operations);
63        write_to_disk(output, code)?;
64    }
65
66    let resources = by_resource.keys().copied().collect_vec();
67    let mod_code = CodegenClientModule::new(graph, &resources);
68    write_to_disk(output, mod_code)?;
69
70    Ok(())
71}
72
73/// Generates one or more `#[doc]` attributes for a schema description,
74/// wrapping at 80 characters for readability.
75pub fn doc_attrs(description: &str) -> TokenStream {
76    let lines = textwrap::wrap(description, 80)
77        .into_iter()
78        .map(|line| quote!(#[doc = #line]));
79    quote! { #(#lines)* }
80}