use lib_ruby_parser_nodes::{template::*, Message, MessageField};
const TEMPLATE: &str = "// This file is auto-generated by {{ helper generated-by }}
use crate::DiagnosticMessage;
use crate::blobs::Blob;
use crate::containers::ExternalStringPtr as StringPtr;
{{ each message }}<dnl>
/// External {{ helper message-camelcase-name }}
#[repr(C)]
pub struct {{ helper message-camelcase-name }} {
pub(crate) blob: Blob<Self>,
}
extern \"C\" {
fn {{ helper extern-variant-getter-name }}(blob: *const Blob<DiagnosticMessage>) -> *const Blob<{{ helper message-camelcase-name }}>;
{{ each message-field }}<dnl>
fn {{ helper extern-field-getter-name }}(blob: *const Blob<{{ helper message-camelcase-name }}>) -> *const Blob<{{ helper message-field-rust-field-type }}>;
{{ end }}<dnl>
}
impl {{ helper message-camelcase-name }} {
{{ each message-field }}<dnl>
/// Returns `{{ helper message-field-name }}` field
pub fn get_{{ helper message-field-name }}(&self) -> &{{ helper message-field-rust-field-type }} {
unsafe {
#[allow(trivial_casts)]
({{ helper extern-field-getter-name }}(&self.blob) as *const {{ helper message-field-rust-field-type }}).as_ref().unwrap()
}
}
{{ end }}<dnl>
}
impl std::fmt::Debug for {{ helper message-camelcase-name }} {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(\"{{ helper message-camelcase-name }}\")
{{ each message-field }}<dnl>
.field(\"{{ helper message-field-name }}\", self.get_{{ helper message-field-name }}())
{{ end }}<dnl>
.finish()
}
}
impl PartialEq for {{ helper message-camelcase-name }} {
#[allow(unused_variables)]
fn eq(&self, other: &Self) -> bool {
{{ if message-has-no-fields }}<dnl>
true
{{ else }}<dnl>
{{ each message-field }}<dnl>
if self.get_{{ helper message-field-name }}() != other.get_{{ helper message-field-name }}() {
return false
}
{{ end }}<dnl>
true
{{ end }}<dnl>
}
}
impl DiagnosticMessage {
/// Casts `self` to `Option<&{{ helper message-camelcase-name }}>`, return `None` if variant doesn't match
pub fn as_{{ helper message-lower-name }}(&self) -> Option<&{{ helper message-camelcase-name }}> {
unsafe {
({{ helper extern-variant-getter-name }}(&self.blob) as *const {{ helper message-camelcase-name }}).as_ref()
}
}
}
{{ end }}<dnl>
";
pub(crate) fn codegen() {
let template = TemplateRoot::new(TEMPLATE).unwrap();
let mut fns = crate::codegen::fns::default_fns!();
fns.register::<Message, F::Helper>(
"extern-variant-getter-name",
lib_ruby_parser_bindings::helpers::messages::variant_getter::name,
);
fns.register::<MessageField, F::Helper>(
"extern-field-getter-name",
lib_ruby_parser_bindings::helpers::messages::field_getter::name,
);
let contents = template.render(ALL_DATA, &fns);
std::fs::write("src/error/message/external/variants.rs", contents).unwrap();
}