1use core::ops::Range;
2
3use facet_core::{Field, FieldFlags};
4
5use crate::Peek;
6use alloc::{vec, vec::Vec};
7
8use super::{PeekEnum, PeekStruct, PeekTuple};
9
10pub trait HasFields<'mem, 'facet, 'shape> {
15 fn fields(&self) -> FieldIter<'mem, 'facet, 'shape>;
17
18 fn fields_for_serialize(&self) -> FieldsForSerializeIter<'mem, 'facet, 'shape> {
20 FieldsForSerializeIter {
21 stack: vec![self.fields()],
22 }
23 }
24}
25
26pub struct FieldIter<'mem, 'facet, 'shape> {
28 state: FieldIterState<'mem, 'facet, 'shape>,
29 range: Range<usize>,
30}
31
32enum FieldIterState<'mem, 'facet, 'shape> {
33 Struct(PeekStruct<'mem, 'facet, 'shape>),
34 Tuple(PeekTuple<'mem, 'facet, 'shape>),
35 Enum {
36 peek_enum: PeekEnum<'mem, 'facet, 'shape>,
37 fields: &'shape [Field<'shape>],
38 },
39 FlattenedEnum {
40 field: Field<'shape>,
41 value: Peek<'mem, 'facet, 'shape>,
42 },
43}
44
45impl<'mem, 'facet, 'shape> FieldIter<'mem, 'facet, 'shape> {
46 #[inline]
47 pub(crate) fn new_struct(struct_: PeekStruct<'mem, 'facet, 'shape>) -> Self {
48 Self {
49 range: 0..struct_.ty.fields.len(),
50 state: FieldIterState::Struct(struct_),
51 }
52 }
53
54 #[inline]
55 pub(crate) fn new_enum(enum_: PeekEnum<'mem, 'facet, 'shape>) -> Self {
56 let variant = match enum_.active_variant() {
58 Ok(v) => v,
59 Err(e) => panic!("Cannot get active variant: {e:?}"),
60 };
61 let fields = &variant.data.fields;
62
63 Self {
64 range: 0..fields.len(),
65 state: FieldIterState::Enum {
66 peek_enum: enum_,
67 fields,
68 },
69 }
70 }
71
72 #[inline]
73 pub(crate) fn new_tuple(tuple: PeekTuple<'mem, 'facet, 'shape>) -> Self {
74 Self {
75 range: 0..tuple.len(),
76 state: FieldIterState::Tuple(tuple),
77 }
78 }
79
80 fn get_field_by_index(
81 &self,
82 index: usize,
83 ) -> Option<(Field<'shape>, Peek<'mem, 'facet, 'shape>)> {
84 match self.state {
85 FieldIterState::Struct(peek_struct) => {
86 let field = peek_struct.ty.fields.get(index).copied()?;
87 let value = peek_struct.field(index).ok()?;
88 Some((field, value))
89 }
90 FieldIterState::Tuple(peek_tuple) => {
91 let field = peek_tuple.ty.fields.get(index).copied()?;
92 let value = peek_tuple.field(index)?;
93 Some((field, value))
94 }
95 FieldIterState::Enum { peek_enum, fields } => {
96 let field = fields[index];
98 let field_value = match peek_enum.field(index) {
100 Ok(Some(v)) => v,
101 Ok(None) => return None,
102 Err(e) => panic!("Cannot get field: {e:?}"),
103 };
104 Some((field, field_value))
106 }
107 FieldIterState::FlattenedEnum { field, value } => {
108 if index == 0 {
109 Some((field, value))
110 } else {
111 None
112 }
113 }
114 }
115 }
116}
117
118impl<'mem, 'facet, 'shape> Iterator for FieldIter<'mem, 'facet, 'shape> {
119 type Item = (Field<'shape>, Peek<'mem, 'facet, 'shape>);
120
121 #[inline]
122 fn next(&mut self) -> Option<Self::Item> {
123 loop {
124 let index = self.range.next()?;
125
126 let Some(field) = self.get_field_by_index(index) else {
127 continue;
128 };
129
130 return Some(field);
131 }
132 }
133
134 #[inline]
135 fn size_hint(&self) -> (usize, Option<usize>) {
136 self.range.size_hint()
137 }
138}
139
140impl DoubleEndedIterator for FieldIter<'_, '_, '_> {
141 #[inline]
142 fn next_back(&mut self) -> Option<Self::Item> {
143 loop {
144 let index = self.range.next_back()?;
145
146 let Some(field) = self.get_field_by_index(index) else {
147 continue;
148 };
149
150 return Some(field);
151 }
152 }
153}
154
155impl ExactSizeIterator for FieldIter<'_, '_, '_> {}
156
157pub struct FieldsForSerializeIter<'mem, 'facet, 'shape> {
159 stack: Vec<FieldIter<'mem, 'facet, 'shape>>,
160}
161
162impl<'mem, 'facet, 'shape> Iterator for FieldsForSerializeIter<'mem, 'facet, 'shape> {
163 type Item = (Field<'shape>, Peek<'mem, 'facet, 'shape>);
164
165 fn next(&mut self) -> Option<Self::Item> {
166 loop {
167 let mut fields = self.stack.pop()?;
168 let Some((mut field, peek)) = fields.next() else {
169 continue;
170 };
171 self.stack.push(fields);
172
173 let Some(data) = peek.data().thin() else {
174 continue;
175 };
176 let should_skip = unsafe { field.should_skip_serializing(data) };
177
178 if should_skip {
179 continue;
180 }
181
182 if field.flags.contains(FieldFlags::FLATTEN) && !field.flattened {
183 if let Ok(struct_peek) = peek.into_struct() {
184 self.stack.push(FieldIter::new_struct(struct_peek))
185 } else if let Ok(enum_peek) = peek.into_enum() {
186 field.name = enum_peek
200 .active_variant()
201 .expect("Failed to get active variant")
202 .name;
203 field.flattened = true;
204 self.stack.push(FieldIter {
205 range: 0..1,
206 state: FieldIterState::FlattenedEnum { field, value: peek },
207 });
208 } else {
209 panic!("cannot flatten a {}", field.shape())
211 }
212 } else {
213 return Some((field, peek));
214 }
215 }
216 }
217}