use darling::{FromDeriveInput, FromField};
#[derive(Debug, FromDeriveInput)]
#[darling(attributes(ros2), supports(struct_named))]
pub struct Ros2TypeOpts {
pub ident: syn::Ident,
pub generics: syn::Generics,
#[darling(default = "default_package")]
pub package: String,
#[darling(default = "default_interface_type")]
pub interface_type: String,
#[darling(default)]
pub uuid_path: Option<String>,
#[darling(default)]
pub skip_wrapper: bool,
}
fn default_package() -> String {
"default_pkg".to_string()
}
fn default_interface_type() -> String {
"msg".to_string()
}
#[derive(Debug, Clone, FromField)]
#[darling(attributes(ros2))]
pub struct Ros2FieldOpts {
pub ident: Option<syn::Ident>,
pub ty: syn::Type,
#[darling(default)]
pub ros2_type: Option<String>,
#[darling(default)]
pub capacity: Option<u64>,
#[darling(default)]
pub string_capacity: Option<u64>,
#[darling(default)]
pub sequence: bool,
#[darling(default)]
pub string: bool,
#[darling(default)]
pub wstring: bool,
#[darling(default)]
pub default: Option<String>,
}
pub fn parse_fields(input: &syn::DeriveInput) -> Result<Vec<Ros2FieldOpts>, syn::Error> {
let fields = match &input.data {
syn::Data::Struct(data) => match &data.fields {
syn::Fields::Named(fields) => &fields.named,
_ => {
return Err(syn::Error::new_spanned(
input,
"ROS2 derives can only be used on structs with named fields",
));
}
},
_ => {
return Err(syn::Error::new_spanned(
input,
"ROS2 derives can only be used on structs",
));
}
};
fields
.iter()
.map(|f| {
Ros2FieldOpts::from_field(f).map_err(|e| {
syn::Error::new_spanned(f, format!("Failed to parse field attributes: {}", e))
})
})
.collect()
}