facet_reflect/partial/
heap_value.rs1use crate::Peek;
2use crate::ReflectError;
3use crate::trace;
4use alloc::boxed::Box;
5use core::ptr::NonNull;
6use core::{alloc::Layout, marker::PhantomData};
7use facet_core::{Facet, PtrConst, PtrMut, Shape};
8
9pub struct HeapValue<'facet> {
11 pub(crate) guard: Option<Guard>,
12 pub(crate) shape: &'static Shape,
13 pub(crate) phantom: PhantomData<&'facet ()>,
14}
15
16impl<'facet> Drop for HeapValue<'facet> {
17 fn drop(&mut self) {
18 if let Some(guard) = self.guard.take() {
19 if let Some(drop_fn) = self.shape.vtable.drop_in_place {
20 unsafe { drop_fn(PtrMut::new(guard.ptr)) };
21 }
22 drop(guard);
23 }
24 }
25}
26
27impl<'facet> HeapValue<'facet> {
28 pub fn peek(&self) -> Peek<'_, 'facet> {
30 unsafe { Peek::unchecked_new(PtrConst::new(self.guard.as_ref().unwrap().ptr), self.shape) }
31 }
32
33 pub fn shape(&self) -> &'static Shape {
35 self.shape
36 }
37
38 pub fn materialize<T: Facet<'facet>>(mut self) -> Result<T, ReflectError> {
40 trace!(
41 "HeapValue::materialize: Materializing heap value with shape {} to type {}",
42 self.shape,
43 T::SHAPE
44 );
45 if self.shape != T::SHAPE {
46 trace!(
47 "HeapValue::materialize: Shape mismatch! Expected {}, but heap value has {}",
48 T::SHAPE,
49 self.shape
50 );
51 return Err(ReflectError::WrongShape {
52 expected: self.shape,
53 actual: T::SHAPE,
54 });
55 }
56
57 trace!("HeapValue::materialize: Shapes match, proceeding with materialization");
58 let guard = self.guard.take().unwrap();
59 let data = PtrConst::new(guard.ptr);
60 let res = unsafe { data.read::<T>() };
61 drop(guard); trace!("HeapValue::materialize: Successfully materialized value");
63 Ok(res)
64 }
65}
66
67impl<'facet> HeapValue<'facet> {
68 pub fn fmt_display(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
70 if let Some(display_fn) = self.shape.vtable.display {
71 unsafe { display_fn(PtrConst::new(self.guard.as_ref().unwrap().ptr), f) }
72 } else {
73 write!(f, "⟨{}⟩", self.shape)
74 }
75 }
76
77 pub fn fmt_debug(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
79 if let Some(debug_fn) = self.shape.vtable.debug {
80 unsafe { debug_fn(PtrConst::new(self.guard.as_ref().unwrap().ptr), f) }
81 } else {
82 write!(f, "⟨{}⟩", self.shape)
83 }
84 }
85}
86
87impl<'facet> core::fmt::Display for HeapValue<'facet> {
88 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
89 self.fmt_display(f)
90 }
91}
92
93impl<'facet> core::fmt::Debug for HeapValue<'facet> {
94 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
95 self.fmt_debug(f)
96 }
97}
98
99impl<'facet> PartialEq for HeapValue<'facet> {
100 fn eq(&self, other: &Self) -> bool {
101 if self.shape != other.shape {
102 return false;
103 }
104 if let Some(eq_fn) = self.shape.vtable.partial_eq {
105 unsafe {
106 eq_fn(
107 PtrConst::new(self.guard.as_ref().unwrap().ptr),
108 PtrConst::new(other.guard.as_ref().unwrap().ptr),
109 )
110 }
111 } else {
112 false
113 }
114 }
115}
116
117impl<'facet> PartialOrd for HeapValue<'facet> {
118 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
119 if self.shape != other.shape {
120 return None;
121 }
122 if let Some(partial_ord_fn) = self.shape.vtable.partial_ord {
123 unsafe {
124 partial_ord_fn(
125 PtrConst::new(self.guard.as_ref().unwrap().ptr),
126 PtrConst::new(other.guard.as_ref().unwrap().ptr),
127 )
128 }
129 } else {
130 None
131 }
132 }
133}
134
135pub struct Guard {
141 pub(crate) ptr: NonNull<u8>,
143 pub(crate) layout: Layout,
145}
146
147impl Drop for Guard {
148 fn drop(&mut self) {
149 if self.layout.size() != 0 {
150 trace!(
151 "Deallocating memory at ptr: {:p}, size: {}, align: {}",
152 self.ptr,
153 self.layout.size(),
154 self.layout.align()
155 );
156 unsafe { alloc::alloc::dealloc(self.ptr.as_ptr(), self.layout) };
158 }
159 }
160}
161
162impl<'facet> HeapValue<'facet> {
163 pub(crate) unsafe fn into_box_unchecked<T: Facet<'facet>>(mut self) -> Box<T> {
169 let guard = self.guard.take().unwrap();
170 let ptr = guard.ptr.as_ptr() as *mut T;
171 core::mem::forget(guard);
173 unsafe { Box::from_raw(ptr) }
174 }
175
176 pub unsafe fn as_ref<T>(&self) -> &T {
182 unsafe { &*(self.guard.as_ref().unwrap().ptr.as_ptr() as *const T) }
183 }
184}