ploidy_core/codegen/
mod.rs1use std::path::Path;
2
3use miette::{Context, IntoDiagnostic};
4
5pub mod unique;
6
7pub use unique::{UniqueNames, WordSegments};
8
9pub fn write_to_disk(output: &Path, code: impl IntoCode) -> miette::Result<()> {
10 let code = code.into_code();
11 let path = output.join(code.path());
12 let string = code.into_string()?;
13 if let Some(parent) = path.parent() {
14 std::fs::create_dir_all(parent)
15 .into_diagnostic()
16 .with_context(|| format!("Failed to create directory `{}`", parent.display()))?;
17 }
18 std::fs::write(&path, string)
19 .into_diagnostic()
20 .with_context(|| format!("Failed to write `{}`", path.display()))?;
21 Ok(())
22}
23
24pub trait Code {
25 fn path(&self) -> &str;
26 fn into_string(self) -> miette::Result<String>;
27}
28
29#[cfg(feature = "proc-macro2")]
30impl<T: AsRef<str>> Code for (T, proc_macro2::TokenStream) {
31 fn path(&self) -> &str {
32 self.0.as_ref()
33 }
34
35 fn into_string(self) -> miette::Result<String> {
36 use quote::ToTokens;
37 let file = syn::parse2(self.1.into_token_stream()).into_diagnostic();
38 match file {
39 Ok(file) => Ok(prettyplease::unparse(&file)),
40 Err(err) => Err(err.context(format!("Failed to format `{}`", self.0.as_ref()))),
41 }
42 }
43}
44
45#[cfg(feature = "cargo_toml")]
46impl<T: serde::Serialize> Code for (&'static str, cargo_toml::Manifest<T>) {
47 fn path(&self) -> &str {
48 self.0
49 }
50
51 fn into_string(self) -> miette::Result<String> {
52 toml::to_string_pretty(&self.1)
53 .into_diagnostic()
54 .with_context(|| format!("Failed to serialize `{}`", self.0))
55 }
56}
57
58pub trait IntoCode {
59 type Code: Code;
60
61 fn into_code(self) -> Self::Code;
62}
63
64impl<T: Code> IntoCode for T {
65 type Code = T;
66
67 fn into_code(self) -> Self::Code {
68 self
69 }
70}