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}