1use core::{cmp::Ordering, marker::PhantomData};
2use facet_core::{
3 Def, Facet, GenericPtr, PointerType, PtrMut, Shape, StructKind, Type, TypeNameOpts, UserType,
4 ValueVTable,
5};
6
7use crate::{PeekNdArray, PeekSet, ReflectError, ScalarType};
8
9use super::{
10 ListLikeDef, PeekEnum, PeekList, PeekListLike, PeekMap, PeekOption, PeekPointer, PeekStruct,
11 PeekTuple, tuple::TupleType,
12};
13
14#[derive(Clone, Copy, PartialEq, Eq, Hash)]
16pub struct ValueId {
17 pub(crate) shape: &'static Shape,
18 pub(crate) ptr: *const u8,
19}
20
21impl ValueId {
22 #[inline]
23 pub(crate) fn new(shape: &'static Shape, ptr: *const u8) -> Self {
24 Self { shape, ptr }
25 }
26}
27
28impl core::fmt::Display for ValueId {
29 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
30 write!(f, "{}@{:p}", self.shape, self.ptr)
31 }
32}
33
34impl core::fmt::Debug for ValueId {
35 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
36 core::fmt::Display::fmt(self, f)
37 }
38}
39
40#[derive(Clone, Copy)]
46pub struct Peek<'mem, 'facet> {
47 pub(crate) data: GenericPtr<'mem>,
49
50 pub(crate) shape: &'static Shape,
52
53 invariant: PhantomData<fn(&'facet ()) -> &'facet ()>,
54}
55
56impl<'mem, 'facet> Peek<'mem, 'facet> {
57 pub fn new<T: Facet<'facet> + ?Sized>(t: &'mem T) -> Self {
59 Self {
60 data: GenericPtr::new(t),
61 shape: T::SHAPE,
62 invariant: PhantomData,
63 }
64 }
65
66 pub unsafe fn unchecked_new(data: impl Into<GenericPtr<'mem>>, shape: &'static Shape) -> Self {
75 Self {
76 data: data.into(),
77 shape,
78 invariant: PhantomData,
79 }
80 }
81
82 #[inline(always)]
84 pub fn vtable(&self) -> &'static ValueVTable {
85 self.shape.vtable
86 }
87
88 #[inline]
90 pub fn id(&self) -> ValueId {
91 ValueId::new(self.shape, self.data.as_byte_ptr())
92 }
93
94 #[inline]
96 pub fn ptr_eq(&self, other: &Peek<'_, '_>) -> bool {
97 self.data.as_byte_ptr() == other.data.as_byte_ptr()
98 }
99
100 #[inline]
106 pub fn partial_eq(&self, other: &Peek<'_, '_>) -> Option<bool> {
107 match (self.data, other.data) {
108 (GenericPtr::Thin(a), GenericPtr::Thin(b)) => unsafe {
109 (self.vtable().sized().unwrap().partial_eq)().map(|f| f(a, b))
110 },
111 (GenericPtr::Wide(a), GenericPtr::Wide(b)) => unsafe {
112 (self.vtable().r#unsized().unwrap().partial_eq)().map(|f| f(a, b))
113 },
114 _ => None,
115 }
116 }
117
118 #[inline]
124 pub fn partial_cmp(&self, other: &Peek<'_, '_>) -> Option<Option<Ordering>> {
125 match (self.data, other.data) {
126 (GenericPtr::Thin(a), GenericPtr::Thin(b)) => unsafe {
127 (self.vtable().sized().unwrap().partial_ord)().map(|f| f(a, b))
128 },
129 (GenericPtr::Wide(a), GenericPtr::Wide(b)) => unsafe {
130 (self.vtable().r#unsized().unwrap().partial_ord)().map(|f| f(a, b))
131 },
132 _ => None,
133 }
134 }
135 #[inline(always)]
141 pub fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) -> Result<(), ReflectError> {
142 match self.data {
143 GenericPtr::Thin(ptr) => {
144 if let Some(hash_fn) = (self.vtable().sized().unwrap().hash)() {
145 let hasher_opaque = PtrMut::new(hasher);
146 unsafe {
147 hash_fn(ptr, hasher_opaque, |opaque, bytes| {
148 opaque.as_mut::<H>().write(bytes)
149 })
150 };
151 return Ok(());
152 }
153 }
154 GenericPtr::Wide(ptr) => {
155 if let Some(hash_fn) = (self.vtable().r#unsized().unwrap().hash)() {
156 let hasher_opaque = PtrMut::new(hasher);
157 unsafe {
158 hash_fn(ptr, hasher_opaque, |opaque, bytes| {
159 opaque.as_mut::<H>().write(bytes)
160 })
161 };
162 return Ok(());
163 }
164 }
165 }
166 Err(ReflectError::OperationFailed {
167 shape: self.shape(),
168 operation: "hash",
169 })
170 }
171
172 #[inline(always)]
183 pub fn type_name(
184 &self,
185 f: &mut core::fmt::Formatter<'_>,
186 opts: TypeNameOpts,
187 ) -> core::fmt::Result {
188 (self.shape.vtable.type_name())(f, opts)
189 }
190
191 #[inline(always)]
193 pub const fn shape(&self) -> &'static Shape {
194 self.shape
195 }
196
197 #[inline(always)]
199 pub const fn data(&self) -> GenericPtr<'mem> {
200 self.data
201 }
202
203 #[inline]
205 pub fn scalar_type(&self) -> Option<ScalarType> {
206 ScalarType::try_from_shape(self.shape)
207 }
208
209 #[inline]
215 pub fn get<T: Facet<'facet> + ?Sized>(&self) -> Result<&T, ReflectError> {
216 if self.shape != T::SHAPE {
217 Err(ReflectError::WrongShape {
218 expected: self.shape,
219 actual: T::SHAPE,
220 })
221 } else {
222 Ok(unsafe { self.data.get::<T>() })
223 }
224 }
225
226 pub fn as_str(&self) -> Option<&'mem str> {
229 let peek = self.innermost_peek();
230 if let Some(ScalarType::Str) = peek.scalar_type() {
231 unsafe { Some(peek.data.get::<&str>()) }
232 } else if let Some(ScalarType::String) = peek.scalar_type() {
233 unsafe { Some(peek.data.get::<alloc::string::String>().as_str()) }
234 } else if let Type::Pointer(PointerType::Reference(vpt)) = peek.shape.ty {
235 let target_shape = (vpt.target)();
236 if let Some(ScalarType::Str) = ScalarType::try_from_shape(target_shape) {
237 unsafe { Some(peek.data.get::<&str>()) }
238 } else {
239 None
240 }
241 } else {
242 None
243 }
244 }
245
246 #[inline]
249 pub fn as_bytes(&self) -> Option<&'mem [u8]> {
250 if let Type::Pointer(PointerType::Reference(vpt)) = self.shape.ty {
252 let target_shape = (vpt.target)();
253 if let Def::Slice(sd) = target_shape.def {
254 if sd.t().is_type::<u8>() {
255 unsafe { return Some(self.data.get::<&[u8]>()) }
256 }
257 }
258 }
259 None
260 }
261
262 #[inline]
264 pub fn into_struct(self) -> Result<PeekStruct<'mem, 'facet>, ReflectError> {
265 if let Type::User(UserType::Struct(ty)) = self.shape.ty {
266 Ok(PeekStruct { value: self, ty })
267 } else {
268 Err(ReflectError::WasNotA {
269 expected: "struct",
270 actual: self.shape,
271 })
272 }
273 }
274
275 #[inline]
277 pub fn into_enum(self) -> Result<PeekEnum<'mem, 'facet>, ReflectError> {
278 if let Type::User(UserType::Enum(ty)) = self.shape.ty {
279 Ok(PeekEnum { value: self, ty })
280 } else {
281 Err(ReflectError::WasNotA {
282 expected: "enum",
283 actual: self.shape,
284 })
285 }
286 }
287
288 #[inline]
290 pub fn into_map(self) -> Result<PeekMap<'mem, 'facet>, ReflectError> {
291 if let Def::Map(def) = self.shape.def {
292 Ok(PeekMap { value: self, def })
293 } else {
294 Err(ReflectError::WasNotA {
295 expected: "map",
296 actual: self.shape,
297 })
298 }
299 }
300
301 #[inline]
303 pub fn into_set(self) -> Result<PeekSet<'mem, 'facet>, ReflectError> {
304 if let Def::Set(def) = self.shape.def {
305 Ok(PeekSet { value: self, def })
306 } else {
307 Err(ReflectError::WasNotA {
308 expected: "set",
309 actual: self.shape,
310 })
311 }
312 }
313
314 #[inline]
316 pub fn into_list(self) -> Result<PeekList<'mem, 'facet>, ReflectError> {
317 if let Def::List(def) = self.shape.def {
318 return Ok(PeekList { value: self, def });
319 }
320
321 Err(ReflectError::WasNotA {
322 expected: "list",
323 actual: self.shape,
324 })
325 }
326
327 #[inline]
329 pub fn into_ndarray(self) -> Result<PeekNdArray<'mem, 'facet>, ReflectError> {
330 if let Def::NdArray(def) = self.shape.def {
331 return Ok(PeekNdArray { value: self, def });
332 }
333
334 Err(ReflectError::WasNotA {
335 expected: "ndarray",
336 actual: self.shape,
337 })
338 }
339
340 #[inline]
342 pub fn into_list_like(self) -> Result<PeekListLike<'mem, 'facet>, ReflectError> {
343 match self.shape.def {
344 Def::List(def) => Ok(PeekListLike::new(self, ListLikeDef::List(def))),
345 Def::Array(def) => Ok(PeekListLike::new(self, ListLikeDef::Array(def))),
346 Def::Slice(def) => {
347 if matches!(self.data, GenericPtr::Wide(_)) {
350 Ok(PeekListLike::new(self, ListLikeDef::Slice(def)))
351 } else {
352 Err(ReflectError::WasNotA {
353 expected: "slice with wide pointer",
354 actual: self.shape,
355 })
356 }
357 }
358 _ => {
359 match self.shape.ty {
361 Type::Pointer(ptr) => match ptr {
362 PointerType::Reference(vpt) | PointerType::Raw(vpt) => {
363 let target = (vpt.target)();
364 match target.def {
365 Def::Slice(def) => {
366 return Ok(PeekListLike::new(self, ListLikeDef::Slice(def)));
367 }
368 _ => {
369 }
371 }
372 }
373 PointerType::Function(_) => {
374 }
376 },
377 _ => {
378 }
380 }
381
382 Err(ReflectError::WasNotA {
383 expected: "list, array or slice",
384 actual: self.shape,
385 })
386 }
387 }
388 }
389
390 #[inline]
392 pub fn into_pointer(self) -> Result<PeekPointer<'mem, 'facet>, ReflectError> {
393 if let Def::Pointer(def) = self.shape.def {
394 Ok(PeekPointer { value: self, def })
395 } else {
396 Err(ReflectError::WasNotA {
397 expected: "smart pointer",
398 actual: self.shape,
399 })
400 }
401 }
402
403 #[inline]
405 pub fn into_option(self) -> Result<PeekOption<'mem, 'facet>, ReflectError> {
406 if let Def::Option(def) = self.shape.def {
407 Ok(PeekOption { value: self, def })
408 } else {
409 Err(ReflectError::WasNotA {
410 expected: "option",
411 actual: self.shape,
412 })
413 }
414 }
415
416 #[inline]
418 pub fn into_tuple(self) -> Result<PeekTuple<'mem, 'facet>, ReflectError> {
419 if let Type::User(UserType::Struct(struct_type)) = self.shape.ty {
420 if struct_type.kind == StructKind::Tuple {
421 Ok(PeekTuple {
422 value: self,
423 ty: TupleType {
424 fields: struct_type.fields,
425 },
426 })
427 } else {
428 Err(ReflectError::WasNotA {
429 expected: "tuple",
430 actual: self.shape,
431 })
432 }
433 } else {
434 Err(ReflectError::WasNotA {
435 expected: "tuple",
436 actual: self.shape,
437 })
438 }
439 }
440
441 pub fn innermost_peek(self) -> Self {
447 let mut current_peek = self;
448 while let (Some(try_borrow_inner_fn), Some(inner_shape)) = (
449 current_peek
450 .shape
451 .vtable
452 .sized()
453 .and_then(|v| (v.try_borrow_inner)()),
454 current_peek.shape.inner,
455 ) {
456 unsafe {
457 let inner_data = try_borrow_inner_fn(current_peek.data.thin().unwrap()).unwrap_or_else(|e| {
458 panic!("innermost_peek: try_borrow_inner returned an error! was trying to go from {} to {}. error: {e}", current_peek.shape,
459 inner_shape())
460 });
461
462 current_peek = Peek {
463 data: inner_data.into(),
464 shape: inner_shape(),
465 invariant: PhantomData,
466 };
467 }
468 }
469 current_peek
470 }
471}
472
473impl<'mem, 'facet> core::fmt::Display for Peek<'mem, 'facet> {
474 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
475 match self.data {
476 GenericPtr::Thin(ptr) => {
477 if let Some(display_fn) = (self.vtable().sized().unwrap().display)() {
478 return unsafe { display_fn(ptr, f) };
479 }
480 }
481 GenericPtr::Wide(ptr) => {
482 if let Some(display_fn) = (self.vtable().r#unsized().unwrap().display)() {
483 return unsafe { display_fn(ptr, f) };
484 }
485 }
486 }
487 write!(f, "⟨{}⟩", self.shape)
488 }
489}
490
491impl<'mem, 'facet> core::fmt::Debug for Peek<'mem, 'facet> {
492 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
493 match self.data {
494 GenericPtr::Thin(ptr) => {
495 if let Some(debug_fn) = (self.vtable().sized().unwrap().debug)() {
496 return unsafe { debug_fn(ptr, f) };
497 }
498 }
499 GenericPtr::Wide(ptr) => {
500 if let Some(debug_fn) = (self.vtable().r#unsized().unwrap().debug)() {
501 return unsafe { debug_fn(ptr, f) };
502 }
503 }
504 }
505 write!(f, "⟨{}⟩", self.shape)
506 }
507}
508
509impl<'mem, 'facet> core::cmp::PartialEq for Peek<'mem, 'facet> {
510 #[inline]
511 fn eq(&self, other: &Self) -> bool {
512 self.partial_eq(other).unwrap_or(false)
513 }
514}
515
516impl<'mem, 'facet> core::cmp::PartialOrd for Peek<'mem, 'facet> {
517 #[inline]
518 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
519 self.partial_cmp(other).unwrap_or(None)
520 }
521}
522
523impl<'mem, 'facet> core::hash::Hash for Peek<'mem, 'facet> {
524 fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) {
525 self.hash(hasher)
526 .expect("Hashing is not supported for this shape");
527 }
528}