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 {
69 self.0
70 }
71}
72
73impl<T: FromData> std::ops::Deref for Data<T> {
74 type Target = T;
75
76 fn deref(&self) -> &Self::Target {
77 &self.0
78 }
79}
80
81impl<T: FromData> std::ops::DerefMut for Data<T> {
82 fn deref_mut(&mut self) -> &mut Self::Target {
83 &mut self.0
84 }
85}
86
87impl<T: FromData> FromInput for Data<T> {
88 fn from_input(input: &Input) -> crate::Result<Self> {
89 match input {
90 Input::Derive(d) => T::from_data(d.data.clone()).map(Data),
91 _ => Err(Diagnostics::error(
92 input.span(),
93 "Data extractor requires derive input",
94 )),
95 }
96 }
97}