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