1use core::{cmp::Ordering, marker::PhantomData};
2use facet_core::{
3 Def, Facet, PointerType, PtrConst, PtrMut, Shape, StructKind, Type, TypeNameOpts, UserType,
4 ValueVTable,
5};
6
7use crate::{ReflectError, ScalarType};
8
9use super::{
10 ListLikeDef, PeekEnum, PeekList, PeekListLike, PeekMap, PeekSmartPointer, PeekStruct,
11 PeekTuple, tuple::TupleType,
12};
13
14#[derive(Clone, Copy, PartialEq, Eq, Hash)]
16pub struct ValueId<'shape> {
17 pub(crate) shape: &'shape Shape<'shape>,
18 pub(crate) ptr: *const u8,
19}
20
21impl<'shape> ValueId<'shape> {
22 pub(crate) fn new(shape: &'shape Shape<'shape>, ptr: *const u8) -> Self {
23 Self { shape, ptr }
24 }
25}
26
27impl core::fmt::Display for ValueId<'_> {
28 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
29 write!(f, "{}@{:p}", self.shape, self.ptr)
30 }
31}
32
33impl core::fmt::Debug for ValueId<'_> {
34 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
35 core::fmt::Display::fmt(self, f)
36 }
37}
38
39#[derive(Clone, Copy)]
41pub struct Peek<'mem, 'facet, 'shape> {
42 pub(crate) data: PtrConst<'mem>,
44
45 pub(crate) shape: &'shape Shape<'shape>,
47
48 invariant: PhantomData<fn(&'facet ()) -> &'facet ()>,
49}
50
51impl<'mem, 'facet, 'shape> Peek<'mem, 'facet, 'shape> {
52 pub fn new<T: Facet<'facet>>(t: &'mem T) -> Self {
54 Self {
55 data: PtrConst::new(t as *const T),
56 shape: T::SHAPE,
57 invariant: PhantomData,
58 }
59 }
60
61 pub unsafe fn unchecked_new(data: PtrConst<'mem>, shape: &'shape Shape<'shape>) -> Self {
69 Self {
70 data,
71 shape,
72 invariant: PhantomData,
73 }
74 }
75
76 #[inline(always)]
78 pub fn vtable(&self) -> &'shape ValueVTable {
79 self.shape.vtable
80 }
81
82 pub fn id(&self) -> ValueId<'shape> {
84 ValueId::new(self.shape, self.data.as_byte_ptr())
85 }
86
87 #[inline]
89 pub fn ptr_eq(&self, other: &Peek<'_, '_, '_>) -> bool {
90 self.data.as_byte_ptr() == other.data.as_byte_ptr()
91 }
92
93 #[inline]
99 pub fn partial_eq(&self, other: &Peek<'_, '_, '_>) -> Option<bool> {
100 unsafe { (self.shape.vtable.partial_eq)().map(|eq_fn| eq_fn(self.data, other.data)) }
101 }
102
103 #[inline]
109 pub fn partial_cmp(&self, other: &Peek<'_, '_, '_>) -> Option<Ordering> {
110 unsafe {
111 (self.shape.vtable.partial_ord)()
112 .and_then(|partial_ord_fn| partial_ord_fn(self.data, other.data))
113 }
114 }
115
116 #[inline(always)]
122 pub fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) -> bool {
123 unsafe {
124 if let Some(hash_fn) = (self.shape.vtable.hash)() {
125 let hasher_opaque = PtrMut::new(hasher);
126 hash_fn(self.data, hasher_opaque, |opaque, bytes| {
127 opaque.as_mut::<H>().write(bytes)
128 });
129 true
130 } else {
131 false
132 }
133 }
134 }
135
136 #[inline(always)]
147 pub fn type_name(
148 &self,
149 f: &mut core::fmt::Formatter<'_>,
150 opts: TypeNameOpts,
151 ) -> core::fmt::Result {
152 (self.shape.vtable.type_name)(f, opts)
153 }
154
155 #[inline(always)]
157 pub const fn shape(&self) -> &'shape Shape<'shape> {
158 self.shape
159 }
160
161 #[inline(always)]
163 pub const fn data(&self) -> PtrConst<'mem> {
164 self.data
165 }
166
167 pub fn scalar_type(&self) -> Option<ScalarType> {
169 ScalarType::try_from_shape(self.shape)
170 }
171
172 pub fn get<T: Facet<'facet>>(&self) -> Result<&T, ReflectError<'shape>> {
178 if self.shape != T::SHAPE {
179 Err(ReflectError::WrongShape {
180 expected: self.shape,
181 actual: T::SHAPE,
182 })
183 } else {
184 Ok(unsafe { self.data.get::<T>() })
185 }
186 }
187
188 pub fn as_str(&self) -> Option<&'mem str> {
191 let peek = self.innermost_peek();
192 if let Some(ScalarType::Str) = peek.scalar_type() {
193 unsafe { Some(peek.data.get::<&str>()) }
194 } else if let Some(ScalarType::String) = peek.scalar_type() {
195 unsafe { Some(peek.data.get::<alloc::string::String>().as_str()) }
196 } else if let Type::Pointer(PointerType::Reference(vpt)) = peek.shape.ty {
197 let target_shape = (vpt.target)();
198 if let Some(ScalarType::Str) = ScalarType::try_from_shape(target_shape) {
199 unsafe { Some(peek.data.get::<&str>()) }
200 } else {
201 None
202 }
203 } else {
204 None
205 }
206 }
207
208 pub fn into_struct(self) -> Result<PeekStruct<'mem, 'facet, 'shape>, ReflectError<'shape>> {
210 if let Type::User(UserType::Struct(ty)) = self.shape.ty {
211 Ok(PeekStruct { value: self, ty })
212 } else {
213 Err(ReflectError::WasNotA {
214 expected: "struct",
215 actual: self.shape,
216 })
217 }
218 }
219
220 pub fn into_enum(self) -> Result<PeekEnum<'mem, 'facet, 'shape>, ReflectError<'shape>> {
222 if let Type::User(UserType::Enum(ty)) = self.shape.ty {
223 Ok(PeekEnum { value: self, ty })
224 } else {
225 Err(ReflectError::WasNotA {
226 expected: "enum",
227 actual: self.shape,
228 })
229 }
230 }
231
232 pub fn into_map(self) -> Result<PeekMap<'mem, 'facet, 'shape>, ReflectError<'shape>> {
234 if let Def::Map(def) = self.shape.def {
235 Ok(PeekMap { value: self, def })
236 } else {
237 Err(ReflectError::WasNotA {
238 expected: "map",
239 actual: self.shape,
240 })
241 }
242 }
243
244 pub fn into_list(self) -> Result<PeekList<'mem, 'facet, 'shape>, ReflectError<'shape>> {
246 if let Def::List(def) = self.shape.def {
247 return Ok(PeekList { value: self, def });
248 }
249
250 Err(ReflectError::WasNotA {
251 expected: "list",
252 actual: self.shape,
253 })
254 }
255
256 pub fn into_list_like(
258 self,
259 ) -> Result<PeekListLike<'mem, 'facet, 'shape>, ReflectError<'shape>> {
260 match self.shape.def {
261 Def::List(def) => Ok(PeekListLike::new(self, ListLikeDef::List(def))),
262 Def::Array(def) => Ok(PeekListLike::new(self, ListLikeDef::Array(def))),
263 _ => {
264 match self.shape.ty {
266 Type::Pointer(ptr) => match ptr {
267 PointerType::Reference(vpt) | PointerType::Raw(vpt) => {
268 let target = (vpt.target)();
269 match target.def {
270 Def::Slice(def) => {
271 return Ok(PeekListLike::new(self, ListLikeDef::Slice(def)));
272 }
273 _ => {
274 }
276 }
277 }
278 PointerType::Function(_) => {
279 }
281 },
282 _ => {
283 }
285 }
286
287 Err(ReflectError::WasNotA {
288 expected: "list, array or slice",
289 actual: self.shape,
290 })
291 }
292 }
293 }
294
295 pub fn into_smart_pointer(
297 self,
298 ) -> Result<PeekSmartPointer<'mem, 'facet, 'shape>, ReflectError<'shape>> {
299 if let Def::SmartPointer(def) = self.shape.def {
300 Ok(PeekSmartPointer { value: self, def })
301 } else {
302 Err(ReflectError::WasNotA {
303 expected: "smart pointer",
304 actual: self.shape,
305 })
306 }
307 }
308
309 pub fn into_option(
311 self,
312 ) -> Result<super::PeekOption<'mem, 'facet, 'shape>, ReflectError<'shape>> {
313 if let Def::Option(def) = self.shape.def {
314 Ok(super::PeekOption { value: self, def })
315 } else {
316 Err(ReflectError::WasNotA {
317 expected: "option",
318 actual: self.shape,
319 })
320 }
321 }
322
323 pub fn into_tuple(self) -> Result<PeekTuple<'mem, 'facet, 'shape>, ReflectError<'shape>> {
325 if let Type::User(UserType::Struct(struct_type)) = self.shape.ty {
326 if struct_type.kind == StructKind::Tuple {
327 Ok(PeekTuple {
328 value: self,
329 ty: TupleType {
330 fields: struct_type.fields,
331 },
332 })
333 } else {
334 Err(ReflectError::WasNotA {
335 expected: "tuple",
336 actual: self.shape,
337 })
338 }
339 } else {
340 Err(ReflectError::WasNotA {
341 expected: "tuple",
342 actual: self.shape,
343 })
344 }
345 }
346
347 pub fn innermost_peek(self) -> Self {
353 let mut current_peek = self;
354 while let (Some(try_borrow_inner_fn), Some(inner_shape)) = (
355 (current_peek.shape.vtable.try_borrow_inner)(),
356 current_peek.shape.inner,
357 ) {
358 unsafe {
359 let inner_data = try_borrow_inner_fn(current_peek.data).unwrap_or_else(|e| {
360 panic!("innermost_peek: try_borrow_inner returned an error! was trying to go from {} to {}. error: {e}", current_peek.shape,
361 inner_shape())
362 });
363
364 current_peek = Peek {
365 data: inner_data,
366 shape: inner_shape(),
367 invariant: PhantomData,
368 };
369 }
370 }
371 current_peek
372 }
373}
374
375impl<'mem, 'facet, 'shape> core::fmt::Display for Peek<'mem, 'facet, 'shape> {
376 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
377 if let Some(display_fn) = (self.vtable().display)() {
378 unsafe { display_fn(self.data, f) }
379 } else {
380 write!(f, "⟨{}⟩", self.shape)
381 }
382 }
383}
384
385impl<'mem, 'facet, 'shape> core::fmt::Debug for Peek<'mem, 'facet, 'shape> {
386 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
387 if let Some(debug_fn) = (self.vtable().debug)() {
388 unsafe { debug_fn(self.data, f) }
389 } else {
390 write!(f, "⟨{}⟩", self.shape)
391 }
392 }
393}
394
395impl<'mem, 'facet, 'shape> core::cmp::PartialEq for Peek<'mem, 'facet, 'shape> {
396 fn eq(&self, other: &Self) -> bool {
397 if self.shape != other.shape {
398 return false;
399 }
400 let eq_fn = match (self.shape.vtable.partial_eq)() {
401 Some(eq_fn) => eq_fn,
402 None => return false,
403 };
404 unsafe { eq_fn(self.data, other.data) }
405 }
406}
407
408impl<'mem, 'facet, 'shape> core::cmp::PartialOrd for Peek<'mem, 'facet, 'shape> {
409 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
410 if self.shape != other.shape {
411 return None;
412 }
413 let partial_ord_fn = (self.shape.vtable.partial_ord)()?;
414 unsafe { partial_ord_fn(self.data, other.data) }
415 }
416}
417
418impl<'mem, 'facet, 'shape> core::hash::Hash for Peek<'mem, 'facet, 'shape> {
419 fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) {
420 if let Some(hash_fn) = (self.shape.vtable.hash)() {
421 let hasher_opaque = PtrMut::new(hasher);
422 unsafe {
423 hash_fn(self.data, hasher_opaque, |opaque, bytes| {
424 opaque.as_mut::<H>().write(bytes)
425 })
426 };
427 } else {
428 panic!("Hashing is not supported for this shape");
429 }
430 }
431}