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