memkit_async/
container.rs

1//! Async-safe container types.
2
3use std::ops::{Deref, DerefMut};
4use std::ptr::NonNull;
5
6use crate::allocator::MkAsyncFrameAlloc;
7
8/// Async-safe box type.
9pub struct MkAsyncBox<T> {
10    ptr: NonNull<T>,
11    alloc: MkAsyncFrameAlloc,
12}
13
14impl<T> MkAsyncBox<T> {
15    /// Create a new async box.
16    pub async fn new(alloc: MkAsyncFrameAlloc, value: T) -> Option<Self> {
17        let ptr = alloc.alloc::<T>().await?;
18        unsafe {
19            ptr.write(value);
20        }
21        Some(Self {
22            ptr: NonNull::new(ptr)?,
23            alloc,
24        })
25    }
26
27    /// Get the raw pointer.
28    pub fn as_ptr(&self) -> *const T {
29        self.ptr.as_ptr()
30    }
31
32    /// Get the mutable raw pointer.
33    pub fn as_mut_ptr(&mut self) -> *mut T {
34        self.ptr.as_ptr()
35    }
36}
37
38impl<T> Deref for MkAsyncBox<T> {
39    type Target = T;
40
41    fn deref(&self) -> &Self::Target {
42        unsafe { self.ptr.as_ref() }
43    }
44}
45
46impl<T> DerefMut for MkAsyncBox<T> {
47    fn deref_mut(&mut self) -> &mut Self::Target {
48        unsafe { self.ptr.as_mut() }
49    }
50}
51
52impl<T> Drop for MkAsyncBox<T> {
53    fn drop(&mut self) {
54        unsafe {
55            std::ptr::drop_in_place(self.ptr.as_ptr());
56        }
57        self.alloc.release();
58    }
59}
60
61// Safety: MkAsyncBox is Send/Sync if T is
62unsafe impl<T: Send> Send for MkAsyncBox<T> {}
63unsafe impl<T: Sync> Sync for MkAsyncBox<T> {}
64
65/// Async-safe vector type.
66pub struct MkAsyncVec<T> {
67    ptr: *mut T,
68    len: usize,
69    capacity: usize,
70    alloc: MkAsyncFrameAlloc,
71}
72
73impl<T> MkAsyncVec<T> {
74    /// Create a new async vec with capacity.
75    pub async fn with_capacity(alloc: MkAsyncFrameAlloc, capacity: usize) -> Option<Self> {
76        if capacity == 0 {
77            return Some(Self {
78                ptr: std::ptr::null_mut(),
79                len: 0,
80                capacity: 0,
81                alloc,
82            });
83        }
84
85        let layout = std::alloc::Layout::array::<T>(capacity).ok()?;
86        let ptr = alloc.alloc_layout(layout).await? as *mut T;
87        
88        Some(Self {
89            ptr,
90            len: 0,
91            capacity,
92            alloc,
93        })
94    }
95
96    /// Push a value onto the vec.
97    pub fn push(&mut self, value: T) -> Result<(), T> {
98        if self.len >= self.capacity {
99            return Err(value);
100        }
101        unsafe {
102            self.ptr.add(self.len).write(value);
103        }
104        self.len += 1;
105        Ok(())
106    }
107
108    /// Get the length.
109    pub fn len(&self) -> usize {
110        self.len
111    }
112
113    /// Check if empty.
114    pub fn is_empty(&self) -> bool {
115        self.len == 0
116    }
117
118    /// Get the capacity.
119    pub fn capacity(&self) -> usize {
120        self.capacity
121    }
122
123    /// Clear the vec.
124    pub fn clear(&mut self) {
125        for i in 0..self.len {
126            unsafe {
127                std::ptr::drop_in_place(self.ptr.add(i));
128            }
129        }
130        self.len = 0;
131    }
132}
133
134impl<T> Deref for MkAsyncVec<T> {
135    type Target = [T];
136
137    fn deref(&self) -> &Self::Target {
138        if self.ptr.is_null() {
139            &[]
140        } else {
141            unsafe { std::slice::from_raw_parts(self.ptr, self.len) }
142        }
143    }
144}
145
146impl<T> DerefMut for MkAsyncVec<T> {
147    fn deref_mut(&mut self) -> &mut Self::Target {
148        if self.ptr.is_null() {
149            &mut []
150        } else {
151            unsafe { std::slice::from_raw_parts_mut(self.ptr, self.len) }
152        }
153    }
154}
155
156impl<T> Drop for MkAsyncVec<T> {
157    fn drop(&mut self) {
158        self.clear();
159        if self.capacity > 0 {
160            self.alloc.release();
161        }
162    }
163}
164
165unsafe impl<T: Send> Send for MkAsyncVec<T> {}
166unsafe impl<T: Sync> Sync for MkAsyncVec<T> {}