facet_reflect/partial/partial_api/build.rs
1use super::*;
2
3////////////////////////////////////////////////////////////////////////////////////////////////////
4// Build
5////////////////////////////////////////////////////////////////////////////////////////////////////
6impl<'facet, const BORROW: bool> Partial<'facet, BORROW> {
7 /// Builds the value, consuming the Partial.
8 pub fn build(mut self) -> Result<HeapValue<'facet, BORROW>, ReflectError> {
9 if self.frames().len() != 1 {
10 return Err(ReflectError::InvariantViolation {
11 invariant: "Partial::build() expects a single frame — call end() until that's the case",
12 });
13 }
14
15 let frame = self.frames_mut().pop().unwrap();
16
17 // Check initialization before proceeding
18 if let Err(e) = frame.require_full_initialization() {
19 // Put the frame back so Drop can handle cleanup properly
20 self.frames_mut().push(frame);
21 return Err(e);
22 }
23
24 // Check invariants if present
25 // Safety: The value is fully initialized at this point (we just checked with require_full_initialization)
26 let value_ptr = unsafe { frame.data.assume_init().as_const() };
27 if let Some(result) = unsafe { frame.shape.call_invariants(value_ptr) } {
28 match result {
29 Ok(()) => {
30 // Invariants passed
31 }
32 Err(msg) => {
33 // Put the frame back so Drop can handle cleanup properly
34 self.frames_mut().push(frame);
35 // Leak the string to get a 'static lifetime for the error
36 let static_msg: &'static str = Box::leak(msg.into_boxed_str());
37 return Err(ReflectError::InvariantViolation {
38 invariant: static_msg,
39 });
40 }
41 }
42 }
43
44 // Mark as built to prevent Drop from cleaning up the value
45 self.state = PartialState::Built;
46
47 match frame
48 .shape
49 .layout
50 .sized_layout()
51 .map_err(|_layout_err| ReflectError::Unsized {
52 shape: frame.shape,
53 operation: "build (final check for sized layout)",
54 }) {
55 Ok(layout) => {
56 // Determine if we should deallocate based on ownership
57 let should_dealloc = !matches!(frame.ownership, FrameOwnership::ManagedElsewhere);
58
59 Ok(HeapValue {
60 guard: Some(Guard {
61 ptr: unsafe { NonNull::new_unchecked(frame.data.as_mut_byte_ptr()) },
62 layout,
63 should_dealloc,
64 }),
65 shape: frame.shape,
66 phantom: PhantomData,
67 })
68 }
69 Err(e) => {
70 // Put the frame back for proper cleanup
71 self.frames_mut().push(frame);
72 Err(e)
73 }
74 }
75 }
76}