1use std::any::{type_name, Any};
2use std::fmt::{Debug, Formatter};
3use std::mem::ManuallyDrop;
4
5use crate::{BoxerError, Result, ReturnBoxerResult, ValueBoxContainer};
6
7#[repr(C, u8)]
8pub enum ValueBox<T: Any> {
9 Value(Option<Box<T>>),
10 #[cfg(feature = "phlow")]
11 PhlowValue(Box<crate::PhlowValue>),
12}
13
14impl<T: Any> ValueBox<T> {
15 pub fn new(object: T) -> Self {
16 Self::Value(Some(Box::new(object)))
17 }
18
19 #[cfg(feature = "phlow")]
20 pub fn new_phlow(object: T, phlow_type_fn: fn() -> phlow::PhlowType) -> Self {
21 Self::PhlowValue(Box::new(crate::PhlowValue::new(object, phlow_type_fn)))
22 }
23
24 pub fn null() -> Self {
25 Self::Value(None)
26 }
27
28 pub fn has_value(&self) -> bool {
29 match self {
30 Self::Value(value) => value.has_value(),
31 #[cfg(feature = "phlow")]
32 Self::PhlowValue(value) => {
33 <crate::PhlowValue as ValueBoxContainer<T>>::has_value(value)
34 }
35 }
36 }
37
38 pub fn replace_value(&mut self, object: T) -> Option<T> {
39 match self {
40 Self::Value(value) => value.replace_value(object),
41 #[cfg(feature = "phlow")]
42 Self::PhlowValue(value) => value.replace_value(object),
43 }
44 }
45
46 pub fn set_value(&mut self, object: T) {
47 self.replace_value(object);
48 }
49
50 pub fn clone_value(&self) -> Option<T>
51 where
52 T: Clone,
53 {
54 match self {
55 Self::Value(value) => value.clone_value(),
56 #[cfg(feature = "phlow")]
57 Self::PhlowValue(value) => value.clone_value(),
58 }
59 }
60
61 pub fn take_value(&mut self) -> Option<T> {
62 match self {
63 Self::Value(value) => value.take_value(),
64 #[cfg(feature = "phlow")]
65 Self::PhlowValue(value) => value.take_value(),
66 }
67 }
68
69 pub fn into_raw(self) -> *mut Self {
70 into_raw(Box::new(self))
71 }
72}
73
74impl<T: 'static> ValueBox<T> {
75 #[cfg(feature = "phlow")]
76 pub fn phlow_object(&mut self) -> Option<phlow::PhlowObject> {
80 match self {
81 Self::Value(_) => None,
82 Self::PhlowValue(value) => value.phlow_object(),
83 }
84 }
85}
86
87#[repr(transparent)]
88pub struct BoxRef<T: Any> {
89 value_box: ManuallyDrop<Box<ValueBox<T>>>,
90}
91
92impl<T: Any> BoxRef<T> {
93 pub fn with_ref<R>(&self, op: impl FnOnce(&T) -> Result<R>) -> Result<R> {
94 match self.value_box.as_ref() {
95 ValueBox::Value(value) => op(value.as_ref().unwrap()),
96 #[cfg(feature = "phlow")]
97 ValueBox::PhlowValue(value) => match value.as_ref() {
98 crate::PhlowValue::Lazy(value) => {
99 let value = &value.value;
100 op(value.as_ref_safe::<T>().unwrap())
101 }
102 crate::PhlowValue::Object(object) => {
103 let value = object.value_ref::<T>().unwrap();
104 op(&value)
105 }
106 },
107 }
108 }
109
110 pub fn with_mut<R>(&mut self, op: impl FnOnce(&mut T) -> Result<R>) -> Result<R> {
111 match self.value_box.as_mut() {
112 ValueBox::Value(value) => value
113 .as_mut()
114 .ok_or_else(|| BoxerError::NoValue(type_name::<T>().to_string()))
115 .and_then(|value| op(value)),
116 #[cfg(feature = "phlow")]
117 ValueBox::PhlowValue(value) => match value.as_mut() {
118 crate::PhlowValue::Lazy(value) => value
119 .value
120 .as_mut_safe::<T>()
121 .ok_or_else(|| BoxerError::NoValue(type_name::<T>().to_string()))
122 .and_then(|value| op(value)),
123 crate::PhlowValue::Object(object) => {
124 let mut value = object.value_mut::<T>().unwrap();
125 op(&mut value)
126 }
127 },
128 }
129 }
130}
131
132impl<T: Any> Debug for BoxRef<T> {
133 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
134 f.debug_struct("BoxRef")
135 .field(
136 "value",
137 if self.value_box.has_value() {
138 &"Some"
139 } else {
140 &"None"
141 },
142 )
143 .finish()
144 }
145}
146
147impl<T: Any> BoxRef<T> {
148 pub fn replace(&mut self, value: T) -> Option<T> {
149 self.value_box.replace_value(value)
150 }
151
152 pub fn take_value(&mut self) -> Option<T> {
153 self.value_box.take_value()
154 }
155}
156
157pub trait ValueBoxPointer<T: Any> {
158 fn to_ref(&self) -> Result<BoxRef<T>>;
160
161 fn take_value(&self) -> Result<T>;
163
164 fn with_ref<R: Any, F>(&self, op: F) -> Result<R>
167 where
168 F: FnOnce(&T) -> Result<R>,
169 {
170 self.to_ref()?.with_ref(op)
171 }
172
173 fn with_option_ref<R: Any, F>(&self, op: F) -> Result<R>
178 where
179 F: FnOnce(Option<&T>) -> Result<R>,
180 {
181 match self.to_ref() {
182 Ok(value) => value.with_ref(|value| op(Some(value))),
183 Err(_) => op(None),
184 }
185 }
186
187 fn with_ref_ok<R: Any, F>(&self, op: F) -> Result<R>
190 where
191 F: FnOnce(&T) -> R,
192 {
193 self.with_ref(|value| Ok(op(value)))
194 }
195
196 fn with_mut<R: Any, F>(&self, op: F) -> Result<R>
199 where
200 F: FnOnce(&mut T) -> Result<R>,
201 {
202 self.to_ref()?.with_mut(op)
203 }
204
205 fn with_mut_ok<R: Any, F>(&self, op: F) -> Result<R>
208 where
209 F: FnOnce(&mut T) -> R,
210 {
211 self.with_mut(|value| Ok(op(value)))
212 }
213
214 fn with_clone<R: Any, F>(&self, op: F) -> Result<R>
217 where
218 F: FnOnce(T) -> Result<R>,
219 T: Clone,
220 {
221 self.to_ref()?.with_ref(|value| op(value.clone()))
222 }
223
224 fn with_clone_ok<R: Any, F>(&self, op: F) -> Result<R>
227 where
228 F: FnOnce(T) -> R,
229 T: Clone,
230 {
231 self.with_clone(|value| Ok(op(value)))
232 }
233
234 fn with_ref_ref<R: Any, F, P: Any>(&self, ptr: *mut ValueBox<P>, op: F) -> Result<R>
237 where
238 F: FnOnce(&T, &P) -> Result<R>,
239 {
240 self.with_ref(|t| ptr.with_ref(|p| op(t, p)))
241 }
242
243 fn with_ref_ref_ref<R: Any, F, P1: Any, P2: Any>(
246 &self,
247 ptr1: *mut ValueBox<P1>,
248 ptr2: *mut ValueBox<P2>,
249 op: F,
250 ) -> Result<R>
251 where
252 F: FnOnce(&T, &P1, &P2) -> Result<R>,
253 {
254 self.with_ref(|t| ptr1.with_ref(|p1| ptr2.with_ref(|p2| op(t, p1, p2))))
255 }
256
257 fn with_ref_ref_ref_ref<R: Any, F, P1: Any, P2: Any, P3: Any>(
260 &self,
261 ptr1: *mut ValueBox<P1>,
262 ptr2: *mut ValueBox<P2>,
263 ptr3: *mut ValueBox<P3>,
264 op: F,
265 ) -> Result<R>
266 where
267 F: FnOnce(&T, &P1, &P2, &P3) -> Result<R>,
268 {
269 self.with_ref(|t| {
270 ptr1.with_ref(|p1| ptr2.with_ref(|p2| ptr3.with_ref(|p3| op(&t, &p1, &p2, &p3))))
271 })
272 }
273
274 fn replace_value<F>(&self, op: F) -> Result<()>
278 where
279 F: FnOnce(T) -> T,
280 {
281 self.to_ref().and_then(|mut t| {
282 t.take_value()
283 .ok_or_else(|| BoxerError::NoValue(type_name::<T>().to_string()))
284 .map(|previous_value| {
285 let new_value = op(previous_value);
286 t.replace(new_value);
287 })
288 })
289 }
290
291 fn release(self);
292
293 fn has_value(&self) -> bool {
294 self.to_ref().map(|_| true).unwrap_or(false)
295 }
296
297 #[deprecated(since = "0.1.0", note = "please use `has_value` instead")]
298 fn is_valid(&self) -> bool {
299 self.has_value()
300 }
301
302 #[deprecated(since = "0.1.0", note = "please use `with_ref` or `with_mut` instead")]
303 fn with_not_null<Block>(&self, block: Block)
304 where
305 Block: FnOnce(&mut T),
306 {
307 self.with_mut_ok(|value| block(value)).log();
308 }
309
310 #[deprecated(since = "0.1.0", note = "please use `with_ref` or `with_mut` instead")]
311 fn with_not_null_return<Block, Return: Any>(&self, default: Return, block: Block) -> Return
312 where
313 Block: FnOnce(&mut T) -> Return,
314 {
315 self.with_mut_ok(|value| block(value)).or_log(default)
316 }
317
318 #[deprecated(since = "0.1.0", note = "please use `with_ref` or `with_mut` instead")]
319 fn with_value<DefaultBlock, Block, Return: Any>(
320 &self,
321 default: DefaultBlock,
322 block: Block,
323 ) -> Return
324 where
325 DefaultBlock: FnOnce() -> Return,
326 Block: FnOnce(T) -> Return,
327 T: Clone,
328 {
329 self.with_clone_ok(|value| block(value))
330 .unwrap_or_else(|_| default())
331 }
332
333 #[deprecated(since = "0.1.0", note = "please use `with_ref` or `with_mut` instead")]
334 fn with_not_null_value<Block>(&self, block: Block)
335 where
336 Block: FnOnce(T),
337 T: Clone,
338 {
339 self.with_ref_ok(|value| block(value.clone())).log();
340 }
341
342 #[deprecated(since = "0.1.0", note = "please use `with_ref` or `with_mut` instead")]
343 fn with_not_null_value_return<Block, Return: Any>(
344 &self,
345 default: Return,
346 block: Block,
347 ) -> Return
348 where
349 Block: FnOnce(T) -> Return,
350 T: Clone,
351 {
352 self.with_ref_ok(|reference| block(reference.clone()))
353 .unwrap_or(default)
354 }
355}
356
357impl<T: Any> ValueBoxPointer<T> for *mut ValueBox<T> {
358 fn to_ref(&self) -> Result<BoxRef<T>> {
359 if self.is_null() {
360 return BoxerError::NullPointer(type_name::<T>().to_string()).into();
361 }
362 let value_box = ManuallyDrop::new(unsafe { from_raw(*self) });
363
364 if value_box.has_value() {
365 Ok(BoxRef { value_box })
366 } else {
367 BoxerError::NoValue(type_name::<T>().to_string()).into()
368 }
369 }
370
371 fn take_value(&self) -> Result<T> {
372 if self.is_null() {
373 return BoxerError::NullPointer(type_name::<T>().to_string()).into();
374 }
375 let mut value_box = ManuallyDrop::new(unsafe { from_raw(*self) });
376 value_box
377 .take_value()
378 .ok_or(BoxerError::NoValue(type_name::<T>().to_string()))
379 }
380
381 fn release(self) {
382 let result = if self.is_null() {
383 BoxerError::NullPointer(type_name::<T>().to_string()).into()
384 } else {
385 unsafe { Ok(from_raw(self)) }
386 };
387 result.log();
388 }
389}
390
391pub unsafe fn from_raw<T>(pointer: *mut T) -> Box<T> {
394 assert_eq!(
395 pointer.is_null(),
396 false,
397 "from_raw(): Pointer must not be null!"
398 );
399 assert_eq!(
400 std::mem::size_of::<*mut T>(),
401 std::mem::size_of::<*mut std::ffi::c_void>(),
402 "The pointer must be compatible with void*"
403 );
404 Box::from_raw(pointer)
405}
406
407pub fn into_raw<T>(_box: Box<T>) -> *mut T {
408 assert_eq!(
409 std::mem::size_of::<*mut T>(),
410 std::mem::size_of::<*mut std::ffi::c_void>(),
411 "The pointer must be compatible with void*"
412 );
413 Box::into_raw(_box)
414}
415
416#[cfg(test)]
417mod test {
418 #![allow(deprecated)]
419 #![allow(dead_code)]
420
421 use std::error::Error;
422 use std::ffi::c_void;
423 use std::fmt::Display;
424 use std::mem::size_of;
425 use std::rc::Rc;
426
427 use crate::value_box::{ValueBox, ValueBoxPointer};
428
429 use super::*;
430
431 #[derive(Debug)]
432 pub struct CustomError {}
433
434 impl Display for CustomError {
435 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
436 f.write_str("CustomError")
437 }
438 }
439
440 impl Error for CustomError {}
441
442 #[test]
443 pub fn value_box_size_in_memory() -> Result<()> {
444 assert_eq!(size_of::<ValueBox<c_void>>(), size_of::<ValueBox<u8>>());
446 assert_eq!(size_of::<ValueBox<(u64, u64)>>(), size_of::<ValueBox<u8>>());
447 assert_eq!(size_of::<ValueBox<()>>(), size_of::<ValueBox<u8>>());
448 assert_eq!(
449 size_of::<ValueBox<Box<dyn Error>>>(),
450 size_of::<ValueBox<u8>>()
451 );
452
453 Ok(())
454 }
455
456 #[test]
457 pub fn value_box_as_ref_mut() -> Result<()> {
458 let value_box = ValueBox::new(5);
459 let value_box_ptr = value_box.into_raw();
460 let value = value_box_ptr.with_ref_ok(|value| value.clone())?;
461 assert_eq!(value, 5);
462
463 Ok(())
464 }
465
466 #[test]
467 fn value_box_with_not_null_value() {
468 let value_box = ValueBox::new(5);
469
470 let value_box_ptr = value_box.into_raw();
471 assert_eq!(value_box_ptr.is_null(), false);
472
473 let mut result = 0;
474 value_box_ptr.with_not_null_value(|value| result = value * 2);
475 assert_eq!(value_box_ptr.is_null(), false);
476 assert_eq!(result, 10);
477
478 value_box_ptr.release();
479 }
480
481 #[test]
482 fn value_box_with_not_null_value_return() {
483 let value_box = ValueBox::new(5);
484
485 let value_box_ptr = value_box.into_raw();
486 assert_eq!(value_box_ptr.is_null(), false);
487
488 let result = value_box_ptr.with_not_null_value_return(0, |value| value * 2);
489 assert_eq!(value_box_ptr.is_null(), false);
490 assert_eq!(result, 10);
491
492 value_box_ptr.release();
493 }
494
495 #[test]
496 fn value_box_drop() {
497 let value = Rc::new(42);
498
499 let ptr = ValueBox::new(value.clone()).into_raw();
500 assert_eq!(Rc::strong_count(&value), 2);
501 ptr.release();
502
503 assert_eq!(Rc::strong_count(&value), 1);
504 }
505}