ploidy_core/codegen/
mod.rs1use std::path::Path;
28
29use miette::{Context, IntoDiagnostic};
30
31pub mod unique;
32
33pub use unique::{UniqueNames, WordSegments};
34
35pub fn write_to_disk(output: &Path, code: impl IntoCode) -> miette::Result<()> {
36 let code = code.into_code();
37 let path = output.join(code.path());
38 let string = code.into_string()?;
39 if let Some(parent) = path.parent() {
40 std::fs::create_dir_all(parent)
41 .into_diagnostic()
42 .with_context(|| format!("Failed to create directory `{}`", parent.display()))?;
43 }
44 std::fs::write(&path, string)
45 .into_diagnostic()
46 .with_context(|| format!("Failed to write `{}`", path.display()))?;
47 Ok(())
48}
49
50pub trait Code {
51 fn path(&self) -> &str;
52 fn into_string(self) -> miette::Result<String>;
53}
54
55#[cfg(feature = "proc-macro2")]
56impl<T: AsRef<str>> Code for (T, proc_macro2::TokenStream) {
57 fn path(&self) -> &str {
58 self.0.as_ref()
59 }
60
61 fn into_string(self) -> miette::Result<String> {
62 use quote::ToTokens;
63 let file = syn::parse2(self.1.into_token_stream()).into_diagnostic();
64 match file {
65 Ok(file) => Ok(prettyplease::unparse(&file)),
66 Err(err) => Err(err.context(format!("Failed to format `{}`", self.0.as_ref()))),
67 }
68 }
69}
70
71#[cfg(feature = "cargo_toml")]
72impl<T: serde::Serialize> Code for (&'static str, cargo_toml::Manifest<T>) {
73 fn path(&self) -> &str {
74 self.0
75 }
76
77 fn into_string(self) -> miette::Result<String> {
78 toml::to_string_pretty(&self.1)
79 .into_diagnostic()
80 .with_context(|| format!("Failed to serialize `{}`", self.0))
81 }
82}
83
84pub trait IntoCode {
85 type Code: Code;
86
87 fn into_code(self) -> Self::Code;
88}
89
90impl<T: Code> IntoCode for T {
91 type Code = T;
92
93 fn into_code(self) -> Self::Code {
94 self
95 }
96}