1#![cfg_attr(test, feature(pointer_is_aligned_to))]
14#![no_std]
15
16#[cfg(test)]
17mod tests;
18
19extern crate alloc;
20
21use alloc::alloc::realloc;
22use alloc::boxed::Box;
23use core::alloc::Layout;
24use core::mem::MaybeUninit;
25use core::ops::{Deref, DerefMut};
26use core::ptr::NonNull;
27use core::slice;
28use core::sync::atomic::{AtomicUsize, Ordering};
29use stable_deref_trait::{CloneStableDeref, StableDeref};
30use yoke::CloneableCart;
31
32#[repr(C, align(16))]
34struct Chunk([u8; 16]);
35
36const _: () = {
37 assert!(size_of::<Chunk>() == 16);
38 assert!(align_of::<Chunk>() == 16);
39 assert!(align_of::<Chunk>() >= align_of::<u128>());
41 assert!(size_of::<Chunk>() >= size_of::<AtomicUsize>());
43 assert!(align_of::<Chunk>() >= align_of::<AtomicUsize>());
44};
45
46#[repr(C, align(16))]
47struct ConstInnerBuffer {
48 strong_count: AtomicUsize,
49}
50
51const _: () = {
52 assert!(align_of::<ConstInnerBuffer>() == align_of::<Chunk>());
53 assert!(size_of::<ConstInnerBuffer>() == size_of::<Chunk>());
54};
55
56static EMPTY_SHARED_ALIGNED_BUFFER: SharedAlignedBuffer = SharedAlignedBuffer {
57 inner: InnerBuffer {
58 buffer: NonNull::from_ref({
59 static BUFFER: MaybeUninit<ConstInnerBuffer> = MaybeUninit::new(ConstInnerBuffer {
60 strong_count: AtomicUsize::new(1),
61 });
62
63 &BUFFER
64 })
65 .cast::<MaybeUninit<Chunk>>(),
66 capacity: 0,
67 len: 0,
68 },
69};
70
71#[derive(Debug)]
72struct InnerBuffer {
73 buffer: NonNull<MaybeUninit<Chunk>>,
75 capacity: u32,
76 len: u32,
77}
78
79unsafe impl Send for InnerBuffer {}
81unsafe impl Sync for InnerBuffer {}
83
84impl Default for InnerBuffer {
85 #[inline(always)]
86 fn default() -> Self {
87 EMPTY_SHARED_ALIGNED_BUFFER.inner.clone()
88 }
89}
90
91impl Clone for InnerBuffer {
92 #[inline(always)]
93 fn clone(&self) -> Self {
94 let old_count = self.strong_count_ref().fetch_add(1, Ordering::AcqRel);
95 if usize::BITS < u64::BITS && old_count > isize::MAX.cast_unsigned() {
98 self.strong_count_ref().fetch_sub(1, Ordering::AcqRel);
99 panic!("Too many clones of a shared aligned buffer");
100 }
101
102 Self {
103 buffer: self.buffer,
104 capacity: self.capacity,
105 len: self.len,
106 }
107 }
108}
109
110impl Drop for InnerBuffer {
111 #[inline(always)]
112 fn drop(&mut self) {
113 if self.strong_count_ref().fetch_sub(1, Ordering::AcqRel) == 1 {
114 let _: Box<_> = unsafe {
116 Box::from_non_null(NonNull::slice_from_raw_parts(
117 self.buffer,
118 1 + (self.capacity as usize).div_ceil(size_of::<Chunk>()),
119 ))
120 };
121 }
122 }
123}
124
125impl InnerBuffer {
126 #[inline(always)]
131 fn allocate(capacity: u32) -> Self {
132 let buffer = Box::into_non_null(Box::<[Chunk]>::new_uninit_slice(
133 1 + (capacity as usize).div_ceil(size_of::<Chunk>()),
134 ));
135 unsafe {
138 buffer.cast::<AtomicUsize>().write(AtomicUsize::new(1));
139 }
140 Self {
141 buffer: buffer.cast::<MaybeUninit<Chunk>>(),
142 capacity,
143 len: 0,
144 }
145 }
146
147 #[inline(always)]
148 fn resize(&mut self, capacity: u32) {
149 let layout = Layout::for_value(unsafe {
151 slice::from_raw_parts(
152 self.buffer.as_ptr(),
153 1 + (self.capacity as usize).div_ceil(size_of::<Chunk>()),
154 )
155 });
156
157 let new_size = if usize::BITS < u64::BITS {
159 let Some(new_size) = (capacity as usize)
162 .checked_next_multiple_of(size_of::<Chunk>())
163 .and_then(|size| size.checked_add(size_of::<Chunk>()))
164 .filter(|&size| Layout::from_size_align(size, align_of::<Chunk>()).is_ok())
165 else {
166 panic!(
167 "Realloc from {} to {capacity} has failed: too large",
168 self.capacity()
169 );
170 };
171 new_size
172 } else {
173 size_of::<Chunk>() + (capacity as usize).next_multiple_of(size_of::<Chunk>())
174 };
175
176 #[expect(
177 clippy::cast_ptr_alignment,
178 reason = "Cast from correct alignment to bytes and back due to API requirements"
179 )]
180 let new_ptr = unsafe {
184 realloc(self.buffer.as_ptr().cast::<u8>(), layout, new_size)
185 .cast::<MaybeUninit<Chunk>>()
186 };
187 let Some(new_ptr) = NonNull::new(new_ptr) else {
188 panic!("Realloc from {} to {new_size} has failed", self.capacity());
189 };
190
191 self.buffer = new_ptr;
192 self.capacity = capacity;
193 }
194
195 #[inline(always)]
196 const fn len(&self) -> u32 {
197 self.len
198 }
199
200 #[inline(always)]
202 unsafe fn set_len(&mut self, len: u32) {
203 debug_assert!(
204 len <= self.capacity(),
205 "Too many bytes {} > {}",
206 len,
207 self.capacity()
208 );
209 self.len = len;
210 }
211
212 #[inline(always)]
213 const fn capacity(&self) -> u32 {
214 self.capacity
215 }
216
217 #[inline(always)]
218 const fn strong_count_ref(&self) -> &AtomicUsize {
219 unsafe {
222 self.buffer
223 .as_ptr()
224 .cast::<AtomicUsize>()
225 .as_ref_unchecked()
226 }
227 }
228
229 #[inline(always)]
230 const fn as_slice(&self) -> &[u8] {
231 let len = self.len() as usize;
232 unsafe { slice::from_raw_parts(self.as_ptr().cast::<u8>(), len) }
234 }
235
236 #[inline(always)]
237 const fn as_mut_slice(&mut self) -> &mut [u8] {
238 let len = self.len() as usize;
239 unsafe { slice::from_raw_parts_mut(self.as_mut_ptr().cast::<u8>(), len) }
241 }
242
243 #[inline(always)]
244 const fn as_u128_slice(&self) -> &[u128] {
245 let len = self.len() as usize / size_of::<u128>();
246 unsafe { slice::from_raw_parts(self.as_ptr(), len) }
250 }
251
252 #[inline(always)]
253 const fn as_ptr(&self) -> *const u128 {
254 unsafe { self.buffer.as_ptr().cast_const().add(1).cast::<u128>() }
256 }
257
258 #[inline(always)]
259 const fn as_mut_ptr(&mut self) -> *mut u128 {
260 unsafe { self.buffer.as_ptr().add(1).cast::<u128>() }
262 }
263}
264
265#[derive(Debug)]
273pub struct OwnedAlignedBuffer {
274 inner: InnerBuffer,
275}
276
277impl Deref for OwnedAlignedBuffer {
278 type Target = [u8];
279
280 #[inline(always)]
281 fn deref(&self) -> &Self::Target {
282 self.as_slice()
283 }
284}
285
286impl DerefMut for OwnedAlignedBuffer {
287 #[inline(always)]
288 fn deref_mut(&mut self) -> &mut Self::Target {
289 self.as_mut_slice()
290 }
291}
292
293unsafe impl StableDeref for OwnedAlignedBuffer {}
295
296impl Clone for OwnedAlignedBuffer {
297 #[inline(always)]
298 fn clone(&self) -> Self {
299 let mut new_instance = Self::with_capacity(self.capacity());
300 new_instance.copy_from_slice(self.as_slice());
301 new_instance
302 }
303}
304
305impl OwnedAlignedBuffer {
306 #[inline(always)]
313 pub fn with_capacity(capacity: u32) -> Self {
314 Self {
315 inner: InnerBuffer::allocate(capacity),
316 }
317 }
318
319 #[inline(always)]
325 pub fn from_bytes(bytes: &[u8]) -> Self {
326 let mut instance = Self::with_capacity(0);
327 instance.copy_from_slice(bytes);
328 instance
329 }
330
331 #[inline(always)]
332 pub const fn as_slice(&self) -> &[u8] {
333 self.inner.as_slice()
334 }
335
336 #[inline(always)]
337 pub const fn as_mut_slice(&mut self) -> &mut [u8] {
338 self.inner.as_mut_slice()
339 }
340
341 #[inline(always)]
346 pub const fn as_u128_slice(&self) -> &[u128] {
347 self.inner.as_u128_slice()
348 }
349
350 #[inline(always)]
351 pub const fn as_ptr(&self) -> *const u128 {
352 self.inner.as_ptr()
353 }
354
355 #[inline(always)]
356 pub const fn as_mut_ptr(&mut self) -> *mut u128 {
357 self.inner.as_mut_ptr()
358 }
359
360 #[inline(always)]
361 pub fn into_shared(self) -> SharedAlignedBuffer {
362 SharedAlignedBuffer { inner: self.inner }
363 }
364
365 #[inline(always)]
372 pub fn ensure_capacity(&mut self, capacity: u32) {
373 if capacity > self.capacity() {
374 self.inner.resize(capacity);
375 }
376 }
377
378 #[inline(always)]
384 pub fn copy_from_slice(&mut self, bytes: &[u8]) {
385 let Ok(len) = u32::try_from(bytes.len()) else {
386 panic!("Too many bytes {}", bytes.len());
387 };
388
389 if len > self.capacity() {
390 self.inner
391 .resize(len.max(self.capacity().saturating_mul(2)));
392 }
393
394 unsafe {
397 self.as_mut_ptr()
398 .cast::<u8>()
399 .copy_from_nonoverlapping(bytes.as_ptr(), bytes.len());
400
401 self.inner.set_len(len);
402 }
403 }
404
405 #[inline(always)]
412 #[must_use]
413 pub fn append(&mut self, bytes: &[u8]) -> bool {
414 let Ok(len) = u32::try_from(bytes.len()) else {
415 return false;
416 };
417
418 let Some(new_len) = self.len().checked_add(len) else {
419 return false;
420 };
421
422 if new_len > self.capacity() {
423 self.inner
424 .resize(new_len.max(self.capacity().saturating_mul(2)));
425 }
426
427 unsafe {
430 self.as_mut_ptr()
431 .cast::<u8>()
432 .add(self.len() as usize)
433 .copy_from_nonoverlapping(bytes.as_ptr(), bytes.len());
434
435 self.inner.set_len(new_len);
436 }
437
438 true
439 }
440
441 #[inline(always)]
442 pub const fn is_empty(&self) -> bool {
443 self.inner.len() == 0
444 }
445
446 #[inline(always)]
447 pub const fn len(&self) -> u32 {
448 self.inner.len()
449 }
450
451 #[inline(always)]
452 pub const fn capacity(&self) -> u32 {
453 self.inner.capacity()
454 }
455
456 #[inline(always)]
461 pub unsafe fn set_len(&mut self, new_len: u32) {
462 unsafe {
464 self.inner.set_len(new_len);
465 }
466 }
467}
468
469#[derive(Debug, Default, Clone)]
476pub struct SharedAlignedBuffer {
477 inner: InnerBuffer,
478}
479
480impl Deref for SharedAlignedBuffer {
481 type Target = [u8];
482
483 #[inline(always)]
484 fn deref(&self) -> &Self::Target {
485 self.as_slice()
486 }
487}
488
489unsafe impl StableDeref for SharedAlignedBuffer {}
491unsafe impl CloneStableDeref for SharedAlignedBuffer {}
493unsafe impl CloneableCart for SharedAlignedBuffer {}
495
496impl SharedAlignedBuffer {
497 #[inline(always)]
499 pub const fn empty_ref() -> &'static Self {
500 &EMPTY_SHARED_ALIGNED_BUFFER
501 }
502
503 #[inline(always)]
509 pub fn from_bytes(bytes: &[u8]) -> Self {
510 OwnedAlignedBuffer::from_bytes(bytes).into_shared()
511 }
512
513 #[inline(always)]
518 pub fn into_owned(self) -> OwnedAlignedBuffer {
519 if self.inner.strong_count_ref().load(Ordering::Acquire) == 1 {
520 OwnedAlignedBuffer { inner: self.inner }
521 } else {
522 OwnedAlignedBuffer::from_bytes(self.as_slice())
523 }
524 }
525
526 #[inline(always)]
527 pub const fn as_slice(&self) -> &[u8] {
528 self.inner.as_slice()
529 }
530
531 #[inline(always)]
532 pub const fn as_ptr(&self) -> *const u128 {
533 self.inner.as_ptr()
534 }
535
536 #[inline(always)]
537 pub const fn is_empty(&self) -> bool {
538 self.inner.len() == 0
539 }
540
541 #[inline(always)]
542 pub const fn len(&self) -> u32 {
543 self.inner.len()
544 }
545}