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