Skip to main content

musli_zerocopy/buf/
slice_mut.rs

1use core::borrow::Borrow;
2use core::marker::PhantomData;
3use core::mem::{ManuallyDrop, MaybeUninit, align_of, size_of, size_of_val};
4use core::ops::Deref;
5use core::ptr::NonNull;
6use core::slice::{self, SliceIndex};
7
8#[cfg(feature = "alloc")]
9use alloc::borrow::Cow;
10
11use crate::buf::{self, AllocError, Buf, DefaultAlignment, Padder, StoreBuf};
12use crate::endian::{ByteOrder, DefaultEndian};
13use crate::error::{Error, ErrorKind};
14use crate::mem::PackedMaybeUninit;
15use crate::pointer::{DefaultSize, Ref, Size};
16use crate::traits::{UnsizedZeroCopy, ZeroCopy};
17
18/// A fixed buffer wrapping a `&mut [u8]` with a dynamic alignment.
19///
20/// By default this buffer starts out having the same alignment as `usize`,
21/// making it platform specific. But this alignment can grow in demand to the
22/// types being stored in it.
23///
24/// # Examples
25///
26/// ```
27/// use musli_zerocopy::{SliceMut, ZeroCopy};
28///
29/// #[derive(ZeroCopy)]
30/// #[repr(C, align(128))]
31/// struct Custom {
32///     field: u32,
33/// }
34///
35/// let mut buf = [0; 1024];
36/// let mut buf = SliceMut::new(&mut buf);
37/// buf.store(&Custom { field: 10 })?;
38/// # Ok::<_, musli_zerocopy::Error>(())
39/// ```
40pub struct SliceMut<'a, E = DefaultEndian, O = DefaultSize>
41where
42    E: ByteOrder,
43    O: Size,
44{
45    /// Base data pointer.
46    data: NonNull<MaybeUninit<u8>>,
47    /// The initialized length of the buffer.
48    len: usize,
49    /// The capacity of the buffer.
50    capacity: usize,
51    /// The requested alignment.
52    requested: usize,
53    /// Sticky endianness and pointer size.
54    _marker: PhantomData<(&'a mut [MaybeUninit<u8>], E, O)>,
55}
56
57impl<'a> SliceMut<'a> {
58    /// Construct a new empty buffer with a requested default alignment.
59    ///
60    /// The default alignment is guaranteed to be larger than 0.
61    ///
62    /// # Examples
63    ///
64    /// ```
65    /// use musli_zerocopy::SliceMut;
66    ///
67    /// let mut buf = [0; 1024];
68    /// let buf = SliceMut::new(&mut buf);
69    /// assert!(buf.is_empty());
70    /// ```
71    pub fn new(bytes: &'a mut [u8]) -> Self {
72        Self::with_alignment::<DefaultAlignment>(bytes)
73    }
74
75    /// Construct a new empty buffer with a requested default alignment from an
76    /// uninitialized buffer.
77    ///
78    /// The default alignment is guaranteed to be larger than 0.
79    ///
80    /// # Examples
81    ///
82    /// ```
83    /// use std::mem::MaybeUninit;
84    /// use musli_zerocopy::SliceMut;
85    ///
86    /// let mut buf: [MaybeUninit<u8>; 1024] = unsafe { MaybeUninit::uninit().assume_init() };
87    /// let mut buf = SliceMut::new_uninit(&mut buf);
88    /// assert!(buf.is_empty());
89    ///
90    /// let number = buf.store(&42u32)?;
91    /// # Ok::<_, musli_zerocopy::Error>(())
92    /// ```
93    pub fn new_uninit(bytes: &'a mut [MaybeUninit<u8>]) -> Self {
94        Self::with_alignment_uninit::<DefaultAlignment>(bytes)
95    }
96
97    /// Construct a new empty buffer with the an alignment request matching that
98    /// of `T`.
99    ///
100    /// Note that this does not guarantee that the underlying buffer is aligned.
101    ///
102    /// # Examples
103    ///
104    /// ```
105    /// use musli_zerocopy::SliceMut;
106    ///
107    /// let mut buf = [0; 1024];
108    /// let buf = SliceMut::with_alignment::<u64>(&mut buf);
109    /// assert!(buf.is_empty());
110    /// assert_eq!(buf.requested(), 8);
111    /// ```
112    pub fn with_alignment<T>(bytes: &'a mut [u8]) -> Self {
113        let align = align_of::<T>();
114        let capacity = bytes.len();
115
116        Self {
117            data: unsafe { NonNull::new_unchecked(bytes.as_mut_ptr().cast()) },
118            len: 0,
119            capacity,
120            requested: align,
121            _marker: PhantomData,
122        }
123    }
124
125    /// Construct a new empty buffer with the an alignment request matching that
126    /// of `T` from an uninitialized buffer.
127    ///
128    /// Note that this does not guarantee that the underlying buffer is aligned.
129    ///
130    /// # Examples
131    ///
132    /// ```
133    /// use musli_zerocopy::SliceMut;
134    ///
135    /// let mut buf = [0; 1024];
136    /// let buf = SliceMut::with_alignment::<u64>(&mut buf);
137    /// assert!(buf.is_empty());
138    /// assert_eq!(buf.requested(), 8);
139    /// ```
140    pub fn with_alignment_uninit<T>(bytes: &'a mut [MaybeUninit<u8>]) -> Self {
141        let align = align_of::<T>();
142        let capacity = bytes.len();
143
144        Self {
145            data: unsafe { NonNull::new_unchecked(bytes.as_mut_ptr()) },
146            len: 0,
147            capacity,
148            requested: align,
149            _marker: PhantomData,
150        }
151    }
152}
153
154impl<'a, E, O> SliceMut<'a, E, O>
155where
156    E: ByteOrder,
157    O: Size,
158{
159    /// Modify the buffer to utilize the specified pointer size when inserting
160    /// references.
161    ///
162    /// # Examples
163    ///
164    /// ```
165    /// use musli_zerocopy::SliceMut;
166    ///
167    /// let mut buf = SliceMut::new(&mut [0; 16])
168    ///     .with_size::<u8>();
169    /// ```
170    #[inline]
171    pub fn with_size<U>(self) -> SliceMut<'a, E, U>
172    where
173        U: Size,
174    {
175        let this = ManuallyDrop::new(self);
176
177        SliceMut {
178            data: this.data,
179            len: this.len,
180            capacity: this.capacity,
181            requested: this.requested,
182            _marker: PhantomData,
183        }
184    }
185
186    /// Modify the buffer to utilize the specified byte order when inserting
187    /// references.
188    ///
189    /// # Examples
190    ///
191    /// ```
192    /// use musli_zerocopy::{endian, SliceMut};
193    ///
194    /// let mut buf = [0; 1024];
195    /// let mut buf = SliceMut::new(&mut buf)
196    ///     .with_byte_order::<endian::Little>();
197    /// ```
198    #[inline]
199    pub fn with_byte_order<U>(self) -> SliceMut<'a, U, O>
200    where
201        U: ByteOrder,
202    {
203        let this = ManuallyDrop::new(self);
204
205        SliceMut {
206            data: this.data,
207            len: this.len,
208            capacity: this.capacity,
209            requested: this.requested,
210            _marker: PhantomData,
211        }
212    }
213
214    /// Get the current length of the buffer.
215    ///
216    /// # Examples
217    ///
218    /// ```
219    /// use musli_zerocopy::SliceMut;
220    ///
221    /// let mut buf = [0; 1024];
222    /// let buf = SliceMut::new(&mut buf);
223    /// assert_eq!(buf.len(), 0);
224    /// ```
225    #[inline]
226    pub fn len(&self) -> usize {
227        self.len
228    }
229
230    /// Clear the current buffer.
231    ///
232    /// # Examples
233    ///
234    /// ```
235    /// use musli_zerocopy::SliceMut;
236    ///
237    /// let mut buf = [0; 1024];
238    /// let mut buf = SliceMut::new(&mut buf);
239    /// assert_eq!(buf.capacity(), 1024);
240    /// buf.extend_from_slice(&[1, 2, 3, 4])?;
241    ///
242    /// assert_eq!(buf.len(), 4);
243    /// buf.clear();
244    /// assert_eq!(buf.capacity(), 1024);
245    /// assert_eq!(buf.len(), 0);
246    /// # Ok::<_, musli_zerocopy::Error>(())
247    /// ```
248    #[inline]
249    pub fn clear(&mut self) {
250        self.len = 0;
251    }
252
253    /// Test if the buffer is empty.
254    ///
255    /// # Examples
256    ///
257    /// ```
258    /// use musli_zerocopy::SliceMut;
259    ///
260    /// let mut buf = [0; 1024];
261    /// let buf = SliceMut::new(&mut buf);
262    /// assert!(buf.is_empty());
263    /// ```
264    #[inline]
265    pub fn is_empty(&self) -> bool {
266        self.len == 0
267    }
268
269    /// Get the current capacity of the buffer.
270    ///
271    /// # Examples
272    ///
273    /// ```
274    /// use musli_zerocopy::SliceMut;
275    ///
276    /// let mut buf = [0; 1024];
277    /// let buf = SliceMut::new(&mut buf);
278    /// assert_eq!(buf.capacity(), 1024);
279    /// ```
280    #[inline]
281    pub fn capacity(&self) -> usize {
282        self.capacity
283    }
284
285    /// Return the requested alignment of the buffer.
286    ///
287    /// # Examples
288    ///
289    /// ```
290    /// use musli_zerocopy::SliceMut;
291    ///
292    /// let mut buf = [0; 1024];
293    /// let buf = SliceMut::with_alignment::<u64>(&mut buf);
294    /// assert!(buf.is_empty());
295    /// assert_eq!(buf.requested(), 8);
296    /// ```
297    #[inline]
298    pub fn requested(&self) -> usize {
299        self.requested
300    }
301
302    /// Reserve capacity for at least `capacity` more bytes in this buffer.
303    ///
304    /// # Examples
305    ///
306    /// ```
307    /// use musli_zerocopy::SliceMut;
308    ///
309    /// let mut buf = [0; 1024];
310    /// let mut buf = SliceMut::new(&mut buf);
311    /// assert_eq!(buf.capacity(), 1024);
312    ///
313    /// buf.reserve(10);
314    /// assert!(buf.capacity() >= 10);
315    /// ```
316    #[inline]
317    pub fn reserve(&mut self, capacity: usize) -> Result<(), AllocError> {
318        let new_capacity = self
319            .len
320            .checked_add(capacity)
321            .ok_or_else(|| AllocError::capacity(self.capacity, usize::MAX))?;
322        self.ensure_capacity(new_capacity)
323    }
324
325    /// Advance the length of the owned buffer by `size`.
326    ///
327    /// # Safety
328    ///
329    /// The caller must ensure that bytes up until `len() + size` has been
330    /// initialized in this buffer.
331    #[inline]
332    pub unsafe fn advance(&mut self, size: usize) {
333        self.len += size;
334    }
335
336    /// Get get a raw pointer to the current buffer.
337    #[inline]
338    pub fn as_ptr(&self) -> *const MaybeUninit<u8> {
339        self.data.as_ptr() as *const _
340    }
341
342    /// Get get a raw mutable pointer to the current buffer.
343    #[inline]
344    pub fn as_mut_ptr(&mut self) -> *mut MaybeUninit<u8> {
345        self.data.as_ptr()
346    }
347
348    /// Extract a slice containing the entire buffer.
349    ///
350    /// # Examples
351    ///
352    /// ```
353    /// use musli_zerocopy::SliceMut;
354    ///
355    /// let mut buf = [0; 1024];
356    /// let mut buf = SliceMut::new(&mut buf);
357    /// buf.extend_from_slice(b"hello world")?;
358    /// assert_eq!(buf.as_slice(), b"hello world");
359    /// # Ok::<_, musli_zerocopy::Error>(())
360    /// ```
361    #[inline]
362    pub fn as_slice(&self) -> &[u8] {
363        // SAFETY: We only expose the initialized part of the buffer.
364        unsafe { slice::from_raw_parts(self.as_ptr().cast(), self.len()) }
365    }
366
367    /// Extract a mutable slice containing the entire buffer.
368    ///
369    /// # Examples
370    ///
371    /// ```
372    /// use musli_zerocopy::SliceMut;
373    ///
374    /// let mut buf = [0; 1024];
375    /// let mut buf = SliceMut::new(&mut buf);
376    /// buf.extend_from_slice(b"hello world")?;
377    /// buf.as_mut_slice().make_ascii_uppercase();
378    /// assert_eq!(buf.as_slice(), b"HELLO WORLD");
379    /// # Ok::<_, musli_zerocopy::Error>(())
380    /// ```
381    #[inline]
382    pub fn as_mut_slice(&mut self) -> &mut [u8] {
383        // SAFETY: We only expose the initialized part of the buffer.
384        unsafe { slice::from_raw_parts_mut(self.as_mut_ptr().cast(), self.len()) }
385    }
386
387    /// Access the buffer mutably.
388    ///
389    /// # Examples
390    ///
391    /// ```
392    /// use musli_zerocopy::SliceMut;
393    ///
394    /// let mut buf = [0; 1024];
395    /// let mut buf = SliceMut::new(&mut buf);
396    /// let slice = buf.store_unsized("hello world")?;
397    ///
398    /// // SAFETY: We don't manipulate the underlying buffer in a way which leaves uninitialized data.
399    /// let mut buf = unsafe { buf.as_mut_buf() };
400    ///
401    /// buf.load_mut(slice)?.make_ascii_uppercase();
402    /// assert_eq!(buf.load(slice)?, "HELLO WORLD");
403    /// # Ok::<_, musli_zerocopy::Error>(())
404    /// ```
405    ///
406    /// # Safety
407    ///
408    /// Since this allows the underlying buffer to be mutated, depending on how
409    /// the buffer is used it might result in undefined bit-patterns like
410    /// padding bytes being written to it. The caller must ensure this is not
411    /// done with the structures being written by for example calling
412    /// [`ZeroCopy::initialize_padding()`] after the contents of the buffer is
413    /// modified.
414    ///
415    /// See [`Buf::new_mut`] for more information.
416    #[inline]
417    pub unsafe fn as_mut_buf(&mut self) -> &mut Buf {
418        unsafe { Buf::new_mut(self.as_mut_slice()) }
419    }
420
421    /// Store an uninitialized value.
422    ///
423    /// This allows values to be inserted before they can be initialized, which
424    /// can be useful if you need them to be in a certain location in the buffer
425    /// but don't have access to their value yet.
426    ///
427    /// The memory for `T` will be zero-initialized at [`next_offset<T>()`] and
428    /// the length and alignment requirement of `SliceMut` updated to reflect
429    /// that an instance of `T` has been stored. But that representation might
430    /// not match the representation of `T`[^non-zero].
431    ///
432    /// To get the offset where the value will be written, call
433    /// [`next_offset<T>()`] before storing the value.
434    ///
435    /// > **Note:** this does not return [`std::mem::MaybeUninit`], instead we
436    /// > use an internal [`PackedMaybeUninit`] which is similar but has
437    /// > different properties. See [its documentation][PackedMaybeUninit] for
438    /// > more.
439    ///
440    /// [`next_offset<T>()`]: Self::next_offset()
441    /// [^non-zero]: Like with [`NonZero*`][core::num] types.
442    ///
443    /// # Examples
444    ///
445    /// ```
446    /// use musli_zerocopy::mem::PackedMaybeUninit;
447    /// use musli_zerocopy::{SliceMut, Ref, ZeroCopy};
448    ///
449    /// #[derive(ZeroCopy)]
450    /// #[repr(C)]
451    /// struct Custom { field: u32, string: Ref<str> }
452    ///
453    /// let mut buf = [0; 1024];
454    /// let mut buf = SliceMut::new(&mut buf);
455    /// let reference: Ref<PackedMaybeUninit<Custom>> = buf.store_uninit::<Custom>()?;
456    ///
457    /// let string = buf.store_unsized("Hello World!")?;
458    ///
459    /// buf.load_uninit_mut(reference)?.write(&Custom { field: 42, string });
460    ///
461    /// let reference = reference.assume_init();
462    /// assert_eq!(reference.offset(), 0);
463    /// # Ok::<_, musli_zerocopy::Error>(())
464    /// ```
465    #[inline]
466    pub fn store_uninit<T>(&mut self) -> Result<Ref<PackedMaybeUninit<T>, E, O>, Error>
467    where
468        T: ZeroCopy,
469    {
470        // SAFETY: We've just reserved capacity for this write.
471        unsafe {
472            self.next_offset_with_and_reserve(align_of::<T>(), size_of::<T>())?;
473            let offset = self.len;
474            self.data
475                .as_ptr()
476                .add(self.len)
477                .write_bytes(0, size_of::<T>());
478            self.len += size_of::<T>();
479            Ok(Ref::try_with_metadata_unchecked(offset, ())?)
480        }
481    }
482
483    /// Write a reference that might not have been initialized.
484    ///
485    /// This does not prevent [`Ref`] from different instances of [`SliceMut`]
486    /// from being written. It would only result in garbled data, but wouldn't
487    /// be a safety concern.
488    ///
489    /// > **Note:** this does not return [`std::mem::MaybeUninit`], instead we
490    /// > use an internal [`MaybeUninit`] which is similar but has different
491    /// > properties. See [its documentation][MaybeUninit] for more.
492    ///
493    /// # Panics
494    ///
495    /// Panics if the reference [`Ref::offset()`] and size of `T` does not fit
496    /// within the [`len()`] of the current structure. This might happen if you
497    /// try and use a reference constructed from a different [`SliceMut`]
498    /// instance.
499    ///
500    /// [`len()`]: Self::len()
501    ///
502    /// ```should_panic
503    /// use musli_zerocopy::SliceMut;
504    ///
505    /// let mut buf = [0; 1024];
506    /// let mut buf2 = SliceMut::new(&mut buf);
507    /// buf2.store(&10u32);
508    ///
509    /// let number = buf2.store_uninit::<u32>()?;
510    ///
511    /// let mut buf = [0; 0];
512    /// let mut buf1 = SliceMut::new(&mut buf);
513    /// buf1.load_uninit_mut(number)?;
514    /// # Ok::<_, musli_zerocopy::Error>(())
515    /// ```
516    ///
517    /// # Examples
518    ///
519    /// ```
520    /// use musli_zerocopy::{SliceMut, Ref, ZeroCopy};
521    /// use musli_zerocopy::mem::PackedMaybeUninit;
522    ///
523    /// #[derive(ZeroCopy)]
524    /// #[repr(C)]
525    /// struct Custom { field: u32, string: Ref<str> }
526    ///
527    /// let mut buf = [0; 1024];
528    /// let mut buf = SliceMut::new(&mut buf);
529    /// let reference: Ref<PackedMaybeUninit<Custom>> = buf.store_uninit::<Custom>()?;
530    ///
531    /// let string = buf.store_unsized("Hello World!")?;
532    ///
533    /// buf.load_uninit_mut(reference)?.write(&Custom { field: 42, string });
534    ///
535    /// let reference = reference.assume_init();
536    /// assert_eq!(reference.offset(), 0);
537    /// # Ok::<_, musli_zerocopy::Error>(())
538    /// ```
539    #[inline]
540    pub fn load_uninit_mut<T, U, I>(
541        &mut self,
542        reference: Ref<PackedMaybeUninit<T>, U, I>,
543    ) -> Result<&mut PackedMaybeUninit<T>, Error>
544    where
545        T: ZeroCopy,
546        U: ByteOrder,
547        I: Size,
548    {
549        let at = reference.offset();
550
551        // The whole value must fit in the initialized region, since the
552        // returned reference can be used to write `size_of::<T>()` bytes.
553        if at
554            .checked_add(size_of::<T>())
555            .is_none_or(|end| end > self.len)
556        {
557            return Err(Error::new(ErrorKind::OutOfRangeBounds {
558                range: at..at.saturating_add(size_of::<T>()),
559                len: self.len,
560            }));
561        }
562
563        // SAFETY: We've checked that `at..at + size_of::<T>()` is within the
564        // initialized region of the buffer above. `MaybeUninit<T>` has no
565        // representation requirements and is unaligned.
566        Ok(unsafe { &mut *(self.data.as_ptr().add(at) as *mut PackedMaybeUninit<T>) })
567    }
568
569    /// Insert a value with the given size.
570    ///
571    /// The memory for `T` will be initialized at [`next_offset<T>()`] and the
572    /// length and alignment requirement of `SliceMut` updated to reflect that
573    /// an instance of `T` has been stored.
574    ///
575    /// To get the offset where the value will be written, call
576    /// [`next_offset<T>()`] before storing the value or access the offset
577    /// through the [`Ref::offset`] being returned.
578    ///
579    /// [`next_offset<T>()`]: Self::next_offset
580    ///
581    /// # Examples
582    ///
583    /// ```
584    /// use musli_zerocopy::{SliceMut, Ref, ZeroCopy};
585    ///
586    /// #[derive(ZeroCopy)]
587    /// #[repr(C)]
588    /// struct Custom { field: u32, string: Ref<str> }
589    ///
590    /// let mut buf = [0; 1024];
591    /// let mut buf = SliceMut::new(&mut buf);
592    ///
593    /// let string = buf.store_unsized("string")?;
594    /// let custom = buf.store(&Custom { field: 1, string })?;
595    /// let custom2 = buf.store(&Custom { field: 2, string })?;
596    ///
597    /// let buf = buf.to_requested()?;
598    ///
599    /// let custom = buf.load(custom)?;
600    /// assert_eq!(custom.field, 1);
601    /// assert_eq!(buf.load(custom.string)?, "string");
602    ///
603    /// let custom2 = buf.load(custom2)?;
604    /// assert_eq!(custom2.field, 2);
605    /// assert_eq!(buf.load(custom2.string)?, "string");
606    /// # Ok::<_, musli_zerocopy::Error>(())
607    /// ```
608    ///
609    /// Storing an array:
610    ///
611    ///
612    /// ```
613    /// use musli_zerocopy::{ZeroCopy, SliceMut};
614    ///
615    /// // Element with padding.
616    /// #[derive(Debug, PartialEq, ZeroCopy)]
617    /// #[repr(C)]
618    /// struct Element {
619    ///     first: u8,
620    ///     second: u32,
621    /// }
622    ///
623    /// let values = [
624    ///     Element { first: 0x01, second: 0x01020304u32 },
625    ///     Element { first: 0x02, second: 0x01020304u32 }
626    /// ];
627    ///
628    /// let mut buf = [0; 1024];
629    /// let mut buf = SliceMut::new(&mut buf);
630    /// let array = buf.store(&values)?;
631    ///
632    /// let buf = buf.to_requested()?;
633    ///
634    /// assert_eq!(buf.load(array)?, &values);
635    /// # Ok::<_, musli_zerocopy::Error>(())
636    /// ```
637    #[inline]
638    pub fn store<T>(&mut self, value: &T) -> Result<Ref<T, E, O>, Error>
639    where
640        T: ZeroCopy,
641    {
642        self.next_offset_with_and_reserve(align_of::<T>(), size_of::<T>())?;
643
644        // SAFETY: We're ensuring to both align the internal buffer and store
645        // the value.
646        unsafe { self.store_unchecked(value) }
647    }
648
649    /// Insert a value with the given size without ensuring that the buffer has
650    /// the reserved capacity for to or is properly aligned.
651    ///
652    /// This is a low level API which is tricky to use correctly. The
653    /// recommended way to use this is through [`SliceMut::store`].
654    ///
655    /// [`SliceMut::store`]: Self::store
656    ///
657    /// # Safety
658    ///
659    /// The caller has to ensure that the buffer has the required capacity for
660    /// `&T` and is properly aligned. This can easily be accomplished by calling
661    /// [`request_align::<T>()`] followed by [`align_in_place()`] before this
662    /// function. A safe variant of this function is [`SliceMut::store`].
663    ///
664    /// [`align_in_place()`]: Self::align_in_place
665    /// [`SliceMut::store`]: Self::store
666    /// [`request_align::<T>()`]: Self::request_align
667    ///
668    /// # Examples
669    ///
670    /// ```
671    /// use std::mem::size_of;
672    ///
673    /// use musli_zerocopy::{SliceMut, Ref, ZeroCopy};
674    ///
675    /// #[derive(ZeroCopy)]
676    /// #[repr(C, align(4096))]
677    /// struct Custom { field: u32, string: Ref<str> }
678    ///
679    /// let mut buf = [0; 12288];
680    /// let mut buf = SliceMut::new(&mut buf);
681    ///
682    /// let string = buf.store_unsized("string")?;
683    ///
684    /// buf.request_align::<Custom>()?;
685    /// buf.reserve(2 * size_of::<Custom>())?;
686    ///
687    /// // SAFETY: We've ensure that the buffer is internally aligned and sized just above.
688    /// let custom = unsafe { buf.store_unchecked(&Custom { field: 1, string })? };
689    /// let custom2 = unsafe { buf.store_unchecked(&Custom { field: 2, string })? };
690    ///
691    /// let buf = buf.to_requested()?;
692    ///
693    /// let custom = buf.load(custom)?;
694    /// assert_eq!(custom.field, 1);
695    /// assert_eq!(buf.load(custom.string)?, "string");
696    ///
697    /// let custom2 = buf.load(custom2)?;
698    /// assert_eq!(custom2.field, 2);
699    /// assert_eq!(buf.load(custom2.string)?, "string");
700    /// # Ok::<_, musli_zerocopy::Error>(())
701    /// ```
702    #[inline]
703    pub unsafe fn store_unchecked<T>(&mut self, value: &T) -> Result<Ref<T, E, O>, Error>
704    where
705        T: ZeroCopy,
706    {
707        let offset = self.len;
708
709        unsafe {
710            let ptr = NonNull::new_unchecked(self.data.as_ptr().add(offset));
711            buf::store_unaligned(ptr, value);
712            self.len += size_of::<T>();
713            Ok(Ref::try_with_metadata_unchecked(offset, ())?)
714        }
715    }
716
717    /// Either return the current buffer, or allocate one which has a
718    /// [`requested()`] alignment.
719    ///
720    /// [`requested()`]: Self::requested
721    ///
722    /// # Examples
723    ///
724    /// ```
725    /// use musli_zerocopy::SliceMut;
726    ///
727    /// let mut buf = [0; 1024];
728    /// let mut buf = SliceMut::new(&mut buf);
729    ///
730    /// let first = buf.store_unsized("first")?;
731    /// let second = buf.store_unsized("second")?;
732    ///
733    /// let buf = buf.to_requested()?;
734    ///
735    /// assert_eq!(buf.load(first)?, "first");
736    /// assert_eq!(buf.load(second)?, "second");
737    /// # Ok::<_, musli_zerocopy::Error>(())
738    /// ```
739    #[cfg(feature = "alloc")]
740    pub fn to_requested(&self) -> Result<Cow<'_, Buf>, AllocError> {
741        self.to_aligned_with(self.requested)
742    }
743
744    /// Write a value to the buffer.
745    ///
746    /// # Examples
747    ///
748    /// ```
749    /// use musli_zerocopy::SliceMut;
750    ///
751    /// let mut buf = [0; 1024];
752    /// let mut buf = SliceMut::new(&mut buf);
753    ///
754    /// let first = buf.store_unsized("first")?;
755    /// let second = buf.store_unsized("second")?;
756    ///
757    /// let buf = buf.to_requested()?;
758    ///
759    /// assert_eq!(buf.load(first)?, "first");
760    /// assert_eq!(buf.load(second)?, "second");
761    /// # Ok::<_, musli_zerocopy::Error>(())
762    /// ```
763    #[inline]
764    pub fn store_unsized<T>(&mut self, value: &T) -> Result<Ref<T, E, O>, Error>
765    where
766        T: ?Sized + UnsizedZeroCopy,
767    {
768        unsafe {
769            let size = size_of_val(value);
770            self.next_offset_with_and_reserve(T::ALIGN, size)?;
771            let offset = self.len;
772            let ptr = NonNull::new_unchecked(self.data.as_ptr().add(offset));
773            ptr.as_ptr()
774                .copy_from_nonoverlapping(value.as_ptr().cast(), size);
775
776            if T::PADDED {
777                let mut padder = Padder::new(ptr);
778                value.pad(&mut padder);
779                padder.remaining_unsized(value);
780            }
781
782            self.len += size;
783            Ok(Ref::try_with_metadata_unchecked(offset, value.metadata())?)
784        }
785    }
786
787    /// Insert a slice into the buffer.
788    ///
789    /// # Examples
790    ///
791    /// ```
792    /// use musli_zerocopy::SliceMut;
793    ///
794    /// let mut buf = [0; 1024];
795    /// let mut buf = SliceMut::new(&mut buf);
796    ///
797    /// let values = [buf.store_unsized("first")?, buf.store_unsized("second")?];
798    /// let slice = buf.store_slice(&values)?;
799    /// let buf = buf.to_requested()?;
800    ///
801    /// let slice = buf.load(slice)?;
802    /// assert_eq!(buf.load(slice[0])?, "first");
803    /// assert_eq!(buf.load(slice[1])?, "second");
804    /// # Ok::<_, musli_zerocopy::Error>(())
805    /// ```
806    #[inline(always)]
807    pub fn store_slice<T>(&mut self, values: &[T]) -> Result<Ref<[T], E, O>, Error>
808    where
809        T: ZeroCopy,
810    {
811        self.store_unsized(values)
812    }
813
814    /// Extend the buffer from a slice.
815    ///
816    /// Note that this only extends the underlying buffer but does not ensure
817    /// that any required alignment is abided by.
818    ///
819    /// To do this, the caller must call [`request_align()`] with the appropriate
820    /// alignment, otherwise the necessary alignment to decode the buffer again
821    /// will be lost.
822    ///
823    /// [`request_align()`]: Self::request_align
824    ///
825    /// # Errors
826    ///
827    /// This is a raw API, and does not guarantee that any given alignment will
828    /// be respected.
829    ///
830    /// # Examples
831    ///
832    /// ```
833    /// use musli_zerocopy::{SliceMut, Ref};
834    ///
835    /// let mut buf = [0; 1024];
836    /// let mut buf = SliceMut::with_alignment::<()>(&mut buf);
837    ///
838    /// // Add one byte of padding to throw of any incidental alignment.
839    /// buf.extend_from_slice(&[1])?;
840    ///
841    /// let ptr: Ref<u32> = Ref::new(buf.next_offset::<u32>()?);
842    /// buf.extend_from_slice(&[1, 2, 3, 4])?;
843    ///
844    /// let buf = buf.to_requested()?;
845    ///
846    /// assert_eq!(*buf.load(ptr)?, u32::from_ne_bytes([1, 2, 3, 4]));
847    /// # Ok::<_, musli_zerocopy::Error>(())
848    /// ```
849    pub fn extend_from_slice(&mut self, bytes: &[u8]) -> Result<(), AllocError> {
850        self.reserve(bytes.len())?;
851
852        // SAFETY: We just checked that there is space in the slice.
853        unsafe {
854            self.store_bytes(bytes);
855        }
856
857        Ok(())
858    }
859
860    /// Fill and initialize the buffer with `byte` up to `len`.
861    pub(crate) fn fill(&mut self, byte: u8, len: usize) -> Result<(), AllocError> {
862        self.reserve(len)?;
863
864        unsafe {
865            let ptr = self.data.as_ptr().add(self.len);
866            ptr.write_bytes(byte, len);
867            self.len += len;
868        }
869
870        Ok(())
871    }
872
873    /// Store the slice without allocating.
874    ///
875    /// # Safety
876    ///
877    /// The caller must ensure that the buffer has the capacity for
878    /// `bytes.len()` and that the value being stored is not padded as per
879    /// `ZeroCopy::PADDED`.
880    #[inline]
881    pub(crate) unsafe fn store_bytes<T>(&mut self, values: &[T])
882    where
883        T: ZeroCopy,
884    {
885        unsafe {
886            let dst = self.as_mut_ptr().add(self.len);
887            dst.copy_from_nonoverlapping(values.as_ptr().cast(), size_of_val(values));
888            self.len += size_of_val(values);
889        }
890    }
891
892    /// Request that the current buffer should have at least the specified
893    /// alignment and zero-initialize the buffer up to the next position which
894    /// matches the given alignment.
895    ///
896    /// Note that this does not guarantee that the internal buffer is aligned
897    /// in-memory. An instance of [`SliceMut`] cannot guarantee this.
898    ///
899    /// ```
900    /// use musli_zerocopy::SliceMut;
901    /// let mut buf = [0; 1024];
902    /// let mut buf = SliceMut::new(&mut buf);
903    ///
904    /// buf.extend_from_slice(&[1, 2])?;
905    /// buf.request_align::<u32>()?;
906    ///
907    /// assert_eq!(buf.as_slice(), &[1, 2, 0, 0]);
908    /// # Ok::<_, musli_zerocopy::buf::AllocError>(())
909    /// ```
910    ///
911    /// # Safety
912    ///
913    /// The caller must guarantee that the alignment is a power of two.
914    ///
915    /// # Examples
916    ///
917    /// ```
918    /// use musli_zerocopy::SliceMut;
919    ///
920    /// let mut buf = [0; 1024];
921    /// let mut buf = SliceMut::new(&mut buf);
922    /// buf.extend_from_slice(&[1, 2, 3, 4])?;
923    /// buf.request_align::<u64>()?;
924    /// buf.extend_from_slice(&[5, 6, 7, 8])?;
925    ///
926    /// assert_eq!(buf.as_slice(), &[1, 2, 3, 4, 0, 0, 0, 0, 5, 6, 7, 8]);
927    /// # Ok::<_, musli_zerocopy::buf::AllocError>(())
928    /// ```
929    #[inline]
930    pub fn request_align<T>(&mut self) -> Result<(), AllocError>
931    where
932        T: ZeroCopy,
933    {
934        self.requested = self.requested.max(align_of::<T>());
935        self.ensure_aligned_and_reserve(align_of::<T>(), size_of::<T>())?;
936        Ok(())
937    }
938
939    /// Ensure that the current buffer is aligned under the assumption that it
940    /// needs to be allocated.
941    #[inline]
942    fn ensure_aligned_and_reserve(
943        &mut self,
944        align: usize,
945        reserve: usize,
946    ) -> Result<(), AllocError> {
947        let extra = buf::padding_to(self.len, align);
948        self.reserve(extra + reserve)?;
949
950        // SAFETY: The length is ensures to be within the address space.
951        unsafe {
952            self.data.as_ptr().add(self.len).write_bytes(0, extra);
953            self.len += extra;
954        }
955
956        Ok(())
957    }
958
959    /// Construct a pointer aligned for `align` into the current buffer which
960    /// points to the next location that will be written.
961    #[inline]
962    pub(crate) fn next_offset_with_and_reserve(
963        &mut self,
964        align: usize,
965        reserve: usize,
966    ) -> Result<(), AllocError> {
967        if !align.is_power_of_two() {
968            return Err(AllocError::capacity(0, align));
969        }
970        self.requested = self.requested.max(align);
971        self.ensure_aligned_and_reserve(align, reserve)?;
972        Ok(())
973    }
974
975    /// Construct a pointer aligned for `T` into the current buffer which points
976    /// to the next location that will be written.
977    ///
978    /// This ensures that the alignment of the pointer is a multiple of `align`
979    /// and that the current buffer has the capacity for store `T`.
980    ///
981    /// # Examples
982    ///
983    /// ```
984    /// use musli_zerocopy::{SliceMut, Ref};
985    ///
986    /// let mut buf = [0; 1024];
987    /// let mut buf = SliceMut::new(&mut buf);
988    ///
989    /// // Add one byte of padding to throw of any incidental alignment.
990    /// buf.extend_from_slice(&[1])?;
991    ///
992    /// let ptr: Ref<u32> = Ref::new(buf.next_offset::<u32>()?);
993    /// buf.extend_from_slice(&[1, 2, 3, 4])?;
994    ///
995    /// let buf = buf.to_requested()?;
996    ///
997    /// assert_eq!(*buf.load(ptr)?, u32::from_ne_bytes([1, 2, 3, 4]));
998    /// # Ok::<_, musli_zerocopy::Error>(())
999    /// ```
1000    #[inline]
1001    pub fn next_offset<T>(&mut self) -> Result<usize, AllocError> {
1002        // SAFETY: The alignment of `T` is guaranteed to be a power of two. We
1003        // also make sure to reserve space for `T` since it is very likely that
1004        // it will be written immediately after this.
1005        self.next_offset_with_and_reserve(align_of::<T>(), size_of::<T>())?;
1006        Ok(self.len)
1007    }
1008
1009    // Ensure that the new capacity is available or panic.
1010    #[inline]
1011    fn ensure_capacity(&mut self, new_capacity: usize) -> Result<(), AllocError> {
1012        let new_capacity = new_capacity.max(self.requested);
1013
1014        if self.capacity < new_capacity {
1015            return Err(AllocError::capacity(self.capacity, new_capacity));
1016        }
1017
1018        Ok(())
1019    }
1020}
1021
1022/// `SliceMut` are `Send` because the data they reference is unaliased.
1023unsafe impl Send for SliceMut<'_> {}
1024/// `SliceMut` are `Sync` since they are `Send` and the data they reference is
1025/// unaliased.
1026unsafe impl Sync for SliceMut<'_> {}
1027
1028impl<E, O> Deref for SliceMut<'_, E, O>
1029where
1030    E: ByteOrder,
1031    O: Size,
1032{
1033    type Target = Buf;
1034
1035    #[inline]
1036    fn deref(&self) -> &Self::Target {
1037        Buf::new(self.as_slice())
1038    }
1039}
1040
1041impl<E, O> AsRef<Buf> for SliceMut<'_, E, O>
1042where
1043    E: ByteOrder,
1044    O: Size,
1045{
1046    /// Trivial `AsRef<Buf>` implementation for `SliceMut<O>`.
1047    ///
1048    /// # Examples
1049    ///
1050    /// ```
1051    /// use musli_zerocopy::SliceMut;
1052    ///
1053    /// let mut buf = [0; 1024];
1054    /// let mut buf = SliceMut::new(&mut buf);
1055    /// let slice = buf.store_unsized("hello world")?;
1056    ///
1057    /// let buf = buf.to_requested()?;
1058    ///
1059    /// assert_eq!(buf.load(slice)?, "hello world");
1060    /// # Ok::<_, musli_zerocopy::Error>(())
1061    /// ```
1062    #[inline]
1063    fn as_ref(&self) -> &Buf {
1064        self
1065    }
1066}
1067
1068impl<E, O> Borrow<Buf> for SliceMut<'_, E, O>
1069where
1070    E: ByteOrder,
1071    O: Size,
1072{
1073    #[inline]
1074    fn borrow(&self) -> &Buf {
1075        self.as_ref()
1076    }
1077}
1078
1079impl<E, O> StoreBuf for SliceMut<'_, E, O>
1080where
1081    E: ByteOrder,
1082    O: Size,
1083{
1084    type ByteOrder = E;
1085    type Size = O;
1086
1087    #[inline]
1088    fn len(&self) -> usize {
1089        SliceMut::len(self)
1090    }
1091
1092    #[inline]
1093    fn truncate(&mut self, len: usize) {
1094        if self.len > len {
1095            self.len = len;
1096        }
1097    }
1098
1099    #[inline]
1100    fn store_unsized<T>(&mut self, value: &T) -> Result<Ref<T, Self::ByteOrder, Self::Size>, Error>
1101    where
1102        T: ?Sized + UnsizedZeroCopy,
1103    {
1104        SliceMut::store_unsized(self, value)
1105    }
1106
1107    #[inline]
1108    fn store<T>(&mut self, value: &T) -> Result<Ref<T, Self::ByteOrder, Self::Size>, Error>
1109    where
1110        T: ZeroCopy,
1111    {
1112        SliceMut::store(self, value)
1113    }
1114
1115    #[inline]
1116    fn swap<T>(
1117        &mut self,
1118        a: Ref<T, Self::ByteOrder, Self::Size>,
1119        b: Ref<T, Self::ByteOrder, Self::Size>,
1120    ) -> Result<(), Error>
1121    where
1122        T: ZeroCopy,
1123    {
1124        // SAFETY: Since we are swapping two locations which have the same type
1125        // `T`, it does not affect the initialized state of the buffer.
1126        let buf = unsafe { self.as_mut_buf() };
1127        Buf::swap(buf, a, b)
1128    }
1129
1130    #[inline]
1131    fn align_in_place(&mut self) -> Result<(), AllocError> {
1132        // SAFETY: self.requested is guaranteed to be a power of two.
1133        if !buf::is_aligned_with(self.as_ptr(), self.requested) {
1134            return Err(AllocError::misaligned(self.as_ptr(), self.requested));
1135        }
1136
1137        Ok(())
1138    }
1139
1140    #[inline]
1141    fn next_offset<T>(&mut self) -> Result<usize, AllocError> {
1142        SliceMut::next_offset::<T>(self)
1143    }
1144
1145    #[inline]
1146    fn next_offset_with_and_reserve(
1147        &mut self,
1148        align: usize,
1149        reserve: usize,
1150    ) -> Result<(), AllocError> {
1151        SliceMut::next_offset_with_and_reserve(self, align, reserve)
1152    }
1153
1154    #[inline]
1155    fn fill(&mut self, byte: u8, len: usize) -> Result<(), AllocError> {
1156        SliceMut::fill(self, byte, len)
1157    }
1158
1159    #[inline]
1160    fn get<I>(&self, index: I) -> Option<&I::Output>
1161    where
1162        I: SliceIndex<[u8]>,
1163    {
1164        Buf::get(self, index)
1165    }
1166
1167    #[inline]
1168    unsafe fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
1169    where
1170        I: SliceIndex<[u8]>,
1171    {
1172        unsafe { SliceMut::as_mut_buf(self).get_mut(index) }
1173    }
1174
1175    #[inline]
1176    fn as_buf(&self) -> &Buf {
1177        self
1178    }
1179
1180    #[inline]
1181    unsafe fn as_mut_buf(&mut self) -> &mut Buf {
1182        unsafe { SliceMut::as_mut_buf(self) }
1183    }
1184}