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