1#![allow(incomplete_features)]
2#![feature(
3 allocator_api, coerce_unsized,
5 fn_traits, generic_const_exprs,
7 ptr_metadata,
8 tuple_trait, unboxed_closures, unsize,
11 specialization, )]
14#![warn(clippy::all)]
15#![cfg_attr(not(test), no_std)]
16extern crate alloc;
17
18mod impl_fn_traits;
19mod impl_new;
20
21use core::borrow::Borrow;
22use core::borrow::BorrowMut;
23use core::fmt;
24use core::fmt::Debug;
25use core::fmt::Display;
26use core::fmt::Pointer;
27use core::future::Future;
28use core::marker::PhantomData;
29use core::marker::Unsize;
30use core::mem;
31use core::mem::MaybeUninit;
32use core::ops::Deref;
33use core::ops::DerefMut;
34use core::panic::AssertUnwindSafe;
35use core::ptr;
36use core::ptr::Pointee;
37
38use mem::align_of;
39use mem::size_of;
40
41pub struct InplaceBox<T: ?Sized, const SIZE: usize> {
45 storage: MaybeUninit<[u8; SIZE]>,
46 vtable: AssertUnwindSafe<<T as Pointee>::Metadata>,
47 _phantom: PhantomData<T>,
48}
49
50impl<T: ?Sized, const SIZE: usize> InplaceBox<T, SIZE> {
51 const ASSERT_DYN_T: () = assert!(
53 core::mem::size_of::<&T>() == core::mem::size_of::<usize>() * 2,
54 "`InplaceBox` only works for `dyn Trait` types"
55 );
56
57 pub(crate) fn new_impl<'a, U: Sized + Unsize<T> + 'a>(value: U) -> Self {
58 struct AssertSize<ValueT: Sized, DestT: Sized>(
59 PhantomData<(ValueT, DestT)>,
60 );
61 impl<ValueT: Sized, DestT: Sized> AssertSize<ValueT, DestT> {
62 const ASSERT: () = assert!(
63 size_of::<ValueT>() <= size_of::<DestT>(),
64 "Insufficient size of `InplaceBox` to store the object"
65 );
66 const fn check() {
67 () = Self::ASSERT;
68 }
69 }
70 AssertSize::<U, MaybeUninit<[u8; SIZE]>>::check();
71 unsafe { Self::new_unchecked(value) }
73 }
74
75 pub unsafe fn new_unchecked<'a, U: Sized + Unsize<T> + 'a>(
96 value: U,
97 ) -> Self {
98 struct AssertAlignment<ValueT: Sized, T: ?Sized>(
99 PhantomData<(ValueT, T)>,
100 );
101 impl<ValueT: Sized, T: ?Sized> AssertAlignment<ValueT, T> {
102 const ASSERT: () = assert!(
103 align_of::<ValueT>() <= align_of::<<T as Pointee>::Metadata>(),
104 "Value alignment exceeds maximum allowed alignment"
105 );
106 const fn check() {
107 () = Self::ASSERT;
108 }
109 }
110 AssertAlignment::<U, T>::check();
111 () = Self::ASSERT_DYN_T;
112
113 let value_ref: &T = &value;
114 let vtable = AssertUnwindSafe(ptr::metadata(value_ref));
115 let mut res = Self {
116 storage: MaybeUninit::uninit(),
117 vtable,
118 _phantom: PhantomData,
119 };
120 unsafe { res.storage.as_mut_ptr().cast::<U>().write(value) };
121 res
122 }
123
124 unsafe fn as_ptr(&self) -> *const T {
126 let data_ptr = self.storage.as_ptr() as *const ();
127 ptr::from_raw_parts(data_ptr, *self.vtable)
128 }
129
130 unsafe fn as_mut_ptr(&mut self) -> *mut T {
132 let data_ptr = self.storage.as_mut_ptr() as *mut ();
133 ptr::from_raw_parts_mut(data_ptr, *self.vtable)
134 }
135}
136
137impl<T: ?Sized, const SIZE: usize> Deref for InplaceBox<T, SIZE> {
138 type Target = T;
139
140 fn deref(&self) -> &Self::Target {
141 unsafe { &*self.as_ptr() }
142 }
143}
144
145impl<T: ?Sized, const SIZE: usize> DerefMut for InplaceBox<T, SIZE> {
146 fn deref_mut(&mut self) -> &mut Self::Target {
147 unsafe { &mut *self.as_mut_ptr() }
148 }
149}
150
151impl<T: ?Sized, const SIZE: usize> AsRef<T> for InplaceBox<T, SIZE> {
152 fn as_ref(&self) -> &T {
153 self
154 }
155}
156
157impl<T: ?Sized, const SIZE: usize> AsMut<T> for InplaceBox<T, SIZE> {
158 fn as_mut(&mut self) -> &mut T {
159 self
160 }
161}
162
163impl<T: ?Sized, const SIZE: usize> Borrow<T> for InplaceBox<T, SIZE> {
164 fn borrow(&self) -> &T {
165 self
166 }
167}
168
169impl<T: ?Sized, const SIZE: usize> BorrowMut<T> for InplaceBox<T, SIZE> {
170 fn borrow_mut(&mut self) -> &mut T {
171 self
172 }
173}
174
175impl<T: ?Sized + Debug, const SIZE: usize> Debug for InplaceBox<T, SIZE> {
176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 Debug::fmt(&**self, f)
178 }
179}
180
181impl<T: ?Sized + Display, const SIZE: usize> Display for InplaceBox<T, SIZE> {
182 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183 Display::fmt(&**self, f)
184 }
185}
186
187impl<T: ?Sized, const SIZE: usize> Pointer for InplaceBox<T, SIZE> {
188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189 let ptr: *const T = &**self;
190 Pointer::fmt(&ptr, f)
191 }
192}
193
194impl<T: ?Sized + Future, const SIZE: usize> Future for InplaceBox<T, SIZE> {
195 type Output = T::Output;
196
197 fn poll(
198 self: core::pin::Pin<&mut Self>,
199 cx: &mut core::task::Context<'_>,
200 ) -> core::task::Poll<Self::Output> {
201 unsafe {
204 let s = self.get_unchecked_mut();
205 core::pin::Pin::new_unchecked(&mut **s).poll(cx)
206 }
207 }
208}
209
210impl<T: ?Sized, const SIZE: usize> Drop for InplaceBox<T, SIZE> {
211 fn drop(&mut self) {
212 unsafe {
213 ptr::drop_in_place(self.as_mut_ptr());
214 }
215 }
216}