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