1#![feature(ptr_metadata)]
40#![feature(unsize)]
41#![feature(alloc_layout_extra)]
42#![feature(allocator_api)]
43
44pub mod alloc;
45
46pub use dst_init_macros as macros;
47pub use macros::dst;
48use std::alloc::Layout;
49use std::marker::{PhantomData, Unsize};
50use std::ptr::{null, NonNull, Pointee};
51use std::{mem, ptr};
52use std::rc::Rc;
53use std::sync::Arc;
54
55type Metadata<T> = <T as Pointee>::Metadata;
56
57#[inline(always)]
58const fn metadata_of<T: Unsize<Dyn>, Dyn: ?Sized>() -> Metadata<Dyn> {
59 let null: *const T = null();
60 let dyn_null = null as *const Dyn;
61 ptr::metadata(dyn_null)
62}
63
64pub trait Initializer<DstInit: EmplaceInitializer> {
65 type Init;
66}
67
68pub type Init<T, DstInit> = <T as Initializer<DstInit>>::Init;
69
70pub trait EmplaceInitializer {
72 type Output: ?Sized;
73 fn layout(&mut self) -> Layout;
75 fn emplace(self, ptr: NonNull<u8>) -> NonNull<Self::Output>;
77}
78
79pub struct SliceIterInitializer<Iter: Iterator> {
81 size: usize,
82 iter: Iter,
83}
84
85impl<Iter: Iterator> SliceIterInitializer<Iter> {
86 #[inline(always)]
92 pub fn new(size: usize, iter: Iter) -> Self {
93 Self { size, iter }
94 }
95}
96
97impl<Iter: Iterator> EmplaceInitializer for SliceIterInitializer<Iter> {
98 type Output = [Iter::Item];
99
100 #[inline(always)]
101 fn layout(&mut self) -> Layout {
102 Layout::array::<Iter::Item>(self.size).unwrap()
103 }
104
105 #[inline(always)]
106 fn emplace(mut self, ptr: NonNull<u8>) -> NonNull<Self::Output> {
107 unsafe {
108 let mut p: *mut Iter::Item = ptr.as_ptr().cast();
109 for _ in 0..self.size {
110 let item = self.iter.next().unwrap();
111 p.write(item);
112 p = p.add(1);
113 }
114 mem::transmute(NonNull::slice_from_raw_parts(
115 ptr.cast::<Iter::Item>(),
116 self.size,
117 ))
118 }
119 }
120}
121
122pub struct SliceFnInitializer<Item, F: FnMut() -> Item> {
124 size: usize,
125 f: F,
126}
127
128impl<Item, F: FnMut() -> Item> SliceFnInitializer<Item, F> {
129 #[inline(always)]
132 pub fn new(size: usize, f: F) -> Self {
133 Self { size, f }
134 }
135}
136
137impl<Item, F: FnMut() -> Item> EmplaceInitializer for SliceFnInitializer<Item, F> {
138 type Output = [Item];
139
140 #[inline(always)]
141 fn layout(&mut self) -> Layout {
142 Layout::array::<Item>(self.size).unwrap()
143 }
144
145 #[inline(always)]
146 fn emplace(mut self, ptr: NonNull<u8>) -> NonNull<Self::Output> {
147 unsafe {
148 let mut p: *mut Item = ptr.as_ptr().cast();
149 for _ in 0..self.size {
150 let item = (self.f)();
151 p.write(item);
152 p = p.add(1);
153 }
154 NonNull::slice_from_raw_parts(ptr.cast::<Item>(), self.size)
155 }
156 }
157}
158
159pub struct CoercionInitializer<T: Unsize<U>, U: ?Sized> {
170 t: T,
171 phan: PhantomData<U>,
172}
173
174impl<T: Unsize<U>, U: ?Sized> CoercionInitializer<T, U> {
175 #[inline(always)]
176 pub fn new(t: T) -> Self {
177 Self {
178 t,
179 phan: Default::default(),
180 }
181 }
182 #[inline(always)]
183 pub fn fallback(self) -> T {
184 self.t
185 }
186}
187
188impl<T: Unsize<U>, U: ?Sized> EmplaceInitializer for CoercionInitializer<T, U> {
189 type Output = U;
190
191 #[inline(always)]
192 fn layout(&mut self) -> Layout {
193 Layout::new::<T>()
194 }
195
196 #[inline(always)]
197 fn emplace(self, ptr: NonNull<u8>) -> NonNull<Self::Output> {
198 unsafe {
199 let meta = metadata_of::<T, U>();
200 ptr.as_ptr().cast::<T>().write(self.t);
201 NonNull::from_raw_parts(ptr, meta)
202 }
203 }
204}
205
206pub struct DirectInitializer<T> {
208 t: T,
209}
210
211impl<T> DirectInitializer<T> {
212 #[inline(always)]
213 pub fn new(t: T) -> Self {
214 Self { t }
215 }
216
217 #[inline(always)]
218 pub fn fallback(self) -> T {
219 self.t
220 }
221}
222
223impl<T> EmplaceInitializer for DirectInitializer<T> {
224 type Output = T;
225
226 #[inline(always)]
227 fn layout(&mut self) -> Layout {
228 Layout::new::<T>()
229 }
230
231 #[inline(always)]
232 fn emplace(self, ptr: NonNull<u8>) -> NonNull<Self::Output> {
233 unsafe {
234 ptr.as_ptr().cast::<T>().write(self.t);
235 ptr.cast()
236 }
237 }
238}
239
240pub trait BoxExt: Sized {
242
243 type Output: ?Sized;
244
245 fn emplace<Init: EmplaceInitializer<Output = Self::Output>>(init: Init) -> Self;
248}
249
250impl<T: ?Sized> BoxExt for Box<T> {
251
252 type Output = T;
253
254 fn emplace<Init: EmplaceInitializer<Output = Self::Output>>(
257 mut init: Init,
258 ) -> Box<Self::Output> {
259 unsafe {
260 let layout = init.layout();
261 let mem = std::alloc::alloc(layout);
262 let obj = init.emplace(NonNull::new(mem).unwrap());
263 Box::from_raw(obj.as_ptr())
264 }
265 }
266}
267
268impl<T: ?Sized> BoxExt for Rc<T> {
269 type Output = T;
270
271 fn emplace<Init: EmplaceInitializer<Output = Self::Output>>(
274 mut init: Init,
275 ) -> Rc<Self::Output> {
276 unsafe {
277 let layout = init.layout();
278 let mem = std::alloc::alloc(layout);
279 let obj = init.emplace(NonNull::new(mem).unwrap());
280 Rc::from_raw(obj.as_ptr())
281 }
282 }
283}
284
285impl<T: ?Sized> BoxExt for Arc<T> {
286 type Output = T;
287
288 fn emplace<Init: EmplaceInitializer<Output = Self::Output>>(
291 mut init: Init,
292 ) -> Arc<Self::Output> {
293 unsafe {
294 let layout = init.layout();
295 let mem = std::alloc::alloc(layout);
296 let obj = init.emplace(NonNull::new(mem).unwrap());
297 Arc::from_raw(obj.as_ptr())
298 }
299 }
300}
301
302pub type Slice<T> = [T];
304
305pub trait SliceExt {
307 type Item;
308
309 fn fn_init<F>(size: usize, f: F) -> impl EmplaceInitializer<Output = [Self::Item]>
311 where
312 F: FnMut() -> Self::Item;
313
314 fn iter_init<Iter>(size: usize, iter: Iter) -> impl EmplaceInitializer<Output = [Self::Item]>
316 where
317 Iter: Iterator<Item = Self::Item>;
318}
319
320impl<T> SliceExt for Slice<T> {
321 type Item = T;
322
323 #[inline(always)]
325 fn fn_init<F>(size: usize, f: F) -> impl EmplaceInitializer<Output = [Self::Item]>
326 where
327 F: FnMut() -> Self::Item,
328 {
329 SliceFnInitializer::new(size, f)
330 }
331
332 fn iter_init<Iter>(size: usize, iter: Iter) -> impl EmplaceInitializer<Output = [Self::Item]>
334 where
335 Iter: Iterator<Item = Self::Item>,
336 {
337 SliceIterInitializer::new(size, iter)
338 }
339}
340
341pub struct RawInitializer<Output:?Sized, F>{
342 layout:Layout,
343 emplacer:F,
344 phan:PhantomData<Output>,
345}
346
347impl<Output, F> RawInitializer<Output,F>
348 where Output:?Sized, F:FnOnce(NonNull<u8>)->NonNull<Output>
349{
350 pub fn new(layout:Layout, f:F)->Self{
351 Self{
352 layout,
353 emplacer:f,
354 phan:Default::default()
355 }
356 }
357}
358
359impl<Output, F> EmplaceInitializer for RawInitializer<Output, F>
360 where Output:?Sized, F:FnOnce(NonNull<u8>)->NonNull<Output>
361{
362 type Output = Output;
363
364 fn layout(&mut self) -> Layout {
365 self.layout
366 }
367
368 fn emplace(self, ptr: NonNull<u8>) -> NonNull<Self::Output> {
369 (self.emplacer)(ptr)
370 }
371}
372
373#[cfg(test)]
374pub mod test {
375 use crate::{self as dst_init, RawInitializer};
376 use crate::{
377 CoercionInitializer, DirectInitializer, EmplaceInitializer,
378 SliceFnInitializer, SliceIterInitializer,
379 };
380 use dst_init_macros::dst;
381 use std::alloc;
382 use std::alloc::Layout;
383 use std::fmt::{Debug, Formatter};
384 use std::ptr::NonNull;
385
386 #[dst]
387 #[derive(Debug)]
388 struct Test<A, B, C, D> {
389 a: A,
390 b: B,
391 c: C,
392 dst: [(C, D)],
393 }
394
395 #[dst]
396 #[derive(Debug)]
397 struct Test1<A, B, C, D> {
398 a: usize,
399 t: Test<A, B, C, D>,
400 }
401
402 #[test]
403 fn test() {
404 let t = TestInit {
405 a: 1usize,
406 b: 1u8,
407 c: 1u8,
408 dst: SliceIterInitializer::new(3, (0..).map(|i| (i as u8, i as usize))),
409 };
410 let u = Test1Init { a: 1usize, t };
411 let a = alloc(u);
412 println!("{:?}", a)
413 }
414
415 fn alloc<O: ?Sized, Init: EmplaceInitializer<Output = O>>(mut init: Init) -> Box<O> {
416 unsafe {
417 let layout = init.layout();
418 let ptr = alloc::alloc(layout);
419 if ptr.is_null() {
420 panic!("no memory");
421 }
422 let ptr = init.emplace(NonNull::new(ptr).unwrap());
423 Box::from_raw(ptr.as_ptr())
424 }
425 }
426
427 #[derive(PartialEq, Copy, Clone)]
428 pub struct FstStruct {
429 a: u8,
430 b: usize,
431 c: f64,
432 }
433 impl Debug for FstStruct {
434 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
435 write!(f, "{},{},{}", self.a, self.b, self.c)
436 }
437 }
438
439 #[allow(dead_code)]
440 #[derive(Debug)]
441 pub struct DstStruct<Data: Debug + ?Sized> {
442 a: u8,
443 b: usize,
444 c: u8,
445 d: Data,
446 }
447
448 #[test]
449 fn test_direct_initializer() {
450 #[inline(never)]
451 fn test<T: PartialEq + Debug>(a: T, b: T) {
452 let mut init = DirectInitializer::new(a);
453 let layout = init.layout();
454 assert_eq!(layout, Layout::new::<T>());
455 let obj = alloc(init);
456 assert_eq!(*obj, b);
457 }
458
459 test(12345usize, 12345usize);
460 test(127u8, 127u8);
461 test(456131248u32, 456131248u32);
462 test(4123456789u64, 4123456789u64);
463 test(1.0f64, 1.0f64);
464
465 let a = FstStruct {
466 a: 159,
467 b: 47521,
468 c: 12345.12345,
469 };
470 test(a, a);
471 }
472
473 #[test]
474 fn test_coercion_initializer() {
475 let a = FstStruct {
476 a: 159,
477 b: 47521,
478 c: 12345.12345,
479 };
480 let init = CoercionInitializer::new(a);
481 let data: Box<dyn Debug> = alloc(init);
482 assert_eq!(format!("{:?}", &*data), "159,47521,12345.12345");
483
484 let create = || DstStruct {
485 a: 156,
486 b: 157,
487 c: 175,
488 d: [1usize, 13123usize, 13123usize],
489 };
490 let init = CoercionInitializer::new(create());
491 let data: Box<DstStruct<[usize]>> = alloc(init);
492 assert_eq!(format!("{:?}", data), format!("{:?}", create()));
493 }
494
495 #[test]
496 fn test_slice_fn_initializer() {
497 let mut i = 0;
498 let init = SliceFnInitializer::new(10065, || {
499 i += 1;
500 i
501 });
502 let data = alloc(init);
503 i = 1;
504 for x in data.iter() {
505 assert_eq!(i, *x);
506 i += 1;
507 }
508 }
509
510 #[test]
511 fn test_slice_iter_initializer() {
512 let init = SliceIterInitializer::new(100, 0..100);
513 let data = alloc(init);
514 for x in 0..100 {
515 assert_eq!(data[x], x)
516 }
517 }
518
519 #[test]
520 fn test_raw_initializer(){
521 let init = RawInitializer::new(Layout::new::<[u8;10]>(),|ptr|{unsafe{
522 let mut ptr = ptr.as_ptr();
523 let tmp = ptr;
524 for x in 0..10{
525 *ptr = x as u8;
526 ptr = ptr.add(1);
527 }
528 return NonNull::new(std::ptr::slice_from_raw_parts_mut(tmp, 10)).expect("error when creating NonNull");
529 }});
530 let data = alloc(init);
531 for x in 0..10 {
532 assert_eq!(data[x], x as u8)
533 }
534 }
535}