facet_reflect/partial/
heap_value.rs1use crate::Peek;
2use crate::ReflectError;
3use crate::trace;
4use core::ptr::NonNull;
5use core::{alloc::Layout, marker::PhantomData};
6use facet_core::{Facet, PtrConst, PtrMut, Shape};
7
8pub struct HeapValue<'facet, const BORROW: bool = true> {
14 pub(crate) guard: Option<Guard>,
15 pub(crate) shape: &'static Shape,
16 pub(crate) phantom: PhantomData<&'facet ()>,
17}
18
19impl<'facet, const BORROW: bool> Drop for HeapValue<'facet, BORROW> {
20 fn drop(&mut self) {
21 if let Some(guard) = self.guard.take() {
22 unsafe {
23 self.shape
24 .call_drop_in_place(PtrMut::new(guard.ptr.as_ptr()));
25 }
26 drop(guard);
27 }
28 }
29}
30
31impl<'facet, const BORROW: bool> HeapValue<'facet, BORROW> {
32 pub fn peek(&self) -> Peek<'_, 'facet> {
34 unsafe {
35 Peek::unchecked_new(
36 PtrConst::new(self.guard.as_ref().unwrap().ptr.as_ptr()),
37 self.shape,
38 )
39 }
40 }
41
42 pub fn shape(&self) -> &'static Shape {
44 self.shape
45 }
46
47 pub fn materialize<T: Facet<'facet>>(mut self) -> Result<T, ReflectError> {
49 trace!(
50 "HeapValue::materialize: Materializing heap value with shape {} to type {}",
51 self.shape,
52 T::SHAPE
53 );
54 if self.shape != T::SHAPE {
55 trace!(
56 "HeapValue::materialize: Shape mismatch! Expected {}, but heap value has {}",
57 T::SHAPE,
58 self.shape
59 );
60 return Err(ReflectError::WrongShape {
61 expected: self.shape,
62 actual: T::SHAPE,
63 });
64 }
65
66 trace!("HeapValue::materialize: Shapes match, proceeding with materialization");
67 let guard = self.guard.take().unwrap();
68 let data = PtrConst::new(guard.ptr.as_ptr());
69 let res = unsafe { data.read::<T>() };
70 drop(guard); trace!("HeapValue::materialize: Successfully materialized value");
72 Ok(res)
73 }
74}
75
76impl<'facet, const BORROW: bool> HeapValue<'facet, BORROW> {
77 pub fn fmt_display(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
79 let ptr = PtrConst::new(self.guard.as_ref().unwrap().ptr.as_ptr());
80 if let Some(result) = unsafe { self.shape.call_display(ptr, f) } {
81 return result;
82 }
83 write!(f, "⟨{}⟩", self.shape)
84 }
85
86 pub fn fmt_debug(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
88 let ptr = PtrConst::new(self.guard.as_ref().unwrap().ptr.as_ptr());
89 if let Some(result) = unsafe { self.shape.call_debug(ptr, f) } {
90 return result;
91 }
92 write!(f, "⟨{}⟩", self.shape)
93 }
94}
95
96impl<'facet, const BORROW: bool> core::fmt::Display for HeapValue<'facet, BORROW> {
97 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
98 self.fmt_display(f)
99 }
100}
101
102impl<'facet, const BORROW: bool> core::fmt::Debug for HeapValue<'facet, BORROW> {
103 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
104 self.fmt_debug(f)
105 }
106}
107
108impl<'facet, const BORROW: bool> PartialEq for HeapValue<'facet, BORROW> {
109 fn eq(&self, other: &Self) -> bool {
110 if self.shape != other.shape {
111 return false;
112 }
113 let self_ptr = PtrConst::new(self.guard.as_ref().unwrap().ptr.as_ptr());
114 let other_ptr = PtrConst::new(other.guard.as_ref().unwrap().ptr.as_ptr());
115 unsafe { self.shape.call_partial_eq(self_ptr, other_ptr) }.unwrap_or(false)
116 }
117}
118
119impl<'facet, const BORROW: bool> PartialOrd for HeapValue<'facet, BORROW> {
120 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
121 if self.shape != other.shape {
122 return None;
123 }
124 let self_ptr = PtrConst::new(self.guard.as_ref().unwrap().ptr.as_ptr());
125 let other_ptr = PtrConst::new(other.guard.as_ref().unwrap().ptr.as_ptr());
126 unsafe { self.shape.call_partial_cmp(self_ptr, other_ptr) }.flatten()
127 }
128}
129
130pub struct Guard {
136 pub(crate) ptr: NonNull<u8>,
138 pub(crate) layout: Layout,
140 pub(crate) should_dealloc: bool,
143}
144
145impl Drop for Guard {
146 fn drop(&mut self) {
147 if self.should_dealloc && self.layout.size() != 0 {
148 trace!(
149 "Deallocating memory at ptr: {:p}, size: {}, align: {}",
150 self.ptr,
151 self.layout.size(),
152 self.layout.align()
153 );
154 unsafe { alloc::alloc::dealloc(self.ptr.as_ptr(), self.layout) };
156 }
157 }
158}
159
160impl<'facet, const BORROW: bool> HeapValue<'facet, BORROW> {
161 pub unsafe fn as_ref<T>(&self) -> &T {
167 unsafe { &*(self.guard.as_ref().unwrap().ptr.as_ptr() as *const T) }
168 }
169}