facet_reflect/peek/
enum_.rs1use facet_core::{EnumDef, EnumRepr, Field, Shape, Variant};
2
3use crate::Peek;
4
5use super::HasFields;
6
7#[derive(Clone, Copy)]
9pub struct PeekEnum<'mem, 'facet_lifetime> {
10 pub(crate) value: Peek<'mem, 'facet_lifetime>,
15
16 pub(crate) def: EnumDef,
18}
19
20impl core::fmt::Debug for PeekEnum<'_, '_> {
21 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
22 if let Some(debug_fn) = self.vtable().debug {
23 unsafe { debug_fn(self.data, f) }
24 } else {
25 write!(f, "⟨{}⟩", self.shape)
26 }
27 }
28}
29
30pub fn peek_enum(shape: &'static Shape) -> Option<EnumDef> {
32 match shape.def {
33 facet_core::Def::Enum(enum_def) => Some(enum_def),
34 _ => None,
35 }
36}
37
38pub fn peek_enum_repr(shape: &'static Shape) -> Option<EnumRepr> {
40 peek_enum(shape).map(|enum_def| enum_def.repr)
41}
42
43pub fn peek_enum_variants(shape: &'static Shape) -> Option<&'static [Variant]> {
45 peek_enum(shape).map(|enum_def| enum_def.variants)
46}
47
48impl<'mem, 'facet_lifetime> core::ops::Deref for PeekEnum<'mem, 'facet_lifetime> {
49 type Target = Peek<'mem, 'facet_lifetime>;
50
51 #[inline(always)]
52 fn deref(&self) -> &Self::Target {
53 &self.value
54 }
55}
56
57impl<'mem, 'facet_lifetime> PeekEnum<'mem, 'facet_lifetime> {
58 #[inline(always)]
60 pub fn def(self) -> EnumDef {
61 self.def
62 }
63
64 #[inline(always)]
66 pub fn repr(self) -> EnumRepr {
67 self.def.repr
68 }
69
70 #[inline(always)]
72 pub fn variants(self) -> &'static [Variant] {
73 self.def.variants
74 }
75
76 #[inline(always)]
78 pub fn variant_count(self) -> usize {
79 self.def.variants.len()
80 }
81
82 #[inline(always)]
84 pub fn variant_name(self, index: usize) -> Option<&'static str> {
85 self.def.variants.get(index).map(|variant| variant.name)
86 }
87
88 #[inline]
90 pub fn discriminant(self) -> i64 {
91 unsafe {
93 let data = self.value.data();
94 match self.def.repr {
95 EnumRepr::U8 => data.read::<u8>() as i64,
96 EnumRepr::U16 => data.read::<u16>() as i64,
97 EnumRepr::U32 => data.read::<u32>() as i64,
98 EnumRepr::U64 => data.read::<u64>() as i64,
99 EnumRepr::USize => data.read::<usize>() as i64,
100 EnumRepr::I8 => data.read::<i8>() as i64,
101 EnumRepr::I16 => data.read::<i16>() as i64,
102 EnumRepr::I32 => data.read::<i32>() as i64,
103 EnumRepr::I64 => data.read::<i64>(),
104 EnumRepr::ISize => data.read::<isize>() as i64,
105 _ => {
106 data.read::<u32>() as i64
108 }
109 }
110 }
111 }
112
113 #[inline]
115 pub fn variant_index(self) -> usize {
116 let discriminant = self.discriminant();
117
118 self.def
120 .variants
121 .iter()
122 .position(|variant| variant.discriminant == discriminant)
123 .expect("No variant found with matching discriminant")
124 }
125
126 #[inline]
128 pub fn active_variant(self) -> &'static Variant {
129 let index = self.variant_index();
130 &self.def.variants[index]
131 }
132
133 #[inline]
135 pub fn variant_name_active(self) -> &'static str {
136 self.active_variant().name
137 }
138
139 pub fn field(self, index: usize) -> Option<Peek<'mem, 'facet_lifetime>> {
143 let variant = self.active_variant();
144 let fields = &variant.data.fields;
145
146 if index >= fields.len() {
147 return None;
148 }
149
150 let field = &fields[index];
151 let field_data = unsafe { self.value.data().field(field.offset) };
152 Some(unsafe { Peek::unchecked_new(field_data, field.shape()) })
153 }
154
155 pub fn field_index(self, field_name: &str) -> Option<usize> {
157 let variant = self.active_variant();
158 variant
159 .data
160 .fields
161 .iter()
162 .position(|f| f.name == field_name)
163 }
164
165 pub fn field_by_name(self, field_name: &str) -> Option<Peek<'mem, 'facet_lifetime>> {
167 let index = self.field_index(field_name)?;
168 self.field(index)
169 }
170}
171
172impl<'mem, 'facet_lifetime> HasFields<'mem, 'facet_lifetime> for PeekEnum<'mem, 'facet_lifetime> {
173 fn fields(&self) -> impl DoubleEndedIterator<Item = (Field, Peek<'mem, 'facet_lifetime>)> {
174 let variant = self.active_variant();
176 let fields = &variant.data.fields;
177
178 (0..fields.len()).filter_map(move |i| {
180 let field = fields[i];
182 let field_value = self.field(i)?;
184 Some((field, field_value))
186 })
187 }
188}