1use core::ops::Range;
2
3use facet_core::Field;
4
5use crate::Peek;
6use alloc::{vec, vec::Vec};
7
8use super::{PeekEnum, PeekStruct, PeekTuple};
9
10#[derive(Clone, Copy, Debug)]
15pub struct FieldItem {
16 pub field: Field,
18 pub name: &'static str,
20 pub flattened: bool,
22}
23
24impl FieldItem {
25 #[inline]
27 pub fn new(field: Field) -> Self {
28 Self {
29 name: field.name,
30 field,
31 flattened: false,
32 }
33 }
34
35 #[inline]
37 pub fn flattened_enum(field: Field, variant_name: &'static str) -> Self {
38 Self {
39 name: variant_name,
40 field,
41 flattened: true,
42 }
43 }
44}
45
46pub trait HasFields<'mem, 'facet> {
51 fn fields(&self) -> FieldIter<'mem, 'facet>;
53
54 fn fields_for_serialize(&self) -> FieldsForSerializeIter<'mem, 'facet> {
56 FieldsForSerializeIter {
57 stack: vec![FieldsForSerializeIterState::Fields(self.fields())],
58 }
59 }
60}
61
62pub struct FieldIter<'mem, 'facet> {
64 state: FieldIterState<'mem, 'facet>,
65 range: Range<usize>,
66}
67
68enum FieldIterState<'mem, 'facet> {
69 Struct(PeekStruct<'mem, 'facet>),
70 Tuple(PeekTuple<'mem, 'facet>),
71 Enum {
72 peek_enum: PeekEnum<'mem, 'facet>,
73 fields: &'static [Field],
74 },
75}
76
77impl<'mem, 'facet> FieldIter<'mem, 'facet> {
78 #[inline]
79 pub(crate) fn new_struct(struct_: PeekStruct<'mem, 'facet>) -> Self {
80 Self {
81 range: 0..struct_.ty.fields.len(),
82 state: FieldIterState::Struct(struct_),
83 }
84 }
85
86 #[inline]
87 pub(crate) fn new_enum(enum_: PeekEnum<'mem, 'facet>) -> Self {
88 let variant = match enum_.active_variant() {
90 Ok(v) => v,
91 Err(e) => panic!("Cannot get active variant: {e:?}"),
92 };
93 let fields = &variant.data.fields;
94
95 Self {
96 range: 0..fields.len(),
97 state: FieldIterState::Enum {
98 peek_enum: enum_,
99 fields,
100 },
101 }
102 }
103
104 #[inline]
105 pub(crate) fn new_tuple(tuple: PeekTuple<'mem, 'facet>) -> Self {
106 Self {
107 range: 0..tuple.len(),
108 state: FieldIterState::Tuple(tuple),
109 }
110 }
111
112 fn get_field_by_index(&self, index: usize) -> Option<(Field, Peek<'mem, 'facet>)> {
113 match self.state {
114 FieldIterState::Struct(peek_struct) => {
115 let field = peek_struct.ty.fields.get(index).copied()?;
116 let value = peek_struct.field(index).ok()?;
117 Some((field, value))
118 }
119 FieldIterState::Tuple(peek_tuple) => {
120 let field = peek_tuple.ty.fields.get(index).copied()?;
121 let value = peek_tuple.field(index)?;
122 Some((field, value))
123 }
124 FieldIterState::Enum { peek_enum, fields } => {
125 let field = fields[index];
127 let field_value = match peek_enum.field(index) {
129 Ok(Some(v)) => v,
130 Ok(None) => return None,
131 Err(e) => panic!("Cannot get field: {e:?}"),
132 };
133 Some((field, field_value))
135 }
136 }
137 }
138}
139
140impl<'mem, 'facet> Iterator for FieldIter<'mem, 'facet> {
141 type Item = (Field, Peek<'mem, 'facet>);
142
143 #[inline]
144 fn next(&mut self) -> Option<Self::Item> {
145 loop {
146 let index = self.range.next()?;
147
148 let Some(field) = self.get_field_by_index(index) else {
149 continue;
150 };
151
152 return Some(field);
153 }
154 }
155
156 #[inline]
157 fn size_hint(&self) -> (usize, Option<usize>) {
158 self.range.size_hint()
159 }
160}
161
162impl DoubleEndedIterator for FieldIter<'_, '_> {
163 #[inline]
164 fn next_back(&mut self) -> Option<Self::Item> {
165 loop {
166 let index = self.range.next_back()?;
167
168 let Some(field) = self.get_field_by_index(index) else {
169 continue;
170 };
171
172 return Some(field);
173 }
174 }
175}
176
177impl ExactSizeIterator for FieldIter<'_, '_> {}
178
179pub struct FieldsForSerializeIter<'mem, 'facet> {
181 stack: Vec<FieldsForSerializeIterState<'mem, 'facet>>,
182}
183
184enum FieldsForSerializeIterState<'mem, 'facet> {
185 Fields(FieldIter<'mem, 'facet>),
187 FlattenedEnum {
189 field_item: Option<FieldItem>,
190 value: Peek<'mem, 'facet>,
191 },
192}
193
194impl<'mem, 'facet> Iterator for FieldsForSerializeIter<'mem, 'facet> {
195 type Item = (FieldItem, Peek<'mem, 'facet>);
196
197 fn next(&mut self) -> Option<Self::Item> {
198 loop {
199 let state = self.stack.pop()?;
200
201 match state {
202 FieldsForSerializeIterState::FlattenedEnum { field_item, value } => {
203 if let Some(item) = field_item {
205 return Some((item, value));
206 }
207 continue;
209 }
210 FieldsForSerializeIterState::Fields(mut fields) => {
211 let Some((field, peek)) = fields.next() else {
212 continue;
213 };
214 self.stack.push(FieldsForSerializeIterState::Fields(fields));
215
216 let data = peek.data();
217 let should_skip = unsafe { field.should_skip_serializing(data) };
218
219 if should_skip {
220 continue;
221 }
222
223 if field.is_flattened() {
224 if let Ok(struct_peek) = peek.into_struct() {
225 self.stack.push(FieldsForSerializeIterState::Fields(
226 FieldIter::new_struct(struct_peek),
227 ))
228 } else if let Ok(enum_peek) = peek.into_enum() {
229 let variant_name = enum_peek
243 .active_variant()
244 .expect("Failed to get active variant")
245 .name;
246 let field_item = FieldItem::flattened_enum(field, variant_name);
247 self.stack.push(FieldsForSerializeIterState::FlattenedEnum {
248 field_item: Some(field_item),
249 value: peek,
250 });
251 } else if let Ok(option_peek) = peek.into_option() {
252 if let Some(inner_peek) = option_peek.value() {
255 if let Ok(struct_peek) = inner_peek.into_struct() {
256 self.stack.push(FieldsForSerializeIterState::Fields(
257 FieldIter::new_struct(struct_peek),
258 ))
259 } else if let Ok(enum_peek) = inner_peek.into_enum() {
260 let variant_name = enum_peek
261 .active_variant()
262 .expect("Failed to get active variant")
263 .name;
264 let field_item = FieldItem::flattened_enum(field, variant_name);
265 self.stack.push(FieldsForSerializeIterState::FlattenedEnum {
266 field_item: Some(field_item),
267 value: inner_peek,
268 });
269 } else {
270 panic!(
271 "cannot flatten Option<{}> - inner type must be struct or enum",
272 inner_peek.shape()
273 )
274 }
275 }
276 } else {
278 panic!("cannot flatten a {}", field.shape())
280 }
281 } else {
282 return Some((FieldItem::new(field), peek));
283 }
284 }
285 }
286 }
287 }
288}