use typify::{TypeSpace, TypeSpaceSettings};
use crate::schema::ContractSchema;
use crate::targets::{header, type_name};
use crate::CompileError;
pub struct EmitInput<'a> {
pub schema: &'a ContractSchema,
pub raw_schema_json: &'a str,
pub epoch: u32,
}
pub fn emit(input: &EmitInput<'_>) -> Result<String, CompileError> {
let body = typify_body(input)?;
Ok(format!(
"{header}{body}",
header = header(input.schema, input.epoch, "//"),
))
}
fn typify_body(input: &EmitInput<'_>) -> Result<String, CompileError> {
let mut value: serde_json::Value =
serde_json::from_str(input.raw_schema_json).map_err(|error| invalid(&error))?;
value["title"] = serde_json::Value::String(type_name(input.schema));
let root: schemars::schema::RootSchema =
serde_json::from_value(value).map_err(|error| invalid(&error))?;
let settings = TypeSpaceSettings::default();
let mut space = TypeSpace::new(&settings);
space
.add_root_schema(root)
.map_err(|error| invalid(&error))?;
let file = syn::parse2::<syn::File>(space.to_stream()).map_err(|error| invalid(&error))?;
Ok(prettyplease::unparse(&file))
}
fn invalid(error: &dyn std::fmt::Display) -> CompileError {
CompileError::InvalidSchema {
message: format!("typify Rust generation rejected the schema: {error}"),
}
}