musli_zerocopy/buf/owned_buf.rs
1use core::alloc::Layout;
2use core::borrow::Borrow;
3use core::marker::PhantomData;
4use core::mem::{ManuallyDrop, MaybeUninit, align_of, size_of, size_of_val};
5use core::ops::Deref;
6use core::ptr::NonNull;
7use core::slice::{self, SliceIndex};
8
9#[cfg(feature = "std")]
10use std::io;
11
12use alloc::alloc;
13
14use crate::buf::{self, AllocError, Buf, DefaultAlignment, Padder, StoreBuf};
15use crate::endian::{ByteOrder, DefaultEndian};
16use crate::error::{Error, ErrorKind};
17use crate::mem::PackedMaybeUninit;
18use crate::pointer::{DefaultSize, Ref, Size};
19use crate::traits::{UnsizedZeroCopy, ZeroCopy};
20
21/// An allocating buffer with dynamic alignment.
22///
23/// By default this buffer starts out having the same alignment as `usize`,
24/// making it platform specific. But this alignment can grow in demand to the
25/// types being stored in it.
26///
27/// # Examples
28///
29/// ```
30/// use musli_zerocopy::{OwnedBuf, ZeroCopy};
31///
32/// #[derive(ZeroCopy)]
33/// #[repr(C, align(128))]
34/// struct Custom {
35/// field: u32
36/// }
37///
38/// let mut buf = OwnedBuf::new();
39/// buf.store(&Custom { field: 10 })?;
40/// assert!(buf.alignment() >= 128);
41/// # Ok::<_, musli_zerocopy::Error>(())
42/// ```
43pub struct OwnedBuf<E = DefaultEndian, O = DefaultSize>
44where
45 E: ByteOrder,
46 O: Size,
47{
48 data: NonNull<MaybeUninit<u8>>,
49 /// The initialized length of the buffer.
50 len: usize,
51 /// The capacity of the buffer.
52 capacity: usize,
53 /// The requested alignment.
54 requested: usize,
55 /// The current alignment.
56 align: usize,
57 /// Holding onto the current pointer size.
58 _marker: PhantomData<(E, O)>,
59}
60
61impl Default for OwnedBuf {
62 #[inline]
63 fn default() -> Self {
64 Self::new()
65 }
66}
67
68impl OwnedBuf {
69 /// Construct a new empty buffer with the default alignment.
70 ///
71 /// The default alignment is guaranteed to be larger than 0.
72 ///
73 /// # Examples
74 ///
75 /// ```
76 /// use musli_zerocopy::OwnedBuf;
77 ///
78 /// let buf = OwnedBuf::new();
79 /// assert!(buf.is_empty());
80 /// assert!(buf.alignment() > 0);
81 /// assert!(buf.alignment() >= buf.requested());
82 /// ```
83 pub const fn new() -> Self {
84 Self::with_alignment::<DefaultAlignment>()
85 }
86
87 /// Allocate a new buffer with the given capacity and default alignment.
88 ///
89 /// The buffer must allocate for at least the given `capacity`, but might
90 /// allocate more. If the capacity specified is `0` it will not allocate.
91 ///
92 /// # Errors
93 ///
94 /// Errors if the specified capacity and memory layout are illegal, which
95 /// happens if:
96 /// * The alignment is not a power of two.
97 /// * The specified capacity causes the needed memory to overflow
98 /// `isize::MAX`.
99 ///
100 /// ```should_panic
101 /// use std::mem::align_of;
102 ///
103 /// use musli_zerocopy::{endian, DefaultAlignment, OwnedBuf};
104 ///
105 /// let max = isize::MAX as usize - (align_of::<DefaultAlignment>() - 1);
106 /// OwnedBuf::<endian::Native, u32>::with_capacity(max)?;
107 /// # Ok::<_, musli_zerocopy::buf::AllocError>(())
108 /// ```
109 ///
110 /// # Examples
111 ///
112 /// ```
113 /// use musli_zerocopy::OwnedBuf;
114 ///
115 /// let buf = OwnedBuf::with_capacity(6)?;
116 /// assert!(buf.capacity() >= 6);
117 /// # Ok::<_, musli_zerocopy::Error>(())
118 /// ```
119 pub fn with_capacity(capacity: usize) -> Result<Self, AllocError> {
120 Self::with_capacity_and_alignment::<DefaultAlignment>(capacity)
121 }
122
123 /// Construct a new empty buffer with an alignment matching that of `T`.
124 ///
125 /// # Examples
126 ///
127 /// ```
128 /// use musli_zerocopy::OwnedBuf;
129 ///
130 /// let buf = OwnedBuf::with_alignment::<u64>();
131 /// assert!(buf.is_empty());
132 /// assert!(buf.alignment() >= 8);
133 /// assert_eq!(buf.requested(), 8);
134 /// ```
135 pub const fn with_alignment<T>() -> Self {
136 let align = align_of::<T>();
137
138 Self {
139 // SAFETY: Alignment is asserted through `T`.
140 data: unsafe { dangling(align) },
141 len: 0,
142 capacity: 0,
143 requested: align,
144 align,
145 _marker: PhantomData,
146 }
147 }
148
149 /// Allocate a new buffer with the given `capacity` and an alignment
150 /// matching that of `T`.
151 ///
152 /// The buffer must allocate for at least the given `capacity`, but might
153 /// allocate more. If the capacity specified is `0` it will not allocate.
154 ///
155 /// # Errors
156 ///
157 /// Errors if the specified capacity and memory layout are illegal, which
158 /// happens if:
159 /// * The alignment is not a power of two.
160 /// * The specified capacity causes the needed memory to overflow
161 /// `isize::MAX`.
162 ///
163 /// ```should_panic
164 /// use musli_zerocopy::OwnedBuf;
165 ///
166 /// let max = isize::MAX as usize - (8 - 1);
167 /// OwnedBuf::with_capacity_and_alignment::<u64>(max)?;
168 /// # Ok::<_, musli_zerocopy::buf::AllocError>(())
169 /// ```
170 ///
171 /// # Examples
172 ///
173 /// ```
174 /// use musli_zerocopy::OwnedBuf;
175 ///
176 /// let buf = OwnedBuf::with_capacity_and_alignment::<u16>(6)?;
177 /// assert!(buf.capacity() >= 6);
178 /// assert!(buf.alignment() >= 2);
179 /// # Ok::<_, musli_zerocopy::Error>(())
180 /// ```
181 pub fn with_capacity_and_alignment<T>(capacity: usize) -> Result<Self, AllocError> {
182 // SAFETY: Alignment of `T` is always a power of two.
183 Ok(unsafe { Self::with_capacity_and_custom_alignment(capacity, align_of::<T>())? })
184 }
185}
186
187impl<E, O> OwnedBuf<E, O>
188where
189 E: ByteOrder,
190 O: Size,
191{
192 /// Modify the buffer to utilize the specified pointer size when inserting
193 /// references.
194 ///
195 /// # Examples
196 ///
197 /// ```
198 /// use musli_zerocopy::OwnedBuf;
199 ///
200 /// let mut buf = OwnedBuf::with_capacity(1024)?
201 /// .with_size::<u8>();
202 /// # Ok::<_, musli_zerocopy::Error>(())
203 /// ```
204 #[inline]
205 pub fn with_size<U>(self) -> OwnedBuf<E, U>
206 where
207 U: Size,
208 {
209 let this = ManuallyDrop::new(self);
210
211 OwnedBuf {
212 data: this.data,
213 len: this.len,
214 capacity: this.capacity,
215 requested: this.requested,
216 align: this.align,
217 _marker: PhantomData,
218 }
219 }
220
221 /// Modify the buffer to utilize the specified byte order when inserting
222 /// references.
223 ///
224 /// # Examples
225 ///
226 /// ```
227 /// use musli_zerocopy::{endian, OwnedBuf};
228 ///
229 /// let mut buf = OwnedBuf::with_capacity(1024)?
230 /// .with_byte_order::<endian::Little>();
231 /// # Ok::<_, musli_zerocopy::Error>(())
232 /// ```
233 #[inline]
234 pub fn with_byte_order<U>(self) -> OwnedBuf<U, O>
235 where
236 U: ByteOrder,
237 {
238 let this = ManuallyDrop::new(self);
239
240 OwnedBuf {
241 data: this.data,
242 len: this.len,
243 capacity: this.capacity,
244 requested: this.requested,
245 align: this.align,
246 _marker: PhantomData,
247 }
248 }
249
250 // # Safety
251 //
252 // The specified alignment must be a power of two.
253 pub(crate) unsafe fn with_capacity_and_custom_alignment(
254 capacity: usize,
255 align: usize,
256 ) -> Result<Self, AllocError> where {
257 if capacity == 0 {
258 return Ok(Self {
259 // SAFETY: Alignment is asserted through `T`.
260 data: unsafe { dangling(align) },
261 len: 0,
262 capacity: 0,
263 requested: align,
264 align,
265 _marker: PhantomData,
266 });
267 }
268
269 let layout = Layout::from_size_align(capacity, align).expect("Illegal memory layout");
270
271 unsafe {
272 let data = alloc::alloc(layout);
273
274 if data.is_null() {
275 return Err(AllocError::alloc_error(layout));
276 }
277
278 Ok(Self {
279 data: NonNull::new_unchecked(data.cast()),
280 len: 0,
281 capacity,
282 requested: align,
283 align,
284 _marker: PhantomData,
285 })
286 }
287 }
288
289 /// Get the current length of the buffer.
290 ///
291 /// # Examples
292 ///
293 /// ```
294 /// use musli_zerocopy::OwnedBuf;
295 ///
296 /// let buf = OwnedBuf::new();
297 /// assert_eq!(buf.len(), 0);
298 /// ```
299 #[inline]
300 pub fn len(&self) -> usize {
301 self.len
302 }
303
304 /// Clear the current buffer.
305 ///
306 /// This won't cause any reallocations.
307 ///
308 /// # Examples
309 ///
310 /// ```
311 /// use musli_zerocopy::OwnedBuf;
312 ///
313 /// let mut buf = OwnedBuf::new();
314 /// assert_eq!(buf.capacity(), 0);
315 /// buf.extend_from_slice(&[1, 2, 3, 4])?;
316 ///
317 /// assert_eq!(buf.len(), 4);
318 /// buf.clear();
319 /// assert!(buf.capacity() > 0);
320 /// assert_eq!(buf.len(), 0);
321 /// # Ok::<_, musli_zerocopy::Error>(())
322 /// ```
323 #[inline]
324 pub fn clear(&mut self) {
325 self.len = 0;
326 }
327
328 /// Test if the buffer is empty.
329 ///
330 /// # Examples
331 ///
332 /// ```
333 /// use musli_zerocopy::OwnedBuf;
334 ///
335 /// let buf = OwnedBuf::new();
336 /// assert!(buf.is_empty());
337 /// ```
338 #[inline]
339 pub fn is_empty(&self) -> bool {
340 self.len == 0
341 }
342
343 /// Get the current capacity of the buffer.
344 ///
345 /// # Examples
346 ///
347 /// ```
348 /// use musli_zerocopy::OwnedBuf;
349 ///
350 /// let buf = OwnedBuf::new();
351 /// assert_eq!(buf.capacity(), 0);
352 /// ```
353 #[inline]
354 pub fn capacity(&self) -> usize {
355 self.capacity
356 }
357
358 /// Return the requested alignment of the buffer.
359 ///
360 /// # Examples
361 ///
362 /// ```
363 /// use musli_zerocopy::OwnedBuf;
364 ///
365 /// let buf = OwnedBuf::with_alignment::<u64>();
366 /// assert!(buf.is_empty());
367 /// assert!(buf.alignment() >= 8);
368 /// assert_eq!(buf.requested(), 8);
369 /// ```
370 #[inline]
371 pub fn requested(&self) -> usize {
372 self.requested
373 }
374
375 /// Reserve capacity for at least `capacity` more bytes in this buffer.
376 ///
377 /// # Examples
378 ///
379 /// ```
380 /// use musli_zerocopy::OwnedBuf;
381 ///
382 /// let mut buf = OwnedBuf::new();
383 /// assert_eq!(buf.capacity(), 0);
384 ///
385 /// buf.reserve(10);
386 /// assert!(buf.capacity() >= 10);
387 /// ```
388 #[inline]
389 pub fn reserve(&mut self, capacity: usize) -> Result<(), AllocError> {
390 let new_capacity = self
391 .len
392 .checked_add(capacity)
393 .ok_or_else(|| AllocError::capacity(self.capacity, usize::MAX))?;
394 self.ensure_capacity(new_capacity)?;
395 Ok(())
396 }
397
398 /// Advance the length of the owned buffer by `size`.
399 ///
400 /// # Safety
401 ///
402 /// The caller must ensure that bytes up until `len() + size` has been
403 /// initialized in this buffer.
404 #[inline]
405 pub unsafe fn advance(&mut self, size: usize) {
406 self.len += size;
407 }
408
409 /// Get get a raw pointer to the current buffer.
410 #[inline]
411 pub(crate) fn as_ptr(&self) -> *const u8 {
412 self.data.as_ptr() as *const _
413 }
414
415 /// Get get a raw mutable pointer to the current buffer.
416 #[inline]
417 pub(crate) fn as_mut_ptr(&mut self) -> *mut MaybeUninit<u8> {
418 self.data.as_ptr()
419 }
420
421 /// Get get a raw mutable pointer to the current buffer.
422 #[inline]
423 #[cfg(test)]
424 pub(crate) fn as_nonnull(&mut self) -> NonNull<MaybeUninit<u8>> {
425 self.data
426 }
427
428 /// Extract a slice containing the entire buffer.
429 ///
430 /// # Examples
431 ///
432 /// ```
433 /// use musli_zerocopy::OwnedBuf;
434 ///
435 /// let mut buf = OwnedBuf::new();
436 /// buf.extend_from_slice(b"hello world")?;
437 /// assert_eq!(buf.as_slice(), b"hello world");
438 /// # Ok::<_, musli_zerocopy::Error>(())
439 /// ```
440 #[inline]
441 pub fn as_slice(&self) -> &[u8] {
442 unsafe { slice::from_raw_parts(self.as_ptr(), self.len()) }
443 }
444
445 /// Extract a mutable slice containing the entire buffer.
446 ///
447 /// # Examples
448 ///
449 /// ```
450 /// use musli_zerocopy::OwnedBuf;
451 ///
452 /// let mut buf = OwnedBuf::new();
453 /// buf.extend_from_slice(b"hello world")?;
454 /// buf.as_mut_slice().make_ascii_uppercase();
455 /// assert_eq!(buf.as_slice(), b"HELLO WORLD");
456 /// # Ok::<_, musli_zerocopy::Error>(())
457 /// ```
458 #[inline]
459 pub fn as_mut_slice(&mut self) -> &mut [u8] {
460 // SAFETY: We only expose the initialized part of the buffer.
461 unsafe { slice::from_raw_parts_mut(self.as_mut_ptr().cast(), self.len()) }
462 }
463
464 /// Access the buffer mutably.
465 ///
466 /// # Examples
467 ///
468 /// ```
469 /// use musli_zerocopy::OwnedBuf;
470 ///
471 /// let mut buf = OwnedBuf::new();
472 /// let slice = buf.store_unsized("hello world")?;
473 ///
474 /// // SAFETY: We don't manipulate the underlying buffer in a way which leaves uninitialized data.
475 /// let buf = unsafe { buf.as_mut_buf() };
476 ///
477 /// buf.load_mut(slice)?.make_ascii_uppercase();
478 /// assert_eq!(buf.load(slice)?, "HELLO WORLD");
479 /// # Ok::<_, musli_zerocopy::Error>(())
480 /// ```
481 ///
482 /// # Safety
483 ///
484 /// Since this allows the underlying buffer to be mutated, depending on how
485 /// the buffer is used it might result in undefined bit-patterns like
486 /// padding bytes being written to it. The caller must ensure this is not
487 /// done with the structures being written by for example calling
488 /// [`ZeroCopy::initialize_padding()`] after the contents of the buffer is
489 /// modified.
490 ///
491 /// See [`Buf::new_mut`] for more information.
492 #[inline]
493 pub unsafe fn as_mut_buf(&mut self) -> &mut Buf {
494 unsafe { Buf::new_mut(self.as_mut_slice()) }
495 }
496
497 /// Store an uninitialized value.
498 ///
499 /// This allows values to be inserted before they can be initialized, which
500 /// can be useful if you need them to be in a certain location in the buffer
501 /// but don't have access to their value yet.
502 ///
503 /// The memory for `T` will be zero-initialized at [`next_offset<T>()`] and
504 /// the length and alignment requirement of `OwnedBuf` updated to reflect
505 /// that an instance of `T` has been stored. But that representation might
506 /// not match the representation of `T`[^non-zero].
507 ///
508 /// To get the offset where the value will be written, call
509 /// [`next_offset<T>()`] before storing the value.
510 ///
511 /// > **Note:** this does not return [`MaybeUninit`], instead we use an
512 /// > internal [`MaybeUninit`] which is similar but has different
513 /// > properties. See [its documentation][MaybeUninit] for more.
514 ///
515 /// [`next_offset<T>()`]: Self::next_offset()
516 /// [^non-zero]: Like with [`NonZero*`][core::num] types.
517 ///
518 /// # Examples
519 ///
520 /// ```
521 /// use musli_zerocopy::mem::PackedMaybeUninit;
522 /// use musli_zerocopy::{OwnedBuf, Ref, ZeroCopy};
523 ///
524 /// #[derive(ZeroCopy)]
525 /// #[repr(C)]
526 /// struct Custom { field: u32, string: Ref<str> }
527 ///
528 /// let mut buf = OwnedBuf::new();
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 store_uninit<T>(&mut self) -> Result<Ref<PackedMaybeUninit<T>, E, O>, Error>
541 where
542 T: ZeroCopy,
543 {
544 // SAFETY: We've just reserved capacity for this write.
545 unsafe {
546 self.next_offset_with_and_reserve(align_of::<T>(), size_of::<T>())?;
547 let offset = self.len;
548
549 self.data
550 .as_ptr()
551 .add(self.len)
552 .write_bytes(0, size_of::<T>());
553
554 self.len += size_of::<T>();
555 Ok(Ref::try_with_metadata_unchecked(offset, ())?)
556 }
557 }
558
559 /// Write a reference that might not have been initialized.
560 ///
561 /// This does not prevent [`Ref`] from different instances of [`OwnedBuf`]
562 /// from being written. It would only result in garbled data, but wouldn't
563 /// be a safety concern.
564 ///
565 /// > **Note:** this does not return [`std::mem::MaybeUninit`], instead we
566 /// > use an internal [`MaybeUninit`] which is similar but has different
567 /// > properties. See [its documentation][MaybeUninit] for more.
568 ///
569 /// # Errors
570 ///
571 /// Errors if the reference [`Ref::offset()`] and size of `T` does not fit
572 /// within the [`len()`] of the current structure. This might happen if you
573 /// try and use a reference constructed from a different [`OwnedBuf`]
574 /// instance.
575 ///
576 /// [`len()`]: Self::len()
577 ///
578 /// ```should_panic
579 /// use musli_zerocopy::OwnedBuf;
580 ///
581 /// let mut buf2 = OwnedBuf::new();
582 /// let number = buf2.store_uninit::<u32>()?;
583 ///
584 /// let mut buf1 = OwnedBuf::new();
585 /// buf1.load_uninit_mut(number)?.write(&42u32);
586 /// # Ok::<_, musli_zerocopy::Error>(())
587 /// ```
588 ///
589 /// # Examples
590 ///
591 /// ```
592 /// use musli_zerocopy::{OwnedBuf, Ref, ZeroCopy};
593 /// use musli_zerocopy::mem::PackedMaybeUninit;
594 ///
595 /// #[derive(ZeroCopy)]
596 /// #[repr(C)]
597 /// struct Custom { field: u32, string: Ref<str> }
598 ///
599 /// let mut buf = OwnedBuf::new();
600 /// let reference: Ref<PackedMaybeUninit<Custom>> = buf.store_uninit::<Custom>()?;
601 ///
602 /// let string = buf.store_unsized("Hello World!")?;
603 ///
604 /// buf.load_uninit_mut(reference)?.write(&Custom { field: 42, string });
605 ///
606 /// let reference = reference.assume_init();
607 /// assert_eq!(reference.offset(), 0);
608 /// # Ok::<_, musli_zerocopy::Error>(())
609 /// ```
610 #[inline]
611 pub fn load_uninit_mut<T, U, I>(
612 &mut self,
613 at: Ref<PackedMaybeUninit<T>, U, I>,
614 ) -> Result<&mut PackedMaybeUninit<T>, Error>
615 where
616 T: ZeroCopy,
617 U: ByteOrder,
618 I: Size,
619 {
620 let offset = at.offset();
621
622 if offset + size_of::<T>() > self.len {
623 return Err(Error::new(ErrorKind::OutOfRangeBounds {
624 range: offset..offset + size_of::<T>(),
625 len: self.len,
626 }));
627 }
628
629 // SAFETY: `MaybeUninit<T>` has no representation requirements and is
630 // unaligned.
631 Ok(unsafe { &mut *(self.data.as_ptr().add(offset) as *mut PackedMaybeUninit<T>) })
632 }
633
634 /// Insert a value with the given size.
635 ///
636 /// The memory for `T` will be initialized at [`next_offset<T>()`] and the
637 /// length and alignment requirement of `OwnedBuf` updated to reflect that
638 /// an instance of `T` has been stored.
639 ///
640 /// To get the offset where the value will be written, call
641 /// [`next_offset<T>()`] before storing the value or access the offset
642 /// through the [`Ref::offset`] being returned.
643 ///
644 /// [`next_offset<T>()`]: Self::next_offset
645 ///
646 /// # Examples
647 ///
648 /// ```
649 /// use musli_zerocopy::{OwnedBuf, Ref, ZeroCopy};
650 ///
651 /// #[derive(ZeroCopy)]
652 /// #[repr(C)]
653 /// struct Custom { field: u32, string: Ref<str> }
654 ///
655 /// let mut buf = OwnedBuf::new();
656 ///
657 /// let string = buf.store_unsized("string")?;
658 /// let custom = buf.store(&Custom { field: 1, string })?;
659 /// let custom2 = buf.store(&Custom { field: 2, string })?;
660 ///
661 /// let custom = buf.load(custom)?;
662 /// assert_eq!(custom.field, 1);
663 /// assert_eq!(buf.load(custom.string)?, "string");
664 ///
665 /// let custom2 = buf.load(custom2)?;
666 /// assert_eq!(custom2.field, 2);
667 /// assert_eq!(buf.load(custom2.string)?, "string");
668 /// # Ok::<_, musli_zerocopy::Error>(())
669 /// ```
670 ///
671 /// Storing an array:
672 ///
673 ///
674 /// ```
675 /// use musli_zerocopy::{ZeroCopy, OwnedBuf};
676 ///
677 /// // Element with padding.
678 /// #[derive(Debug, PartialEq, ZeroCopy)]
679 /// #[repr(C)]
680 /// struct Element {
681 /// first: u8,
682 /// second: u32,
683 /// }
684 ///
685 /// let values = [
686 /// Element { first: 0x01, second: 0x01020304u32 },
687 /// Element { first: 0x02, second: 0x01020304u32 }
688 /// ];
689 ///
690 /// let mut buf = OwnedBuf::new();
691 /// let array = buf.store(&values)?;
692 /// assert_eq!(buf.load(array)?, &values);
693 /// # Ok::<_, musli_zerocopy::Error>(())
694 /// ```
695 #[inline]
696 pub fn store<T>(&mut self, value: &T) -> Result<Ref<T, E, O>, Error>
697 where
698 T: ZeroCopy,
699 {
700 self.next_offset_with_and_reserve(align_of::<T>(), size_of::<T>())?;
701
702 // SAFETY: We're ensuring to both align the internal buffer and store
703 // the value.
704 unsafe { self.store_unchecked(value) }
705 }
706
707 /// Insert a value with the given size without ensuring that the buffer has
708 /// the reserved capacity for to or is properly aligned.
709 ///
710 /// This is a low level API which is tricky to use correctly. The
711 /// recommended way to use this is through [`OwnedBuf::store`].
712 ///
713 /// [`OwnedBuf::store`]: Self::store
714 ///
715 /// # Safety
716 ///
717 /// The caller has to ensure that the buffer has the required capacity for
718 /// `&T` and is properly aligned. This can easily be accomplished by calling
719 /// [`request_align::<T>()`] followed by [`align_in_place()`] before this
720 /// function. A safe variant of this function is [`OwnedBuf::store`].
721 ///
722 /// [`align_in_place()`]: Self::align_in_place
723 /// [`OwnedBuf::store`]: Self::store
724 /// [`request_align::<T>()`]: Self::request_align
725 ///
726 /// # Examples
727 ///
728 /// ```
729 /// use std::mem::size_of;
730 ///
731 /// use musli_zerocopy::{OwnedBuf, Ref, ZeroCopy};
732 ///
733 /// #[derive(ZeroCopy)]
734 /// #[repr(C, align(4096))]
735 /// struct Custom { field: u32, string: Ref<str> }
736 ///
737 /// let mut buf = OwnedBuf::new();
738 ///
739 /// let string = buf.store_unsized("string")?;
740 ///
741 /// buf.request_align::<Custom>()?;
742 /// buf.reserve(2 * size_of::<Custom>());
743 /// buf.align_in_place()?;
744 ///
745 /// // SAFETY: We've ensure that the buffer is internally aligned and sized just above.
746 /// let custom = unsafe { buf.store_unchecked(&Custom { field: 1, string })? };
747 /// let custom2 = unsafe { buf.store_unchecked(&Custom { field: 2, string })? };
748 ///
749 /// let custom = buf.load(custom)?;
750 /// assert_eq!(custom.field, 1);
751 /// assert_eq!(buf.load(custom.string)?, "string");
752 ///
753 /// let custom2 = buf.load(custom2)?;
754 /// assert_eq!(custom2.field, 2);
755 /// assert_eq!(buf.load(custom2.string)?, "string");
756 /// # Ok::<_, musli_zerocopy::Error>(())
757 /// ```
758 #[inline]
759 pub unsafe fn store_unchecked<T>(&mut self, value: &T) -> Result<Ref<T, E, O>, Error>
760 where
761 T: ZeroCopy,
762 {
763 let offset = self.len;
764
765 unsafe {
766 let ptr = NonNull::new_unchecked(self.data.as_ptr().add(offset));
767 buf::store_unaligned(ptr, value);
768 self.len += size_of::<T>();
769 // SAFETY: We trust the calculated offset since there language
770 // invariants ensures that it cannot overflow the container size.
771 Ok(Ref::try_with_metadata_unchecked(offset, ())?)
772 }
773 }
774
775 /// Write a value to the buffer.
776 ///
777 /// ```
778 /// use musli_zerocopy::OwnedBuf;
779 ///
780 /// let mut buf = OwnedBuf::new();
781 ///
782 /// let first = buf.store_unsized("first")?;
783 /// let second = buf.store_unsized("second")?;
784 ///
785 /// dbg!(first, second);
786 ///
787 /// assert_eq!(buf.load(first)?, "first");
788 /// assert_eq!(buf.load(second)?, "second");
789 /// # Ok::<_, musli_zerocopy::Error>(())
790 /// ```
791 #[inline]
792 pub fn store_unsized<T>(&mut self, value: &T) -> Result<Ref<T, E, O>, Error>
793 where
794 T: ?Sized + UnsizedZeroCopy,
795 {
796 unsafe {
797 let size = size_of_val(value);
798 self.next_offset_with_and_reserve(T::ALIGN, size)?;
799 let offset = self.len;
800 let ptr = NonNull::new_unchecked(self.data.as_ptr().add(offset));
801 ptr.as_ptr()
802 .copy_from_nonoverlapping(value.as_ptr().cast(), size);
803
804 if T::PADDED {
805 let mut padder = Padder::new(ptr);
806 value.pad(&mut padder);
807 padder.remaining_unsized(value);
808 }
809
810 self.len += size;
811
812 // SAFETY: We trust the calculated offset since there language
813 // invariants ensures that it cannot overflow the container size.
814 Ok(Ref::try_with_metadata_unchecked(offset, value.metadata())?)
815 }
816 }
817
818 /// Insert a slice into the buffer.
819 ///
820 /// # Examples
821 ///
822 /// ```
823 /// use musli_zerocopy::OwnedBuf;
824 ///
825 /// let mut buf = OwnedBuf::new();
826 ///
827 /// let values = [buf.store_unsized("first")?, buf.store_unsized("second")?];
828 /// let slice_ref = buf.store_slice(&values)?;
829 ///
830 /// let slice = buf.load(slice_ref)?;
831 /// assert_eq!(buf.load(slice[0])?, "first");
832 /// assert_eq!(buf.load(slice[1])?, "second");
833 /// # Ok::<_, musli_zerocopy::Error>(())
834 /// ```
835 #[inline(always)]
836 pub fn store_slice<T>(&mut self, values: &[T]) -> Result<Ref<[T], E, O>, Error>
837 where
838 T: ZeroCopy,
839 {
840 self.store_unsized(values)
841 }
842
843 /// Extend the buffer from a slice.
844 ///
845 /// Note that this only extends the underlying buffer but does not ensure
846 /// that any required alignment is abided by.
847 ///
848 /// To do this, the caller must call [`request_align()`] with the appropriate
849 /// alignment, otherwise the necessary alignment to decode the buffer again
850 /// will be lost.
851 ///
852 /// [`request_align()`]: Self::request_align
853 ///
854 /// # Errors
855 ///
856 /// This is a raw API, and does not guarantee that any given alignment will
857 /// be respected. The following exemplifies incorrect use since the u32 type
858 /// required a 4-byte alignment:
859 ///
860 /// ```
861 /// use musli_zerocopy::{OwnedBuf, Ref};
862 ///
863 /// let mut buf = OwnedBuf::with_alignment::<u32>();
864 ///
865 /// // Add one byte of padding to throw of any incidental alignment.
866 /// buf.extend_from_slice(&[1])?;
867 ///
868 /// let ptr: Ref<u32> = Ref::new(buf.next_offset::<u8>()?);
869 /// buf.extend_from_slice(&[1, 2, 3, 4])?;
870 ///
871 /// // This will succeed because the buffer follows its interior alignment:
872 /// let buf = buf.as_ref();
873 ///
874 /// // This will fail, because the buffer is not aligned.
875 /// assert!(buf.load(ptr).is_err());
876 /// # Ok::<_, musli_zerocopy::Error>(())
877 /// ```
878 ///
879 /// # Examples
880 ///
881 /// ```
882 /// use musli_zerocopy::{OwnedBuf, Ref};
883 ///
884 /// let mut buf = OwnedBuf::with_alignment::<()>();
885 ///
886 /// // Add one byte of padding to throw of any incidental alignment.
887 /// buf.extend_from_slice(&[1])?;
888 ///
889 /// let ptr: Ref<u32> = Ref::new(buf.next_offset::<u32>()?);
890 /// buf.extend_from_slice(&[1, 2, 3, 4])?;
891 ///
892 /// // This will succeed because the buffer follows its interior alignment:
893 /// let buf = buf.as_ref();
894 ///
895 /// assert_eq!(*buf.load(ptr)?, u32::from_ne_bytes([1, 2, 3, 4]));
896 /// # Ok::<_, musli_zerocopy::Error>(())
897 /// ```
898 pub fn extend_from_slice(&mut self, bytes: &[u8]) -> Result<(), AllocError> {
899 self.reserve(bytes.len())?;
900
901 // SAFETY: We just allocated space for the slice.
902 unsafe {
903 self.store_bytes(bytes);
904 }
905
906 Ok(())
907 }
908
909 /// Fill and initialize the buffer with `byte` up to `len`.
910 pub(crate) fn fill(&mut self, byte: u8, len: usize) -> Result<(), AllocError> {
911 self.reserve(len)?;
912
913 unsafe {
914 let ptr = self.data.as_ptr().add(self.len);
915 ptr.write_bytes(byte, len);
916 self.len += len;
917 }
918
919 Ok(())
920 }
921
922 /// Store the slice without allocating.
923 ///
924 /// # Safety
925 ///
926 /// The caller must ensure that the buffer has the capacity for
927 /// `bytes.len()` and that the value being stored is not padded as per
928 /// `ZeroCopy::PADDED`.
929 #[inline]
930 pub(crate) unsafe fn store_bytes<T>(&mut self, values: &[T])
931 where
932 T: ZeroCopy,
933 {
934 unsafe {
935 let dst = self.as_mut_ptr().add(self.len);
936 dst.copy_from_nonoverlapping(values.as_ptr().cast(), size_of_val(values));
937 self.len += size_of_val(values);
938 }
939 }
940
941 /// Align a buffer in place if necessary.
942 ///
943 /// If [`requested()`] does not equal [`alignment()`] this will cause the buffer
944 /// to be reallocated before it is returned.
945 ///
946 /// [`requested()`]: Self::requested
947 /// [`alignment()`]: Buf::alignment
948 /// [`as_ref`]: Self::as_ref
949 ///
950 /// # Examples
951 ///
952 /// A buffer has to be a aligned in order for `load` calls to succeed
953 /// without errors.
954 ///
955 /// ```
956 /// use musli_zerocopy::OwnedBuf;
957 ///
958 /// let mut buf = OwnedBuf::with_alignment::<()>();
959 /// let number = buf.store(&1u32)?;
960 ///
961 /// buf.align_in_place()?;
962 ///
963 /// assert_eq!(buf.load(number)?, &1u32);
964 /// # Ok::<_, musli_zerocopy::Error>(())
965 /// ```
966 ///
967 /// Example using a mutable buffer. A buffer has to be a aligned in order
968 /// for `load` and `load_mut` calls to succeed without errors.
969 ///
970 /// ```
971 /// use musli_zerocopy::OwnedBuf;
972 ///
973 /// let mut buf = OwnedBuf::with_alignment::<()>();
974 /// let number = buf.store(&1u32)?;
975 ///
976 /// buf.align_in_place()?;
977 ///
978 /// // SAFETY: We're not writing data in a way which leaves uninitialized regions.
979 /// unsafe {
980 /// *buf.as_mut_buf().load_mut(number)? += 1;
981 /// }
982 /// assert_eq!(buf.load(number)?, &2u32);
983 /// # Ok::<_, musli_zerocopy::Error>(())
984 /// ```
985 #[inline]
986 pub fn align_in_place(&mut self) -> Result<(), AllocError> {
987 // SAFETY: self.requested is guaranteed to be a power of two.
988 if !buf::is_aligned_with(self.as_ptr(), self.requested) {
989 let (old_layout, new_layout) = self.layouts(self.capacity);
990 self.alloc_new(old_layout, new_layout)?;
991 }
992
993 Ok(())
994 }
995
996 /// Request that the current buffer should have at least the specified
997 /// alignment and zero-initialize the buffer up to the next position which
998 /// matches the given alignment.
999 ///
1000 /// Note that this does not guarantee that the internal buffer is aligned
1001 /// in-memory, to ensure this you can use [`align_in_place()`].
1002 ///
1003 /// ```
1004 /// use musli_zerocopy::OwnedBuf;
1005 /// let mut buf = OwnedBuf::new();
1006 ///
1007 /// buf.extend_from_slice(&[1, 2])?;
1008 /// buf.request_align::<u32>()?;
1009 ///
1010 /// assert_eq!(buf.as_slice(), &[1, 2, 0, 0]);
1011 /// # Ok::<_, musli_zerocopy::Error>(())
1012 /// ```
1013 ///
1014 /// Calling this function only causes the underlying buffer to be realigned
1015 /// if a reallocation is triggered due to reaching its [`capacity()`].
1016 ///
1017 /// ```
1018 /// use musli_zerocopy::{endian, OwnedBuf};
1019 /// let mut buf = OwnedBuf::<endian::Native, u32>::with_capacity_and_alignment::<u16>(32)?;
1020 ///
1021 /// buf.extend_from_slice(&[1, 2])?;
1022 /// assert!(buf.alignment() >= 2);
1023 /// buf.request_align::<u32>()?;
1024 ///
1025 /// assert_eq!(buf.requested(), 4);
1026 /// assert!(buf.alignment() >= 2);
1027 ///
1028 /// buf.extend_from_slice(&[0; 32])?;
1029 /// assert_eq!(buf.requested(), 4);
1030 /// assert!(buf.alignment() >= 4);
1031 /// # Ok::<_, musli_zerocopy::Error>(())
1032 /// ```
1033 ///
1034 /// [`capacity()`]: Self::capacity
1035 /// [`align_in_place()`]: Self::align_in_place
1036 ///
1037 /// # Safety
1038 ///
1039 /// The caller must guarantee that the alignment is a power of two.
1040 ///
1041 /// # Examples
1042 ///
1043 /// ```
1044 /// use musli_zerocopy::OwnedBuf;
1045 ///
1046 /// let mut buf = OwnedBuf::new();
1047 /// buf.extend_from_slice(&[1, 2, 3, 4])?;
1048 /// buf.request_align::<u64>()?;
1049 /// buf.extend_from_slice(&[5, 6, 7, 8])?;
1050 ///
1051 /// assert_eq!(buf.as_slice(), &[1, 2, 3, 4, 0, 0, 0, 0, 5, 6, 7, 8]);
1052 /// # Ok::<_, musli_zerocopy::Error>(())
1053 /// ```
1054 #[inline]
1055 pub fn request_align<T>(&mut self) -> Result<(), AllocError>
1056 where
1057 T: ZeroCopy,
1058 {
1059 self.requested = self.requested.max(align_of::<T>());
1060 self.ensure_aligned_and_reserve(align_of::<T>(), size_of::<T>())?;
1061 Ok(())
1062 }
1063
1064 /// Ensure that the current buffer is aligned under the assumption that it needs to be allocated.
1065 #[inline]
1066 fn ensure_aligned_and_reserve(
1067 &mut self,
1068 align: usize,
1069 reserve: usize,
1070 ) -> Result<(), AllocError> {
1071 let extra = buf::padding_to(self.len, align);
1072 self.reserve(extra + reserve)?;
1073
1074 // SAFETY: The length is ensures to be within the address space.
1075 unsafe {
1076 self.data.as_ptr().add(self.len).write_bytes(0, extra);
1077 self.len += extra;
1078 }
1079
1080 Ok(())
1081 }
1082
1083 /// Construct a pointer aligned for `align` into the current buffer which
1084 /// points to the next location that will be written.
1085 #[inline]
1086 pub(crate) fn next_offset_with_and_reserve(
1087 &mut self,
1088 align: usize,
1089 reserve: usize,
1090 ) -> Result<(), AllocError> {
1091 if !align.is_power_of_two() {
1092 return Err(AllocError::capacity(0, align));
1093 }
1094 self.requested = self.requested.max(align);
1095 self.ensure_aligned_and_reserve(align, reserve)?;
1096 Ok(())
1097 }
1098
1099 /// Construct an offset aligned for `T` into the current buffer which points
1100 /// to the next location that will be written.
1101 ///
1102 /// This ensures that the alignment of the pointer is a multiple of `align`
1103 /// and that the current buffer has the capacity for store `T`.
1104 ///
1105 /// # Examples
1106 ///
1107 /// ```
1108 /// use musli_zerocopy::{OwnedBuf, Ref};
1109 ///
1110 /// let mut buf = OwnedBuf::new();
1111 ///
1112 /// // Add one byte of padding to throw of any incidental alignment.
1113 /// buf.extend_from_slice(&[1])?;
1114 ///
1115 /// let ptr: Ref<u32> = Ref::new(buf.next_offset::<u32>()?);
1116 /// buf.extend_from_slice(&[1, 2, 3, 4])?;
1117 ///
1118 /// // This will succeed because the buffer follows its interior alignment:
1119 /// let buf = buf.as_ref();
1120 ///
1121 /// assert_eq!(*buf.load(ptr)?, u32::from_ne_bytes([1, 2, 3, 4]));
1122 /// # Ok::<_, musli_zerocopy::Error>(())
1123 /// ```
1124 #[inline]
1125 pub fn next_offset<T>(&mut self) -> Result<usize, AllocError> {
1126 // SAFETY: The alignment of `T` is guaranteed to be a power of two. We
1127 // also make sure to reserve space for `T` since it is very likely that
1128 // it will be written immediately after this.
1129 self.next_offset_with_and_reserve(align_of::<T>(), size_of::<T>())?;
1130 Ok(self.len)
1131 }
1132
1133 // We never want this call to be inlined, because we take great care to
1134 // ensure that reallocations we perform publicly are performed in a sparse
1135 // way.
1136 #[inline(never)]
1137 fn ensure_capacity(&mut self, new_capacity: usize) -> Result<(), AllocError> {
1138 let new_capacity = new_capacity.max(self.requested);
1139
1140 if self.capacity >= new_capacity {
1141 return Ok(());
1142 }
1143
1144 let new_capacity = new_capacity.max((self.capacity as f32 * 1.5) as usize);
1145 let (old_layout, new_layout) = self.layouts(new_capacity);
1146
1147 if old_layout.size() == 0 {
1148 self.alloc_init(new_layout)
1149 } else if new_layout.align() == old_layout.align() {
1150 self.alloc_realloc(old_layout, new_layout)
1151 } else {
1152 self.alloc_new(old_layout, new_layout)
1153 }
1154 }
1155
1156 /// Return a pair of the currently allocated layout, and new layout that is
1157 /// requested with the given capacity.
1158 #[inline]
1159 fn layouts(&self, new_capacity: usize) -> (Layout, Layout) {
1160 // SAFETY: The existing layout cannot be invalid since it's either
1161 // checked as it's replacing the old layout, or is initialized with
1162 // known good values.
1163 let old_layout = unsafe { Layout::from_size_align_unchecked(self.capacity, self.align) };
1164 let layout =
1165 Layout::from_size_align(new_capacity, self.requested).expect("Proposed layout invalid");
1166 (old_layout, layout)
1167 }
1168
1169 /// Perform the initial allocation with the given layout and capacity.
1170 fn alloc_init(&mut self, new_layout: Layout) -> Result<(), AllocError> {
1171 unsafe {
1172 let ptr = alloc::alloc(new_layout);
1173
1174 if ptr.is_null() {
1175 return Err(AllocError::alloc_error(new_layout));
1176 }
1177
1178 self.data = NonNull::new_unchecked(ptr.cast());
1179 self.capacity = new_layout.size();
1180 self.align = self.requested;
1181 Ok(())
1182 }
1183 }
1184
1185 /// Reallocate, note that the alignment of the old layout must match the new
1186 /// one.
1187 fn alloc_realloc(&mut self, old_layout: Layout, new_layout: Layout) -> Result<(), AllocError> {
1188 debug_assert_eq!(old_layout.align(), new_layout.align());
1189
1190 unsafe {
1191 let ptr = alloc::realloc(self.as_mut_ptr().cast(), old_layout, new_layout.size());
1192
1193 if ptr.is_null() {
1194 return Err(AllocError::alloc_error(new_layout));
1195 }
1196
1197 // NB: We may simply forget the old allocation, since `realloc` is
1198 // responsible for freeing it.
1199 self.data = NonNull::new_unchecked(ptr.cast());
1200 self.capacity = new_layout.size();
1201 Ok(())
1202 }
1203 }
1204
1205 /// Perform a new allocation, deallocating the old one in the process.
1206 #[inline(always)]
1207 fn alloc_new(&mut self, old_layout: Layout, new_layout: Layout) -> Result<(), AllocError> {
1208 unsafe {
1209 let ptr = alloc::alloc(new_layout);
1210
1211 if ptr.is_null() {
1212 return Err(AllocError::alloc_error(new_layout));
1213 }
1214
1215 ptr.copy_from_nonoverlapping(self.as_ptr(), self.len);
1216 alloc::dealloc(self.as_mut_ptr().cast(), old_layout);
1217
1218 // We've deallocated the old pointer.
1219 self.data = NonNull::new_unchecked(ptr.cast());
1220 self.capacity = new_layout.size();
1221 self.align = self.requested;
1222 Ok(())
1223 }
1224 }
1225}
1226
1227/// `OwnedBuf` are `Send` because the data they reference is unaliased.
1228unsafe impl Send for OwnedBuf {}
1229/// `OwnedBuf` are `Sync` since they are `Send` and the data they reference is
1230/// unaliased.
1231unsafe impl Sync for OwnedBuf {}
1232
1233impl<E, O> Deref for OwnedBuf<E, O>
1234where
1235 E: ByteOrder,
1236 O: Size,
1237{
1238 type Target = Buf;
1239
1240 #[inline]
1241 fn deref(&self) -> &Self::Target {
1242 Buf::new(self.as_slice())
1243 }
1244}
1245
1246impl<E, O> AsRef<Buf> for OwnedBuf<E, O>
1247where
1248 E: ByteOrder,
1249 O: Size,
1250{
1251 /// Trivial `AsRef<Buf>` implementation for `OwnedBuf<O>`.
1252 ///
1253 /// # Examples
1254 ///
1255 /// ```
1256 /// use musli_zerocopy::OwnedBuf;
1257 ///
1258 /// let mut buf = OwnedBuf::new();
1259 /// let slice = buf.store_unsized("hello world")?;
1260 /// let buf = buf.as_ref();
1261 ///
1262 /// assert_eq!(buf.load(slice)?, "hello world");
1263 /// # Ok::<_, musli_zerocopy::Error>(())
1264 /// ```
1265 #[inline]
1266 fn as_ref(&self) -> &Buf {
1267 self
1268 }
1269}
1270
1271impl<E, O> Borrow<Buf> for OwnedBuf<E, O>
1272where
1273 E: ByteOrder,
1274 O: Size,
1275{
1276 #[inline]
1277 fn borrow(&self) -> &Buf {
1278 self.as_ref()
1279 }
1280}
1281
1282/// Clone the [`OwnedBuf`].
1283///
1284/// While this causes another allocation, it doesn't ensure that the returned
1285/// buffer has the [`requested()`] alignment. To achieve this prefer using
1286/// [`align_in_place()`].
1287///
1288/// [`requested()`]: Self::requested()
1289/// [`align_in_place()`]: Self::align_in_place
1290///
1291/// # Examples
1292///
1293/// ```
1294/// use std::mem::align_of;
1295///
1296/// use musli_zerocopy::{endian, OwnedBuf};
1297///
1298/// assert_ne!(align_of::<u16>(), align_of::<u32>());
1299///
1300/// let mut buf = OwnedBuf::<endian::Native, u32>::with_capacity_and_alignment::<u16>(32)?;
1301/// buf.extend_from_slice(&[1, 2, 3, 4])?;
1302/// buf.request_align::<u32>()?;
1303///
1304/// let buf2 = buf.clone();
1305/// assert!(buf2.alignment() >= align_of::<u16>());
1306///
1307/// buf.align_in_place()?;
1308/// assert!(buf.alignment() >= align_of::<u32>());
1309/// # Ok::<_, musli_zerocopy::Error>(())
1310/// ```
1311impl<E, O> Clone for OwnedBuf<E, O>
1312where
1313 E: ByteOrder,
1314 O: Size,
1315{
1316 fn clone(&self) -> Self {
1317 unsafe {
1318 let result = Self::with_capacity_and_custom_alignment(self.len, self.align);
1319
1320 let mut new = match result {
1321 Ok(new) => ManuallyDrop::new(new),
1322 Err(_) => alloc::handle_alloc_error(Layout::from_size_align_unchecked(
1323 self.len, self.align,
1324 )),
1325 };
1326
1327 new.as_mut_ptr()
1328 .copy_from_nonoverlapping(self.as_ptr().cast(), self.len);
1329 // Set requested to the same as original.
1330 new.requested = self.requested;
1331 new.len = self.len;
1332 ManuallyDrop::into_inner(new)
1333 }
1334 }
1335}
1336
1337impl<E, O> Drop for OwnedBuf<E, O>
1338where
1339 E: ByteOrder,
1340 O: Size,
1341{
1342 fn drop(&mut self) {
1343 unsafe {
1344 if self.capacity != 0 {
1345 // SAFETY: This is guaranteed to be valid per the construction
1346 // of this type.
1347 let layout = Layout::from_size_align_unchecked(self.capacity, self.align);
1348 alloc::dealloc(self.data.as_ptr().cast(), layout);
1349 }
1350 }
1351 }
1352}
1353
1354const unsafe fn dangling(align: usize) -> NonNull<MaybeUninit<u8>> {
1355 unsafe { NonNull::new_unchecked(invalid_mut(align)) }
1356}
1357
1358// Replace with `core::ptr::invalid_mut` once stable.
1359#[allow(clippy::useless_transmute)]
1360const fn invalid_mut<T>(addr: usize) -> *mut T {
1361 // FIXME(strict_provenance_magic): I am magic and should be a compiler
1362 // intrinsic. We use transmute rather than a cast so tools like Miri can
1363 // tell that this is *not* the same as from_exposed_addr. SAFETY: every
1364 // valid integer is also a valid pointer (as long as you don't dereference
1365 // that pointer).
1366 unsafe { core::mem::transmute(addr) }
1367}
1368
1369impl<E, O> StoreBuf for OwnedBuf<E, O>
1370where
1371 E: ByteOrder,
1372 O: Size,
1373{
1374 type ByteOrder = E;
1375 type Size = O;
1376
1377 #[inline]
1378 fn len(&self) -> usize {
1379 OwnedBuf::len(self)
1380 }
1381
1382 #[inline]
1383 fn truncate(&mut self, len: usize) {
1384 if self.len > len {
1385 self.len = len;
1386 }
1387 }
1388
1389 #[inline]
1390 fn store_unsized<T>(&mut self, value: &T) -> Result<Ref<T, Self::ByteOrder, Self::Size>, Error>
1391 where
1392 T: ?Sized + UnsizedZeroCopy,
1393 {
1394 OwnedBuf::store_unsized(self, value)
1395 }
1396
1397 #[inline]
1398 fn store<T>(&mut self, value: &T) -> Result<Ref<T, Self::ByteOrder, Self::Size>, Error>
1399 where
1400 T: ZeroCopy,
1401 {
1402 OwnedBuf::store(self, value)
1403 }
1404
1405 #[inline]
1406 fn swap<T>(
1407 &mut self,
1408 a: Ref<T, Self::ByteOrder, Self::Size>,
1409 b: Ref<T, Self::ByteOrder, Self::Size>,
1410 ) -> Result<(), Error>
1411 where
1412 T: ZeroCopy,
1413 {
1414 // SAFETY: Since we are swapping two locations which have the same type
1415 // `T`, it does not affect the initialized state of the buffer.
1416 let buf = unsafe { self.as_mut_buf() };
1417 Buf::swap(buf, a, b)
1418 }
1419
1420 #[inline]
1421 fn align_in_place(&mut self) -> Result<(), AllocError> {
1422 OwnedBuf::align_in_place(self)
1423 }
1424
1425 #[inline]
1426 fn next_offset<T>(&mut self) -> Result<usize, AllocError> {
1427 OwnedBuf::next_offset::<T>(self)
1428 }
1429
1430 #[inline]
1431 fn next_offset_with_and_reserve(
1432 &mut self,
1433 align: usize,
1434 reserve: usize,
1435 ) -> Result<(), AllocError> {
1436 OwnedBuf::next_offset_with_and_reserve(self, align, reserve)
1437 }
1438
1439 #[inline]
1440 fn fill(&mut self, byte: u8, len: usize) -> Result<(), AllocError> {
1441 OwnedBuf::fill(self, byte, len)
1442 }
1443
1444 #[inline]
1445 fn get<I>(&self, index: I) -> Option<&I::Output>
1446 where
1447 I: SliceIndex<[u8]>,
1448 {
1449 Buf::get(self, index)
1450 }
1451
1452 #[inline]
1453 unsafe fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
1454 where
1455 I: SliceIndex<[u8]>,
1456 {
1457 unsafe { OwnedBuf::as_mut_buf(self).get_mut(index) }
1458 }
1459
1460 #[inline]
1461 fn as_buf(&self) -> &Buf {
1462 self
1463 }
1464
1465 #[inline]
1466 unsafe fn as_mut_buf(&mut self) -> &mut Buf {
1467 unsafe { OwnedBuf::as_mut_buf(self) }
1468 }
1469}
1470
1471#[cfg(feature = "std")]
1472#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
1473impl io::Write for OwnedBuf {
1474 #[inline]
1475 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1476 self.extend_from_slice(buf).map_err(io::Error::other)?;
1477 Ok(buf.len())
1478 }
1479
1480 #[inline]
1481 fn flush(&mut self) -> io::Result<()> {
1482 Ok(())
1483 }
1484}