bevy_save_erased_serde/
any.rs1use crate::alloc::Box;
2#[cfg(no_maybe_uninit)]
3use core::marker::PhantomData;
4use core::mem;
5#[cfg(not(no_maybe_uninit))]
6use core::mem::MaybeUninit;
7use core::ptr;
8
9#[cfg(feature = "unstable-debug")]
10use core::any;
11
12pub struct Any {
13 value: Value,
14 drop: unsafe fn(&mut Value),
15 fingerprint: Fingerprint,
16
17 #[cfg(feature = "unstable-debug")]
19 type_name: &'static str,
20}
21
22union Value {
23 ptr: *mut (),
24 inline: [MaybeUninit<usize>; 2],
25}
26
27fn is_small<T>() -> bool {
28 cfg!(not(no_maybe_uninit))
29 && mem::size_of::<T>() <= mem::size_of::<Value>()
30 && mem::align_of::<T>() <= mem::align_of::<Value>()
31}
32
33impl Any {
34 pub(crate) unsafe fn new<T>(t: T) -> Self {
45 let value: Value;
46 let drop: unsafe fn(&mut Value);
47 let fingerprint = Fingerprint::of::<T>();
48
49 if is_small::<T>() {
50 let mut inline = [MaybeUninit::uninit(); 2];
51 unsafe { ptr::write(inline.as_mut_ptr() as *mut T, t) };
52 value = Value { inline };
53 unsafe fn inline_drop<T>(value: &mut Value) {
54 unsafe { ptr::drop_in_place(value.inline.as_mut_ptr() as *mut T) }
55 }
56 drop = inline_drop::<T>;
57 } else {
58 let ptr = Box::into_raw(Box::new(t)) as *mut ();
59 value = Value { ptr };
60 unsafe fn ptr_drop<T>(value: &mut Value) {
61 mem::drop(unsafe { Box::from_raw(value.ptr as *mut T) });
62 }
63 drop = ptr_drop::<T>;
64 };
65
66 #[cfg(not(feature = "unstable-debug"))]
69 {
70 Any {
71 value,
72 drop,
73 fingerprint,
74 }
75 }
76
77 #[cfg(feature = "unstable-debug")]
78 {
79 let type_name = any::type_name::<T>();
80 Any {
81 value,
82 drop,
83 fingerprint,
84 type_name,
85 }
86 }
87 }
88
89 pub(crate) unsafe fn view<T>(&mut self) -> &mut T {
91 if cfg!(not(miri)) && self.fingerprint != Fingerprint::of::<T>() {
92 self.invalid_cast_to::<T>();
93 }
94
95 let ptr = if is_small::<T>() {
96 unsafe { self.value.inline.as_mut_ptr() as *mut T }
97 } else {
98 unsafe { self.value.ptr as *mut T }
99 };
100
101 unsafe { &mut *ptr }
102 }
103
104 pub(crate) unsafe fn take<T>(mut self) -> T {
106 if cfg!(not(miri)) && self.fingerprint != Fingerprint::of::<T>() {
107 self.invalid_cast_to::<T>();
108 }
109
110 if is_small::<T>() {
111 let ptr = unsafe { self.value.inline.as_mut_ptr() as *mut T };
112 let value = unsafe { ptr::read(ptr) };
113 mem::forget(self);
114 value
115 } else {
116 let ptr = unsafe { self.value.ptr as *mut T };
117 let box_t = unsafe { Box::from_raw(ptr) };
118 mem::forget(self);
119 *box_t
120 }
121 }
122
123 #[cfg(not(feature = "unstable-debug"))]
124 fn invalid_cast_to<T>(&self) -> ! {
125 panic!("invalid cast; enable `unstable-debug` feature to debug");
126 }
127
128 #[cfg(feature = "unstable-debug")]
129 fn invalid_cast_to<T>(&self) -> ! {
130 let from = self.type_name;
131 let to = any::type_name::<T>();
132 panic!("invalid cast: {} to {}", from, to);
133 }
134}
135
136impl Drop for Any {
137 fn drop(&mut self) {
138 unsafe { (self.drop)(&mut self.value) }
139 }
140}
141
142#[cfg(no_maybe_uninit)]
143#[derive(Copy, Clone)]
144struct MaybeUninit<T>(PhantomData<T>);
145
146#[cfg(no_maybe_uninit)]
147impl<T> MaybeUninit<T> {
148 fn uninit() -> Self {
149 MaybeUninit(PhantomData)
150 }
151}
152
153#[derive(Debug, Eq, PartialEq)]
154struct Fingerprint {
155 size: usize,
156 align: usize,
157 #[cfg(include_fnptr_in_fingerprint)]
158 id: usize,
159}
160
161impl Fingerprint {
162 fn of<T>() -> Fingerprint {
163 Fingerprint {
164 size: mem::size_of::<T>(),
165 align: mem::align_of::<T>(),
166 #[cfg(include_fnptr_in_fingerprint)]
171 id: Fingerprint::of::<T> as usize,
172 }
173 }
174}
175
176#[test]
177fn test_fingerprint() {
178 assert_eq!(Fingerprint::of::<usize>(), Fingerprint::of::<usize>());
179 assert_eq!(Fingerprint::of::<&str>(), Fingerprint::of::<&'static str>());
180
181 assert_ne!(Fingerprint::of::<u32>(), Fingerprint::of::<[u8; 4]>());
182 assert_ne!(Fingerprint::of::<u32>(), Fingerprint::of::<[u32; 2]>());
183
184 if cfg!(all(include_fnptr_in_fingerprint, not(miri))) {
185 assert_ne!(Fingerprint::of::<usize>(), Fingerprint::of::<isize>());
186 assert_ne!(Fingerprint::of::<usize>(), Fingerprint::of::<&usize>());
187 assert_ne!(Fingerprint::of::<&usize>(), Fingerprint::of::<&&usize>());
188 assert_ne!(Fingerprint::of::<&usize>(), Fingerprint::of::<&mut usize>());
189
190 struct A;
191 struct B;
192 assert_ne!(Fingerprint::of::<A>(), Fingerprint::of::<B>());
193 }
194}