Coverage Report

Created: 2025-08-26 06:31

/rust/registry/src/index.crates.io-6f17d22bba15001f/erased-serde-0.4.6/src/any.rs
Line
Count
Source (jump to first uncovered line)
1
use alloc::boxed::Box;
2
use core::any::TypeId;
3
use core::mem::{self, MaybeUninit};
4
use core::ptr;
5
6
#[cfg(feature = "unstable-debug")]
7
use core::any;
8
9
pub struct Any {
10
    value: Value,
11
    drop: unsafe fn(&mut Value),
12
    type_id: TypeId,
13
14
    /// For panic messages only. Not used for comparison.
15
    #[cfg(feature = "unstable-debug")]
16
    type_name: &'static str,
17
}
18
19
union Value {
20
    ptr: *mut (),
21
    inline: [MaybeUninit<usize>; 2],
22
}
23
24
0
fn is_small<T>() -> bool {
25
0
    mem::size_of::<T>() <= mem::size_of::<Value>()
26
0
        && mem::align_of::<T>() <= mem::align_of::<Value>()
27
0
}
28
29
impl Any {
30
    // This is unsafe -- caller must not hold on to the Any beyond the lifetime
31
    // of T.
32
    //
33
    // Example of bad code:
34
    //
35
    //    let s = "bad".to_owned();
36
    //    let a = Any::new(&s);
37
    //    drop(s);
38
    //
39
    // Now `a.as_ref()` and `a.take()` return references to a dead String.
40
0
    pub(crate) unsafe fn new<T>(t: T) -> Self {
41
0
        let value: Value;
42
0
        let drop: unsafe fn(&mut Value);
43
0
        let type_id = typeid::of::<T>();
44
0
45
0
        if is_small::<T>() {
46
0
            let mut inline = [MaybeUninit::uninit(); 2];
47
0
            unsafe { ptr::write(inline.as_mut_ptr().cast::<T>(), t) };
48
0
            value = Value { inline };
49
0
            unsafe fn inline_drop<T>(value: &mut Value) {
50
0
                unsafe { ptr::drop_in_place(value.inline.as_mut_ptr().cast::<T>()) }
51
0
            }
52
0
            drop = inline_drop::<T>;
53
0
        } else {
54
0
            let ptr = Box::into_raw(Box::new(t)).cast::<()>();
55
0
            value = Value { ptr };
56
0
            unsafe fn ptr_drop<T>(value: &mut Value) {
57
0
                mem::drop(unsafe { Box::from_raw(value.ptr.cast::<T>()) });
58
0
            }
59
0
            drop = ptr_drop::<T>;
60
0
        }
61
62
0
        Any {
63
0
            value,
64
0
            drop,
65
0
            type_id,
66
0
            #[cfg(feature = "unstable-debug")]
67
0
            type_name: any::type_name::<T>(),
68
0
        }
69
0
    }
70
71
    // This is unsafe -- caller is responsible that T is the correct type.
72
0
    pub(crate) unsafe fn take<T>(mut self) -> T {
73
0
        if self.type_id != typeid::of::<T>() {
74
0
            self.invalid_cast_to::<T>();
75
0
        }
76
0
77
0
        if is_small::<T>() {
78
0
            let ptr = unsafe { self.value.inline.as_mut_ptr().cast::<T>() };
79
0
            let value = unsafe { ptr::read(ptr) };
80
0
            mem::forget(self);
81
0
            value
82
        } else {
83
0
            let ptr = unsafe { self.value.ptr.cast::<T>() };
84
0
            let box_t = unsafe { Box::from_raw(ptr) };
85
0
            mem::forget(self);
86
0
            *box_t
87
        }
88
0
    }
89
90
    #[cfg(not(feature = "unstable-debug"))]
91
0
    fn invalid_cast_to<T>(&self) -> ! {
92
0
        panic!("invalid cast; enable `unstable-debug` feature to debug");
93
    }
94
95
    #[cfg(feature = "unstable-debug")]
96
    fn invalid_cast_to<T>(&self) -> ! {
97
        let from = self.type_name;
98
        let to = any::type_name::<T>();
99
        panic!("invalid cast: {} to {}", from, to);
100
    }
101
}
102
103
impl Drop for Any {
104
0
    fn drop(&mut self) {
105
0
        unsafe { (self.drop)(&mut self.value) }
106
0
    }
107
}