zyn_core/extract/
fields.rs1use proc_macro2::Span;
2use syn::spanned::Spanned;
3
4use crate::diagnostic::Diagnostics;
5use crate::types::Input;
6
7use super::FromInput;
8
9pub trait FromFields: Sized {
14 fn from_fields(fields: syn::Fields) -> crate::Result<Self>;
15}
16
17impl FromFields for syn::Fields {
18 fn from_fields(fields: syn::Fields) -> crate::Result<Self> {
19 Ok(fields)
20 }
21}
22
23impl FromFields for syn::FieldsNamed {
24 fn from_fields(fields: syn::Fields) -> crate::Result<Self> {
25 match fields {
26 syn::Fields::Named(f) => Ok(f),
27 _ => Err(Diagnostics::error(
28 Span::call_site(),
29 "expected named fields",
30 )),
31 }
32 }
33}
34
35impl FromFields for syn::FieldsUnnamed {
36 fn from_fields(fields: syn::Fields) -> crate::Result<Self> {
37 match fields {
38 syn::Fields::Unnamed(f) => Ok(f),
39 _ => Err(Diagnostics::error(
40 Span::call_site(),
41 "expected unnamed fields",
42 )),
43 }
44 }
45}
46
47pub struct Fields<T: FromFields = syn::Fields>(T);
60
61impl<T: FromFields> Fields<T> {
62 pub fn inner(self) -> T {
64 self.0
65 }
66}
67
68impl<T: FromFields> std::ops::Deref for Fields<T> {
69 type Target = T;
70
71 fn deref(&self) -> &Self::Target {
72 &self.0
73 }
74}
75
76impl<T: FromFields> std::ops::DerefMut for Fields<T> {
77 fn deref_mut(&mut self) -> &mut Self::Target {
78 &mut self.0
79 }
80}
81
82impl<T: FromFields> FromInput for Fields<T> {
83 fn from_input(input: &Input) -> crate::Result<Self> {
84 let raw = match input {
85 Input::Derive(d) => match &d.data {
86 syn::Data::Struct(s) => s.fields.clone(),
87 _ => {
88 return Err(Diagnostics::error(
89 d.ident.span(),
90 "expected struct input for Fields extractor",
91 ));
92 }
93 },
94 Input::Item(syn::Item::Struct(s)) => s.fields.clone(),
95 _ => {
96 return Err(Diagnostics::error(
97 input.span(),
98 "expected struct input for Fields extractor",
99 ));
100 }
101 };
102
103 T::from_fields(raw).map(Fields)
104 }
105}