1use crate::{
2 alloc::{BufferAllocator, Global},
3 raw::RawAlignedBuffer,
4 UniqueAlignedBuffer, DEFAULT_BUFFER_ALIGNMENT,
5};
6use std::{fmt, ops, slice::SliceIndex};
7
8pub struct SharedAlignedBuffer<const ALIGNMENT: usize = DEFAULT_BUFFER_ALIGNMENT, A = Global>
13where
14 A: BufferAllocator<ALIGNMENT>,
15{
16 pub(crate) buf: RawAlignedBuffer<ALIGNMENT, A>,
17}
18
19impl<const ALIGNMENT: usize, A> Default for SharedAlignedBuffer<ALIGNMENT, A>
20where
21 A: BufferAllocator<ALIGNMENT> + Default,
22{
23 #[inline]
24 #[must_use]
25 fn default() -> Self {
26 Self::new_in(A::default())
27 }
28}
29
30impl<const ALIGNMENT: usize> SharedAlignedBuffer<ALIGNMENT> {
31 #[inline]
44 #[must_use]
45 pub const fn new() -> Self {
46 Self::new_in(Global)
47 }
48}
49
50impl<const ALIGNMENT: usize, A> SharedAlignedBuffer<ALIGNMENT, A>
51where
52 A: BufferAllocator<ALIGNMENT>,
53{
54 #[inline]
67 #[must_use]
68 pub const fn new_in(alloc: A) -> Self {
69 let buf = RawAlignedBuffer::new_in(alloc);
70 Self { buf }
71 }
72
73 #[inline]
88 pub fn as_slice(&self) -> &[u8] {
89 self
90 }
91
92 #[inline]
123 pub fn as_ptr(&self) -> *const u8 {
124 self.buf.ptr()
127 }
128
129 #[inline]
142 pub fn len(&self) -> usize {
143 self.buf.cap_or_len()
145 }
146
147 pub fn is_empty(&self) -> bool {
159 self.len() == 0
160 }
161
162 #[inline]
164 pub fn is_unique(&self) -> bool {
165 self.buf.is_unique()
166 }
167
168 #[inline]
170 pub fn ref_count(&self) -> usize {
171 self.buf.ref_count()
172 }
173
174 pub fn try_unique(mut this: Self) -> Result<UniqueAlignedBuffer<ALIGNMENT, A>, Self> {
192 if this.is_unique() {
193 let len = this.len();
194 this.buf.reset_cap();
195 Ok(UniqueAlignedBuffer { buf: this.buf, len })
196 } else {
197 Err(this)
198 }
199 }
200}
201
202impl<const ALIGNMENT: usize, A> Clone for SharedAlignedBuffer<ALIGNMENT, A>
203where
204 A: BufferAllocator<ALIGNMENT> + Clone,
205{
206 fn clone(&self) -> Self {
207 Self {
208 buf: self.buf.ref_clone(),
209 }
210 }
211}
212
213impl<const ALIGNMENT: usize, A> From<UniqueAlignedBuffer<ALIGNMENT, A>>
214 for SharedAlignedBuffer<ALIGNMENT, A>
215where
216 A: BufferAllocator<ALIGNMENT>,
217{
218 #[inline]
219 fn from(buf: UniqueAlignedBuffer<ALIGNMENT, A>) -> Self {
220 buf.into_shared()
221 }
222}
223
224impl<const ALIGNMENT: usize, A> ops::Deref for SharedAlignedBuffer<ALIGNMENT, A>
225where
226 A: BufferAllocator<ALIGNMENT>,
227{
228 type Target = [u8];
229
230 #[inline]
231 fn deref(&self) -> &Self::Target {
232 unsafe { std::slice::from_raw_parts(self.as_ptr(), self.len()) }
233 }
234}
235
236impl<I: SliceIndex<[u8]>, const ALIGNMENT: usize, A> ops::Index<I>
237 for SharedAlignedBuffer<ALIGNMENT, A>
238where
239 A: BufferAllocator<ALIGNMENT>,
240{
241 type Output = I::Output;
242
243 #[inline]
244 fn index(&self, index: I) -> &Self::Output {
245 ops::Index::index(&**self, index)
246 }
247}
248
249impl<const ALIGNMENT: usize, A> fmt::Debug for SharedAlignedBuffer<ALIGNMENT, A>
250where
251 A: BufferAllocator<ALIGNMENT>,
252{
253 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
254 fmt::Debug::fmt(&**self, f)
255 }
256}
257
258impl<const ALIGNMENT: usize, A> AsRef<[u8]> for SharedAlignedBuffer<ALIGNMENT, A>
259where
260 A: BufferAllocator<ALIGNMENT>,
261{
262 #[inline]
263 fn as_ref(&self) -> &[u8] {
264 self
265 }
266}
267
268#[cfg(feature = "stable-deref-trait")]
269unsafe impl<const ALIGNMENT: usize, A> stable_deref_trait::StableDeref
270 for SharedAlignedBuffer<ALIGNMENT, A>
271where
272 A: BufferAllocator<ALIGNMENT>,
273{
274}
275
276#[cfg(feature = "stable-deref-trait")]
277unsafe impl<const ALIGNMENT: usize, A> stable_deref_trait::CloneStableDeref
278 for SharedAlignedBuffer<ALIGNMENT, A>
279where
280 A: BufferAllocator<ALIGNMENT> + Clone,
281{
282}
283
284#[cfg(test)]
285mod tests {
286 use super::*;
287
288 #[test]
289 fn clones_returns_same_pointer() {
290 let mut buf = UniqueAlignedBuffer::<16>::with_capacity(10);
291 buf.extend([1, 2, 3]);
292 let buf = SharedAlignedBuffer::from(buf);
293 let buf2 = buf.clone();
294 assert_eq!(buf.as_ptr(), buf2.as_ptr());
295 }
296
297 #[test]
298 fn try_unique_returns_err_when_not_unique() {
299 let x = UniqueAlignedBuffer::<16>::from_iter([1, 2, 3, 4]).into_shared();
300 let _y = SharedAlignedBuffer::clone(&x);
301 assert!(SharedAlignedBuffer::try_unique(x).is_err());
302 }
303
304 #[test]
305 fn sharing_does_not_shrink_the_buffer() {
306 let buf = UniqueAlignedBuffer::<64>::with_capacity(10);
307 let cap = buf.capacity();
308 let buf = buf.into_shared();
309 assert_eq!(&*buf, &[]);
310
311 let buf = UniqueAlignedBuffer::try_from(buf).unwrap();
312 assert_eq!(&*buf, &[]);
313 assert_eq!(buf.capacity(), cap);
314 }
315
316 const _: () = {
318 const fn assert_send_sync<T: Send + Sync>() {}
319 assert_send_sync::<SharedAlignedBuffer<16>>();
320 };
321}