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