facet_reflect/peek/
fields.rs1use 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> {
15 fn fields(&self) -> FieldIter<'mem, 'facet>;
17
18 fn fields_for_serialize(&self) -> FieldsForSerializeIter<'mem, 'facet> {
20 FieldsForSerializeIter {
21 stack: vec![self.fields()],
22 }
23 }
24}
25
26pub struct FieldIter<'mem, 'facet> {
28 state: FieldIterState<'mem, 'facet>,
29 range: Range<usize>,
30}
31
32enum FieldIterState<'mem, 'facet> {
33 Struct(PeekStruct<'mem, 'facet>),
34 Tuple(PeekTuple<'mem, 'facet>),
35 Enum {
36 peek_enum: PeekEnum<'mem, 'facet>,
37 fields: &'static [Field],
38 },
39 FlattenedEnum {
40 field: Field,
41 value: Peek<'mem, 'facet>,
42 },
43}
44
45impl<'mem, 'facet> FieldIter<'mem, 'facet> {
46 #[inline]
47 pub(crate) fn new_struct(struct_: PeekStruct<'mem, 'facet>) -> 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>) -> 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>) -> Self {
74 Self {
75 range: 0..tuple.len(),
76 state: FieldIterState::Tuple(tuple),
77 }
78 }
79
80 fn get_field_by_index(&self, index: usize) -> Option<(Field, Peek<'mem, 'facet>)> {
81 match self.state {
82 FieldIterState::Struct(peek_struct) => {
83 let field = peek_struct.ty.fields.get(index).copied()?;
84 let value = peek_struct.field(index).ok()?;
85 Some((field, value))
86 }
87 FieldIterState::Tuple(peek_tuple) => {
88 let field = peek_tuple.ty.fields.get(index).copied()?;
89 let value = peek_tuple.field(index)?;
90 Some((field, value))
91 }
92 FieldIterState::Enum { peek_enum, fields } => {
93 let field = fields[index];
95 let field_value = match peek_enum.field(index) {
97 Ok(Some(v)) => v,
98 Ok(None) => return None,
99 Err(e) => panic!("Cannot get field: {e:?}"),
100 };
101 Some((field, field_value))
103 }
104 FieldIterState::FlattenedEnum { field, value } => {
105 if index == 0 {
106 Some((field, value))
107 } else {
108 None
109 }
110 }
111 }
112 }
113}
114
115impl<'mem, 'facet> Iterator for FieldIter<'mem, 'facet> {
116 type Item = (Field, Peek<'mem, 'facet>);
117
118 #[inline]
119 fn next(&mut self) -> Option<Self::Item> {
120 loop {
121 let index = self.range.next()?;
122
123 let Some(field) = self.get_field_by_index(index) else {
124 continue;
125 };
126
127 return Some(field);
128 }
129 }
130
131 #[inline]
132 fn size_hint(&self) -> (usize, Option<usize>) {
133 self.range.size_hint()
134 }
135}
136
137impl DoubleEndedIterator for FieldIter<'_, '_> {
138 #[inline]
139 fn next_back(&mut self) -> Option<Self::Item> {
140 loop {
141 let index = self.range.next_back()?;
142
143 let Some(field) = self.get_field_by_index(index) else {
144 continue;
145 };
146
147 return Some(field);
148 }
149 }
150}
151
152impl ExactSizeIterator for FieldIter<'_, '_> {}
153
154pub struct FieldsForSerializeIter<'mem, 'facet> {
156 stack: Vec<FieldIter<'mem, 'facet>>,
157}
158
159impl<'mem, 'facet> Iterator for FieldsForSerializeIter<'mem, 'facet> {
160 type Item = (Field, Peek<'mem, 'facet>);
161
162 fn next(&mut self) -> Option<Self::Item> {
163 loop {
164 let mut fields = self.stack.pop()?;
165 let Some((mut field, peek)) = fields.next() else {
166 continue;
167 };
168 self.stack.push(fields);
169
170 let data = peek.data();
171 let should_skip = unsafe { field.should_skip_serializing(data) };
172
173 if should_skip {
174 continue;
175 }
176
177 if field.flags.contains(FieldFlags::FLATTEN) && !field.flattened {
178 if let Ok(struct_peek) = peek.into_struct() {
179 self.stack.push(FieldIter::new_struct(struct_peek))
180 } else if let Ok(enum_peek) = peek.into_enum() {
181 field.name = enum_peek
195 .active_variant()
196 .expect("Failed to get active variant")
197 .name;
198 field.flattened = true;
199 self.stack.push(FieldIter {
200 range: 0..1,
201 state: FieldIterState::FlattenedEnum { field, value: peek },
202 });
203 } else if let Ok(option_peek) = peek.into_option() {
204 if let Some(inner_peek) = option_peek.value() {
207 if let Ok(struct_peek) = inner_peek.into_struct() {
208 self.stack.push(FieldIter::new_struct(struct_peek))
209 } else if let Ok(enum_peek) = inner_peek.into_enum() {
210 field.name = enum_peek
211 .active_variant()
212 .expect("Failed to get active variant")
213 .name;
214 field.flattened = true;
215 self.stack.push(FieldIter {
216 range: 0..1,
217 state: FieldIterState::FlattenedEnum {
218 field,
219 value: inner_peek,
220 },
221 });
222 } else {
223 panic!(
224 "cannot flatten Option<{}> - inner type must be struct or enum",
225 inner_peek.shape()
226 )
227 }
228 }
229 } else {
231 panic!("cannot flatten a {}", field.shape())
233 }
234 } else {
235 return Some((field, peek));
236 }
237 }
238 }
239}