1use proc_macro2::Span;
2use syn::spanned::Spanned;
3
4use crate::mark;
5use crate::types::Input;
6
7use super::FromInput;
8
9pub trait FromData: Sized {
14 fn from_data(data: syn::Data, span: Span) -> crate::Result<Self>;
15}
16
17impl FromData for syn::Data {
18 fn from_data(data: syn::Data, _span: Span) -> crate::Result<Self> {
19 Ok(data)
20 }
21}
22
23impl FromData for syn::DataStruct {
24 fn from_data(data: syn::Data, span: Span) -> crate::Result<Self> {
25 match data {
26 syn::Data::Struct(s) => Ok(s),
27 _ => Err(mark::error("expected struct data").span(span).build()),
28 }
29 }
30}
31
32impl FromData for syn::DataEnum {
33 fn from_data(data: syn::Data, span: Span) -> crate::Result<Self> {
34 match data {
35 syn::Data::Enum(e) => Ok(e),
36 _ => Err(mark::error("expected enum data").span(span).build()),
37 }
38 }
39}
40
41impl FromData for syn::DataUnion {
42 fn from_data(data: syn::Data, span: Span) -> crate::Result<Self> {
43 match data {
44 syn::Data::Union(u) => Ok(u),
45 _ => Err(mark::error("expected union data").span(span).build()),
46 }
47 }
48}
49
50pub struct Data<T: FromData = syn::Data>(T);
63
64impl<T: FromData> Data<T> {
65 pub fn inner(self) -> T {
67 self.0
68 }
69}
70
71impl<T: FromData> std::ops::Deref for Data<T> {
72 type Target = T;
73
74 fn deref(&self) -> &Self::Target {
75 &self.0
76 }
77}
78
79impl<T: FromData> std::ops::DerefMut for Data<T> {
80 fn deref_mut(&mut self) -> &mut Self::Target {
81 &mut self.0
82 }
83}
84
85impl<T: FromData> FromInput for Data<T> {
86 fn from_input(input: &Input) -> crate::Result<Self> {
87 match input {
88 Input::Derive(d) => T::from_data(d.data.clone(), d.ident.span()).map(Data),
89 _ => Err(mark::error("Data extractor requires derive input")
90 .span(input.span())
91 .build()),
92 }
93 }
94}