shape_value/v2/
typed_result.rs1use super::string_obj::StringObj;
10
11pub const RESULT_TAG_OK: u8 = 0;
13pub const RESULT_TAG_ERR: u8 = 1;
15
16#[repr(C)]
27pub struct ResultF64Str {
28 pub tag: u8,
29 pub _pad: [u8; 7],
30 payload: u64, }
32
33impl ResultF64Str {
34 #[inline]
36 pub fn ok(value: f64) -> Self {
37 Self {
38 tag: RESULT_TAG_OK,
39 _pad: [0; 7],
40 payload: value.to_bits(),
41 }
42 }
43
44 #[inline]
46 pub fn err(err_ptr: *const StringObj) -> Self {
47 Self {
48 tag: RESULT_TAG_ERR,
49 _pad: [0; 7],
50 payload: err_ptr as u64,
51 }
52 }
53
54 #[inline]
55 pub fn is_ok(&self) -> bool {
56 self.tag == RESULT_TAG_OK
57 }
58
59 #[inline]
60 pub fn is_err(&self) -> bool {
61 self.tag == RESULT_TAG_ERR
62 }
63
64 #[inline]
66 pub fn unwrap_ok(&self) -> f64 {
67 debug_assert!(self.is_ok());
68 f64::from_bits(self.payload)
69 }
70
71 #[inline]
73 pub fn unwrap_err(&self) -> *const StringObj {
74 debug_assert!(self.is_err());
75 self.payload as *const StringObj
76 }
77}
78
79#[repr(C)]
90pub struct ResultI64Str {
91 pub tag: u8,
92 pub _pad: [u8; 7],
93 payload: u64, }
95
96impl ResultI64Str {
97 #[inline]
99 pub fn ok(value: i64) -> Self {
100 Self {
101 tag: RESULT_TAG_OK,
102 _pad: [0; 7],
103 payload: value as u64,
104 }
105 }
106
107 #[inline]
109 pub fn err(err_ptr: *const StringObj) -> Self {
110 Self {
111 tag: RESULT_TAG_ERR,
112 _pad: [0; 7],
113 payload: err_ptr as u64,
114 }
115 }
116
117 #[inline]
118 pub fn is_ok(&self) -> bool {
119 self.tag == RESULT_TAG_OK
120 }
121
122 #[inline]
123 pub fn is_err(&self) -> bool {
124 self.tag == RESULT_TAG_ERR
125 }
126
127 #[inline]
129 pub fn unwrap_ok(&self) -> i64 {
130 debug_assert!(self.is_ok());
131 self.payload as i64
132 }
133
134 #[inline]
136 pub fn unwrap_err(&self) -> *const StringObj {
137 debug_assert!(self.is_err());
138 self.payload as *const StringObj
139 }
140}
141
142#[repr(C)]
153pub struct ResultPtrStr {
154 pub tag: u8,
155 pub _pad: [u8; 7],
156 payload: u64, }
158
159impl ResultPtrStr {
160 #[inline]
162 pub fn ok(ptr: *const u8) -> Self {
163 Self {
164 tag: RESULT_TAG_OK,
165 _pad: [0; 7],
166 payload: ptr as u64,
167 }
168 }
169
170 #[inline]
172 pub fn err(err_ptr: *const StringObj) -> Self {
173 Self {
174 tag: RESULT_TAG_ERR,
175 _pad: [0; 7],
176 payload: err_ptr as u64,
177 }
178 }
179
180 #[inline]
181 pub fn is_ok(&self) -> bool {
182 self.tag == RESULT_TAG_OK
183 }
184
185 #[inline]
186 pub fn is_err(&self) -> bool {
187 self.tag == RESULT_TAG_ERR
188 }
189
190 #[inline]
192 pub fn unwrap_ok(&self) -> *const u8 {
193 debug_assert!(self.is_ok());
194 self.payload as *const u8
195 }
196
197 #[inline]
199 pub fn unwrap_err(&self) -> *const StringObj {
200 debug_assert!(self.is_err());
201 self.payload as *const StringObj
202 }
203}
204
205pub const RESULT_OFFSET_TAG: usize = 0;
207pub const RESULT_OFFSET_PAYLOAD: usize = 8;
208
209#[cfg(test)]
210mod tests {
211 use super::*;
212
213 #[test]
216 fn test_result_f64_ok() {
217 let r = ResultF64Str::ok(3.14);
218 assert!(r.is_ok());
219 assert!(!r.is_err());
220 assert!((r.unwrap_ok() - 3.14).abs() < f64::EPSILON);
221 }
222
223 #[test]
224 fn test_result_f64_err() {
225 let err = StringObj::new("something went wrong");
226 let r = ResultF64Str::err(err);
227 assert!(r.is_err());
228 assert!(!r.is_ok());
229 assert_eq!(r.unwrap_err(), err as *const StringObj);
230 unsafe { StringObj::drop(err) };
231 }
232
233 #[test]
234 fn test_size_of_result_f64_str() {
235 assert_eq!(std::mem::size_of::<ResultF64Str>(), 16);
236 }
237
238 #[test]
241 fn test_result_i64_ok() {
242 let r = ResultI64Str::ok(42);
243 assert!(r.is_ok());
244 assert_eq!(r.unwrap_ok(), 42);
245 }
246
247 #[test]
248 fn test_result_i64_ok_negative() {
249 let r = ResultI64Str::ok(-100);
250 assert!(r.is_ok());
251 assert_eq!(r.unwrap_ok(), -100);
252 }
253
254 #[test]
255 fn test_result_i64_err() {
256 let err = StringObj::new("i64 error");
257 let r = ResultI64Str::err(err);
258 assert!(r.is_err());
259 assert_eq!(r.unwrap_err(), err as *const StringObj);
260 unsafe { StringObj::drop(err) };
261 }
262
263 #[test]
264 fn test_size_of_result_i64_str() {
265 assert_eq!(std::mem::size_of::<ResultI64Str>(), 16);
266 }
267
268 #[test]
271 fn test_result_ptr_ok() {
272 let val: u8 = 99;
273 let r = ResultPtrStr::ok(&val as *const u8);
274 assert!(r.is_ok());
275 assert_eq!(r.unwrap_ok(), &val as *const u8);
276 }
277
278 #[test]
279 fn test_result_ptr_err() {
280 let err = StringObj::new("ptr error");
281 let r = ResultPtrStr::err(err);
282 assert!(r.is_err());
283 assert_eq!(r.unwrap_err(), err as *const StringObj);
284 unsafe { StringObj::drop(err) };
285 }
286
287 #[test]
288 fn test_size_of_result_ptr_str() {
289 assert_eq!(std::mem::size_of::<ResultPtrStr>(), 16);
290 }
291
292 #[test]
295 fn test_result_field_offsets() {
296 let r = ResultF64Str::ok(1.0);
297 let base = &r as *const _ as usize;
298 let tag_offset = &r.tag as *const _ as usize - base;
299 let payload_offset = &r.payload as *const _ as usize - base;
300
301 assert_eq!(tag_offset, RESULT_OFFSET_TAG);
302 assert_eq!(payload_offset, RESULT_OFFSET_PAYLOAD);
303 }
304
305 #[test]
308 fn test_tag_constants() {
309 assert_eq!(RESULT_TAG_OK, 0);
310 assert_eq!(RESULT_TAG_ERR, 1);
311 assert_ne!(RESULT_TAG_OK, RESULT_TAG_ERR);
312 }
313}