serde_untagged/
any.rs

1use alloc::boxed::Box;
2#[cfg(any(debug_assertions, miri))]
3use core::any::{self, TypeId};
4use core::mem;
5
6pub(crate) struct ErasedValue {
7    ptr: *mut (),
8    drop: unsafe fn(*mut ()),
9    #[cfg(any(debug_assertions, miri))]
10    type_id: TypeId,
11    #[cfg(any(debug_assertions, miri))]
12    type_name: &'static str,
13}
14
15impl ErasedValue {
16    pub(crate) unsafe fn new<T>(value: T) -> Self {
17        ErasedValue {
18            ptr: Box::into_raw(Box::new(value)).cast(),
19            drop: {
20                unsafe fn drop<T>(ptr: *mut ()) {
21                    let _ = unsafe { Box::from_raw(ptr.cast::<T>()) };
22                }
23                drop::<T>
24            },
25            #[cfg(any(debug_assertions, miri))]
26            type_id: typeid::of::<T>(),
27            #[cfg(any(debug_assertions, miri))]
28            type_name: any::type_name::<T>(),
29        }
30    }
31
32    pub(crate) unsafe fn take<T>(self) -> T {
33        #[cfg(any(debug_assertions, miri))]
34        assert_eq!(
35            self.type_id,
36            typeid::of::<T>(),
37            "ErasedValue mismatch: {} vs {}",
38            self.type_name,
39            any::type_name::<T>(),
40        );
41
42        let b = unsafe { Box::from_raw(self.ptr.cast::<T>()) };
43        mem::forget(self);
44        *b
45    }
46}
47
48impl Drop for ErasedValue {
49    fn drop(&mut self) {
50        unsafe { (self.drop)(self.ptr) }
51    }
52}