facet_reflect/peek/
dynamic_value.rs1use facet_core::{DynDateTimeKind, DynValueKind, DynamicValueDef};
4
5use super::Peek;
6
7#[derive(Clone, Copy)]
12pub struct PeekDynamicValue<'mem, 'facet> {
13 pub(crate) value: Peek<'mem, 'facet>,
15
16 pub(crate) def: DynamicValueDef,
18}
19
20impl<'mem, 'facet> PeekDynamicValue<'mem, 'facet> {
21 #[inline(always)]
23 pub fn def(&self) -> DynamicValueDef {
24 self.def
25 }
26
27 #[inline(always)]
29 pub fn peek(&self) -> Peek<'mem, 'facet> {
30 self.value
31 }
32
33 #[inline]
35 pub fn kind(&self) -> DynValueKind {
36 unsafe { (self.def.vtable.get_kind)(self.value.data()) }
37 }
38
39 #[inline]
41 pub fn is_null(&self) -> bool {
42 self.kind() == DynValueKind::Null
43 }
44
45 #[inline]
47 pub fn as_bool(&self) -> Option<bool> {
48 unsafe { (self.def.vtable.get_bool)(self.value.data()) }
49 }
50
51 #[inline]
53 pub fn as_i64(&self) -> Option<i64> {
54 unsafe { (self.def.vtable.get_i64)(self.value.data()) }
55 }
56
57 #[inline]
59 pub fn as_u64(&self) -> Option<u64> {
60 unsafe { (self.def.vtable.get_u64)(self.value.data()) }
61 }
62
63 #[inline]
65 pub fn as_f64(&self) -> Option<f64> {
66 unsafe { (self.def.vtable.get_f64)(self.value.data()) }
67 }
68
69 #[inline]
71 pub fn as_str(&self) -> Option<&'mem str> {
72 unsafe { (self.def.vtable.get_str)(self.value.data()) }
73 }
74
75 #[inline]
77 pub fn as_bytes(&self) -> Option<&'mem [u8]> {
78 self.def
79 .vtable
80 .get_bytes
81 .and_then(|f| unsafe { f(self.value.data()) })
82 }
83
84 #[inline]
88 #[allow(clippy::type_complexity)]
89 pub fn as_datetime(&self) -> Option<(i32, u8, u8, u8, u8, u8, u32, DynDateTimeKind)> {
90 self.def
91 .vtable
92 .get_datetime
93 .and_then(|f| unsafe { f(self.value.data()) })
94 }
95
96 #[inline]
98 pub fn array_len(&self) -> Option<usize> {
99 unsafe { (self.def.vtable.array_len)(self.value.data()) }
100 }
101
102 #[inline]
104 pub fn array_get(&self, index: usize) -> Option<Peek<'mem, 'facet>> {
105 let ptr = unsafe { (self.def.vtable.array_get)(self.value.data(), index)? };
106 Some(unsafe { Peek::unchecked_new(ptr, self.value.shape()) })
108 }
109
110 #[inline]
112 pub fn object_len(&self) -> Option<usize> {
113 unsafe { (self.def.vtable.object_len)(self.value.data()) }
114 }
115
116 #[inline]
118 pub fn object_get_entry(&self, index: usize) -> Option<(&'mem str, Peek<'mem, 'facet>)> {
119 let (key, value_ptr) =
120 unsafe { (self.def.vtable.object_get_entry)(self.value.data(), index)? };
121 Some((key, unsafe {
123 Peek::unchecked_new(value_ptr, self.value.shape())
124 }))
125 }
126
127 #[inline]
129 pub fn object_get(&self, key: &str) -> Option<Peek<'mem, 'facet>> {
130 let ptr = unsafe { (self.def.vtable.object_get)(self.value.data(), key)? };
131 Some(unsafe { Peek::unchecked_new(ptr, self.value.shape()) })
133 }
134
135 #[inline]
137 pub fn array_iter(&self) -> Option<PeekDynamicValueArrayIter<'mem, 'facet>> {
138 let len = self.array_len()?;
139 Some(PeekDynamicValueArrayIter {
140 dyn_value: *self,
141 index: 0,
142 len,
143 })
144 }
145
146 #[inline]
148 pub fn object_iter(&self) -> Option<PeekDynamicValueObjectIter<'mem, 'facet>> {
149 let len = self.object_len()?;
150 Some(PeekDynamicValueObjectIter {
151 dyn_value: *self,
152 index: 0,
153 len,
154 })
155 }
156
157 pub fn structural_hash_inner<H: core::hash::Hasher>(&self, hasher: &mut H) {
161 use core::hash::Hash;
162
163 let kind = self.kind();
165 core::mem::discriminant(&kind).hash(hasher);
166
167 match kind {
168 DynValueKind::Null => {
169 }
171 DynValueKind::Bool => {
172 if let Some(b) = self.as_bool() {
173 b.hash(hasher);
174 }
175 }
176 DynValueKind::Number => {
177 if let Some(n) = self.as_i64() {
179 0u8.hash(hasher); n.hash(hasher);
181 } else if let Some(n) = self.as_u64() {
182 1u8.hash(hasher); n.hash(hasher);
184 } else if let Some(n) = self.as_f64() {
185 2u8.hash(hasher); n.to_bits().hash(hasher);
187 }
188 }
189 DynValueKind::String => {
190 if let Some(s) = self.as_str() {
191 s.hash(hasher);
192 }
193 }
194 DynValueKind::Bytes => {
195 if let Some(b) = self.as_bytes() {
196 b.hash(hasher);
197 }
198 }
199 DynValueKind::Array => {
200 if let Some(len) = self.array_len() {
201 len.hash(hasher);
202 if let Some(iter) = self.array_iter() {
203 for elem in iter {
204 elem.structural_hash(hasher);
205 }
206 }
207 }
208 }
209 DynValueKind::Object => {
210 if let Some(len) = self.object_len() {
211 len.hash(hasher);
212 if let Some(iter) = self.object_iter() {
213 for (key, value) in iter {
214 key.hash(hasher);
215 value.structural_hash(hasher);
216 }
217 }
218 }
219 }
220 DynValueKind::DateTime | DynValueKind::QName | DynValueKind::Uuid => {
221 if let Some(s) = self.as_str() {
223 s.hash(hasher);
224 }
225 }
226 }
227 }
228}
229
230pub struct PeekDynamicValueArrayIter<'mem, 'facet> {
232 dyn_value: PeekDynamicValue<'mem, 'facet>,
233 index: usize,
234 len: usize,
235}
236
237impl<'mem, 'facet> Iterator for PeekDynamicValueArrayIter<'mem, 'facet> {
238 type Item = Peek<'mem, 'facet>;
239
240 #[inline]
241 fn next(&mut self) -> Option<Self::Item> {
242 if self.index >= self.len {
243 return None;
244 }
245 let item = self.dyn_value.array_get(self.index)?;
246 self.index += 1;
247 Some(item)
248 }
249
250 #[inline]
251 fn size_hint(&self) -> (usize, Option<usize>) {
252 let remaining = self.len.saturating_sub(self.index);
253 (remaining, Some(remaining))
254 }
255}
256
257impl ExactSizeIterator for PeekDynamicValueArrayIter<'_, '_> {}
258
259pub struct PeekDynamicValueObjectIter<'mem, 'facet> {
261 dyn_value: PeekDynamicValue<'mem, 'facet>,
262 index: usize,
263 len: usize,
264}
265
266impl<'mem, 'facet> Iterator for PeekDynamicValueObjectIter<'mem, 'facet> {
267 type Item = (&'mem str, Peek<'mem, 'facet>);
268
269 #[inline]
270 fn next(&mut self) -> Option<Self::Item> {
271 if self.index >= self.len {
272 return None;
273 }
274 let entry = self.dyn_value.object_get_entry(self.index)?;
275 self.index += 1;
276 Some(entry)
277 }
278
279 #[inline]
280 fn size_hint(&self) -> (usize, Option<usize>) {
281 let remaining = self.len.saturating_sub(self.index);
282 (remaining, Some(remaining))
283 }
284}
285
286impl ExactSizeIterator for PeekDynamicValueObjectIter<'_, '_> {}
287
288impl core::fmt::Debug for PeekDynamicValue<'_, '_> {
289 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
290 f.debug_struct("PeekDynamicValue")
291 .field("kind", &self.kind())
292 .finish_non_exhaustive()
293 }
294}