use proc_macro2::{Ident, Span, TokenStream};
use quote::ToTokens;
use crate::ParseResult;
use crate::util::{KvParser, bail};
pub enum GodotAttribute {
Transparent { span: Span },
Via { span: Span, via_type: ViaType },
}
impl GodotAttribute {
pub fn parse_attribute(item: &venial::Item) -> ParseResult<Self> {
let mut parser = KvParser::parse_required(item.attributes(), "godot", item)?;
let attribute = Self::parse(&mut parser)?;
parser.finish()?;
Ok(attribute)
}
fn parse(parser: &mut KvParser) -> ParseResult<Self> {
let span = parser.span();
if parser.handle_alone("transparent")? {
return Ok(Self::Transparent { span });
}
if let Some(via_type) = parser.handle_ident("via")? {
return Ok(Self::Via {
span,
via_type: ViaType::parse_ident(via_type)?,
});
}
bail!(
span,
"expected either `#[godot(transparent)]` or `#[godot(via = <via_type>)]`"
)
}
pub fn span(&self) -> Span {
match self {
GodotAttribute::Transparent { span } => *span,
GodotAttribute::Via { span, .. } => *span,
}
}
}
pub enum ViaType {
GString { gstring_ident: Ident },
Int { int_ident: Ident },
}
impl ViaType {
fn parse_ident(ident: Ident) -> ParseResult<Self> {
let via_type = match ident.to_string().as_str() {
"GString" => ViaType::GString {
gstring_ident: ident,
},
"i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" => {
ViaType::Int { int_ident: ident }
}
other => {
return bail!(
ident,
"Via type `{other}` is not supported, expected one of: GString, i8, i16, i32, i64, u8, u16, u32"
);
}
};
Ok(via_type)
}
}
impl ToTokens for ViaType {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
ViaType::GString { gstring_ident } => gstring_ident.to_tokens(tokens),
ViaType::Int { int_ident } => int_ident.to_tokens(tokens),
}
}
}