facet_reflect/peek/
enum_.rs1use facet_core::{EnumDef, EnumRepr, Shape, Variant};
2
3#[derive(Clone, Copy)]
5pub struct PeekEnum<'mem> {
6 pub(crate) value: crate::Peek<'mem>,
11
12 pub(crate) def: EnumDef,
14}
15
16pub fn peek_enum(shape: &'static Shape) -> Option<EnumDef> {
18 match shape.def {
19 facet_core::Def::Enum(enum_def) => Some(enum_def),
20 _ => None,
21 }
22}
23
24pub fn peek_enum_repr(shape: &'static Shape) -> Option<EnumRepr> {
26 peek_enum(shape).map(|enum_def| enum_def.repr)
27}
28
29pub fn peek_enum_variants(shape: &'static Shape) -> Option<&'static [Variant]> {
31 peek_enum(shape).map(|enum_def| enum_def.variants)
32}
33
34impl<'mem> core::ops::Deref for PeekEnum<'mem> {
35 type Target = crate::Peek<'mem>;
36
37 #[inline(always)]
38 fn deref(&self) -> &Self::Target {
39 &self.value
40 }
41}
42
43impl<'mem> PeekEnum<'mem> {
44 #[inline(always)]
46 pub fn def(self) -> EnumDef {
47 self.def
48 }
49
50 #[inline(always)]
52 pub fn repr(self) -> EnumRepr {
53 self.def.repr
54 }
55
56 #[inline(always)]
58 pub fn variants(self) -> &'static [Variant] {
59 self.def.variants
60 }
61
62 #[inline(always)]
64 pub fn variant_count(self) -> usize {
65 self.def.variants.len()
66 }
67
68 #[inline(always)]
70 pub fn variant_name(self, index: usize) -> Option<&'static str> {
71 self.def.variants.get(index).map(|variant| variant.name)
72 }
73
74 #[inline]
76 pub fn discriminant(self) -> i64 {
77 unsafe {
79 let data = self.value.data();
80 match self.def.repr {
81 EnumRepr::U8 => data.read::<u8>() as i64,
82 EnumRepr::U16 => data.read::<u16>() as i64,
83 EnumRepr::U32 => data.read::<u32>() as i64,
84 EnumRepr::U64 => data.read::<u64>() as i64,
85 EnumRepr::USize => data.read::<usize>() as i64,
86 EnumRepr::I8 => data.read::<i8>() as i64,
87 EnumRepr::I16 => data.read::<i16>() as i64,
88 EnumRepr::I32 => data.read::<i32>() as i64,
89 EnumRepr::I64 => data.read::<i64>(),
90 EnumRepr::ISize => data.read::<isize>() as i64,
91 _ => {
92 data.read::<u32>() as i64
94 }
95 }
96 }
97 }
98
99 #[inline]
101 pub fn variant_index(self) -> usize {
102 let discriminant = self.discriminant();
103
104 self.def
106 .variants
107 .iter()
108 .position(|variant| variant.discriminant == discriminant)
109 .expect("No variant found with matching discriminant")
110 }
111
112 #[inline]
114 pub fn active_variant(self) -> &'static Variant {
115 let index = self.variant_index();
116 &self.def.variants[index]
117 }
118
119 #[inline]
121 pub fn variant_name_active(self) -> &'static str {
122 self.active_variant().name
123 }
124
125 pub fn field(self, index: usize) -> Option<crate::Peek<'mem>> {
129 let variant = self.active_variant();
130 let fields = &variant.data.fields;
131
132 if index >= fields.len() {
133 return None;
134 }
135
136 let field = &fields[index];
137 let field_data = unsafe { self.value.data().field(field.offset) };
138 Some(crate::Peek {
139 data: field_data,
140 shape: field.shape(),
141 })
142 }
143
144 pub fn field_index(self, field_name: &str) -> Option<usize> {
146 let variant = self.active_variant();
147 variant
148 .data
149 .fields
150 .iter()
151 .position(|f| f.name == field_name)
152 }
153
154 pub fn field_by_name(self, field_name: &str) -> Option<crate::Peek<'mem>> {
156 let index = self.field_index(field_name)?;
157 self.field(index)
158 }
159
160 #[inline]
162 pub fn fields(self) -> impl Iterator<Item = (&'static facet_core::Field, crate::Peek<'mem>)> {
163 let variant = self.active_variant();
164 let fields = &variant.data.fields;
165
166 fields.iter().map(move |field| {
168 let field_data = unsafe { self.value.data().field(field.offset) };
169 let peek = crate::Peek {
170 data: field_data,
171 shape: field.shape(),
172 };
173 (field, peek)
174 })
175 }
176}