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 match self.scalar_type() {
471 Some(ScalarType::F32) => {
472 if let Ok(v) = self.get::<f32>() {
473 v.to_bits().hash(hasher);
474 return;
475 }
476 }
477 Some(ScalarType::F64) => {
478 if let Ok(v) = self.get::<f64>() {
479 v.to_bits().hash(hasher);
480 return;
481 }
482 }
483 _ => {}
484 }
485 panic!(
486 "structural_hash: type {} has no Hash impl and cannot be structurally hashed",
487 self.shape
488 );
489 }
490 }
491 }
492 }
493 }
494
495 #[inline(always)]
506 pub fn type_name(
507 &self,
508 f: &mut core::fmt::Formatter<'_>,
509 opts: TypeNameOpts,
510 ) -> core::fmt::Result {
511 if let Some(type_name_fn) = self.shape.type_name {
512 type_name_fn(self.shape, f, opts)
513 } else {
514 write!(f, "{}", self.shape.type_identifier)
515 }
516 }
517
518 #[inline(always)]
520 pub const fn shape(&self) -> &'static Shape {
521 self.shape
522 }
523
524 #[inline(always)]
526 pub const fn data(&self) -> PtrConst {
527 self.data
528 }
529
530 #[inline]
532 pub fn scalar_type(&self) -> Option<ScalarType> {
533 ScalarType::try_from_shape(self.shape)
534 }
535
536 #[inline]
542 pub fn get<T: Facet<'facet> + ?Sized>(&self) -> Result<&'mem T, ReflectError> {
543 if self.shape != T::SHAPE {
544 Err(ReflectError::WrongShape {
545 expected: self.shape,
546 actual: T::SHAPE,
547 })
548 } else {
549 Ok(unsafe { self.data.get::<T>() })
550 }
551 }
552
553 pub fn as_str(&self) -> Option<&'mem str> {
556 let peek = self.innermost_peek();
557 if let Some(ScalarType::Str) = peek.scalar_type()
561 && !matches!(peek.shape.ty, Type::Pointer(_))
562 {
563 return unsafe { Some(peek.data.get::<str>()) };
566 }
567 #[cfg(feature = "alloc")]
568 if let Some(ScalarType::String) = peek.scalar_type() {
569 return unsafe { Some(peek.data.get::<alloc::string::String>().as_str()) };
570 }
571 #[cfg(feature = "alloc")]
572 if let Some(ScalarType::CowStr) = peek.scalar_type() {
573 return unsafe { Some(peek.data.get::<alloc::borrow::Cow<'mem, str>>().as_ref()) };
574 }
575
576 if let Type::Pointer(PointerType::Reference(vpt)) = peek.shape.ty {
578 let target_shape = vpt.target;
579
580 if let Type::Pointer(PointerType::Reference(inner_vpt)) = target_shape.ty {
582 let inner_target_shape = inner_vpt.target;
583 if let Some(ScalarType::Str) = ScalarType::try_from_shape(inner_target_shape) {
584 let outer_ptr: *const *const &str =
587 unsafe { peek.data.as_ptr::<*const &str>() };
588 let inner_ref: &str = unsafe { **outer_ptr };
589 return Some(inner_ref);
590 }
591 } else if let Some(ScalarType::Str) = ScalarType::try_from_shape(target_shape)
592 && !matches!(target_shape.ty, Type::Pointer(_))
593 {
594 return unsafe { Some(peek.data.get::<&str>()) };
596 }
597 }
598 None
599 }
600
601 #[inline]
604 pub fn as_bytes(&self) -> Option<&'mem [u8]> {
605 if let Type::Pointer(PointerType::Reference(vpt)) = self.shape.ty {
607 let target_shape = vpt.target;
608 if let Def::Slice(sd) = target_shape.def
609 && sd.t().is_type::<u8>()
610 {
611 unsafe { return Some(self.data.get::<&[u8]>()) }
612 }
613 }
614 None
615 }
616
617 #[inline]
619 pub fn into_struct(self) -> Result<PeekStruct<'mem, 'facet>, ReflectError> {
620 if let Type::User(UserType::Struct(ty)) = self.shape.ty {
621 Ok(PeekStruct { value: self, ty })
622 } else {
623 Err(ReflectError::WasNotA {
624 expected: "struct",
625 actual: self.shape,
626 })
627 }
628 }
629
630 #[inline]
632 pub fn into_enum(self) -> Result<PeekEnum<'mem, 'facet>, ReflectError> {
633 if let Type::User(UserType::Enum(ty)) = self.shape.ty {
634 Ok(PeekEnum { value: self, ty })
635 } else {
636 Err(ReflectError::WasNotA {
637 expected: "enum",
638 actual: self.shape,
639 })
640 }
641 }
642
643 #[inline]
645 pub fn into_map(self) -> Result<PeekMap<'mem, 'facet>, ReflectError> {
646 if let Def::Map(def) = self.shape.def {
647 Ok(PeekMap { value: self, def })
648 } else {
649 Err(ReflectError::WasNotA {
650 expected: "map",
651 actual: self.shape,
652 })
653 }
654 }
655
656 #[inline]
658 pub fn into_set(self) -> Result<PeekSet<'mem, 'facet>, ReflectError> {
659 if let Def::Set(def) = self.shape.def {
660 Ok(PeekSet { value: self, def })
661 } else {
662 Err(ReflectError::WasNotA {
663 expected: "set",
664 actual: self.shape,
665 })
666 }
667 }
668
669 #[inline]
671 pub fn into_list(self) -> Result<PeekList<'mem, 'facet>, ReflectError> {
672 if let Def::List(def) = self.shape.def {
673 return Ok(PeekList { value: self, def });
674 }
675
676 Err(ReflectError::WasNotA {
677 expected: "list",
678 actual: self.shape,
679 })
680 }
681
682 #[inline]
684 pub fn into_ndarray(self) -> Result<PeekNdArray<'mem, 'facet>, ReflectError> {
685 if let Def::NdArray(def) = self.shape.def {
686 return Ok(PeekNdArray { value: self, def });
687 }
688
689 Err(ReflectError::WasNotA {
690 expected: "ndarray",
691 actual: self.shape,
692 })
693 }
694
695 #[inline]
697 pub fn into_list_like(self) -> Result<PeekListLike<'mem, 'facet>, ReflectError> {
698 match self.shape.def {
699 Def::List(def) => Ok(PeekListLike::new(self, ListLikeDef::List(def))),
700 Def::Array(def) => Ok(PeekListLike::new(self, ListLikeDef::Array(def))),
701 Def::Slice(def) => {
702 Ok(PeekListLike::new(self, ListLikeDef::Slice(def)))
705 }
706 _ => {
707 match self.shape.ty {
709 Type::Pointer(ptr) => match ptr {
710 PointerType::Reference(vpt) | PointerType::Raw(vpt) => {
711 let target = vpt.target;
712 match target.def {
713 Def::Slice(def) => {
714 let ptr = unsafe { self.data.as_ptr::<*const [()]>() };
715 let ptr = PtrConst::new(unsafe {
716 NonNull::new_unchecked((*ptr) as *mut [()]).as_ptr()
717 });
718 let peek = unsafe { Peek::unchecked_new(ptr, def.t) };
719
720 return Ok(PeekListLike::new(peek, ListLikeDef::Slice(def)));
721 }
722 _ => {
723 }
725 }
726 }
727 PointerType::Function(_) => {
728 }
730 },
731 _ => {
732 }
734 }
735
736 Err(ReflectError::WasNotA {
737 expected: "list, array or slice",
738 actual: self.shape,
739 })
740 }
741 }
742 }
743
744 #[inline]
746 pub fn into_pointer(self) -> Result<PeekPointer<'mem, 'facet>, ReflectError> {
747 if let Def::Pointer(def) = self.shape.def {
748 Ok(PeekPointer { value: self, def })
749 } else {
750 Err(ReflectError::WasNotA {
751 expected: "smart pointer",
752 actual: self.shape,
753 })
754 }
755 }
756
757 #[inline]
759 pub fn into_option(self) -> Result<PeekOption<'mem, 'facet>, ReflectError> {
760 if let Def::Option(def) = self.shape.def {
761 Ok(PeekOption { value: self, def })
762 } else {
763 Err(ReflectError::WasNotA {
764 expected: "option",
765 actual: self.shape,
766 })
767 }
768 }
769
770 #[inline]
772 pub fn into_result(self) -> Result<PeekResult<'mem, 'facet>, ReflectError> {
773 if let Def::Result(def) = self.shape.def {
774 Ok(PeekResult { value: self, def })
775 } else {
776 Err(ReflectError::WasNotA {
777 expected: "result",
778 actual: self.shape,
779 })
780 }
781 }
782
783 #[inline]
785 pub fn into_tuple(self) -> Result<PeekTuple<'mem, 'facet>, ReflectError> {
786 if let Type::User(UserType::Struct(struct_type)) = self.shape.ty {
787 if struct_type.kind == StructKind::Tuple {
788 Ok(PeekTuple {
789 value: self,
790 ty: TupleType {
791 fields: struct_type.fields,
792 },
793 })
794 } else {
795 Err(ReflectError::WasNotA {
796 expected: "tuple",
797 actual: self.shape,
798 })
799 }
800 } else {
801 Err(ReflectError::WasNotA {
802 expected: "tuple",
803 actual: self.shape,
804 })
805 }
806 }
807
808 #[inline]
810 pub fn into_dynamic_value(self) -> Result<PeekDynamicValue<'mem, 'facet>, ReflectError> {
811 if let Def::DynamicValue(def) = self.shape.def {
812 Ok(PeekDynamicValue { value: self, def })
813 } else {
814 Err(ReflectError::WasNotA {
815 expected: "dynamic value",
816 actual: self.shape,
817 })
818 }
819 }
820
821 pub fn innermost_peek(self) -> Self {
827 let mut current_peek = self;
828 while let Some(inner_shape) = current_peek.shape.inner {
829 let result = unsafe { current_peek.shape.call_try_borrow_inner(current_peek.data) };
831 match result {
832 Some(Ok(inner_data)) => {
833 current_peek = Peek {
834 data: inner_data.as_const(),
835 shape: inner_shape,
836 _invariant: PhantomData,
837 };
838 }
839 Some(Err(e)) => {
840 panic!(
841 "innermost_peek: try_borrow_inner returned an error! was trying to go from {} to {}. error: {e}",
842 current_peek.shape, inner_shape
843 );
844 }
845 None => {
846 break;
848 }
849 }
850 }
851 current_peek
852 }
853
854 #[cfg(feature = "alloc")]
859 pub fn custom_serialization(&self, field: Field) -> Result<OwnedPeek<'mem>, ReflectError> {
860 let Some(proxy_def) = field.proxy() else {
861 return Err(ReflectError::OperationFailed {
862 shape: self.shape,
863 operation: "field does not have a proxy definition",
864 });
865 };
866
867 let target_shape = proxy_def.shape;
868 let tptr = target_shape.allocate().map_err(|_| ReflectError::Unsized {
869 shape: target_shape,
870 operation: "Not a Sized type",
871 })?;
872 let ser_res = unsafe { (proxy_def.convert_out)(self.data(), tptr) };
873 let err = match ser_res {
874 Ok(rptr) => {
875 if rptr.as_uninit() != tptr {
876 ReflectError::CustomSerializationError {
877 message: "convert_out did not return the expected pointer".into(),
878 src_shape: self.shape,
879 dst_shape: target_shape,
880 }
881 } else {
882 return Ok(OwnedPeek {
883 shape: target_shape,
884 data: rptr,
885 _phantom: PhantomData,
886 });
887 }
888 }
889 Err(message) => ReflectError::CustomSerializationError {
890 message,
891 src_shape: self.shape,
892 dst_shape: target_shape,
893 },
894 };
895 unsafe {
897 target_shape.deallocate_uninit(tptr).unwrap()
899 };
900 Err(err)
901 }
902
903 #[cfg(feature = "alloc")]
911 pub fn custom_serialization_from_shape(&self) -> Result<Option<OwnedPeek<'mem>>, ReflectError> {
912 let Some(proxy_def) = self.shape.proxy else {
913 return Ok(None);
914 };
915
916 let target_shape = proxy_def.shape;
917 let tptr = target_shape.allocate().map_err(|_| ReflectError::Unsized {
918 shape: target_shape,
919 operation: "Not a Sized type",
920 })?;
921
922 let ser_res = unsafe { (proxy_def.convert_out)(self.data(), tptr) };
923 let err = match ser_res {
924 Ok(rptr) => {
925 if rptr.as_uninit() != tptr {
926 ReflectError::CustomSerializationError {
927 message: "proxy convert_out did not return the expected pointer".into(),
928 src_shape: self.shape,
929 dst_shape: target_shape,
930 }
931 } else {
932 return Ok(Some(OwnedPeek {
933 shape: target_shape,
934 data: rptr,
935 _phantom: PhantomData,
936 }));
937 }
938 }
939 Err(message) => ReflectError::CustomSerializationError {
940 message,
941 src_shape: self.shape,
942 dst_shape: target_shape,
943 },
944 };
945
946 unsafe {
948 target_shape.deallocate_uninit(tptr).unwrap()
950 };
951 Err(err)
952 }
953}
954
955impl<'mem, 'facet> core::fmt::Display for Peek<'mem, 'facet> {
956 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
957 if let Some(result) = unsafe { self.shape.call_display(self.data, f) } {
958 return result;
959 }
960 write!(f, "⟨{}⟩", self.shape)
961 }
962}
963
964impl<'mem, 'facet> core::fmt::Debug for Peek<'mem, 'facet> {
965 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
966 if let Some(result) = unsafe { self.shape.call_debug(self.data, f) } {
967 return result;
968 }
969
970 write!(f, "⟨{}⟩", self.shape)
971 }
972}
973
974impl<'mem, 'facet> core::cmp::PartialEq for Peek<'mem, 'facet> {
975 #[inline]
976 fn eq(&self, other: &Self) -> bool {
977 self.partial_eq(other).unwrap_or(false)
978 }
979}
980
981impl<'mem, 'facet> core::cmp::PartialOrd for Peek<'mem, 'facet> {
982 #[inline]
983 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
984 self.partial_cmp(other).unwrap_or(None)
985 }
986}
987
988impl<'mem, 'facet> core::hash::Hash for Peek<'mem, 'facet> {
989 fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) {
990 self.hash(hasher)
991 .expect("Hashing is not supported for this shape");
992 }
993}
994
995#[derive(Clone, Copy)]
1039pub struct CovariantPeek<'mem, 'facet> {
1040 data: PtrConst,
1042
1043 shape: &'static Shape,
1045
1046 _covariant: PhantomData<(&'mem (), &'facet ())>,
1052}
1053
1054impl<'mem, 'facet> CovariantPeek<'mem, 'facet> {
1055 #[inline]
1072 pub fn new(peek: Peek<'mem, 'facet>) -> Option<Self> {
1073 if peek.variance() == Variance::Covariant {
1074 Some(Self {
1075 data: peek.data,
1076 shape: peek.shape,
1077 _covariant: PhantomData,
1078 })
1079 } else {
1080 None
1081 }
1082 }
1083
1084 #[inline]
1101 pub fn new_unchecked(peek: Peek<'mem, 'facet>) -> Self {
1102 Self::new(peek).unwrap_or_else(|| {
1103 panic!(
1104 "CovariantPeek::new_unchecked called on non-covariant type {} (variance: {:?})",
1105 peek.shape,
1106 peek.variance()
1107 )
1108 })
1109 }
1110
1111 #[inline]
1126 pub fn from_ref<T: Facet<'facet> + ?Sized>(t: &'mem T) -> Option<Self> {
1127 Self::new(Peek::new(t))
1128 }
1129
1130 #[inline]
1135 pub fn into_peek(self) -> Peek<'mem, 'facet> {
1136 Peek {
1137 data: self.data,
1138 shape: self.shape,
1139 _invariant: PhantomData,
1140 }
1141 }
1142
1143 #[inline]
1145 pub const fn shape(&self) -> &'static Shape {
1146 self.shape
1147 }
1148
1149 #[inline]
1151 pub const fn data(&self) -> PtrConst {
1152 self.data
1153 }
1154}
1155
1156impl<'mem, 'facet> core::ops::Deref for CovariantPeek<'mem, 'facet> {
1157 type Target = Peek<'mem, 'facet>;
1158
1159 #[inline]
1160 fn deref(&self) -> &Self::Target {
1161 unsafe { &*(self as *const CovariantPeek<'mem, 'facet> as *const Peek<'mem, 'facet>) }
1170 }
1171}
1172
1173impl<'mem, 'facet> core::fmt::Debug for CovariantPeek<'mem, 'facet> {
1174 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1175 f.debug_struct("CovariantPeek")
1176 .field("shape", &self.shape)
1177 .field("data", &self.data)
1178 .finish()
1179 }
1180}
1181
1182impl<'mem, 'facet> core::fmt::Display for CovariantPeek<'mem, 'facet> {
1183 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1184 core::fmt::Display::fmt(&**self, f)
1185 }
1186}
1187
1188#[cfg(test)]
1189mod tests {
1190 use super::*;
1191
1192 #[test]
1196 fn test_peek_as_str_empty_string() {
1197 let peek = Peek::new("");
1198 assert_eq!(peek.as_str(), Some(""));
1199 }
1200
1201 #[test]
1202 fn test_peek_as_str_non_empty_string() {
1203 let peek = Peek::new("hello");
1204 assert_eq!(peek.as_str(), Some("hello"));
1205 }
1206
1207 #[test]
1208 #[cfg(feature = "alloc")]
1209 fn test_peek_as_str_owned_string() {
1210 let s = alloc::string::String::from("owned string");
1211 let peek = Peek::new(&s);
1212 assert_eq!(peek.as_str(), Some("owned string"));
1213 }
1214
1215 #[test]
1218 fn test_peek_as_str_double_reference() {
1219 let value = &"hello";
1220 let peek = Peek::new(&value);
1221 assert_eq!(peek.as_str(), Some("hello"));
1222 }
1223
1224 #[test]
1225 fn test_covariant_peek_from_covariant_type() {
1226 let value = 42i32;
1228 let peek = Peek::new(&value);
1229 let covariant = CovariantPeek::new(peek);
1230 assert!(covariant.is_some());
1231
1232 let covariant = covariant.unwrap();
1234 assert_eq!(covariant.shape(), peek.shape());
1235 }
1236
1237 #[test]
1238 fn test_covariant_peek_from_ref() {
1239 let value = 42i32;
1240 let covariant = CovariantPeek::from_ref(&value);
1241 assert!(covariant.is_some());
1242 }
1243
1244 #[test]
1245 fn test_covariant_peek_deref_to_peek() {
1246 let value = "hello";
1247 let peek = Peek::new(&value);
1248 let covariant = CovariantPeek::new(peek).unwrap();
1249
1250 assert_eq!(covariant.as_str(), Some("hello"));
1252 assert_eq!(covariant.shape(), peek.shape());
1253 }
1254
1255 #[test]
1256 fn test_covariant_peek_into_peek() {
1257 let value = 42i32;
1258 let original_peek = Peek::new(&value);
1259 let covariant = CovariantPeek::new(original_peek).unwrap();
1260 let recovered_peek = covariant.into_peek();
1261
1262 assert_eq!(recovered_peek.shape(), original_peek.shape());
1263 }
1264
1265 #[test]
1266 fn test_covariant_peek_lifetime_covariance() {
1267 fn use_shorter<'a>(_p: CovariantPeek<'_, 'a>) {}
1270
1271 let value = 42i32;
1272 let covariant: CovariantPeek<'_, 'static> = CovariantPeek::from_ref(&value).unwrap();
1273
1274 use_shorter(covariant);
1276 }
1277
1278 #[test]
1279 #[cfg(feature = "alloc")]
1280 fn test_covariant_peek_vec_type() {
1281 let vec = alloc::vec![1i32, 2, 3];
1283 let peek = Peek::new(&vec);
1284 let covariant = CovariantPeek::new(peek);
1285 assert!(covariant.is_some());
1286 }
1287
1288 #[test]
1289 #[cfg(feature = "alloc")]
1290 fn test_covariant_peek_option_type() {
1291 let opt = Some(42i32);
1293 let peek = Peek::new(&opt);
1294 let covariant = CovariantPeek::new(peek);
1295 assert!(covariant.is_some());
1296 }
1297
1298 #[test]
1299 fn test_spanned_structural_hash_ignores_span() {
1300 use crate::{Span, Spanned};
1301 use core::hash::Hasher;
1302 use std::hash::DefaultHasher;
1303
1304 let a = Spanned::new(42i32, Span::new(0, 10));
1306 let b = Spanned::new(42i32, Span::new(100, 20));
1307
1308 let mut hasher_a = DefaultHasher::new();
1310 Peek::new(&a).structural_hash(&mut hasher_a);
1311 let hash_a = hasher_a.finish();
1312
1313 let mut hasher_b = DefaultHasher::new();
1314 Peek::new(&b).structural_hash(&mut hasher_b);
1315 let hash_b = hasher_b.finish();
1316
1317 assert_eq!(
1318 hash_a, hash_b,
1319 "Spanned values with same inner value should have same structural hash"
1320 );
1321 }
1322
1323 #[test]
1324 fn test_spanned_structural_hash_differs_for_different_values() {
1325 use crate::{Span, Spanned};
1326 use core::hash::Hasher;
1327 use std::hash::DefaultHasher;
1328
1329 let a = Spanned::new(42i32, Span::new(0, 10));
1331 let b = Spanned::new(99i32, Span::new(0, 10));
1332
1333 let mut hasher_a = DefaultHasher::new();
1335 Peek::new(&a).structural_hash(&mut hasher_a);
1336 let hash_a = hasher_a.finish();
1337
1338 let mut hasher_b = DefaultHasher::new();
1339 Peek::new(&b).structural_hash(&mut hasher_b);
1340 let hash_b = hasher_b.finish();
1341
1342 assert_ne!(
1343 hash_a, hash_b,
1344 "Spanned values with different inner values should have different structural hashes"
1345 );
1346 }
1347
1348 #[test]
1349 fn test_spanned_field_metadata() {
1350 use crate::Spanned;
1351 use facet_core::{Type, UserType};
1352
1353 let shape = <Spanned<i32> as facet_core::Facet>::SHAPE;
1355
1356 let struct_type = match shape.ty {
1358 Type::User(UserType::Struct(st)) => st,
1359 _ => panic!("Expected struct type"),
1360 };
1361
1362 let span_field = struct_type
1364 .fields
1365 .iter()
1366 .find(|f| f.name == "span")
1367 .expect("Should have span field");
1368
1369 assert!(
1370 span_field.is_metadata(),
1371 "span field should be marked as metadata"
1372 );
1373 assert_eq!(
1374 span_field.metadata_kind(),
1375 Some("span"),
1376 "span field should have metadata kind 'span'"
1377 );
1378
1379 let value_field = struct_type
1381 .fields
1382 .iter()
1383 .find(|f| f.name == "value")
1384 .expect("Should have value field");
1385
1386 assert!(
1387 !value_field.is_metadata(),
1388 "value field should not be marked as metadata"
1389 );
1390 }
1391}