1use syn::Data;
17
18pub trait DataExt {
33 fn is_struct(&self) -> bool;
35 fn is_enum(&self) -> bool;
37 fn is_union(&self) -> bool;
39 fn as_struct(&self) -> Option<&syn::DataStruct>;
41 fn as_enum(&self) -> Option<&syn::DataEnum>;
43 fn as_union(&self) -> Option<&syn::DataUnion>;
45 fn span(&self) -> proc_macro2::Span;
47}
48
49impl DataExt for Data {
50 fn is_struct(&self) -> bool {
51 matches!(self, Self::Struct(_))
52 }
53
54 fn is_enum(&self) -> bool {
55 matches!(self, Self::Enum(_))
56 }
57
58 fn is_union(&self) -> bool {
59 matches!(self, Self::Union(_))
60 }
61
62 fn as_struct(&self) -> Option<&syn::DataStruct> {
63 match self {
64 Self::Struct(s) => Some(s),
65 _ => None,
66 }
67 }
68
69 fn as_enum(&self) -> Option<&syn::DataEnum> {
70 match self {
71 Self::Enum(e) => Some(e),
72 _ => None,
73 }
74 }
75
76 fn as_union(&self) -> Option<&syn::DataUnion> {
77 match self {
78 Self::Union(u) => Some(u),
79 _ => None,
80 }
81 }
82
83 fn span(&self) -> proc_macro2::Span {
84 use syn::spanned::Spanned;
85 match self {
86 Self::Struct(s) => s.struct_token.span,
87 Self::Enum(e) => e.enum_token.span,
88 Self::Union(u) => u.union_token.span(),
89 }
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 fn data_from(input: &str) -> Data {
98 let di: syn::DeriveInput = syn::parse_str(input).unwrap();
99 di.data
100 }
101
102 mod predicates {
103 use super::*;
104
105 #[test]
106 fn struct_variant() {
107 let data = data_from("struct Foo { x: i32 }");
108 assert!(data.is_struct());
109 assert!(!data.is_enum());
110 assert!(!data.is_union());
111 }
112
113 #[test]
114 fn enum_variant() {
115 let data = data_from("enum Foo { A, B }");
116 assert!(!data.is_struct());
117 assert!(data.is_enum());
118 assert!(!data.is_union());
119 }
120
121 #[test]
122 fn union_variant() {
123 let data = data_from("union Foo { x: i32, y: u32 }");
124 assert!(!data.is_struct());
125 assert!(!data.is_enum());
126 assert!(data.is_union());
127 }
128 }
129
130 mod conversions {
131 use super::*;
132
133 #[test]
134 fn as_struct_some() {
135 let data = data_from("struct Foo { x: i32 }");
136 assert!(data.as_struct().is_some());
137 }
138
139 #[test]
140 fn as_struct_none() {
141 let data = data_from("enum Foo { A }");
142 assert!(data.as_struct().is_none());
143 }
144
145 #[test]
146 fn as_enum_some() {
147 let data = data_from("enum Foo { A, B }");
148 assert!(data.as_enum().is_some());
149 }
150
151 #[test]
152 fn as_enum_none() {
153 let data = data_from("struct Foo;");
154 assert!(data.as_enum().is_none());
155 }
156
157 #[test]
158 fn as_union_some() {
159 let data = data_from("union Foo { x: i32, y: u32 }");
160 assert!(data.as_union().is_some());
161 }
162
163 #[test]
164 fn as_union_none() {
165 let data = data_from("struct Foo;");
166 assert!(data.as_union().is_none());
167 }
168 }
169}