use std::path::Path;
use miette::{Context, IntoDiagnostic};
pub mod unique;
pub use unique::{AsKebabCase, AsPascalCase, AsSnakeCase, NamePart, UniqueName, UniqueNames};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct WrittenFile {
pub path: String,
pub size: usize,
}
pub fn write_to_disk(output: &Path, code: impl IntoCode) -> miette::Result<WrittenFile> {
let code = code.into_code();
let relative = code.path().to_owned();
let absolute = output.join(&relative);
let string = code.into_string()?;
if let Some(parent) = absolute.parent() {
std::fs::create_dir_all(parent)
.into_diagnostic()
.with_context(|| format!("Failed to create directory `{}`", parent.display()))?;
}
let size = string.len();
std::fs::write(&absolute, string)
.into_diagnostic()
.with_context(|| format!("Failed to write `{}`", absolute.display()))?;
Ok(WrittenFile {
path: relative,
size,
})
}
pub trait Code {
fn path(&self) -> &str;
fn into_string(self) -> miette::Result<String>;
}
#[cfg(feature = "proc-macro2")]
impl<T: AsRef<str>> Code for (T, proc_macro2::TokenStream) {
fn path(&self) -> &str {
self.0.as_ref()
}
fn into_string(self) -> miette::Result<String> {
use quote::ToTokens;
let file = syn::parse2(self.1.into_token_stream()).into_diagnostic();
match file {
Ok(file) => Ok(prettyplease::unparse(&file)),
Err(err) => Err(err.context(format!("Failed to format `{}`", self.0.as_ref()))),
}
}
}
pub trait IntoCode {
type Code: Code;
fn into_code(self) -> Self::Code;
}
impl<T: Code> IntoCode for T {
type Code = T;
fn into_code(self) -> Self::Code {
self
}
}