facet_reflect/partial/partial_api/
result.rs

1use super::*;
2use crate::AllocatedShape;
3
4////////////////////////////////////////////////////////////////////////////////////////////////////
5// Result
6////////////////////////////////////////////////////////////////////////////////////////////////////
7impl<const BORROW: bool> Partial<'_, BORROW> {
8    /// Begin building the Ok variant of a Result
9    pub fn begin_ok(mut self) -> Result<Self, ReflectError> {
10        // Verify we're working with a Result and get the def
11        let result_def = {
12            let frame = self.frames().last().unwrap();
13            match frame.allocated.shape().def {
14                Def::Result(def) => def,
15                _ => {
16                    return Err(ReflectError::WasNotA {
17                        expected: "Result",
18                        actual: frame.allocated.shape(),
19                    });
20                }
21            }
22        };
23
24        // Check if we need to handle re-initialization.
25        let needs_reinit = {
26            let frame = self.frames().last().unwrap();
27            frame.is_init
28                || matches!(
29                    frame.tracker,
30                    Tracker::Result {
31                        building_inner: false,
32                        ..
33                    }
34                )
35        };
36
37        if needs_reinit {
38            self.prepare_for_reinitialization();
39        }
40
41        // Set tracker to indicate we're building the Ok value
42        let frame = self.frames_mut().last_mut().unwrap();
43        frame.tracker = Tracker::Result {
44            is_ok: true,
45            building_inner: true,
46        };
47
48        // Get the Ok type shape
49        let inner_shape = result_def.t;
50
51        // Allocate memory for the inner value
52        let inner_layout =
53            inner_shape
54                .layout
55                .sized_layout()
56                .map_err(|_| ReflectError::Unsized {
57                    shape: inner_shape,
58                    operation: "begin_ok, allocating Result Ok value",
59                })?;
60
61        let inner_data = if inner_layout.size() == 0 {
62            // For ZST, use a non-null but unallocated pointer
63            PtrUninit::new(NonNull::<u8>::dangling().as_ptr())
64        } else {
65            // Allocate memory for the inner value
66            let ptr = unsafe { ::alloc::alloc::alloc(inner_layout) };
67            let Some(ptr) = NonNull::new(ptr) else {
68                ::alloc::alloc::handle_alloc_error(inner_layout);
69            };
70            PtrUninit::new(ptr.as_ptr())
71        };
72
73        // Create a new frame for the inner value
74        let inner_frame = Frame::new(
75            inner_data,
76            AllocatedShape::new(inner_shape, inner_layout.size()),
77            FrameOwnership::Owned,
78        );
79        self.frames_mut().push(inner_frame);
80
81        Ok(self)
82    }
83
84    /// Begin building the Err variant of a Result
85    pub fn begin_err(mut self) -> Result<Self, ReflectError> {
86        // Verify we're working with a Result and get the def
87        let result_def = {
88            let frame = self.frames().last().unwrap();
89            match frame.allocated.shape().def {
90                Def::Result(def) => def,
91                _ => {
92                    return Err(ReflectError::WasNotA {
93                        expected: "Result",
94                        actual: frame.allocated.shape(),
95                    });
96                }
97            }
98        };
99
100        // Check if we need to handle re-initialization.
101        let needs_reinit = {
102            let frame = self.frames().last().unwrap();
103            frame.is_init
104                || matches!(
105                    frame.tracker,
106                    Tracker::Result {
107                        building_inner: false,
108                        ..
109                    }
110                )
111        };
112
113        if needs_reinit {
114            self.prepare_for_reinitialization();
115        }
116
117        // Set tracker to indicate we're building the Err value
118        let frame = self.frames_mut().last_mut().unwrap();
119        frame.tracker = Tracker::Result {
120            is_ok: false,
121            building_inner: true,
122        };
123
124        // Get the Err type shape
125        let inner_shape = result_def.e;
126
127        // Allocate memory for the inner value
128        let inner_layout =
129            inner_shape
130                .layout
131                .sized_layout()
132                .map_err(|_| ReflectError::Unsized {
133                    shape: inner_shape,
134                    operation: "begin_err, allocating Result Err value",
135                })?;
136
137        let inner_data = if inner_layout.size() == 0 {
138            // For ZST, use a non-null but unallocated pointer
139            PtrUninit::new(NonNull::<u8>::dangling().as_ptr())
140        } else {
141            // Allocate memory for the inner value
142            let ptr = unsafe { ::alloc::alloc::alloc(inner_layout) };
143            let Some(ptr) = NonNull::new(ptr) else {
144                ::alloc::alloc::handle_alloc_error(inner_layout);
145            };
146            PtrUninit::new(ptr.as_ptr())
147        };
148
149        // Create a new frame for the inner value
150        let inner_frame = Frame::new(
151            inner_data,
152            AllocatedShape::new(inner_shape, inner_layout.size()),
153            FrameOwnership::Owned,
154        );
155        self.frames_mut().push(inner_frame);
156
157        Ok(self)
158    }
159}