storage_api/
global_storage.rs1extern crate alloc;
2
3use crate::{MultipleStorage, Storage, StorageAllocError, StorageHandle};
4use core::{alloc::Layout, ptr::NonNull};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub struct GlobalHandle(pub NonNull<()>);
10
11unsafe impl Send for GlobalHandle {}
12unsafe impl Sync for GlobalHandle {}
13
14impl StorageHandle for GlobalHandle {}
15
16#[derive(Default, Clone, Copy)]
20pub struct Global;
21
22unsafe impl Storage for Global {
23 type Handle = GlobalHandle;
24
25 unsafe fn resolve(&self, handle: Self::Handle) -> NonNull<()> {
26 handle.0
27 }
28
29 fn allocate(&self, layout: Layout) -> Result<(Self::Handle, usize), StorageAllocError> {
30 match layout.size() {
31 0 => Ok((
32 GlobalHandle(unsafe {
33 NonNull::new_unchecked(core::ptr::without_provenance_mut(layout.align()))
34 }),
35 0,
36 )),
37 size => match NonNull::new(unsafe { alloc::alloc::alloc(layout) }.cast()) {
38 Some(ptr) => Ok((GlobalHandle(ptr), size)),
39 None => Err(StorageAllocError),
40 },
41 }
42 }
43
44 unsafe fn deallocate(&self, layout: Layout, handle: Self::Handle) {
45 match layout.size() {
46 0 => (),
47 _ => unsafe { alloc::alloc::dealloc(handle.0.as_ptr().cast(), layout) },
48 }
49 }
50
51 unsafe fn grow(
52 &self,
53 old_layout: Layout,
54 new_layout: Layout,
55 handle: Self::Handle,
56 ) -> Result<(Self::Handle, usize), StorageAllocError> {
57 unsafe { self.realloc(old_layout, new_layout, handle.0) }
58 }
59
60 unsafe fn shrink(
61 &self,
62 old_layout: Layout,
63 new_layout: Layout,
64 handle: Self::Handle,
65 ) -> Result<(Self::Handle, usize), StorageAllocError> {
66 unsafe { self.realloc(old_layout, new_layout, handle.0) }
67 }
68}
69
70impl Global {
71 unsafe fn realloc(
72 &self,
73 old_layout: Layout,
74 new_layout: Layout,
75 old_alloc: NonNull<()>,
76 ) -> Result<(GlobalHandle, usize), StorageAllocError> {
77 match (old_layout.size(), new_layout.size()) {
78 (0, 0) => Ok((GlobalHandle(old_alloc), 0)),
79 (0, _) => self.allocate(new_layout),
80 (_, 0) => {
81 let new_alloc = self.allocate(new_layout)?;
82 unsafe {
83 self.deallocate(old_layout, GlobalHandle(old_alloc));
84 }
85 Ok(new_alloc)
86 }
87 (old_size, new_size) => {
88 if old_layout.align() >= new_layout.align() {
89 let ptr = NonNull::new(
90 unsafe {
91 alloc::alloc::realloc(old_alloc.as_ptr().cast(), old_layout, new_size)
92 }
93 .cast(),
94 )
95 .ok_or(StorageAllocError)?;
96 Ok((GlobalHandle(ptr), new_size))
97 } else {
98 let (new_alloc, _) = self.allocate(new_layout)?;
99 unsafe {
100 core::ptr::copy_nonoverlapping(
101 old_alloc.as_ptr().cast::<u8>(),
102 new_alloc.0.as_ptr().cast::<u8>(),
103 old_size,
104 );
105 self.deallocate(old_layout, GlobalHandle(old_alloc));
106 }
107 Ok((new_alloc, new_size))
108 }
109 }
110 }
111 }
112}
113
114unsafe impl MultipleStorage for Global {}