Skip to main content

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(self.err(ReflectErrorKind::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        // Get the type_plan before modifying tracker
43        let parent_type_plan = self.frames().last().unwrap().type_plan;
44        self.mode.stack_mut().last_mut().unwrap().tracker = Tracker::Result {
45            is_ok: true,
46            building_inner: true,
47        };
48
49        // Get the Ok type shape
50        let inner_shape = result_def.t;
51
52        // Allocate memory for the inner value
53        let inner_layout = inner_shape.layout.sized_layout().map_err(|_| {
54            self.err(ReflectErrorKind::Unsized {
55                shape: inner_shape,
56                operation: "begin_ok, allocating Result Ok value",
57            })
58        })?;
59
60        let inner_data = if inner_layout.size() == 0 {
61            // For ZST, use a non-null but unallocated pointer
62            PtrUninit::new(NonNull::<u8>::dangling().as_ptr())
63        } else {
64            // Allocate memory for the inner value
65            let ptr = unsafe { ::alloc::alloc::alloc(inner_layout) };
66            let Some(ptr) = NonNull::new(ptr) else {
67                ::alloc::alloc::handle_alloc_error(inner_layout);
68            };
69            PtrUninit::new(ptr.as_ptr())
70        };
71
72        // Create a new frame for the inner value
73        // Get child type plan NodeId for Result Ok type
74        let (ok_node_id, _err_node_id) = self
75            .root_plan
76            .result_nodes_id(parent_type_plan)
77            .expect("TypePlan should have Result nodes");
78        let inner_frame = Frame::new(
79            inner_data,
80            AllocatedShape::new(inner_shape, inner_layout.size()),
81            FrameOwnership::Owned,
82            ok_node_id,
83        );
84        self.mode.stack_mut().push(inner_frame);
85
86        Ok(self)
87    }
88
89    /// Begin building the Err variant of a Result
90    pub fn begin_err(mut self) -> Result<Self, ReflectError> {
91        // Verify we're working with a Result and get the def
92        let result_def = {
93            let frame = self.frames().last().unwrap();
94            match frame.allocated.shape().def {
95                Def::Result(def) => def,
96                _ => {
97                    return Err(self.err(ReflectErrorKind::WasNotA {
98                        expected: "Result",
99                        actual: frame.allocated.shape(),
100                    }));
101                }
102            }
103        };
104
105        // Check if we need to handle re-initialization.
106        let needs_reinit = {
107            let frame = self.frames().last().unwrap();
108            frame.is_init
109                || matches!(
110                    frame.tracker,
111                    Tracker::Result {
112                        building_inner: false,
113                        ..
114                    }
115                )
116        };
117
118        if needs_reinit {
119            self.prepare_for_reinitialization();
120        }
121
122        // Set tracker to indicate we're building the Err value
123        // Get the type_plan before modifying tracker
124        let parent_type_plan = self.frames().last().unwrap().type_plan;
125        self.mode.stack_mut().last_mut().unwrap().tracker = Tracker::Result {
126            is_ok: false,
127            building_inner: true,
128        };
129
130        // Get the Err type shape
131        let inner_shape = result_def.e;
132
133        // Allocate memory for the inner value
134        let inner_layout = inner_shape.layout.sized_layout().map_err(|_| {
135            self.err(ReflectErrorKind::Unsized {
136                shape: inner_shape,
137                operation: "begin_err, allocating Result Err value",
138            })
139        })?;
140
141        let inner_data = if inner_layout.size() == 0 {
142            // For ZST, use a non-null but unallocated pointer
143            PtrUninit::new(NonNull::<u8>::dangling().as_ptr())
144        } else {
145            // Allocate memory for the inner value
146            let ptr = unsafe { ::alloc::alloc::alloc(inner_layout) };
147            let Some(ptr) = NonNull::new(ptr) else {
148                ::alloc::alloc::handle_alloc_error(inner_layout);
149            };
150            PtrUninit::new(ptr.as_ptr())
151        };
152
153        // Create a new frame for the inner value
154        // Get child type plan NodeId for Result Err type
155        let (_ok_node_id, err_node_id) = self
156            .root_plan
157            .result_nodes_id(parent_type_plan)
158            .expect("TypePlan should have Result nodes");
159        let inner_frame = Frame::new(
160            inner_data,
161            AllocatedShape::new(inner_shape, inner_layout.size()),
162            FrameOwnership::Owned,
163            err_node_id,
164        );
165        self.mode.stack_mut().push(inner_frame);
166
167        Ok(self)
168    }
169}