1#![feature(const_block_items, box_vec_non_null)]
12#![cfg_attr(test, feature(pointer_is_aligned_to))]
13#![no_std]
14
15#[cfg(test)]
16mod tests;
17
18extern crate alloc;
19
20use alloc::alloc::realloc;
21use alloc::boxed::Box;
22use core::alloc::Layout;
23use core::mem::MaybeUninit;
24use core::ops::{Deref, DerefMut};
25use core::ptr::NonNull;
26use core::slice;
27use core::sync::atomic::{AtomicU32, Ordering};
28use stable_deref_trait::{CloneStableDeref, StableDeref};
29use yoke::CloneableCart;
30
31const {
32 assert!(
33 align_of::<u128>() == size_of::<u128>(),
34 "Size and alignment are both 16 bytes"
35 );
36 assert!(size_of::<u128>() >= size_of::<AtomicU32>());
37 assert!(align_of::<u128>() >= align_of::<AtomicU32>());
38}
39
40#[repr(C, align(16))]
41struct ConstInnerBuffer {
42 strong_count: AtomicU32,
43}
44
45const {
46 assert!(align_of::<ConstInnerBuffer>() == align_of::<u128>());
47 assert!(size_of::<ConstInnerBuffer>() == size_of::<u128>());
48}
49
50static EMPTY_SHARED_ALIGNED_BUFFER: SharedAlignedBuffer = SharedAlignedBuffer {
51 inner: InnerBuffer {
52 buffer: NonNull::from_ref({
53 static BUFFER: MaybeUninit<ConstInnerBuffer> = MaybeUninit::new(ConstInnerBuffer {
54 strong_count: AtomicU32::new(1),
55 });
56
57 &BUFFER
58 })
59 .cast::<MaybeUninit<u128>>(),
60 capacity: 0,
61 len: 0,
62 },
63};
64
65#[derive(Debug)]
66struct InnerBuffer {
67 buffer: NonNull<MaybeUninit<u128>>,
69 capacity: u32,
70 len: u32,
71}
72
73unsafe impl Send for InnerBuffer {}
75unsafe impl Sync for InnerBuffer {}
77
78impl Default for InnerBuffer {
79 #[inline(always)]
80 fn default() -> Self {
81 EMPTY_SHARED_ALIGNED_BUFFER.inner.clone()
82 }
83}
84
85impl Clone for InnerBuffer {
86 #[inline(always)]
87 fn clone(&self) -> Self {
88 self.strong_count_ref().fetch_add(1, Ordering::AcqRel);
89
90 Self {
91 buffer: self.buffer,
92 capacity: self.capacity,
93 len: self.len,
94 }
95 }
96}
97
98impl Drop for InnerBuffer {
99 #[inline(always)]
100 fn drop(&mut self) {
101 if self.strong_count_ref().fetch_sub(1, Ordering::AcqRel) == 1 {
102 let _: Box<_> = unsafe {
104 Box::from_non_null(NonNull::slice_from_raw_parts(
105 self.buffer,
106 1 + (self.capacity as usize).div_ceil(size_of::<u128>()),
107 ))
108 };
109 }
110 }
111}
112
113impl InnerBuffer {
114 #[inline(always)]
119 fn allocate(capacity: u32) -> Self {
120 let buffer = Box::into_non_null(Box::<[u128]>::new_uninit_slice(
121 1 + (capacity as usize).div_ceil(size_of::<u128>()),
122 ));
123 unsafe {
126 buffer.cast::<AtomicU32>().write(AtomicU32::new(1));
127 }
128 Self {
129 buffer: buffer.cast::<MaybeUninit<u128>>(),
130 capacity,
131 len: 0,
132 }
133 }
134
135 #[inline(always)]
136 fn resize(&mut self, capacity: u32) {
137 let layout = Layout::for_value(unsafe {
139 slice::from_raw_parts(
140 self.buffer.as_ptr(),
141 1 + (self.capacity as usize).div_ceil(size_of::<u128>()),
142 )
143 });
144
145 let new_size = size_of::<u128>() + (capacity as usize).next_multiple_of(layout.align());
147
148 #[expect(
149 clippy::cast_ptr_alignment,
150 reason = "Cast from correct alignment to bytes and back due to API requirements"
151 )]
152 let new_ptr = unsafe {
155 realloc(self.buffer.as_ptr().cast::<u8>(), layout, new_size).cast::<MaybeUninit<u128>>()
156 };
157 let Some(new_ptr) = NonNull::new(new_ptr) else {
158 panic!("Realloc from {} to {new_size} has failed", self.capacity());
159 };
160
161 self.buffer = new_ptr;
162 self.capacity = capacity;
163 }
164
165 #[inline(always)]
166 const fn len(&self) -> u32 {
167 self.len
168 }
169
170 #[inline(always)]
172 unsafe fn set_len(&mut self, len: u32) {
173 debug_assert!(
174 len <= self.capacity(),
175 "Too many bytes {} > {}",
176 len,
177 self.capacity()
178 );
179 self.len = len;
180 }
181
182 #[inline(always)]
183 const fn capacity(&self) -> u32 {
184 self.capacity
185 }
186
187 #[inline(always)]
188 const fn strong_count_ref(&self) -> &AtomicU32 {
189 unsafe { self.buffer.as_ptr().cast::<AtomicU32>().as_ref_unchecked() }
192 }
193
194 #[inline(always)]
195 const fn as_slice(&self) -> &[u8] {
196 let len = self.len() as usize;
197 unsafe { slice::from_raw_parts(self.as_ptr(), len) }
199 }
200
201 #[inline(always)]
202 const fn as_mut_slice(&mut self) -> &mut [u8] {
203 let len = self.len() as usize;
204 unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), len) }
206 }
207
208 #[inline(always)]
209 const fn as_ptr(&self) -> *const u8 {
210 unsafe { self.buffer.as_ptr().cast_const().add(1).cast::<u8>() }
212 }
213
214 #[inline(always)]
215 const fn as_mut_ptr(&mut self) -> *mut u8 {
216 unsafe { self.buffer.as_ptr().add(1).cast::<u8>() }
218 }
219}
220
221#[derive(Debug)]
229pub struct OwnedAlignedBuffer {
230 inner: InnerBuffer,
231}
232
233impl Deref for OwnedAlignedBuffer {
234 type Target = [u8];
235
236 #[inline(always)]
237 fn deref(&self) -> &Self::Target {
238 self.as_slice()
239 }
240}
241
242impl DerefMut for OwnedAlignedBuffer {
243 #[inline(always)]
244 fn deref_mut(&mut self) -> &mut Self::Target {
245 self.as_mut_slice()
246 }
247}
248
249unsafe impl StableDeref for OwnedAlignedBuffer {}
251
252impl Clone for OwnedAlignedBuffer {
253 #[inline(always)]
254 fn clone(&self) -> Self {
255 let mut new_instance = Self::with_capacity(self.capacity());
256 new_instance.copy_from_slice(self.as_slice());
257 new_instance
258 }
259}
260
261impl OwnedAlignedBuffer {
262 #[inline(always)]
266 pub fn with_capacity(capacity: u32) -> Self {
267 Self {
268 inner: InnerBuffer::allocate(capacity),
269 }
270 }
271
272 #[inline(always)]
277 pub fn from_bytes(bytes: &[u8]) -> Self {
278 let mut instance = Self::with_capacity(0);
279 instance.copy_from_slice(bytes);
280 instance
281 }
282
283 #[inline(always)]
284 pub const fn as_slice(&self) -> &[u8] {
285 self.inner.as_slice()
286 }
287
288 #[inline(always)]
289 pub const fn as_mut_slice(&mut self) -> &mut [u8] {
290 self.inner.as_mut_slice()
291 }
292
293 #[inline(always)]
294 pub const fn as_ptr(&self) -> *const u8 {
295 self.inner.as_ptr()
296 }
297
298 #[inline(always)]
299 pub const fn as_mut_ptr(&mut self) -> *mut u8 {
300 self.inner.as_mut_ptr()
301 }
302
303 #[inline(always)]
304 pub fn into_shared(self) -> SharedAlignedBuffer {
305 SharedAlignedBuffer { inner: self.inner }
306 }
307
308 #[inline(always)]
312 pub fn ensure_capacity(&mut self, capacity: u32) {
313 if capacity > self.capacity() {
314 self.inner.resize(capacity);
315 }
316 }
317
318 #[inline(always)]
323 pub fn copy_from_slice(&mut self, bytes: &[u8]) {
324 let Ok(len) = u32::try_from(bytes.len()) else {
325 panic!("Too many bytes {}", bytes.len());
326 };
327
328 if len > self.capacity() {
329 self.inner
330 .resize(len.max(self.capacity().saturating_mul(2)));
331 }
332
333 unsafe {
336 self.as_mut_ptr()
337 .copy_from_nonoverlapping(bytes.as_ptr(), bytes.len());
338
339 self.inner.set_len(len);
340 }
341 }
342
343 #[inline(always)]
347 #[must_use]
348 pub fn append(&mut self, bytes: &[u8]) -> bool {
349 let Ok(len) = u32::try_from(bytes.len()) else {
350 return false;
351 };
352
353 let Some(new_len) = self.len().checked_add(len) else {
354 return false;
355 };
356
357 if new_len > self.capacity() {
358 self.inner
359 .resize(new_len.max(self.capacity().saturating_mul(2)));
360 }
361
362 unsafe {
365 self.as_mut_ptr()
366 .add(self.len() as usize)
367 .copy_from_nonoverlapping(bytes.as_ptr(), bytes.len());
368
369 self.inner.set_len(new_len);
370 }
371
372 true
373 }
374
375 #[inline(always)]
376 pub const fn is_empty(&self) -> bool {
377 self.inner.len() == 0
378 }
379
380 #[inline(always)]
381 pub const fn len(&self) -> u32 {
382 self.inner.len()
383 }
384
385 #[inline(always)]
386 pub const fn capacity(&self) -> u32 {
387 self.inner.capacity()
388 }
389
390 #[inline(always)]
398 pub unsafe fn set_len(&mut self, new_len: u32) {
399 unsafe {
401 self.inner.set_len(new_len);
402 }
403 }
404}
405
406#[derive(Debug, Default, Clone)]
416pub struct SharedAlignedBuffer {
417 inner: InnerBuffer,
418}
419
420impl Deref for SharedAlignedBuffer {
421 type Target = [u8];
422
423 #[inline(always)]
424 fn deref(&self) -> &Self::Target {
425 self.as_slice()
426 }
427}
428
429unsafe impl StableDeref for SharedAlignedBuffer {}
431unsafe impl CloneStableDeref for SharedAlignedBuffer {}
433unsafe impl CloneableCart for SharedAlignedBuffer {}
435
436impl SharedAlignedBuffer {
437 #[inline(always)]
439 pub const fn empty_ref() -> &'static Self {
440 &EMPTY_SHARED_ALIGNED_BUFFER
441 }
442
443 #[inline(always)]
448 pub fn from_bytes(bytes: &[u8]) -> Self {
449 OwnedAlignedBuffer::from_bytes(bytes).into_shared()
450 }
451
452 #[inline(always)]
459 pub fn into_owned(self) -> OwnedAlignedBuffer {
460 if self.inner.strong_count_ref().load(Ordering::Acquire) == 1 {
461 OwnedAlignedBuffer { inner: self.inner }
462 } else {
463 OwnedAlignedBuffer::from_bytes(self.as_slice())
464 }
465 }
466
467 #[inline(always)]
468 pub const fn as_slice(&self) -> &[u8] {
469 self.inner.as_slice()
470 }
471
472 #[inline(always)]
473 pub const fn as_ptr(&self) -> *const u8 {
474 self.inner.as_ptr()
475 }
476
477 #[inline(always)]
478 pub const fn is_empty(&self) -> bool {
479 self.inner.len() == 0
480 }
481
482 #[inline(always)]
483 pub const fn len(&self) -> u32 {
484 self.inner.len()
485 }
486}