Skip to main content

musli_zerocopy/buf/
buf.rs

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