1use core::{cmp::Ordering, marker::PhantomData, ptr::NonNull};
2#[cfg(feature = "alloc")]
3use facet_core::Field;
4use facet_core::{
5 Def, Facet, PointerType, PtrConst, Shape, StructKind, Type, TypeNameOpts, UserType,
6 VTableErased, Variance,
7};
8
9use crate::{PeekNdArray, PeekSet, ReflectError, ScalarType};
10
11use super::{
12 ListLikeDef, PeekDynamicValue, PeekEnum, PeekList, PeekListLike, PeekMap, PeekOption,
13 PeekPointer, PeekResult, PeekStruct, PeekTuple, tuple::TupleType,
14};
15
16#[cfg(feature = "alloc")]
17use super::OwnedPeek;
18
19#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Hash)]
21pub struct ValueId {
22 pub(crate) shape: &'static Shape,
23 pub(crate) ptr: *const u8,
24}
25
26impl ValueId {
27 #[inline]
28 pub(crate) fn new(shape: &'static Shape, ptr: *const u8) -> Self {
29 Self { shape, ptr }
30 }
31}
32
33impl core::fmt::Display for ValueId {
34 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
35 write!(f, "{}@{:p}", self.shape, self.ptr)
36 }
37}
38
39impl core::fmt::Debug for ValueId {
40 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
41 core::fmt::Display::fmt(self, f)
42 }
43}
44
45#[allow(clippy::type_complexity)]
67#[derive(Clone, Copy)]
68pub struct Peek<'mem, 'facet> {
69 pub(crate) data: PtrConst,
71
72 pub(crate) shape: &'static Shape,
74
75 _invariant: PhantomData<(&'mem (), fn(&'facet ()) -> &'facet ())>,
88}
89
90impl<'mem, 'facet> Peek<'mem, 'facet> {
91 pub fn new<T: Facet<'facet> + ?Sized>(t: &'mem T) -> Self {
93 Self {
94 data: PtrConst::new(NonNull::from(t).as_ptr()),
95 shape: T::SHAPE,
96 _invariant: PhantomData,
97 }
98 }
99
100 pub unsafe fn unchecked_new(data: PtrConst, shape: &'static Shape) -> Self {
109 Self {
110 data,
111 shape,
112 _invariant: PhantomData,
113 }
114 }
115
116 #[inline]
125 pub fn variance(&self) -> Variance {
126 self.shape.computed_variance()
127 }
128
129 #[inline]
138 pub fn shrink_lifetime<'shorter>(self) -> Peek<'mem, 'shorter>
139 where
140 'facet: 'shorter,
141 {
142 self.try_shrink_lifetime()
143 .expect("shrink_lifetime requires a covariant type")
144 }
145
146 #[inline]
151 pub fn try_shrink_lifetime<'shorter>(self) -> Option<Peek<'mem, 'shorter>>
152 where
153 'facet: 'shorter,
154 {
155 if self.variance() == Variance::Covariant {
156 Some(Peek {
157 data: self.data,
158 shape: self.shape,
159 _invariant: PhantomData,
160 })
161 } else {
162 None
163 }
164 }
165
166 #[inline]
175 pub fn grow_lifetime<'longer>(self) -> Peek<'mem, 'longer>
176 where
177 'longer: 'facet,
178 {
179 self.try_grow_lifetime()
180 .expect("grow_lifetime requires a contravariant type")
181 }
182
183 #[inline]
188 pub fn try_grow_lifetime<'longer>(self) -> Option<Peek<'mem, 'longer>>
189 where
190 'longer: 'facet,
191 {
192 if self.variance() == Variance::Contravariant {
193 Some(Peek {
194 data: self.data,
195 shape: self.shape,
196 _invariant: PhantomData,
197 })
198 } else {
199 None
200 }
201 }
202
203 #[inline(always)]
205 pub fn vtable(&self) -> VTableErased {
206 self.shape.vtable
207 }
208
209 #[inline]
211 pub fn id(&self) -> ValueId {
212 ValueId::new(self.shape, self.data.raw_ptr())
213 }
214
215 #[inline]
217 pub fn ptr_eq(&self, other: &Peek<'_, '_>) -> bool {
218 self.data.raw_ptr() == other.data.raw_ptr()
219 }
220
221 #[inline]
227 pub fn partial_eq(&self, other: &Peek<'_, '_>) -> Result<bool, ReflectError> {
228 if self.shape != other.shape {
229 return Err(ReflectError::WrongShape {
230 expected: self.shape,
231 actual: other.shape,
232 });
233 }
234
235 if let Some(result) = unsafe { self.shape.call_partial_eq(self.data, other.data) } {
236 return Ok(result);
237 }
238
239 Err(ReflectError::OperationFailed {
240 shape: self.shape(),
241 operation: "partial_eq",
242 })
243 }
244
245 #[inline]
251 pub fn partial_cmp(&self, other: &Peek<'_, '_>) -> Result<Option<Ordering>, ReflectError> {
252 if self.shape != other.shape {
253 return Err(ReflectError::WrongShape {
254 expected: self.shape,
255 actual: other.shape,
256 });
257 }
258
259 if let Some(result) = unsafe { self.shape.call_partial_cmp(self.data, other.data) } {
260 return Ok(result);
261 }
262
263 Err(ReflectError::OperationFailed {
264 shape: self.shape(),
265 operation: "partial_cmp",
266 })
267 }
268
269 #[inline(always)]
275 pub fn hash(&self, hasher: &mut dyn core::hash::Hasher) -> Result<(), ReflectError> {
276 let mut proxy = facet_core::HashProxy::new(hasher);
277 if unsafe { self.shape.call_hash(self.data, &mut proxy) }.is_some() {
278 return Ok(());
279 }
280
281 Err(ReflectError::OperationFailed {
282 shape: self.shape(),
283 operation: "hash",
284 })
285 }
286
287 pub fn structural_hash<H: core::hash::Hasher>(&self, hasher: &mut H) {
298 use core::hash::Hash;
299
300 self.shape.id.hash(hasher);
302
303 let mut proxy = facet_core::HashProxy::new(hasher);
305 if unsafe { self.shape.call_hash(self.data, &mut proxy) }.is_some() {
306 return;
307 }
308
309 match self.shape.ty {
311 Type::User(UserType::Struct(struct_type)) => {
312 (struct_type.kind as u8).hash(hasher);
314
315 for field in struct_type.fields {
317 if field.is_metadata() {
319 continue;
320 }
321
322 field.name.hash(hasher);
324
325 let field_offset = field.offset;
327 let field_shape = field.shape();
328 let field_ptr = unsafe { self.data.field(field_offset) };
329 let field_peek = unsafe { Peek::unchecked_new(field_ptr, field_shape) };
330 field_peek.structural_hash(hasher);
331 }
332 }
333
334 Type::User(UserType::Enum(_enum_type)) => {
335 if let Ok(peek_enum) = self.into_enum()
337 && let Ok(variant) = peek_enum.active_variant()
338 {
339 variant.name.hash(hasher);
341
342 match variant.data.kind {
344 StructKind::Unit => {
345 }
347 StructKind::TupleStruct | StructKind::Tuple => {
348 use super::HasFields;
350 for (_field, peek) in peek_enum.fields() {
351 peek.structural_hash(hasher);
352 }
353 }
354 StructKind::Struct => {
355 use super::HasFields;
357 for (field, peek) in peek_enum.fields() {
358 field.name.hash(hasher);
359 peek.structural_hash(hasher);
360 }
361 }
362 }
363 }
364 }
365
366 _ => {
367 match self.shape.def {
369 Def::List(_) | Def::Array(_) | Def::Slice(_) => {
370 if let Ok(list_like) = self.into_list_like() {
371 list_like.len().hash(hasher);
373
374 for elem in list_like.iter() {
376 elem.structural_hash(hasher);
377 }
378 }
379 }
380
381 Def::Map(_) => {
382 if let Ok(map) = self.into_map() {
383 map.len().hash(hasher);
385
386 for (key, value) in map.iter() {
388 key.structural_hash(hasher);
389 value.structural_hash(hasher);
390 }
391 }
392 }
393
394 Def::Set(_) => {
395 if let Ok(set) = self.into_set() {
396 set.len().hash(hasher);
398
399 for elem in set.iter() {
401 elem.structural_hash(hasher);
402 }
403 }
404 }
405
406 Def::Option(_) => {
407 if let Ok(opt) = self.into_option() {
408 if let Some(inner) = opt.value() {
409 true.hash(hasher);
410 inner.structural_hash(hasher);
411 } else {
412 false.hash(hasher);
413 }
414 }
415 }
416
417 Def::Result(_) => {
418 if let Ok(result) = self.into_result() {
419 if result.is_ok() {
420 0u8.hash(hasher);
421 if let Some(ok_val) = result.ok() {
422 ok_val.structural_hash(hasher);
423 }
424 } else {
425 1u8.hash(hasher);
426 if let Some(err_val) = result.err() {
427 err_val.structural_hash(hasher);
428 }
429 }
430 }
431 }
432
433 Def::Pointer(_) => {
434 if let Ok(ptr) = self.into_pointer()
435 && let Some(inner) = ptr.borrow_inner()
436 {
437 inner.structural_hash(hasher);
438 }
439 }
440
441 Def::DynamicValue(_) => {
442 if let Ok(dyn_val) = self.into_dynamic_value() {
443 dyn_val.structural_hash_inner(hasher);
445 }
446 }
447
448 Def::NdArray(_) => {
449 if let Ok(arr) = self.into_ndarray() {
451 let n_dim = arr.n_dim();
452 n_dim.hash(hasher);
453 for i in 0..n_dim {
454 if let Some(dim) = arr.dim(i) {
455 dim.hash(hasher);
456 }
457 }
458 let count = arr.count();
460 for i in 0..count {
461 if let Some(elem) = arr.get(i) {
462 elem.structural_hash(hasher);
463 }
464 }
465 }
466 }
467
468 Def::Scalar | Def::Undefined | _ => {
469 panic!(
470 "structural_hash: type {} has no Hash impl and cannot be structurally hashed",
471 self.shape
472 );
473 }
474 }
475 }
476 }
477 }
478
479 #[inline(always)]
490 pub fn type_name(
491 &self,
492 f: &mut core::fmt::Formatter<'_>,
493 opts: TypeNameOpts,
494 ) -> core::fmt::Result {
495 if let Some(type_name_fn) = self.shape.type_name {
496 type_name_fn(self.shape, f, opts)
497 } else {
498 write!(f, "{}", self.shape.type_identifier)
499 }
500 }
501
502 #[inline(always)]
504 pub const fn shape(&self) -> &'static Shape {
505 self.shape
506 }
507
508 #[inline(always)]
510 pub const fn data(&self) -> PtrConst {
511 self.data
512 }
513
514 #[inline]
516 pub fn scalar_type(&self) -> Option<ScalarType> {
517 ScalarType::try_from_shape(self.shape)
518 }
519
520 #[inline]
526 pub fn get<T: Facet<'facet> + ?Sized>(&self) -> Result<&'mem T, ReflectError> {
527 if self.shape != T::SHAPE {
528 Err(ReflectError::WrongShape {
529 expected: self.shape,
530 actual: T::SHAPE,
531 })
532 } else {
533 Ok(unsafe { self.data.get::<T>() })
534 }
535 }
536
537 pub fn as_str(&self) -> Option<&'mem str> {
540 let peek = self.innermost_peek();
541 if let Some(ScalarType::Str) = peek.scalar_type()
545 && !matches!(peek.shape.ty, Type::Pointer(_))
546 {
547 return unsafe { Some(peek.data.get::<str>()) };
550 }
551 #[cfg(feature = "alloc")]
552 if let Some(ScalarType::String) = peek.scalar_type() {
553 return unsafe { Some(peek.data.get::<alloc::string::String>().as_str()) };
554 }
555
556 if let Type::Pointer(PointerType::Reference(vpt)) = peek.shape.ty {
558 let target_shape = vpt.target;
559
560 if let Type::Pointer(PointerType::Reference(inner_vpt)) = target_shape.ty {
562 let inner_target_shape = inner_vpt.target;
563 if let Some(ScalarType::Str) = ScalarType::try_from_shape(inner_target_shape) {
564 let outer_ptr: *const *const &str =
567 unsafe { peek.data.as_ptr::<*const &str>() };
568 let inner_ref: &str = unsafe { **outer_ptr };
569 return Some(inner_ref);
570 }
571 } else if let Some(ScalarType::Str) = ScalarType::try_from_shape(target_shape)
572 && !matches!(target_shape.ty, Type::Pointer(_))
573 {
574 return unsafe { Some(peek.data.get::<&str>()) };
576 }
577 }
578 None
579 }
580
581 #[inline]
584 pub fn as_bytes(&self) -> Option<&'mem [u8]> {
585 if let Type::Pointer(PointerType::Reference(vpt)) = self.shape.ty {
587 let target_shape = vpt.target;
588 if let Def::Slice(sd) = target_shape.def
589 && sd.t().is_type::<u8>()
590 {
591 unsafe { return Some(self.data.get::<&[u8]>()) }
592 }
593 }
594 None
595 }
596
597 #[inline]
599 pub fn into_struct(self) -> Result<PeekStruct<'mem, 'facet>, ReflectError> {
600 if let Type::User(UserType::Struct(ty)) = self.shape.ty {
601 Ok(PeekStruct { value: self, ty })
602 } else {
603 Err(ReflectError::WasNotA {
604 expected: "struct",
605 actual: self.shape,
606 })
607 }
608 }
609
610 #[inline]
612 pub fn into_enum(self) -> Result<PeekEnum<'mem, 'facet>, ReflectError> {
613 if let Type::User(UserType::Enum(ty)) = self.shape.ty {
614 Ok(PeekEnum { value: self, ty })
615 } else {
616 Err(ReflectError::WasNotA {
617 expected: "enum",
618 actual: self.shape,
619 })
620 }
621 }
622
623 #[inline]
625 pub fn into_map(self) -> Result<PeekMap<'mem, 'facet>, ReflectError> {
626 if let Def::Map(def) = self.shape.def {
627 Ok(PeekMap { value: self, def })
628 } else {
629 Err(ReflectError::WasNotA {
630 expected: "map",
631 actual: self.shape,
632 })
633 }
634 }
635
636 #[inline]
638 pub fn into_set(self) -> Result<PeekSet<'mem, 'facet>, ReflectError> {
639 if let Def::Set(def) = self.shape.def {
640 Ok(PeekSet { value: self, def })
641 } else {
642 Err(ReflectError::WasNotA {
643 expected: "set",
644 actual: self.shape,
645 })
646 }
647 }
648
649 #[inline]
651 pub fn into_list(self) -> Result<PeekList<'mem, 'facet>, ReflectError> {
652 if let Def::List(def) = self.shape.def {
653 return Ok(PeekList { value: self, def });
654 }
655
656 Err(ReflectError::WasNotA {
657 expected: "list",
658 actual: self.shape,
659 })
660 }
661
662 #[inline]
664 pub fn into_ndarray(self) -> Result<PeekNdArray<'mem, 'facet>, ReflectError> {
665 if let Def::NdArray(def) = self.shape.def {
666 return Ok(PeekNdArray { value: self, def });
667 }
668
669 Err(ReflectError::WasNotA {
670 expected: "ndarray",
671 actual: self.shape,
672 })
673 }
674
675 #[inline]
677 pub fn into_list_like(self) -> Result<PeekListLike<'mem, 'facet>, ReflectError> {
678 match self.shape.def {
679 Def::List(def) => Ok(PeekListLike::new(self, ListLikeDef::List(def))),
680 Def::Array(def) => Ok(PeekListLike::new(self, ListLikeDef::Array(def))),
681 Def::Slice(def) => {
682 Ok(PeekListLike::new(self, ListLikeDef::Slice(def)))
685 }
686 _ => {
687 match self.shape.ty {
689 Type::Pointer(ptr) => match ptr {
690 PointerType::Reference(vpt) | PointerType::Raw(vpt) => {
691 let target = vpt.target;
692 match target.def {
693 Def::Slice(def) => {
694 let ptr = unsafe { self.data.as_ptr::<*const [()]>() };
695 let ptr = PtrConst::new(unsafe {
696 NonNull::new_unchecked((*ptr) as *mut [()]).as_ptr()
697 });
698 let peek = unsafe { Peek::unchecked_new(ptr, def.t) };
699
700 return Ok(PeekListLike::new(peek, ListLikeDef::Slice(def)));
701 }
702 _ => {
703 }
705 }
706 }
707 PointerType::Function(_) => {
708 }
710 },
711 _ => {
712 }
714 }
715
716 Err(ReflectError::WasNotA {
717 expected: "list, array or slice",
718 actual: self.shape,
719 })
720 }
721 }
722 }
723
724 #[inline]
726 pub fn into_pointer(self) -> Result<PeekPointer<'mem, 'facet>, ReflectError> {
727 if let Def::Pointer(def) = self.shape.def {
728 Ok(PeekPointer { value: self, def })
729 } else {
730 Err(ReflectError::WasNotA {
731 expected: "smart pointer",
732 actual: self.shape,
733 })
734 }
735 }
736
737 #[inline]
739 pub fn into_option(self) -> Result<PeekOption<'mem, 'facet>, ReflectError> {
740 if let Def::Option(def) = self.shape.def {
741 Ok(PeekOption { value: self, def })
742 } else {
743 Err(ReflectError::WasNotA {
744 expected: "option",
745 actual: self.shape,
746 })
747 }
748 }
749
750 #[inline]
752 pub fn into_result(self) -> Result<PeekResult<'mem, 'facet>, ReflectError> {
753 if let Def::Result(def) = self.shape.def {
754 Ok(PeekResult { value: self, def })
755 } else {
756 Err(ReflectError::WasNotA {
757 expected: "result",
758 actual: self.shape,
759 })
760 }
761 }
762
763 #[inline]
765 pub fn into_tuple(self) -> Result<PeekTuple<'mem, 'facet>, ReflectError> {
766 if let Type::User(UserType::Struct(struct_type)) = self.shape.ty {
767 if struct_type.kind == StructKind::Tuple {
768 Ok(PeekTuple {
769 value: self,
770 ty: TupleType {
771 fields: struct_type.fields,
772 },
773 })
774 } else {
775 Err(ReflectError::WasNotA {
776 expected: "tuple",
777 actual: self.shape,
778 })
779 }
780 } else {
781 Err(ReflectError::WasNotA {
782 expected: "tuple",
783 actual: self.shape,
784 })
785 }
786 }
787
788 #[inline]
790 pub fn into_dynamic_value(self) -> Result<PeekDynamicValue<'mem, 'facet>, ReflectError> {
791 if let Def::DynamicValue(def) = self.shape.def {
792 Ok(PeekDynamicValue { value: self, def })
793 } else {
794 Err(ReflectError::WasNotA {
795 expected: "dynamic value",
796 actual: self.shape,
797 })
798 }
799 }
800
801 pub fn innermost_peek(self) -> Self {
807 let mut current_peek = self;
808 while let Some(inner_shape) = current_peek.shape.inner {
809 let result = unsafe { current_peek.shape.call_try_borrow_inner(current_peek.data) };
811 match result {
812 Some(Ok(inner_data)) => {
813 current_peek = Peek {
814 data: inner_data.as_const(),
815 shape: inner_shape,
816 _invariant: PhantomData,
817 };
818 }
819 Some(Err(e)) => {
820 panic!(
821 "innermost_peek: try_borrow_inner returned an error! was trying to go from {} to {}. error: {e}",
822 current_peek.shape, inner_shape
823 );
824 }
825 None => {
826 break;
828 }
829 }
830 }
831 current_peek
832 }
833
834 #[cfg(feature = "alloc")]
839 pub fn custom_serialization(&self, field: Field) -> Result<OwnedPeek<'mem>, ReflectError> {
840 let Some(proxy_def) = field.proxy() else {
841 return Err(ReflectError::OperationFailed {
842 shape: self.shape,
843 operation: "field does not have a proxy definition",
844 });
845 };
846
847 let target_shape = proxy_def.shape;
848 let tptr = target_shape.allocate().map_err(|_| ReflectError::Unsized {
849 shape: target_shape,
850 operation: "Not a Sized type",
851 })?;
852 let ser_res = unsafe { (proxy_def.convert_out)(self.data(), tptr) };
853 let err = match ser_res {
854 Ok(rptr) => {
855 if rptr.as_uninit() != tptr {
856 ReflectError::CustomSerializationError {
857 message: "convert_out did not return the expected pointer".into(),
858 src_shape: self.shape,
859 dst_shape: target_shape,
860 }
861 } else {
862 return Ok(OwnedPeek {
863 shape: target_shape,
864 data: rptr,
865 _phantom: PhantomData,
866 });
867 }
868 }
869 Err(message) => ReflectError::CustomSerializationError {
870 message,
871 src_shape: self.shape,
872 dst_shape: target_shape,
873 },
874 };
875 unsafe {
877 target_shape.deallocate_uninit(tptr).unwrap()
879 };
880 Err(err)
881 }
882
883 #[cfg(feature = "alloc")]
891 pub fn custom_serialization_from_shape(&self) -> Result<Option<OwnedPeek<'mem>>, ReflectError> {
892 let Some(proxy_def) = self.shape.proxy else {
893 return Ok(None);
894 };
895
896 let target_shape = proxy_def.shape;
897 let tptr = target_shape.allocate().map_err(|_| ReflectError::Unsized {
898 shape: target_shape,
899 operation: "Not a Sized type",
900 })?;
901
902 let ser_res = unsafe { (proxy_def.convert_out)(self.data(), tptr) };
903 let err = match ser_res {
904 Ok(rptr) => {
905 if rptr.as_uninit() != tptr {
906 ReflectError::CustomSerializationError {
907 message: "proxy convert_out did not return the expected pointer".into(),
908 src_shape: self.shape,
909 dst_shape: target_shape,
910 }
911 } else {
912 return Ok(Some(OwnedPeek {
913 shape: target_shape,
914 data: rptr,
915 _phantom: PhantomData,
916 }));
917 }
918 }
919 Err(message) => ReflectError::CustomSerializationError {
920 message,
921 src_shape: self.shape,
922 dst_shape: target_shape,
923 },
924 };
925
926 unsafe {
928 target_shape.deallocate_uninit(tptr).unwrap()
930 };
931 Err(err)
932 }
933}
934
935impl<'mem, 'facet> core::fmt::Display for Peek<'mem, 'facet> {
936 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
937 if let Some(result) = unsafe { self.shape.call_display(self.data, f) } {
938 return result;
939 }
940 write!(f, "⟨{}⟩", self.shape)
941 }
942}
943
944impl<'mem, 'facet> core::fmt::Debug for Peek<'mem, 'facet> {
945 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
946 if let Some(result) = unsafe { self.shape.call_debug(self.data, f) } {
947 return result;
948 }
949
950 write!(f, "⟨{}⟩", self.shape)
951 }
952}
953
954impl<'mem, 'facet> core::cmp::PartialEq for Peek<'mem, 'facet> {
955 #[inline]
956 fn eq(&self, other: &Self) -> bool {
957 self.partial_eq(other).unwrap_or(false)
958 }
959}
960
961impl<'mem, 'facet> core::cmp::PartialOrd for Peek<'mem, 'facet> {
962 #[inline]
963 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
964 self.partial_cmp(other).unwrap_or(None)
965 }
966}
967
968impl<'mem, 'facet> core::hash::Hash for Peek<'mem, 'facet> {
969 fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) {
970 self.hash(hasher)
971 .expect("Hashing is not supported for this shape");
972 }
973}
974
975#[derive(Clone, Copy)]
1019pub struct CovariantPeek<'mem, 'facet> {
1020 data: PtrConst,
1022
1023 shape: &'static Shape,
1025
1026 _covariant: PhantomData<(&'mem (), &'facet ())>,
1032}
1033
1034impl<'mem, 'facet> CovariantPeek<'mem, 'facet> {
1035 #[inline]
1052 pub fn new(peek: Peek<'mem, 'facet>) -> Option<Self> {
1053 if peek.variance() == Variance::Covariant {
1054 Some(Self {
1055 data: peek.data,
1056 shape: peek.shape,
1057 _covariant: PhantomData,
1058 })
1059 } else {
1060 None
1061 }
1062 }
1063
1064 #[inline]
1081 pub fn new_unchecked(peek: Peek<'mem, 'facet>) -> Self {
1082 Self::new(peek).unwrap_or_else(|| {
1083 panic!(
1084 "CovariantPeek::new_unchecked called on non-covariant type {} (variance: {:?})",
1085 peek.shape,
1086 peek.variance()
1087 )
1088 })
1089 }
1090
1091 #[inline]
1106 pub fn from_ref<T: Facet<'facet> + ?Sized>(t: &'mem T) -> Option<Self> {
1107 Self::new(Peek::new(t))
1108 }
1109
1110 #[inline]
1115 pub fn into_peek(self) -> Peek<'mem, 'facet> {
1116 Peek {
1117 data: self.data,
1118 shape: self.shape,
1119 _invariant: PhantomData,
1120 }
1121 }
1122
1123 #[inline]
1125 pub const fn shape(&self) -> &'static Shape {
1126 self.shape
1127 }
1128
1129 #[inline]
1131 pub const fn data(&self) -> PtrConst {
1132 self.data
1133 }
1134}
1135
1136impl<'mem, 'facet> core::ops::Deref for CovariantPeek<'mem, 'facet> {
1137 type Target = Peek<'mem, 'facet>;
1138
1139 #[inline]
1140 fn deref(&self) -> &Self::Target {
1141 unsafe { &*(self as *const CovariantPeek<'mem, 'facet> as *const Peek<'mem, 'facet>) }
1150 }
1151}
1152
1153impl<'mem, 'facet> core::fmt::Debug for CovariantPeek<'mem, 'facet> {
1154 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1155 f.debug_struct("CovariantPeek")
1156 .field("shape", &self.shape)
1157 .field("data", &self.data)
1158 .finish()
1159 }
1160}
1161
1162impl<'mem, 'facet> core::fmt::Display for CovariantPeek<'mem, 'facet> {
1163 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1164 core::fmt::Display::fmt(&**self, f)
1165 }
1166}
1167
1168#[cfg(test)]
1169mod tests {
1170 use super::*;
1171
1172 #[test]
1176 fn test_peek_as_str_empty_string() {
1177 let peek = Peek::new("");
1178 assert_eq!(peek.as_str(), Some(""));
1179 }
1180
1181 #[test]
1182 fn test_peek_as_str_non_empty_string() {
1183 let peek = Peek::new("hello");
1184 assert_eq!(peek.as_str(), Some("hello"));
1185 }
1186
1187 #[test]
1188 #[cfg(feature = "alloc")]
1189 fn test_peek_as_str_owned_string() {
1190 let s = alloc::string::String::from("owned string");
1191 let peek = Peek::new(&s);
1192 assert_eq!(peek.as_str(), Some("owned string"));
1193 }
1194
1195 #[test]
1198 fn test_peek_as_str_double_reference() {
1199 let value = &"hello";
1200 let peek = Peek::new(&value);
1201 assert_eq!(peek.as_str(), Some("hello"));
1202 }
1203
1204 #[test]
1205 fn test_covariant_peek_from_covariant_type() {
1206 let value = 42i32;
1208 let peek = Peek::new(&value);
1209 let covariant = CovariantPeek::new(peek);
1210 assert!(covariant.is_some());
1211
1212 let covariant = covariant.unwrap();
1214 assert_eq!(covariant.shape(), peek.shape());
1215 }
1216
1217 #[test]
1218 fn test_covariant_peek_from_ref() {
1219 let value = 42i32;
1220 let covariant = CovariantPeek::from_ref(&value);
1221 assert!(covariant.is_some());
1222 }
1223
1224 #[test]
1225 fn test_covariant_peek_deref_to_peek() {
1226 let value = "hello";
1227 let peek = Peek::new(&value);
1228 let covariant = CovariantPeek::new(peek).unwrap();
1229
1230 assert_eq!(covariant.as_str(), Some("hello"));
1232 assert_eq!(covariant.shape(), peek.shape());
1233 }
1234
1235 #[test]
1236 fn test_covariant_peek_into_peek() {
1237 let value = 42i32;
1238 let original_peek = Peek::new(&value);
1239 let covariant = CovariantPeek::new(original_peek).unwrap();
1240 let recovered_peek = covariant.into_peek();
1241
1242 assert_eq!(recovered_peek.shape(), original_peek.shape());
1243 }
1244
1245 #[test]
1246 fn test_covariant_peek_lifetime_covariance() {
1247 fn use_shorter<'a>(_p: CovariantPeek<'_, 'a>) {}
1250
1251 let value = 42i32;
1252 let covariant: CovariantPeek<'_, 'static> = CovariantPeek::from_ref(&value).unwrap();
1253
1254 use_shorter(covariant);
1256 }
1257
1258 #[test]
1259 #[cfg(feature = "alloc")]
1260 fn test_covariant_peek_vec_type() {
1261 let vec = alloc::vec![1i32, 2, 3];
1263 let peek = Peek::new(&vec);
1264 let covariant = CovariantPeek::new(peek);
1265 assert!(covariant.is_some());
1266 }
1267
1268 #[test]
1269 #[cfg(feature = "alloc")]
1270 fn test_covariant_peek_option_type() {
1271 let opt = Some(42i32);
1273 let peek = Peek::new(&opt);
1274 let covariant = CovariantPeek::new(peek);
1275 assert!(covariant.is_some());
1276 }
1277
1278 #[test]
1279 fn test_spanned_structural_hash_ignores_span() {
1280 use crate::{Span, Spanned};
1281 use core::hash::Hasher;
1282 use std::hash::DefaultHasher;
1283
1284 let a = Spanned::new(42i32, Span::new(0, 10));
1286 let b = Spanned::new(42i32, Span::new(100, 20));
1287
1288 let mut hasher_a = DefaultHasher::new();
1290 Peek::new(&a).structural_hash(&mut hasher_a);
1291 let hash_a = hasher_a.finish();
1292
1293 let mut hasher_b = DefaultHasher::new();
1294 Peek::new(&b).structural_hash(&mut hasher_b);
1295 let hash_b = hasher_b.finish();
1296
1297 assert_eq!(
1298 hash_a, hash_b,
1299 "Spanned values with same inner value should have same structural hash"
1300 );
1301 }
1302
1303 #[test]
1304 fn test_spanned_structural_hash_differs_for_different_values() {
1305 use crate::{Span, Spanned};
1306 use core::hash::Hasher;
1307 use std::hash::DefaultHasher;
1308
1309 let a = Spanned::new(42i32, Span::new(0, 10));
1311 let b = Spanned::new(99i32, Span::new(0, 10));
1312
1313 let mut hasher_a = DefaultHasher::new();
1315 Peek::new(&a).structural_hash(&mut hasher_a);
1316 let hash_a = hasher_a.finish();
1317
1318 let mut hasher_b = DefaultHasher::new();
1319 Peek::new(&b).structural_hash(&mut hasher_b);
1320 let hash_b = hasher_b.finish();
1321
1322 assert_ne!(
1323 hash_a, hash_b,
1324 "Spanned values with different inner values should have different structural hashes"
1325 );
1326 }
1327
1328 #[test]
1329 fn test_spanned_field_metadata() {
1330 use crate::Spanned;
1331 use facet_core::{Type, UserType};
1332
1333 let shape = <Spanned<i32> as facet_core::Facet>::SHAPE;
1335
1336 let struct_type = match shape.ty {
1338 Type::User(UserType::Struct(st)) => st,
1339 _ => panic!("Expected struct type"),
1340 };
1341
1342 let span_field = struct_type
1344 .fields
1345 .iter()
1346 .find(|f| f.name == "span")
1347 .expect("Should have span field");
1348
1349 assert!(
1350 span_field.is_metadata(),
1351 "span field should be marked as metadata"
1352 );
1353 assert_eq!(
1354 span_field.metadata_kind(),
1355 Some("span"),
1356 "span field should have metadata kind 'span'"
1357 );
1358
1359 let value_field = struct_type
1361 .fields
1362 .iter()
1363 .find(|f| f.name == "value")
1364 .expect("Should have value field");
1365
1366 assert!(
1367 !value_field.is_metadata(),
1368 "value field should not be marked as metadata"
1369 );
1370 }
1371}