use proc_macro2::TokenStream;
use proc_macro_error::abort;
use quote::quote;
use crate::struct_gen::StructGenerator;
pub struct StructWithUnnamedFields<'s> {
gen: &'s StructGenerator,
}
impl<'s> StructWithUnnamedFields<'s> {
pub fn new(gen: &'s StructGenerator) -> Self {
if gen.fields.len() != 1 {
abort!(
gen.span,
"structs with unnamed fields must have only one field"
);
}
Self { gen }
}
pub fn gen(&self) -> TokenStream {
let fn_apply = self.gen_fn_apply();
let fn_get_options = self.gen_fn_get_options();
let fn_get_subfields = self.gen_fn_get_subfields();
let fn_to_node = self.gen_fn_to_node();
let fn_get_value_any = self.gen_fn_get_value_any();
quote! {
#fn_apply
#fn_get_options
#fn_get_subfields
#fn_to_node
#fn_get_value_any
}
}
fn gen_fn_apply(&self) -> TokenStream {
quote! {
fn apply(&mut self, data: ibuilder::Input, current_fields: &[String]) -> Result<(), ibuilder::ChooseError> {
self.0.apply(data, current_fields)
}
}
}
fn gen_fn_get_options(&self) -> TokenStream {
quote! {
fn get_options(&self, current_fields: &[String]) -> ibuilder::Options {
self.0.get_options(current_fields)
}
}
}
fn gen_fn_get_subfields(&self) -> TokenStream {
quote! {
fn get_subfields(&self, current_fields: &[String]) -> Vec<String> {
self.0.get_subfields(current_fields)
}
}
}
fn gen_fn_to_node(&self) -> TokenStream {
let name = self.gen.actual_name();
quote! {
fn to_node(&self) -> ibuilder::nodes::Node {
ibuilder::nodes::Node::Composite(
#name.to_string(),
vec![ibuilder::nodes::FieldKind::Unnamed(self.0.to_node())],
)
}
}
}
fn gen_fn_get_value_any(&self) -> TokenStream {
let ident = &self.gen.ident;
quote! {
fn get_value_any(&self) -> Option<Box<dyn std::any::Any>> {
Some(Box::new(#ident(*self.0.get_value_any()?.downcast().unwrap())))
}
}
}
}