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