1use syn::spanned::Spanned;
2
3use crate::mark;
4use crate::types::Input;
5
6use super::FromInput;
7
8pub trait FromData: Sized {
13 fn from_data(data: syn::Data) -> crate::Result<Self>;
14}
15
16impl FromData for syn::Data {
17 fn from_data(data: syn::Data) -> crate::Result<Self> {
18 Ok(data)
19 }
20}
21
22impl FromData for syn::DataStruct {
23 fn from_data(data: syn::Data) -> crate::Result<Self> {
24 match data {
25 syn::Data::Struct(s) => Ok(s),
26 syn::Data::Enum(e) => Err(mark::error("expected struct data")
27 .span(e.enum_token.span())
28 .build()),
29 syn::Data::Union(u) => Err(mark::error("expected struct data")
30 .span(u.union_token.span())
31 .build()),
32 }
33 }
34}
35
36impl FromData for syn::DataEnum {
37 fn from_data(data: syn::Data) -> crate::Result<Self> {
38 match data {
39 syn::Data::Enum(e) => Ok(e),
40 syn::Data::Struct(s) => Err(mark::error("expected enum data")
41 .span(s.struct_token.span())
42 .build()),
43 syn::Data::Union(u) => Err(mark::error("expected enum data")
44 .span(u.union_token.span())
45 .build()),
46 }
47 }
48}
49
50impl FromData for syn::DataUnion {
51 fn from_data(data: syn::Data) -> crate::Result<Self> {
52 match data {
53 syn::Data::Union(u) => Ok(u),
54 syn::Data::Struct(s) => Err(mark::error("expected union data")
55 .span(s.struct_token.span())
56 .build()),
57 syn::Data::Enum(e) => Err(mark::error("expected union data")
58 .span(e.enum_token.span())
59 .build()),
60 }
61 }
62}
63
64pub struct Data<T: FromData = syn::Data>(T);
77
78impl<T: FromData> Data<T> {
79 pub fn inner(self) -> T {
81 self.0
82 }
83}
84
85impl<T: FromData> std::ops::Deref for Data<T> {
86 type Target = T;
87
88 fn deref(&self) -> &Self::Target {
89 &self.0
90 }
91}
92
93impl<T: FromData> std::ops::DerefMut for Data<T> {
94 fn deref_mut(&mut self) -> &mut Self::Target {
95 &mut self.0
96 }
97}
98
99impl<T: FromData> FromInput for Data<T> {
100 fn from_input(input: &Input) -> crate::Result<Self> {
101 match input {
102 Input::Derive(d) => T::from_data(d.data.clone()).map(Data),
103 _ => Err(mark::error("Data extractor requires derive input")
104 .span(input.span())
105 .build()),
106 }
107 }
108}