odra_ir/
odra_type_item.rs1use proc_macro2::Ident;
2use syn::{DataEnum, DataStruct, DeriveInput, Fields, Variant};
3
4pub enum OdraTypeItem {
6 Struct(OdraStruct),
7 Enum(OdraEnum)
8}
9
10pub struct OdraStruct {
11 struct_ident: Ident,
12 fields: Vec<Ident>
13}
14
15impl OdraStruct {
16 pub fn struct_ident(&self) -> &Ident {
17 &self.struct_ident
18 }
19
20 pub fn fields(&self) -> &[Ident] {
21 self.fields.as_ref()
22 }
23}
24
25pub struct OdraEnum {
26 enum_ident: Ident,
27 variants: Vec<Variant>
28}
29
30impl OdraEnum {
31 pub fn enum_ident(&self) -> &Ident {
32 &self.enum_ident
33 }
34
35 pub fn variants(&self) -> &[Variant] {
36 &self.variants
37 }
38}
39
40impl OdraTypeItem {
41 pub fn parse(input: DeriveInput) -> Result<Self, syn::Error> {
42 let ident = input.ident.clone();
43 match &input.data {
44 syn::Data::Struct(DataStruct {
45 fields: Fields::Named(named_fields),
46 ..
47 }) => Ok(OdraTypeItem::Struct(OdraStruct {
48 struct_ident: ident,
49 fields: named_fields
50 .named
51 .iter()
52 .map(|f| f.ident.clone().unwrap())
53 .collect()
54 })),
55 syn::Data::Enum(DataEnum { variants, .. }) => {
56 let is_valid = variants
57 .iter()
58 .all(|v| matches!(v.fields, syn::Fields::Unit));
59 if is_valid {
60 Ok(OdraTypeItem::Enum(OdraEnum {
61 enum_ident: ident,
62 variants: variants.iter().map(Clone::clone).collect()
63 }))
64 } else {
65 Err(syn::Error::new_spanned(
66 input,
67 "Expected a unit enum variant."
68 ))
69 }
70 }
71 _ => Err(syn::Error::new_spanned(
72 input,
73 "Expected a struct or enum with named fields."
74 ))
75 }
76 }
77
78 pub fn ident(&self) -> &Ident {
79 match self {
80 OdraTypeItem::Struct(s) => s.struct_ident(),
81 OdraTypeItem::Enum(e) => e.enum_ident()
82 }
83 }
84}