1use core::ops::Range;
2
3use alloc::borrow::Cow;
4use facet_core::Field;
5
6use crate::Peek;
7use alloc::{string::String, vec, vec::Vec};
8
9use super::{PeekEnum, PeekStruct, PeekTuple};
10
11#[derive(Clone, Debug)]
17pub struct FieldItem {
18 pub field: Option<Field>,
20 pub name: Cow<'static, str>,
22 pub flattened: bool,
24}
25
26impl FieldItem {
27 #[inline]
29 pub fn new(field: Field) -> Self {
30 Self {
31 name: Cow::Borrowed(field.name),
32 field: Some(field),
33 flattened: false,
34 }
35 }
36
37 #[inline]
39 pub fn flattened_enum(field: Field, variant_name: &'static str) -> Self {
40 Self {
41 name: Cow::Borrowed(variant_name),
42 field: Some(field),
43 flattened: true,
44 }
45 }
46
47 #[inline]
49 pub fn flattened_map_entry(key: String) -> Self {
50 Self {
51 name: Cow::Owned(key),
52 field: None,
53 flattened: true,
54 }
55 }
56}
57
58pub trait HasFields<'mem, 'facet> {
63 fn fields(&self) -> FieldIter<'mem, 'facet>;
65
66 fn fields_for_serialize(&self) -> FieldsForSerializeIter<'mem, 'facet> {
68 FieldsForSerializeIter {
69 stack: vec![FieldsForSerializeIterState::Fields(self.fields())],
70 }
71 }
72}
73
74pub struct FieldIter<'mem, 'facet> {
76 state: FieldIterState<'mem, 'facet>,
77 range: Range<usize>,
78}
79
80enum FieldIterState<'mem, 'facet> {
81 Struct(PeekStruct<'mem, 'facet>),
82 Tuple(PeekTuple<'mem, 'facet>),
83 Enum {
84 peek_enum: PeekEnum<'mem, 'facet>,
85 fields: &'static [Field],
86 },
87}
88
89impl<'mem, 'facet> FieldIter<'mem, 'facet> {
90 #[inline]
91 pub(crate) fn new_struct(struct_: PeekStruct<'mem, 'facet>) -> Self {
92 Self {
93 range: 0..struct_.ty.fields.len(),
94 state: FieldIterState::Struct(struct_),
95 }
96 }
97
98 #[inline]
99 pub(crate) fn new_enum(enum_: PeekEnum<'mem, 'facet>) -> Self {
100 let variant = match enum_.active_variant() {
102 Ok(v) => v,
103 Err(e) => panic!("Cannot get active variant: {e:?}"),
104 };
105 let fields = &variant.data.fields;
106
107 Self {
108 range: 0..fields.len(),
109 state: FieldIterState::Enum {
110 peek_enum: enum_,
111 fields,
112 },
113 }
114 }
115
116 #[inline]
117 pub(crate) fn new_tuple(tuple: PeekTuple<'mem, 'facet>) -> Self {
118 Self {
119 range: 0..tuple.len(),
120 state: FieldIterState::Tuple(tuple),
121 }
122 }
123
124 fn get_field_by_index(&self, index: usize) -> Option<(Field, Peek<'mem, 'facet>)> {
125 match self.state {
126 FieldIterState::Struct(peek_struct) => {
127 let field = peek_struct.ty.fields.get(index).copied()?;
128 let value = peek_struct.field(index).ok()?;
129 Some((field, value))
130 }
131 FieldIterState::Tuple(peek_tuple) => {
132 let field = peek_tuple.ty.fields.get(index).copied()?;
133 let value = peek_tuple.field(index)?;
134 Some((field, value))
135 }
136 FieldIterState::Enum { peek_enum, fields } => {
137 let field = fields[index];
139 let field_value = match peek_enum.field(index) {
141 Ok(Some(v)) => v,
142 Ok(None) => return None,
143 Err(e) => panic!("Cannot get field: {e:?}"),
144 };
145 Some((field, field_value))
147 }
148 }
149 }
150}
151
152impl<'mem, 'facet> Iterator for FieldIter<'mem, 'facet> {
153 type Item = (Field, Peek<'mem, 'facet>);
154
155 #[inline]
156 fn next(&mut self) -> Option<Self::Item> {
157 loop {
158 let index = self.range.next()?;
159
160 let Some(field) = self.get_field_by_index(index) else {
161 continue;
162 };
163
164 return Some(field);
165 }
166 }
167
168 #[inline]
169 fn size_hint(&self) -> (usize, Option<usize>) {
170 self.range.size_hint()
171 }
172}
173
174impl DoubleEndedIterator for FieldIter<'_, '_> {
175 #[inline]
176 fn next_back(&mut self) -> Option<Self::Item> {
177 loop {
178 let index = self.range.next_back()?;
179
180 let Some(field) = self.get_field_by_index(index) else {
181 continue;
182 };
183
184 return Some(field);
185 }
186 }
187}
188
189impl ExactSizeIterator for FieldIter<'_, '_> {}
190
191pub struct FieldsForSerializeIter<'mem, 'facet> {
193 stack: Vec<FieldsForSerializeIterState<'mem, 'facet>>,
194}
195
196enum FieldsForSerializeIterState<'mem, 'facet> {
197 Fields(FieldIter<'mem, 'facet>),
199 FlattenedEnum {
201 field_item: Option<FieldItem>,
202 value: Peek<'mem, 'facet>,
203 },
204 FlattenedMap {
206 map_iter: super::PeekMapIter<'mem, 'facet>,
207 },
208}
209
210impl<'mem, 'facet> Iterator for FieldsForSerializeIter<'mem, 'facet> {
211 type Item = (FieldItem, Peek<'mem, 'facet>);
212
213 fn next(&mut self) -> Option<Self::Item> {
214 loop {
215 let state = self.stack.pop()?;
216
217 match state {
218 FieldsForSerializeIterState::FlattenedEnum { field_item, value } => {
219 if let Some(item) = field_item {
221 return Some((item, value));
222 }
223 continue;
225 }
226 FieldsForSerializeIterState::FlattenedMap { mut map_iter } => {
227 if let Some((key_peek, value_peek)) = map_iter.next() {
229 self.stack
231 .push(FieldsForSerializeIterState::FlattenedMap { map_iter });
232 if let Ok(key_str) = key_peek.get::<String>() {
234 let field_item = FieldItem::flattened_map_entry(key_str.clone());
235 return Some((field_item, value_peek));
236 }
237 continue;
239 }
240 continue;
242 }
243 FieldsForSerializeIterState::Fields(mut fields) => {
244 let Some((field, peek)) = fields.next() else {
245 continue;
246 };
247 self.stack.push(FieldsForSerializeIterState::Fields(fields));
248
249 let data = peek.data();
250 let should_skip = unsafe { field.should_skip_serializing(data) };
251
252 if should_skip {
253 continue;
254 }
255
256 if field.is_flattened() {
257 if let Ok(struct_peek) = peek.into_struct() {
258 self.stack.push(FieldsForSerializeIterState::Fields(
259 FieldIter::new_struct(struct_peek),
260 ))
261 } else if let Ok(enum_peek) = peek.into_enum() {
262 let variant_name = enum_peek
276 .active_variant()
277 .expect("Failed to get active variant")
278 .name;
279 let field_item = FieldItem::flattened_enum(field, variant_name);
280 self.stack.push(FieldsForSerializeIterState::FlattenedEnum {
281 field_item: Some(field_item),
282 value: peek,
283 });
284 } else if let Ok(map_peek) = peek.into_map() {
285 self.stack.push(FieldsForSerializeIterState::FlattenedMap {
287 map_iter: map_peek.iter(),
288 });
289 } else if let Ok(option_peek) = peek.into_option() {
290 if let Some(inner_peek) = option_peek.value() {
293 if let Ok(struct_peek) = inner_peek.into_struct() {
294 self.stack.push(FieldsForSerializeIterState::Fields(
295 FieldIter::new_struct(struct_peek),
296 ))
297 } else if let Ok(enum_peek) = inner_peek.into_enum() {
298 let variant_name = enum_peek
299 .active_variant()
300 .expect("Failed to get active variant")
301 .name;
302 let field_item = FieldItem::flattened_enum(field, variant_name);
303 self.stack.push(FieldsForSerializeIterState::FlattenedEnum {
304 field_item: Some(field_item),
305 value: inner_peek,
306 });
307 } else if let Ok(map_peek) = inner_peek.into_map() {
308 self.stack.push(FieldsForSerializeIterState::FlattenedMap {
309 map_iter: map_peek.iter(),
310 });
311 } else {
312 panic!(
313 "cannot flatten Option<{}> - inner type must be struct, enum, or map",
314 inner_peek.shape()
315 )
316 }
317 }
318 } else {
320 panic!("cannot flatten a {}", field.shape())
322 }
323 } else {
324 return Some((FieldItem::new(field), peek));
325 }
326 }
327 }
328 }
329 }
330}