musli_zerocopy/buf/
buf.rs

1use core::alloc::Layout;
2use core::fmt;
3use core::mem::{align_of, size_of, MaybeUninit};
4use core::ops::{Index, IndexMut, Range};
5use core::ptr::{read_unaligned, NonNull};
6use core::slice::SliceIndex;
7
8#[cfg(feature = "alloc")]
9use alloc::borrow::{Cow, ToOwned};
10
11#[cfg(feature = "alloc")]
12use crate::buf::OwnedBuf;
13use crate::buf::{self, Bindable, Load, LoadMut, Validator};
14use crate::endian::ByteOrder;
15use crate::error::{Error, ErrorKind};
16use crate::pointer::{Ref, Size};
17use crate::traits::{UnsizedZeroCopy, ZeroCopy};
18
19/// A buffer wrapping a slice of bytes.
20///
21/// # Examples
22///
23/// ```
24/// use musli_zerocopy::{Buf, Ref};
25///
26/// let buf = Buf::new(b"Hello World!");
27/// let unsize: Ref<str> = Ref::with_metadata(0, 12);
28///
29/// assert_eq!(buf.load(unsize)?, "Hello World!");
30/// # Ok::<_, musli_zerocopy::Error>(())
31/// ```
32#[repr(transparent)]
33pub struct Buf {
34    data: [u8],
35}
36
37impl Buf {
38    /// Wrap the given bytes as a buffer.
39    ///
40    /// # Examples
41    ///
42    /// ```
43    /// use musli_zerocopy::{Buf, Ref};
44    ///
45    /// let buf = Buf::new(b"Hello World!");
46    /// let unsize: Ref<str> = Ref::with_metadata(0, 12);
47    ///
48    /// assert_eq!(buf.load(unsize)?, "Hello World!");
49    /// # Ok::<_, musli_zerocopy::Error>(())
50    /// ```
51    #[inline]
52    pub const fn new(data: &[u8]) -> &Buf {
53        // SAFETY: The struct is repr(transparent) over [u8].
54        unsafe { &*(data as *const [u8] as *const Self) }
55    }
56
57    /// Wrap the given bytes as a mutable buffer.
58    ///
59    /// # Examples
60    ///
61    /// ```
62    /// use musli_zerocopy::{Buf, Ref};
63    ///
64    /// let mut bytes: [u8; 12] = *b"Hello World!";
65    ///
66    /// let buf = Buf::new_mut(&mut bytes[..]);
67    /// let unsize = Ref::<str>::with_metadata(0, 12);
68    ///
69    /// buf.load_mut(unsize)?.make_ascii_uppercase();
70    /// assert_eq!(buf.load(unsize)?, "HELLO WORLD!");
71    /// # Ok::<_, musli_zerocopy::Error>(())
72    /// ```
73    #[inline]
74    pub fn new_mut(data: &mut [u8]) -> &mut Buf {
75        // SAFETY: The struct is repr(transparent) over [u8].
76        unsafe { &mut *(data as *mut [u8] as *mut Self) }
77    }
78
79    /// Construct a buffer with an alignment matching that of `T` which is
80    /// either wrapped in a [`Buf`] if it is already correctly aligned, or
81    /// inside of an allocated [`OwnedBuf`].
82    ///
83    /// # Examples
84    ///
85    /// ```no_run
86    /// use std::fs::read;
87    ///
88    /// use musli_zerocopy::{Buf, Ref, ZeroCopy};
89    ///
90    /// #[derive(ZeroCopy)]
91    /// #[repr(C)]
92    /// struct Person {
93    ///     name: Ref<str>,
94    ///     age: u32,
95    /// }
96    ///
97    /// let bytes = read("person.bin")?;
98    /// let buf = Buf::new(&bytes).to_aligned::<u128>();
99    ///
100    /// let s = buf.load(Ref::<Person>::zero())?;
101    /// # Ok::<_, anyhow::Error>(())
102    /// ```
103    #[cfg(feature = "alloc")]
104    #[inline]
105    pub fn to_aligned<T>(&self) -> Cow<'_, Buf> {
106        self.to_aligned_with(align_of::<T>())
107    }
108
109    /// Construct a buffer with a specific alignment which is either wrapped in
110    /// a [`Buf`] if it is already correctly aligned, or inside of an allocated
111    /// [`OwnedBuf`].
112    ///
113    /// # Panics
114    ///
115    /// Panics if `align` is not a power of two or if the size of the buffer is
116    /// larger than [`max_capacity_for_align(align)`].
117    ///
118    /// # Examples
119    ///
120    /// ```no_run
121    /// use std::fs::read;
122    ///
123    /// use musli_zerocopy::{Buf, Ref, ZeroCopy};
124    ///
125    /// #[derive(ZeroCopy)]
126    /// #[repr(C)]
127    /// struct Person {
128    ///     name: Ref<str>,
129    ///     age: u32,
130    /// }
131    ///
132    /// let bytes = read("person.bin")?;
133    /// let buf = Buf::new(&bytes).to_aligned_with(16);
134    ///
135    /// let s = buf.load(Ref::<Person>::zero())?;
136    /// # Ok::<_, anyhow::Error>(())
137    /// ```
138    #[cfg(feature = "alloc")]
139    #[inline]
140    pub fn to_aligned_with(&self, align: usize) -> Cow<'_, Buf> {
141        assert!(align.is_power_of_two(), "Alignment must be power of two");
142
143        // SAFETY: align is checked as a power of two just above.
144        if unsafe { self.is_aligned_with_unchecked(align) } {
145            Cow::Borrowed(self)
146        } else {
147            let mut buf =
148                unsafe { OwnedBuf::with_capacity_and_custom_alignment(self.len(), align) };
149
150            // SAFETY: Space for the slice has been allocated.
151            unsafe {
152                buf.store_bytes(&self.data);
153            }
154
155            Cow::Owned(buf)
156        }
157    }
158
159    /// Get the alignment of the current buffer.
160    pub fn alignment(&self) -> usize {
161        // NB: Maximum alignment supported by Rust is 2^29.
162        1usize << (self.data.as_ptr() as usize).trailing_zeros().min(29)
163    }
164
165    /// Test if the current buffer is layout compatible with the given `T`.
166    ///
167    /// # Examples
168    ///
169    /// ```
170    /// use musli_zerocopy::OwnedBuf;
171    ///
172    /// let mut buf = OwnedBuf::with_alignment::<u32>();
173    /// buf.extend_from_slice(&[1, 2, 3, 4]);
174    ///
175    /// assert!(buf.is_compatible_with::<u32>());
176    /// assert!(!buf.is_compatible_with::<u64>());
177    /// ```
178    #[inline]
179    pub fn is_compatible_with<T>(&self) -> bool
180    where
181        T: ZeroCopy,
182    {
183        self.is_compatible(Layout::new::<T>())
184    }
185
186    /// Ensure that the current buffer is layout compatible with the given `T`.
187    ///
188    /// # Examples
189    ///
190    /// ```
191    /// use musli_zerocopy::OwnedBuf;
192    ///
193    /// let mut buf = OwnedBuf::with_alignment::<u32>();
194    /// buf.extend_from_slice(&[1, 2, 3, 4]);
195    ///
196    /// assert!(buf.ensure_compatible_with::<u32>().is_ok());
197    /// assert!(buf.ensure_compatible_with::<u64>().is_err());
198    /// ```
199    #[inline]
200    pub fn ensure_compatible_with<T>(&self) -> Result<(), Error>
201    where
202        T: ZeroCopy,
203    {
204        if !self.is_compatible_with::<T>() {
205            return Err(Error::new(ErrorKind::LayoutMismatch {
206                layout: Layout::new::<T>(),
207                range: self.range(),
208            }));
209        }
210
211        Ok(())
212    }
213
214    /// Get the length of the backing buffer.
215    ///
216    /// # Examples
217    ///
218    /// ```
219    /// use musli_zerocopy::Buf;
220    ///
221    /// let buf = Buf::new(b"Hello World!");
222    /// assert_eq!(buf.len(), 12);
223    /// ```
224    #[inline]
225    pub fn len(&self) -> usize {
226        self.data.len()
227    }
228
229    /// Test if the backing buffer is empty.
230    ///
231    /// # Examples
232    ///
233    /// ```
234    /// use musli_zerocopy::Buf;
235    ///
236    /// let buf = Buf::new(b"Hello World!");
237    /// assert!(!buf.is_empty());
238    ///
239    /// let buf = Buf::new(b"");
240    /// assert!(buf.is_empty());
241    /// ```
242    #[inline]
243    pub fn is_empty(&self) -> bool {
244        self.data.is_empty()
245    }
246
247    /// Returns a reference to an element or subslice depending on the type of
248    /// index.
249    ///
250    /// - If given a position, returns a reference to the element at that
251    ///   position or `None` if out of bounds.
252    /// - If given a range, returns the subslice corresponding to that range, or
253    ///   `None` if out of bounds.
254    ///
255    /// # Examples
256    ///
257    /// ```
258    /// use musli_zerocopy::Buf;
259    ///
260    /// let buf = Buf::new(b"Hello World!");
261    ///
262    /// assert_eq!(buf.get(..5), Some(&b"Hello"[..]));
263    /// # Ok::<_, musli_zerocopy::Error>(())
264    /// ```
265    pub fn get<I>(&self, index: I) -> Option<&I::Output>
266    where
267        I: SliceIndex<[u8]>,
268    {
269        self.data.get(index)
270    }
271
272    /// Returns a mutable reference to an element or subslice depending on the
273    /// type of index (see [`get`]) or `None` if the index is out of bounds.
274    ///
275    /// [`get`]: slice::get
276    ///
277    /// # Examples
278    ///
279    /// ```
280    /// use musli_zerocopy::Buf;
281    ///
282    /// let mut bytes: [u8; 12] = *b"Hello World!";
283    ///
284    /// let buf = Buf::new_mut(&mut bytes[..]);
285    ///
286    /// if let Some(bytes) = buf.get_mut(..) {
287    ///     bytes.make_ascii_uppercase();
288    /// }
289    ///
290    /// assert_eq!(&buf[..], &b"HELLO WORLD!"[..]);
291    /// # Ok::<_, musli_zerocopy::Error>(())
292    /// ```
293    pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
294    where
295        I: SliceIndex<[u8]>,
296    {
297        self.data.get_mut(index)
298    }
299
300    /// Load the given value as a reference.
301    ///
302    /// # Errors
303    ///
304    /// This will error if the current buffer is not aligned for the type `T`,
305    /// or for other reasons specific to what needs to be done to validate a
306    /// `&T` reference.
307    ///
308    /// # Examples
309    ///
310    /// ```
311    /// use musli_zerocopy::OwnedBuf;
312    ///
313    /// let mut buf = OwnedBuf::new();
314    ///
315    /// let first = buf.store_unsized("first");
316    /// let second = buf.store_unsized("second");
317    ///
318    /// let buf = buf.as_ref();
319    ///
320    /// assert_eq!(buf.load(first)?, "first");
321    /// assert_eq!(buf.load(second)?, "second");
322    /// # Ok::<_, musli_zerocopy::Error>(())
323    /// ```
324    #[inline]
325    pub fn load<T>(&self, ptr: T) -> Result<&T::Target, Error>
326    where
327        T: Load,
328    {
329        ptr.load(self)
330    }
331
332    /// Load a value of type `T` at the given `offset`.
333    ///
334    /// # Errors
335    ///
336    /// This will error if the current buffer is not aligned for the type `T`,
337    /// or for other reasons specific to what needs to be done to validate a
338    /// `&T` reference.
339    ///
340    /// # Examples
341    ///
342    /// ```
343    /// use musli_zerocopy::OwnedBuf;
344    ///
345    /// let mut buf = OwnedBuf::new();
346    ///
347    /// buf.store(&1u32);
348    /// buf.store(&2u32);
349    ///
350    /// let buf = buf.as_ref();
351    ///
352    /// assert_eq!(buf.load_at::<u32>(0)?, &1u32);
353    /// assert_eq!(buf.load_at::<u32>(4)?, &2u32);
354    /// # Ok::<_, musli_zerocopy::Error>(())
355    /// ```
356    pub fn load_at<T>(&self, offset: usize) -> Result<&T, Error>
357    where
358        T: ZeroCopy,
359    {
360        self.load_sized::<T>(offset)
361    }
362
363    /// Load a value of type `T` mutably at the given `offset`.
364    ///
365    /// # Errors
366    ///
367    /// This will error if the current buffer is not aligned for the type `T`,
368    /// or for other reasons specific to what needs to be done to validate a
369    /// `&T` reference.
370    ///
371    /// # Examples
372    ///
373    /// ```
374    /// use musli_zerocopy::OwnedBuf;
375    ///
376    /// let mut buf = OwnedBuf::new();
377    ///
378    /// buf.store(&1u32);
379    /// buf.store(&2u32);
380    ///
381    /// *buf.load_at_mut::<u32>(0)? += 10;
382    ///
383    /// assert_eq!(buf.load_at::<u32>(0)?, &11u32);
384    /// assert_eq!(buf.load_at::<u32>(4)?, &2u32);
385    /// # Ok::<_, musli_zerocopy::Error>(())
386    /// ```
387    pub fn load_at_mut<T>(&mut self, offset: usize) -> Result<&mut T, Error>
388    where
389        T: ZeroCopy,
390    {
391        self.load_sized_mut::<T>(offset)
392    }
393
394    /// Load an unaligned value of type `T` at the given `offset`.
395    ///
396    /// # Errors
397    ///
398    /// This will error if the memory at `offset` is not valid for the type `T`.
399    ///
400    /// # Examples
401    ///
402    /// ```
403    /// use musli_zerocopy::OwnedBuf;
404    ///
405    /// let mut buf = OwnedBuf::new();
406    ///
407    /// buf.store(&42u8);
408    /// buf.store(&[1u8, 0, 0, 0]);
409    /// buf.store(&[2u8, 0, 0, 0]);
410    ///
411    /// assert_eq!(buf.load_at_unaligned::<u32>(1)?, 1u32.to_le());
412    /// assert_eq!(buf.load_at_unaligned::<u32>(5)?, 2u32.to_le());
413    /// # Ok::<_, musli_zerocopy::Error>(())
414    /// ```
415    pub fn load_at_unaligned<T>(&self, offset: usize) -> Result<T, Error>
416    where
417        T: ZeroCopy,
418    {
419        self.load_sized_unaligned::<T>(offset)
420    }
421
422    /// Load the given value as a mutable reference.
423    ///
424    /// # Errors
425    ///
426    /// This will error if the current buffer is not aligned for the type `T`,
427    /// or for other reasons specific to what needs to be done to validate a
428    /// `&mut T` reference.
429    ///
430    /// # Examples
431    ///
432    /// ```
433    /// use musli_zerocopy::OwnedBuf;
434    ///
435    /// let mut buf = OwnedBuf::new();
436    ///
437    /// let first = buf.store_unsized("first");
438    /// let second = buf.store_unsized("second");
439    ///
440    /// let buf = buf.as_mut();
441    ///
442    /// buf.load_mut(first)?.make_ascii_uppercase();
443    ///
444    /// assert_eq!(buf.load(first)?, "FIRST");
445    /// assert_eq!(buf.load(second)?, "second");
446    /// # Ok::<_, musli_zerocopy::Error>(())
447    /// ```
448    #[inline]
449    pub fn load_mut<T>(&mut self, ptr: T) -> Result<&mut T::Target, Error>
450    where
451        T: LoadMut,
452    {
453        ptr.load_mut(self)
454    }
455
456    /// Bind the current buffer to a value.
457    ///
458    /// This provides a more convenient API for complex types like
459    /// [`swiss::MapRef`] and [`swiss::SetRef`], and makes sure that all the
460    /// internals related to the type being bound have been validated.
461    ///
462    /// Binding a type can be be faster in cases where you interact with the
463    /// bound type a lot since accesses do not require validation, but might be
464    /// slower if the access is a "one of", or infrequent.
465    ///
466    /// [`swiss::MapRef`]: crate::swiss::MapRef
467    /// [`swiss::SetRef`]: crate::swiss::SetRef
468    ///
469    /// ## Examples
470    ///
471    /// Binding a [`swiss::Map`] ensures that all the internals of the map have
472    /// been validated:
473    ///
474    /// [`swiss::Map`]: crate::swiss::Map
475    ///
476    /// ```
477    /// use musli_zerocopy::OwnedBuf;
478    /// use musli_zerocopy::swiss;
479    ///
480    /// let mut buf = OwnedBuf::new();
481    ///
482    /// let map = swiss::store_map(&mut buf, [(1, 2), (2, 3)])?;
483    /// let map = buf.bind(map)?;
484    ///
485    /// assert_eq!(map.get(&1)?, Some(&2));
486    /// assert_eq!(map.get(&2)?, Some(&3));
487    /// assert_eq!(map.get(&3)?, None);
488    ///
489    /// assert!(map.contains_key(&1)?);
490    /// assert!(!map.contains_key(&3)?);
491    /// # Ok::<_, musli_zerocopy::Error>(())
492    /// ```
493    #[inline]
494    pub fn bind<T>(&self, ptr: T) -> Result<T::Bound<'_>, Error>
495    where
496        T: Bindable,
497    {
498        ptr.bind(self)
499    }
500
501    /// Cast the current buffer into the given type.
502    ///
503    /// This is usually only used indirectly by deriving [`ZeroCopy`].
504    ///
505    /// [`ZeroCopy`]: derive@crate::ZeroCopy
506    ///
507    /// # Safety
508    ///
509    /// The caller must ensure that the buffer is correctly sized, aligned and
510    /// contains a valid bit pattern for the destination type.
511    #[inline]
512    pub unsafe fn cast<T>(&self) -> &T {
513        &*self.data.as_ptr().cast()
514    }
515
516    /// Cast the current buffer into the given mutable type.
517    ///
518    /// This is usually only used indirectly by deriving [`ZeroCopy`].
519    ///
520    /// [`ZeroCopy`]: derive@crate::ZeroCopy
521    ///
522    /// # Safety
523    ///
524    /// The caller must ensure that the buffer is correctly sized, aligned and
525    /// contains a valid bit pattern for the destination type.
526    #[inline]
527    pub unsafe fn cast_mut<T>(&mut self) -> &mut T {
528        &mut *self.data.as_mut_ptr().cast()
529    }
530
531    /// Construct a validator over the current buffer.
532    ///
533    /// This is a struct validator, which checks that the fields specified in
534    /// order of subsequent calls to [`field`] conform to the `repr(C)`
535    /// representation.
536    ///
537    /// [`field`]: Validator::field
538    ///
539    /// # Examples
540    ///
541    /// ```
542    /// use musli_zerocopy::{OwnedBuf, ZeroCopy};
543    ///
544    /// #[derive(ZeroCopy)]
545    /// #[repr(C)]
546    /// struct Custom { field: u32, field2: u64 }
547    ///
548    /// let mut buf = OwnedBuf::new();
549    ///
550    /// let custom = buf.store(&Custom { field: 42, field2: 85 });
551    ///
552    /// let mut v = buf.validate_struct::<Custom>()?;
553    ///
554    /// // SAFETY: We're only validating fields we know are
555    /// // part of the struct, and do not go beyond.
556    /// unsafe {
557    ///     v.field::<u32>()?;
558    ///     v.field::<u64>()?;
559    /// }
560    /// # Ok::<_, musli_zerocopy::Error>(())
561    /// ```
562    #[inline]
563    pub fn validate_struct<T>(&self) -> Result<Validator<'_, T>, Error>
564    where
565        T: ZeroCopy,
566    {
567        self.ensure_compatible_with::<T>()?;
568        Ok(Validator::from_slice(&self.data))
569    }
570
571    pub(crate) unsafe fn get_range_from(
572        &self,
573        start: usize,
574        align: usize,
575    ) -> Result<(NonNull<u8>, usize), Error> {
576        if self.data.len() < start {
577            return Err(Error::new(ErrorKind::OutOfRangeFromBounds {
578                range: start..,
579                len: self.data.len(),
580            }));
581        };
582
583        let ptr = NonNull::new_unchecked(self.data.as_ptr().add(start) as *mut _);
584        let remaining = self.data.len() - start;
585
586        if !buf::is_aligned_with(ptr.as_ptr(), align) {
587            return Err(Error::new(ErrorKind::AlignmentRangeFromMismatch {
588                range: start..,
589                align,
590            }));
591        }
592
593        Ok((ptr, remaining))
594    }
595
596    pub(crate) unsafe fn get_mut_range_from(
597        &mut self,
598        start: usize,
599        align: usize,
600    ) -> Result<(NonNull<u8>, usize), Error> {
601        if self.data.len() < start {
602            return Err(Error::new(ErrorKind::OutOfRangeFromBounds {
603                range: start..,
604                len: self.data.len(),
605            }));
606        };
607
608        let ptr = NonNull::new_unchecked(self.data.as_mut_ptr().add(start));
609        let remaining = self.data.len() - start;
610
611        if !buf::is_aligned_with(ptr.as_ptr(), align) {
612            return Err(Error::new(ErrorKind::AlignmentRangeFromMismatch {
613                range: start..,
614                align,
615            }));
616        }
617
618        Ok((ptr, remaining))
619    }
620
621    /// Get the given range while checking its required alignment.
622    ///
623    /// # Safety
624    ///
625    /// Specified `align` must be a power of two.
626    #[inline]
627    pub(crate) unsafe fn inner_get(
628        &self,
629        start: usize,
630        end: usize,
631        align: usize,
632    ) -> Result<&[u8], Error> {
633        let buf = self.inner_get_unaligned(start, end)?;
634
635        if !buf::is_aligned_with(buf.as_ptr(), align) {
636            return Err(Error::new(ErrorKind::AlignmentRangeMismatch {
637                addr: buf.as_ptr() as usize,
638                range: start..end,
639                align,
640            }));
641        }
642
643        Ok(buf)
644    }
645
646    /// Get the given range mutably while checking its required alignment.
647    ///
648    /// # Safety
649    ///
650    /// Specified `align` must be a power of two.
651    #[inline]
652    pub(crate) unsafe fn inner_get_mut(
653        &mut self,
654        start: usize,
655        end: usize,
656        align: usize,
657    ) -> Result<&mut [u8], Error> {
658        let buf = self.inner_get_mut_unaligned(start, end)?;
659
660        if !buf::is_aligned_with(buf.as_ptr(), align) {
661            return Err(Error::new(ErrorKind::AlignmentRangeMismatch {
662                addr: buf.as_ptr() as usize,
663                range: start..end,
664                align,
665            }));
666        }
667
668        Ok(buf)
669    }
670
671    /// Get the given range without checking that it corresponds to any given
672    /// alignment.
673    #[inline]
674    pub(crate) fn inner_get_unaligned(&self, start: usize, end: usize) -> Result<&[u8], Error> {
675        let Some(data) = self.data.get(start..end) else {
676            return Err(Error::new(ErrorKind::OutOfRangeBounds {
677                range: start..end,
678                len: self.data.len(),
679            }));
680        };
681
682        Ok(data)
683    }
684
685    /// Get the given range mutably without checking that it corresponds to any given alignment.
686    #[inline]
687    pub(crate) fn inner_get_mut_unaligned(
688        &mut self,
689        start: usize,
690        end: usize,
691    ) -> Result<&mut [u8], Error> {
692        let len = self.data.len();
693
694        let Some(data) = self.data.get_mut(start..end) else {
695            return Err(Error::new(ErrorKind::OutOfRangeBounds {
696                range: start..end,
697                len,
698            }));
699        };
700
701        Ok(data)
702    }
703
704    /// Load an unsized reference.
705    #[inline]
706    pub(crate) fn load_unsized<T, O, E>(&self, unsize: Ref<T, E, O>) -> Result<&T, Error>
707    where
708        T: ?Sized + UnsizedZeroCopy,
709        O: Size,
710        E: ByteOrder,
711    {
712        let start = unsize.offset();
713        let metadata = unsize.metadata();
714
715        // SAFETY: Alignment and size is checked just above when getting the
716        // buffer slice.
717        unsafe {
718            let (buf, remaining) = self.get_range_from(start, T::ALIGN)?;
719            let metadata = T::validate_unsized::<E, O>(buf, remaining, metadata)?;
720            Ok(&*T::with_metadata(buf, metadata))
721        }
722    }
723
724    /// Load an unsized mutable reference.
725    #[inline]
726    pub(crate) fn load_unsized_mut<T, O, E>(
727        &mut self,
728        unsize: Ref<T, E, O>,
729    ) -> Result<&mut T, Error>
730    where
731        T: ?Sized + UnsizedZeroCopy,
732        O: Size,
733        E: ByteOrder,
734    {
735        let start = unsize.offset();
736        let metadata = unsize.metadata();
737
738        // SAFETY: Alignment and size is checked just above when getting the
739        // buffer slice.
740        unsafe {
741            let (buf, remaining) = self.get_mut_range_from(start, T::ALIGN)?;
742            let metadata = T::validate_unsized::<E, O>(buf, remaining, metadata)?;
743            Ok(&mut *T::with_metadata_mut(buf, metadata))
744        }
745    }
746
747    /// Load the given sized value as a reference.
748    #[inline]
749    pub(crate) fn load_sized<T>(&self, offset: usize) -> Result<&T, Error>
750    where
751        T: ZeroCopy,
752    {
753        unsafe {
754            let end = offset + size_of::<T>();
755
756            // SAFETY: align_of::<T>() is always a power of two.
757            let buf = self.inner_get(offset, end, align_of::<T>())?;
758
759            if !T::ANY_BITS {
760                // SAFETY: We've checked the size and alignment of the buffer above.
761                // The remaining safety requirements depend on the implementation of
762                // validate.
763                T::validate(&mut Validator::from_slice(buf))?;
764            }
765
766            // SAFETY: Implementing ANY_BITS is unsafe, and requires that the
767            // type being coerced into can really inhabit any bit pattern.
768            Ok(&*buf.as_ptr().cast())
769        }
770    }
771
772    /// Swap a type `P` by reference.
773    ///
774    /// There are no requirements on alignment, and the two swapped locations
775    /// are permitted to overlap. If the values do overlap, then the overlapping
776    /// region of memory from `a` will be used. This is demonstrated in the
777    /// second example below.
778    ///
779    /// # Errors
780    ///
781    /// Errors in case any of the swapped reference is out of bounds for the
782    /// current buffer.
783    ///
784    /// ```
785    /// use musli_zerocopy::{Buf, Ref};
786    ///
787    /// let mut buf = [0, 1, 2, 3];
788    /// let mut buf = Buf::new_mut(&mut buf);
789    ///
790    /// let mut a = Ref::<u32>::new(0);
791    /// let mut b = Ref::<u32>::new(4);
792    ///
793    /// assert!(buf.swap(a, b).is_err());
794    /// ```
795    ///
796    /// # Examples
797    ///
798    /// ```
799    /// use musli_zerocopy::{Buf, Ref};
800    ///
801    /// let mut buf: [u8; 12] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
802    /// let mut buf = Buf::new_mut(&mut buf);
803    ///
804    /// let mut a = Ref::<u32>::new(2);
805    /// let mut b = Ref::<u32>::new(6);
806    ///
807    /// buf.swap(a, b)?;
808    ///
809    /// assert_eq!(&buf[..], [0, 1, 6, 7, 8, 9, 2, 3, 4, 5, 10, 11]);
810    /// # Ok::<_, musli_zerocopy::Error>(())
811    /// ```
812    ///
813    /// Overlapping positions:
814    ///
815    /// ```
816    /// use musli_zerocopy::{Buf, Ref};
817    ///
818    /// let mut buf: [u8; 7] = [0, 1, 2, 3, 4, 5, 7];
819    /// let mut buf = Buf::new_mut(&mut buf);
820    ///
821    /// let mut a = Ref::<u32>::new(1);
822    /// let mut b = Ref::<u32>::new(2);
823    ///
824    /// buf.swap(a, b)?;
825    ///
826    /// assert_eq!(&buf[..], [0, 2, 1, 2, 3, 4, 7]);
827    /// # Ok::<_, musli_zerocopy::Error>(())
828    /// ```
829    #[inline]
830    pub fn swap<T, E, O>(&mut self, a: Ref<T, E, O>, b: Ref<T, E, O>) -> Result<(), Error>
831    where
832        T: ZeroCopy,
833        E: ByteOrder,
834        O: Size,
835    {
836        let a = a.offset();
837        let b = b.offset();
838
839        if a == b {
840            return Ok(());
841        }
842
843        let start = a.max(b);
844        let end = start + size_of::<T>();
845
846        if end > self.data.len() {
847            return Err(Error::new(ErrorKind::OutOfRangeBounds {
848                range: start..end,
849                len: self.data.len(),
850            }));
851        }
852
853        // SAFETY: We've checked that both locations are in bound and we're
854        // ensuring to utilize the appropriate copy primitive depending on
855        // whether two values may or may not overlap.
856        unsafe {
857            let mut tmp = MaybeUninit::<T>::uninit();
858            let base = self.data.as_mut_ptr();
859
860            let tmp = tmp.as_mut_ptr().cast::<u8>();
861            let a = base.add(a);
862            let b = base.add(b);
863
864            tmp.copy_from_nonoverlapping(a, size_of::<T>());
865            a.copy_from(b, size_of::<T>());
866            b.copy_from_nonoverlapping(tmp, size_of::<T>());
867        }
868
869        Ok(())
870    }
871
872    /// Load the given sized value as a mutable reference.
873    #[inline]
874    pub(crate) fn load_sized_mut<T>(&mut self, offset: usize) -> Result<&mut T, Error>
875    where
876        T: ZeroCopy,
877    {
878        let end = offset + size_of::<T>();
879
880        unsafe {
881            // SAFETY: align_of::<T>() is always a power of two.
882            let buf = self.inner_get_mut(offset, end, align_of::<T>())?;
883
884            if !T::ANY_BITS {
885                // SAFETY: We've checked the size and alignment of the buffer above.
886                // The remaining safety requirements depend on the implementation of
887                // validate.
888                T::validate(&mut Validator::from_slice(buf))?;
889            }
890
891            // SAFETY: Implementing ANY_BITS is unsafe, and requires that the
892            // type being coerced into can really inhabit any bit pattern.
893            Ok(&mut *buf.as_mut_ptr().cast())
894        }
895    }
896
897    /// Load the given sized value as a reference.
898    #[inline]
899    pub(crate) fn load_sized_unaligned<T>(&self, start: usize) -> Result<T, Error>
900    where
901        T: ZeroCopy,
902    {
903        let end = start + size_of::<T>();
904
905        unsafe {
906            // SAFETY: align_of::<T>() is always a power of two.
907            let buf = self.inner_get_unaligned(start, end)?;
908
909            if !T::ANY_BITS {
910                // SAFETY: We've checked the size and alignment of the buffer above.
911                // The remaining safety requirements depend on the implementation of
912                // validate.
913                T::validate(&mut Validator::from_slice(buf))?;
914            }
915
916            // SAFETY: Implementing ANY_BITS is unsafe, and requires that the
917            // type being coerced into can really inhabit any bit pattern.
918            Ok(read_unaligned(buf.as_ptr().cast()))
919        }
920    }
921
922    /// Access the underlying slice as a pointer.
923    #[inline]
924    pub(crate) fn as_ptr(&self) -> *const u8 {
925        self.data.as_ptr()
926    }
927
928    /// The numerical range of the buffer.
929    #[inline]
930    pub(crate) fn range(&self) -> Range<usize> {
931        let range = self.data.as_ptr_range();
932        range.start as usize..range.end as usize
933    }
934
935    /// Test if the current buffer is compatible with the given layout.
936    #[inline]
937    pub(crate) fn is_compatible(&self, layout: Layout) -> bool {
938        // SAFETY: Layout::align is a power of two.
939        unsafe {
940            self.is_aligned_with_unchecked(layout.align()) && self.data.len() >= layout.size()
941        }
942    }
943
944    /// Test if the current allocation uses the alignment of `T`.
945    ///
946    /// # Examples
947    ///
948    /// ```
949    /// use musli_zerocopy::OwnedBuf;
950    ///
951    /// #[repr(align(4096))]
952    /// struct Align4096;
953    ///
954    /// let buf = OwnedBuf::new();
955    /// assert!(buf.is_aligned::<u32>());
956    /// // NB: We might have gotten lucky and hit a wide alignment by chance.
957    /// assert!(buf.is_aligned::<Align4096>() || !buf.is_aligned::<Align4096>());
958    /// ```
959    #[inline]
960    pub fn is_aligned<T>(&self) -> bool {
961        buf::is_aligned_with(self.as_ptr(), align_of::<T>())
962    }
963
964    /// Test if the current allocation uses the specified alignment.
965    ///
966    /// # Panics
967    ///
968    /// Panics if the specified alignment is not a power of two.
969    ///
970    /// ```should_panic
971    /// use musli_zerocopy::OwnedBuf;
972    ///
973    /// let buf = OwnedBuf::new();
974    /// buf.is_aligned_with(0);
975    /// ```
976    ///
977    /// # Examples
978    ///
979    /// ```
980    /// use musli_zerocopy::OwnedBuf;
981    ///
982    /// let buf = OwnedBuf::new();
983    /// assert!(buf.is_aligned_with(8));
984    /// ```
985    #[inline]
986    pub fn is_aligned_with(&self, align: usize) -> bool {
987        assert!(align.is_power_of_two(), "Alignment is not a power of two");
988        // SAFETY: align is a power of two.
989        buf::is_aligned_with(self.as_ptr(), align)
990    }
991
992    #[inline]
993    pub(crate) unsafe fn is_aligned_with_unchecked(&self, align: usize) -> bool {
994        buf::is_aligned_with(self.as_ptr(), align)
995    }
996}
997
998impl fmt::Debug for Buf {
999    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1000        f.debug_tuple("Buf").field(&self.data.len()).finish()
1001    }
1002}
1003
1004#[cfg(feature = "alloc")]
1005impl ToOwned for Buf {
1006    type Owned = OwnedBuf;
1007
1008    #[inline]
1009    fn to_owned(&self) -> Self::Owned {
1010        let mut buf =
1011            unsafe { OwnedBuf::with_capacity_and_custom_alignment(self.len(), self.alignment()) };
1012
1013        buf.extend_from_slice(&self.data);
1014        buf
1015    }
1016}
1017
1018impl AsRef<Buf> for Buf {
1019    /// Trivial `AsRef<Buf>` implementation for `Buf`.
1020    ///
1021    /// # Examples
1022    ///
1023    /// ```
1024    /// use musli_zerocopy::Buf;
1025    ///
1026    /// let buf = Buf::new(&b"Hello World!"[..]);
1027    /// let buf = buf.as_ref();
1028    ///
1029    /// assert_eq!(&buf[..], b"Hello World!");
1030    /// # Ok::<_, musli_zerocopy::Error>(())
1031    /// ```
1032    #[inline]
1033    fn as_ref(&self) -> &Buf {
1034        self
1035    }
1036}
1037
1038impl AsMut<Buf> for Buf {
1039    /// Trivial `AsMut<Buf>` implementation for `Buf`.
1040    ///
1041    /// # Examples
1042    ///
1043    /// ```
1044    /// use musli_zerocopy::Buf;
1045    ///
1046    /// let mut bytes = *b"Hello World!";
1047    /// let buf = Buf::new_mut(&mut bytes[..]);
1048    /// let buf = buf.as_mut();
1049    ///
1050    /// buf[..5].make_ascii_uppercase();
1051    /// assert_eq!(&buf[..], b"HELLO World!");
1052    /// buf[11] = b'?';
1053    /// assert_eq!(&buf[..], b"HELLO World?");
1054    /// # Ok::<_, musli_zerocopy::Error>(())
1055    /// ```
1056    #[inline]
1057    fn as_mut(&mut self) -> &mut Buf {
1058        self
1059    }
1060}
1061
1062/// Index implementation to get a slice or individual byte out of a [`Buf`].
1063///
1064/// # Examples
1065///
1066/// ```
1067/// use musli_zerocopy::Buf;
1068///
1069/// let buf = Buf::new(b"Hello World!");
1070///
1071/// assert_eq!(&buf[..], &b"Hello World!"[..]);
1072/// assert_eq!(buf[0], b'H');
1073/// # Ok::<_, musli_zerocopy::Error>(())
1074/// ```
1075impl<I> Index<I> for Buf
1076where
1077    I: SliceIndex<[u8]>,
1078{
1079    type Output = I::Output;
1080
1081    #[inline]
1082    fn index(&self, index: I) -> &I::Output {
1083        &self.data[index]
1084    }
1085}
1086
1087/// Index implementation to get a mutable slice or individual byte out of a
1088/// [`Buf`].
1089///
1090/// # Examples
1091///
1092/// ```
1093/// use musli_zerocopy::Buf;
1094///
1095/// let mut bytes = *b"Hello World!";
1096/// let mut buf = Buf::new_mut(&mut bytes[..]);
1097///
1098/// buf[..5].make_ascii_uppercase();
1099///
1100/// assert_eq!(&buf[..], &b"HELLO World!"[..]);
1101/// buf[11] = b'?';
1102/// assert_eq!(&buf[..], &b"HELLO World?"[..]);
1103/// # Ok::<_, musli_zerocopy::Error>(())
1104/// ```
1105impl<I> IndexMut<I> for Buf
1106where
1107    I: SliceIndex<[u8]>,
1108{
1109    #[inline]
1110    fn index_mut(&mut self, index: I) -> &mut I::Output {
1111        &mut self.data[index]
1112    }
1113}