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