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 {
63 self.0
64 }
65}
66
67impl<T: FromFields> std::ops::Deref for Fields<T> {
68 type Target = T;
69
70 fn deref(&self) -> &Self::Target {
71 &self.0
72 }
73}
74
75impl<T: FromFields> std::ops::DerefMut for Fields<T> {
76 fn deref_mut(&mut self) -> &mut Self::Target {
77 &mut self.0
78 }
79}
80
81impl<T: FromFields> FromInput for Fields<T> {
82 fn from_input(input: &Input) -> crate::Result<Self> {
83 let raw = match input {
84 Input::Derive(d) => match &d.data {
85 syn::Data::Struct(s) => s.fields.clone(),
86 _ => {
87 return Err(Diagnostics::error(
88 d.ident.span(),
89 "expected struct input for Fields extractor",
90 ));
91 }
92 },
93 Input::Item(syn::Item::Struct(s)) => s.fields.clone(),
94 _ => {
95 return Err(Diagnostics::error(
96 input.span(),
97 "expected struct input for Fields extractor",
98 ));
99 }
100 };
101
102 T::from_fields(raw).map(Fields)
103 }
104}