use core::num::NonZeroUsize;
use crate::EmptyChunk;
use super::{
error::{InsufficientSpace, TryAdvanceError, TryPutAtError},
must_non_zero, panic_advance,
};
use super::error::{EncodeVarintAtError, EncodeVarintError};
use varing::Varint;
pub use putter::Putter;
mod putter;
macro_rules! put_fixed {
($($ty:ty),+$(,)?) => {
paste::paste! {
$(
#[doc = "Puts a `" $ty "` value in little-endian byte order to the buffer at the specified offset without advancing the internal cursor."]
#[doc = "Returns the number of bytes written (always `size_of::<" $ty ">()` for this type)."]
#[doc = "let written = slice.put_" $ty "_le_at(0x1234 as " $ty ", 2);"]
#[doc = "assert_eq!(written, size_of::<" $ty ">());"]
#[inline]
fn [< put_ $ty _le_at>](&mut self, value: $ty, offset: usize) -> usize {
self.put_slice_at(&value.to_le_bytes(), offset)
}
#[doc = "Tries to put `" $ty "` value in little-endian byte order to the buffer at the specified offset without advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`put_" $ty "_le_at`](ChunkMut::put_" $ty "_le_at)."]
#[doc = "assert!(slice.put_" $ty "_le_at_checked(0x1234 as " $ty ", 2).is_some());"]
#[doc = "assert!(slice.put_" $ty "_le_at_checked(0x1234 as " $ty ", 30).is_none()); // Out of bounds"]
#[inline]
fn [< put_ $ty _le_at_checked>](&mut self, value: $ty, offset: usize) -> Option<usize> {
self.put_slice_at_checked(&value.to_le_bytes(), offset)
}
#[doc = "Tries to put `" $ty "` value in little-endian byte order to the buffer at the specified offset without advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`put_" $ty "_le_at`](ChunkMut::put_" $ty "_le_at)."]
#[doc = "assert!(slice.try_put_" $ty "_le_at(0x1234 as " $ty ", 2).is_ok());"]
#[doc = "let err = slice.try_put_" $ty "_le_at(0x1234 as " $ty ", 30).unwrap_err();"]
#[inline]
fn [< try_put_ $ty _le_at>](&mut self, value: $ty, offset: usize) -> Result<usize, TryPutAtError> {
self.try_put_slice_at(&value.to_le_bytes(), offset)
}
#[doc = "Puts `" $ty "` value in big-endian byte order to the buffer at the specified offset without advancing the internal cursor."]
#[doc = "Returns the number of bytes written (always `size_of::<" $ty ">()` for this type)."]
#[doc = "let written = slice.put_" $ty "_be_at(0x1234 as " $ty ", 2);"]
#[doc = "assert_eq!(written, size_of::<" $ty ">());"]
#[inline]
fn [< put_ $ty _be_at>](&mut self, value: $ty, offset: usize) -> usize {
self.put_slice_at(&value.to_be_bytes(), offset)
}
#[doc = "Tries to put `" $ty "` value in big-endian byte order to the buffer at the specified offset without advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`put_" $ty "_be_at`](ChunkMut::put_" $ty "_be_at)."]
#[doc = "assert!(slice.put_" $ty "_be_at_checked(0x1234 as " $ty ", 2).is_some());"]
#[doc = "assert!(slice.put_" $ty "_be_at_checked(0x1234 as " $ty ", 30).is_none()); // Out of bounds"]
#[inline]
fn [< put_ $ty _be_at_checked>](&mut self, value: $ty, offset: usize) -> Option<usize> {
self.put_slice_at_checked(&value.to_be_bytes(), offset)
}
#[doc = "Tries to put `" $ty "` value in big-endian byte order to the buffer at the specified offset without advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`put_" $ty "_be_at`](ChunkMut::put_" $ty "_be_at)."]
#[doc = "assert!(slice.try_put_" $ty "_be_at(0x1234 as " $ty ", 2).is_ok());"]
#[doc = "let err = slice.try_put_" $ty "_be_at(0x1234 as " $ty ", 30).unwrap_err();"]
#[inline]
fn [< try_put_ $ty _be_at>](&mut self, value: $ty, offset: usize) -> Result<usize, TryPutAtError> {
self.try_put_slice_at(&value.to_be_bytes(), offset)
}
#[doc = "Puts `" $ty "` value in native-endian byte order to the buffer at the specified offset without advancing the internal cursor."]
#[doc = "Returns the number of bytes written (always `size_of::<" $ty ">()` for this type)."]
#[doc = "let written = slice.put_" $ty "_ne_at(0x1234 as " $ty ", 2);"]
#[doc = "assert_eq!(written, size_of::<" $ty ">());"]
#[inline]
fn [< put_ $ty _ne_at>](&mut self, value: $ty, offset: usize) -> usize {
self.put_slice_at(&value.to_ne_bytes(), offset)
}
#[doc = "Tries to put `" $ty "` value in native-endian byte order to the buffer at the specified offset without advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`put_" $ty "_ne_at`](ChunkMut::put_" $ty "_ne_at)."]
#[doc = "assert!(slice.put_" $ty "_ne_at_checked(0x1234 as " $ty ", 2).is_some());"]
#[doc = "assert!(slice.put_" $ty "_ne_at_checked(0x1234 as " $ty ", 30).is_none()); // Out of bounds"]
#[inline]
fn [< put_ $ty _ne_at_checked>](&mut self, value: $ty, offset: usize) -> Option<usize> {
self.put_slice_at_checked(&value.to_ne_bytes(), offset)
}
#[doc = "Tries to put `" $ty "` value in native-endian byte order to the buffer at the specified offset without advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`put_" $ty "_ne_at`](ChunkMut::put_" $ty "_ne_at)."]
#[doc = "assert!(slice.try_put_" $ty "_ne_at(0x1234 as " $ty ", 2).is_ok());"]
#[doc = "let err = slice.try_put_" $ty "_ne_at(0x1234 as " $ty ", 30).unwrap_err();"]
#[inline]
fn [< try_put_ $ty _ne_at>](&mut self, value: $ty, offset: usize) -> Result<usize, TryPutAtError> {
self.try_put_slice_at(&value.to_ne_bytes(), offset)
}
#[doc = "Puts `" $ty "` value in little-endian byte order to the beginning of the buffer without advancing the internal cursor."]
#[doc = "Returns the number of bytes written (always `size_of::<" $ty ">()` for this type)."]
#[doc = "let written = slice.put_" $ty "_le(0x1234 as " $ty ");"]
#[doc = "assert_eq!(written, size_of::<" $ty ">());"]
#[inline]
fn [< put_ $ty _le>](&mut self, value: $ty) -> usize {
self.put_slice(&value.to_le_bytes())
}
#[doc = "Tries to put `" $ty "` value in little-endian byte order to the beginning of the buffer without advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`put_" $ty "_le`](ChunkMut::put_" $ty "_le)."]
#[doc = "assert!(slice.put_" $ty "_le_checked(0x1234 as " $ty ").is_some());"]
#[doc = "assert!(small_slice.put_" $ty "_le_checked(0x1234 as " $ty ").is_none()); // Not enough space"]
#[inline]
fn [< put_ $ty _le_checked>](&mut self, value: $ty) -> Option<usize> {
self.put_slice_checked(&value.to_le_bytes())
}
#[doc = "Tries to put `" $ty "` value in little-endian byte order to the beginning of the buffer without advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`put_" $ty "_le`](ChunkMut::put_" $ty "_le)."]
#[doc = "assert!(slice.try_put_" $ty "_le(0x1234 as " $ty ").is_ok());"]
#[doc = "let err = small_slice.try_put_" $ty "_le(0x1234 as " $ty ").unwrap_err();"]
#[inline]
fn [< try_put_ $ty _le>](&mut self, value: $ty) -> Result<usize, InsufficientSpace> {
self.try_put_slice(&value.to_le_bytes())
}
#[doc = "Puts a `" $ty "` value in big-endian byte order to the beginning of the buffer without advancing the internal cursor."]
#[doc = "Returns the number of bytes written (always `size_of::<" $ty ">()` for this type)."]
#[doc = "let written = slice.put_" $ty "_be(0x1234 as " $ty ");"]
#[doc = "assert_eq!(written, size_of::<" $ty ">());"]
#[inline]
fn [< put_ $ty _be>](&mut self, value: $ty) -> usize {
self.put_slice(&value.to_be_bytes())
}
#[doc = "Tries to put `" $ty "` value in big-endian byte order to the beginning of the buffer without advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`put_" $ty "_be`](ChunkMut::put_" $ty "_be)."]
#[doc = "assert!(slice.put_" $ty "_be_checked(0x1234 as " $ty ").is_some());"]
#[doc = "assert!(small_slice.put_" $ty "_be_checked(0x1234 as " $ty ").is_none()); // Not enough space"]
#[inline]
fn [< put_ $ty _be_checked>](&mut self, value: $ty) -> Option<usize> {
self.put_slice_checked(&value.to_be_bytes())
}
#[doc = "Tries to put `" $ty "` value in big-endian byte order to the beginning of the buffer without advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`put_" $ty "_be`](ChunkMut::put_" $ty "_be)."]
#[doc = "assert!(slice.try_put_" $ty "_be(0x1234 as " $ty ").is_ok());"]
#[doc = "let err = small_slice.try_put_" $ty "_be(0x1234 as " $ty ").unwrap_err();"]
#[inline]
fn [< try_put_ $ty _be>](&mut self, value: $ty) -> Result<usize, InsufficientSpace> {
self.try_put_slice(&value.to_be_bytes())
}
#[doc = "Puts `" $ty "` value in native-endian byte order to the beginning of the buffer without advancing the internal cursor."]
#[doc = "Returns the number of bytes written (always `size_of::<" $ty ">()` for this type)."]
#[doc = "let written = slice.put_" $ty "_ne(0x1234 as " $ty ");"]
#[doc = "assert_eq!(written, size_of::<" $ty ">());"]
#[inline]
fn [< put_ $ty _ne>](&mut self, value: $ty) -> usize {
self.put_slice(&value.to_ne_bytes())
}
#[doc = "Tries to put `" $ty "` value in native-endian byte order to the beginning of the buffer without advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`put_" $ty "_ne`](ChunkMut::put_" $ty "_ne)."]
#[doc = "assert!(slice.put_" $ty "_ne_checked(0x1234 as " $ty ").is_some());"]
#[doc = "assert!(small_slice.put_" $ty "_ne_checked(0x1234 as " $ty ").is_none()); // Not enough space"]
#[inline]
fn [< put_ $ty _ne_checked>](&mut self, value: $ty) -> Option<usize> {
self.put_slice_checked(&value.to_ne_bytes())
}
#[doc = "Tries to put `" $ty "` value in native-endian byte order to the beginning of the buffer without advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`put_" $ty "_ne`](ChunkMut::put_" $ty "_ne)."]
#[doc = "assert!(slice.try_put_" $ty "_ne(0x1234 as " $ty ").is_ok());"]
#[doc = "let err = small_slice.try_put_" $ty "_ne(0x1234 as " $ty ").unwrap_err();"]
#[inline]
fn [< try_put_ $ty _ne>](&mut self, value: $ty) -> Result<usize, InsufficientSpace> {
self.try_put_slice(&value.to_ne_bytes())
}
)*
}
};
(@forward $($ty:ty),+$(,)?) => {
paste::paste! {
$(
#[inline]
fn [< put_ $ty _le_at>](&mut self, value: $ty, offset: usize) -> usize {
(**self).[< put_ $ty _le_at>](value, offset)
}
#[inline]
fn [< put_ $ty _le_at_checked>](&mut self, value: $ty, offset: usize) -> Option<usize> {
(**self).[< put_ $ty _le_at_checked>](value, offset)
}
#[inline]
fn [< try_put_ $ty _le_at>](&mut self, value: $ty, offset: usize) -> Result<usize, TryPutAtError> {
(**self).[< try_put_ $ty _le_at>](value, offset)
}
#[inline]
fn [< put_ $ty _be_at>](&mut self, value: $ty, offset: usize) -> usize {
(**self).[< put_ $ty _be_at>](value, offset)
}
#[inline]
fn [< put_ $ty _be_at_checked>](&mut self, value: $ty, offset: usize) -> Option<usize> {
(**self).[< put_ $ty _be_at_checked>](value, offset)
}
#[inline]
fn [< try_put_ $ty _be_at>](&mut self, value: $ty, offset: usize) -> Result<usize, TryPutAtError> {
(**self).[< try_put_ $ty _be_at>](value, offset)
}
#[inline]
fn [< put_ $ty _ne_at>](&mut self, value: $ty, offset: usize) -> usize {
(**self).[< put_ $ty _ne_at>](value, offset)
}
#[inline]
fn [< put_ $ty _ne_at_checked>](&mut self, value: $ty, offset: usize) -> Option<usize> {
(**self).[< put_ $ty _ne_at_checked>](value, offset)
}
#[inline]
fn [< try_put_ $ty _ne_at>](&mut self, value: $ty, offset: usize) -> Result<usize, TryPutAtError> {
(**self).[< try_put_ $ty _ne_at>](value, offset)
}
#[inline]
fn [< put_ $ty _le>](&mut self, value: $ty) -> usize {
(**self).[< put_ $ty _le>](value)
}
#[inline]
fn [< put_ $ty _le_checked>](&mut self, value: $ty) -> Option<usize> {
(**self).[< put_ $ty _le_checked>](value)
}
#[inline]
fn [< try_put_ $ty _le>](&mut self, value: $ty) -> Result<usize, InsufficientSpace> {
(**self).[< try_put_ $ty _le>](value)
}
#[inline]
fn [< put_ $ty _be>](&mut self, value: $ty) -> usize {
(**self).[< put_ $ty _be>](value)
}
#[inline]
fn [< put_ $ty _be_checked>](&mut self, value: $ty) -> Option<usize> {
(**self).[< put_ $ty _be_checked>](value)
}
#[inline]
fn [< try_put_ $ty _be>](&mut self, value: $ty) -> Result<usize, InsufficientSpace> {
(**self).[< try_put_ $ty _be>](value)
}
#[inline]
fn [< put_ $ty _ne>](&mut self, value: $ty) -> usize {
(**self).[< put_ $ty _ne>](value)
}
#[inline]
fn [< put_ $ty _ne_checked>](&mut self, value: $ty) -> Option<usize> {
(**self).[< put_ $ty _ne_checked>](value)
}
#[inline]
fn [< try_put_ $ty _ne>](&mut self, value: $ty) -> Result<usize, InsufficientSpace> {
(**self).[< try_put_ $ty _ne>](value)
}
)*
}
};
}
macro_rules! write_fixed {
($($ty:ty),+$(,)?) => {
paste::paste! {
$(
#[doc = "Writes `" $ty "` value in little-endian byte order to the beginning of the buffer, advancing the internal cursor."]
#[doc = "Returns the number of bytes written (always `size_of::<" $ty ">()` for this type)."]
#[doc = "let written = slice.write_" $ty "_le(0x1234 as " $ty ");"]
#[doc = "assert_eq!(written, size_of::<" $ty ">());"]
#[doc = "assert_eq!(slice.remaining_mut(), 24 - size_of::<" $ty ">());"]
#[inline]
fn [< write_ $ty _le>](&mut self, value: $ty) -> usize {
self.write_slice(&value.to_le_bytes())
}
#[doc = "Tries to write `" $ty "` value in little-endian byte order to the beginning of the buffer, advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`write_" $ty "_le`](ChunkMut::write_" $ty "_le)."]
#[doc = "assert!(slice.write_" $ty "_le_checked(0x1234 as " $ty ").is_some());"]
#[doc = "assert_eq!(slice.remaining_mut(), 24 - size_of::<" $ty ">());"]
#[doc = "assert!(small_slice.write_" $ty "_le_checked(0x1234 as " $ty ").is_none()); // Not enough space"]
#[inline]
fn [< write_ $ty _le_checked>](&mut self, value: $ty) -> Option<usize> {
self.write_slice_checked(&value.to_le_bytes())
}
#[doc = "Tries to write `" $ty "` value in little-endian byte order to the beginning of the buffer, advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`write_" $ty "_le`](ChunkMut::write_" $ty "_le)."]
#[doc = "assert!(slice.try_write_" $ty "_le(0x1234 as " $ty ").is_ok());"]
#[doc = "assert_eq!(slice.remaining_mut(), 24 - size_of::<" $ty ">());"]
#[doc = "let err = small_slice.try_write_" $ty "_le(0x1234 as " $ty ").unwrap_err();"]
#[inline]
fn [< try_write_ $ty _le>](&mut self, value: $ty) -> Result<usize, InsufficientSpace> {
self.try_write_slice(&value.to_le_bytes())
}
#[doc = "Writes `" $ty "` value in big-endian byte order to the beginning of the buffer, advancing the internal cursor."]
#[doc = "Returns the number of bytes written (always `size_of::<" $ty ">()` for this type)."]
#[doc = "let written = slice.write_" $ty "_be(0x1234 as " $ty ");"]
#[doc = "assert_eq!(written, size_of::<" $ty ">());"]
#[doc = "assert_eq!(slice.remaining_mut(), 24 - size_of::<" $ty ">());"]
#[inline]
fn [< write_ $ty _be>](&mut self, value: $ty) -> usize {
self.write_slice(&value.to_be_bytes())
}
#[doc = "Tries to write `" $ty "` value in big-endian byte order to the beginning of the buffer, advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`write_" $ty "_be`](ChunkMut::write_" $ty "_be)."]
#[doc = "assert!(slice.write_" $ty "_be_checked(0x1234 as " $ty ").is_some());"]
#[doc = "assert_eq!(slice.remaining_mut(), 24 - size_of::<" $ty ">());"]
#[doc = "assert!(small_slice.write_" $ty "_be_checked(0x1234 as " $ty ").is_none()); // Not enough space"]
#[inline]
fn [< write_ $ty _be_checked>](&mut self, value: $ty) -> Option<usize> {
self.write_slice_checked(&value.to_be_bytes())
}
#[doc = "Tries to write `" $ty "` value in big-endian byte order to the beginning of the buffer, advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`write_" $ty "_be`](ChunkMut::write_" $ty "_be)."]
#[doc = "assert!(slice.try_write_" $ty "_be(0x1234 as " $ty ").is_ok());"]
#[doc = "assert_eq!(slice.remaining_mut(), 24 - size_of::<" $ty ">());"]
#[doc = "let err = small_slice.try_write_" $ty "_be(0x1234 as " $ty ").unwrap_err();"]
#[inline]
fn [< try_write_ $ty _be>](&mut self, value: $ty) -> Result<usize, InsufficientSpace> {
self.try_write_slice(&value.to_be_bytes())
}
#[doc = "Writes `" $ty "` value in native-endian byte order to the beginning of the buffer, advancing the internal cursor."]
#[doc = "Returns the number of bytes written (always `size_of::<" $ty ">()` for this type)."]
#[doc = "let written = slice.write_" $ty "_ne(0x1234 as " $ty ");"]
#[doc = "assert_eq!(written, size_of::<" $ty ">());"]
#[doc = "assert_eq!(slice.remaining_mut(), 24 - size_of::<" $ty ">());"]
#[inline]
fn [< write_ $ty _ne>](&mut self, value: $ty) -> usize {
self.write_slice(&value.to_ne_bytes())
}
#[doc = "Tries to write `" $ty "` value in native-endian byte order to the beginning of the buffer, advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`write_" $ty "_ne`](ChunkMut::write_" $ty "_ne)."]
#[doc = "assert!(slice.write_" $ty "_ne_checked(0x1234 as " $ty ").is_some());"]
#[doc = "assert_eq!(slice.remaining_mut(), 24 - size_of::<" $ty ">());"]
#[doc = "assert!(small_slice.write_" $ty "_ne_checked(0x1234 as " $ty ").is_none()); // Not enough space"]
#[inline]
fn [< write_ $ty _ne_checked>](&mut self, value: $ty) -> Option<usize> {
self.write_slice_checked(&value.to_ne_bytes())
}
#[doc = "Tries to write `" $ty "` value in native-endian byte order to the beginning of the buffer, advancing the internal cursor."]
#[doc = "This is the non-panicking version of [`write_" $ty "_ne`](ChunkMut::write_" $ty "_ne)."]
#[doc = "assert!(slice.try_write_" $ty "_ne(0x1234 as " $ty ").is_ok());"]
#[doc = "assert_eq!(slice.remaining_mut(), 24 - size_of::<" $ty ">());"]
#[doc = "let err = small_slice.try_write_" $ty "_ne(0x1234 as " $ty ").unwrap_err();"]
#[inline]
fn [< try_write_ $ty _ne>](&mut self, value: $ty) -> Result<usize, InsufficientSpace> {
self.try_write_slice(&value.to_ne_bytes())
}
)*
}
};
(@forward $($ty:ty),+$(,)?) => {
paste::paste! {
$(
#[inline]
fn [< write_ $ty _le>](&mut self, value: $ty) -> usize {
(**self).[< write_ $ty _le>](value)
}
#[inline]
fn [< write_ $ty _le_checked>](&mut self, value: $ty) -> Option<usize> {
(**self).[< write_ $ty _le_checked>](value)
}
#[inline]
fn [< try_write_ $ty _le>](&mut self, value: $ty) -> Result<usize, InsufficientSpace> {
(**self).[< try_write_ $ty _le>](value)
}
#[inline]
fn [< write_ $ty _be>](&mut self, value: $ty) -> usize {
(**self).[< write_ $ty _be>](value)
}
#[inline]
fn [< write_ $ty _be_checked>](&mut self, value: $ty) -> Option<usize> {
(**self).[< write_ $ty _be_checked>](value)
}
#[inline]
fn [< try_write_ $ty _be>](&mut self, value: $ty) -> Result<usize, InsufficientSpace> {
(**self).[< try_write_ $ty _be>](value)
}
#[inline]
fn [< write_ $ty _ne>](&mut self, value: $ty) -> usize {
(**self).[< write_ $ty _ne>](value)
}
#[inline]
fn [< write_ $ty _ne_checked>](&mut self, value: $ty) -> Option<usize> {
(**self).[< write_ $ty _ne_checked>](value)
}
#[inline]
fn [< try_write_ $ty _ne>](&mut self, value: $ty) -> Result<usize, InsufficientSpace> {
(**self).[< try_write_ $ty _ne>](value)
}
)*
}
};
}
pub trait ChunkMut {
fn has_remaining_mut(&self) -> bool {
self.remaining_mut() > 0
}
fn remaining_mut(&self) -> usize;
fn truncate_mut(&mut self, new_len: usize);
fn buffer_mut(&mut self) -> &mut [u8];
#[inline]
fn buffer_mut_from(&mut self, offset: usize) -> &mut [u8] {
&mut self.buffer_mut()[offset..]
}
#[inline]
fn buffer_mut_from_checked(&mut self, offset: usize) -> Option<&mut [u8]> {
if offset > self.remaining_mut() {
None
} else {
Some(&mut self.buffer_mut()[offset..])
}
}
fn advance_mut(&mut self, cnt: usize);
fn try_advance_mut(&mut self, cnt: usize) -> Result<(), TryAdvanceError> {
let remaining = self.remaining_mut();
if remaining < cnt {
return Err(TryAdvanceError::new(must_non_zero(cnt), remaining));
}
self.advance_mut(cnt);
Ok(())
}
fn fill(&mut self, value: u8) {
self.buffer_mut().fill(value);
}
fn prefix_mut(&mut self, len: usize) -> &mut [u8] {
&mut self.buffer_mut()[..len]
}
fn prefix_mut_checked(&mut self, len: usize) -> Option<&mut [u8]> {
if self.remaining_mut() < len {
None
} else {
Some(&mut self.buffer_mut()[..len])
}
}
fn suffix_mut(&mut self, len: usize) -> &mut [u8] {
let total_len = self.remaining_mut();
&mut self.buffer_mut()[total_len - len..]
}
fn suffix_mut_checked(&mut self, len: usize) -> Option<&mut [u8]> {
self
.remaining_mut()
.checked_sub(len)
.map(|start| &mut self.buffer_mut()[start..])
}
fn split_at_mut(&mut self, mid: usize) -> (&mut [u8], &mut [u8]) {
self.buffer_mut().split_at_mut(mid)
}
fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut [u8], &mut [u8])> {
self.buffer_mut().split_at_mut_checked(mid)
}
fn write_slice(&mut self, slice: &[u8]) -> usize {
let len = slice.len();
self.buffer_mut()[..len].copy_from_slice(slice);
self.advance_mut(len);
len
}
fn write_slice_checked(&mut self, slice: &[u8]) -> Option<usize> {
let len = slice.len();
if len <= self.remaining_mut() {
self.buffer_mut()[..len].copy_from_slice(slice);
self.advance_mut(len);
Some(len)
} else {
None
}
}
fn try_write_slice(&mut self, slice: &[u8]) -> Result<usize, InsufficientSpace> {
let len = slice.len();
if len == 0 {
return Ok(0);
}
let space = self.remaining_mut();
if len <= space {
self.buffer_mut()[..len].copy_from_slice(slice);
self.advance_mut(len);
Ok(len)
} else {
Err(InsufficientSpace::new(must_non_zero(len), space))
}
}
write_fixed!(u16, u32, u64, u128, i16, i32, i64, i128, f32, f64);
#[inline]
fn write_u8(&mut self, value: u8) -> usize {
self.write_slice(&[value])
}
#[inline]
fn write_u8_checked(&mut self, value: u8) -> Option<usize> {
self.write_slice_checked(&[value])
}
#[inline]
fn write_i8(&mut self, value: i8) -> usize {
self.write_slice(&[value as u8])
}
#[inline]
fn write_i8_checked(&mut self, value: i8) -> Option<usize> {
self.write_slice_checked(&[value as u8])
}
#[inline]
fn try_write_u8(&mut self, value: u8) -> Result<usize, InsufficientSpace> {
self.try_write_slice(&[value])
}
#[inline]
fn try_write_i8(&mut self, value: i8) -> Result<usize, InsufficientSpace> {
self.try_write_slice(&[value as u8])
}
fn put_slice(&mut self, slice: &[u8]) -> usize {
let len = slice.len();
self.buffer_mut()[..len].copy_from_slice(slice);
len
}
fn put_slice_checked(&mut self, slice: &[u8]) -> Option<usize> {
let len = slice.len();
if len <= self.remaining_mut() {
self.buffer_mut()[..len].copy_from_slice(slice);
Some(len)
} else {
None
}
}
fn try_put_slice(&mut self, slice: &[u8]) -> Result<usize, InsufficientSpace> {
let len = slice.len();
if len == 0 {
return Ok(0);
}
let space = self.remaining_mut();
if len <= space {
self.buffer_mut()[..len].copy_from_slice(slice);
Ok(len)
} else {
Err(InsufficientSpace::new(must_non_zero(len), space))
}
}
fn put_slice_at(&mut self, slice: &[u8], offset: usize) -> usize {
let len = slice.len();
self.buffer_mut()[offset..offset + len].copy_from_slice(slice);
len
}
fn put_slice_at_checked(&mut self, slice: &[u8], offset: usize) -> Option<usize> {
let len = slice.len();
let space = self.remaining_mut();
if offset <= space && len <= space - offset {
self.buffer_mut()[offset..offset + len].copy_from_slice(slice);
Some(len)
} else {
None
}
}
fn try_put_slice_at(&mut self, slice: &[u8], offset: usize) -> Result<usize, TryPutAtError> {
let len = slice.len();
let space = self.remaining_mut();
if len == 0 {
if offset > space {
return Err(TryPutAtError::out_of_bounds(offset, space));
}
return Ok(0);
}
if offset >= space {
return Err(TryPutAtError::out_of_bounds(offset, space));
}
if len <= space - offset {
self.buffer_mut()[offset..offset + len].copy_from_slice(slice);
Ok(len)
} else {
Err(TryPutAtError::insufficient_space(
must_non_zero(len),
space - offset,
offset,
))
}
}
put_fixed!(u16, u32, u64, u128, i16, i32, i64, i128, f32, f64);
#[inline]
fn put_u8(&mut self, value: u8) -> usize {
self.put_slice(&[value])
}
#[inline]
fn put_u8_checked(&mut self, value: u8) -> Option<usize> {
self.put_slice_checked(&[value])
}
#[inline]
fn put_i8(&mut self, value: i8) -> usize {
self.put_slice(&[value as u8])
}
#[inline]
fn put_i8_checked(&mut self, value: i8) -> Option<usize> {
self.put_slice_checked(&[value as u8])
}
#[inline]
fn put_u8_at(&mut self, value: u8, offset: usize) -> usize {
self.put_slice_at(&[value], offset)
}
#[inline]
fn put_u8_at_checked(&mut self, value: u8, offset: usize) -> Option<usize> {
self.put_slice_at_checked(&[value], offset)
}
#[inline]
fn put_i8_at(&mut self, value: i8, offset: usize) -> usize {
self.put_slice_at(&[value as u8], offset)
}
#[inline]
fn put_i8_at_checked(&mut self, value: i8, offset: usize) -> Option<usize> {
self.put_slice_at_checked(&[value as u8], offset)
}
#[inline]
fn try_put_u8(&mut self, value: u8) -> Result<usize, InsufficientSpace> {
self.try_put_slice(&[value])
}
#[inline]
fn try_put_i8(&mut self, value: i8) -> Result<usize, InsufficientSpace> {
self.try_put_slice(&[value as u8])
}
#[inline]
fn try_put_u8_at(&mut self, value: u8, offset: usize) -> Result<usize, TryPutAtError> {
self.try_put_slice_at(&[value], offset)
}
#[inline]
fn try_put_i8_at(&mut self, value: i8, offset: usize) -> Result<usize, TryPutAtError> {
self.try_put_slice_at(&[value as u8], offset)
}
}
pub trait ChunkMutExt: ChunkMut {
#[inline]
fn put_varint<V>(&mut self, value: &V) -> Result<NonZeroUsize, EncodeVarintError>
where
V: Varint,
{
value.encode(self.buffer_mut())
}
#[inline]
fn put_varint_at<V>(
&mut self,
value: &V,
offset: usize,
) -> Result<NonZeroUsize, EncodeVarintAtError>
where
V: Varint,
{
match self.split_at_mut_checked(offset) {
Some((_, suffix)) => match value.encode(suffix) {
Ok(read) => Ok(read),
Err(e) => Err(EncodeVarintAtError::from_varint_error(e, offset)),
},
None => Err(EncodeVarintAtError::out_of_bounds(
offset,
self.remaining_mut(),
)),
}
}
#[inline]
fn write_varint<V>(&mut self, value: &V) -> Result<NonZeroUsize, EncodeVarintError>
where
V: Varint,
{
value.encode(self.buffer_mut()).inspect(|bytes_written| {
self.advance_mut(bytes_written.get());
})
}
}
impl<T: ChunkMut> ChunkMutExt for T {}
macro_rules! deref_forward_buf_mut {
() => {
#[inline]
fn has_remaining_mut(&self) -> bool {
(**self).has_remaining_mut()
}
#[inline]
fn remaining_mut(&self) -> usize {
(**self).remaining_mut()
}
#[inline]
fn advance_mut(&mut self, cnt: usize) {
(**self).advance_mut(cnt)
}
#[inline]
fn try_advance_mut(&mut self, cnt: usize) -> Result<(), TryAdvanceError> {
(**self).try_advance_mut(cnt)
}
#[inline]
fn truncate_mut(&mut self, new_len: usize) {
(**self).truncate_mut(new_len)
}
#[inline]
fn buffer_mut(&mut self) -> &mut [u8] {
(**self).buffer_mut()
}
#[inline]
fn fill(&mut self, value: u8) {
(**self).fill(value)
}
#[inline]
fn prefix_mut(&mut self, len: usize) -> &mut [u8] {
(**self).prefix_mut(len)
}
#[inline]
fn prefix_mut_checked(&mut self, len: usize) -> Option<&mut [u8]> {
(**self).prefix_mut_checked(len)
}
#[inline]
fn suffix_mut(&mut self, len: usize) -> &mut [u8] {
(**self).suffix_mut(len)
}
#[inline]
fn suffix_mut_checked(&mut self, len: usize) -> Option<&mut [u8]> {
(**self).suffix_mut_checked(len)
}
#[inline]
fn split_at_mut(&mut self, mid: usize) -> (&mut [u8], &mut [u8]) {
(**self).split_at_mut(mid)
}
#[inline]
fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut [u8], &mut [u8])> {
(**self).split_at_mut_checked(mid)
}
#[inline]
fn put_slice(&mut self, slice: &[u8]) -> usize {
(**self).put_slice(slice)
}
#[inline]
fn put_slice_checked(&mut self, slice: &[u8]) -> Option<usize> {
(**self).put_slice_checked(slice)
}
#[inline]
fn try_put_slice(&mut self, slice: &[u8]) -> Result<usize, InsufficientSpace> {
(**self).try_put_slice(slice)
}
#[inline]
fn put_slice_at(&mut self, slice: &[u8], offset: usize) -> usize {
(**self).put_slice_at(slice, offset)
}
#[inline]
fn put_slice_at_checked(&mut self, slice: &[u8], offset: usize) -> Option<usize> {
(**self).put_slice_at_checked(slice, offset)
}
#[inline]
fn try_put_slice_at(&mut self, slice: &[u8], offset: usize) -> Result<usize, TryPutAtError> {
(**self).try_put_slice_at(slice, offset)
}
#[inline]
fn put_u8(&mut self, value: u8) -> usize {
(**self).put_u8(value)
}
#[inline]
fn put_u8_checked(&mut self, value: u8) -> Option<usize> {
(**self).put_u8_checked(value)
}
#[inline]
fn try_put_u8(&mut self, value: u8) -> Result<usize, InsufficientSpace> {
(**self).try_put_u8(value)
}
#[inline]
fn put_i8(&mut self, value: i8) -> usize {
(**self).put_i8(value)
}
#[inline]
fn put_i8_checked(&mut self, value: i8) -> Option<usize> {
(**self).put_i8_checked(value)
}
#[inline]
fn try_put_i8(&mut self, value: i8) -> Result<usize, InsufficientSpace> {
(**self).try_put_i8(value)
}
#[inline]
fn put_u8_at(&mut self, value: u8, offset: usize) -> usize {
(**self).put_u8_at(value, offset)
}
#[inline]
fn put_u8_at_checked(&mut self, value: u8, offset: usize) -> Option<usize> {
(**self).put_u8_at_checked(value, offset)
}
#[inline]
fn try_put_u8_at(&mut self, value: u8, offset: usize) -> Result<usize, TryPutAtError> {
(**self).try_put_u8_at(value, offset)
}
#[inline]
fn put_i8_at(&mut self, value: i8, offset: usize) -> usize {
(**self).put_i8_at(value, offset)
}
#[inline]
fn put_i8_at_checked(&mut self, value: i8, offset: usize) -> Option<usize> {
(**self).put_i8_at_checked(value, offset)
}
#[inline]
fn try_put_i8_at(&mut self, value: i8, offset: usize) -> Result<usize, TryPutAtError> {
(**self).try_put_i8_at(value, offset)
}
put_fixed! {
@forward
u16, u32, u64, u128,
i16, i32, i64, i128,
f32, f64
}
#[inline]
fn write_slice(&mut self, slice: &[u8]) -> usize {
(**self).write_slice(slice)
}
#[inline]
fn write_slice_checked(&mut self, slice: &[u8]) -> Option<usize> {
(**self).write_slice_checked(slice)
}
#[inline]
fn try_write_slice(&mut self, slice: &[u8]) -> Result<usize, InsufficientSpace> {
(**self).try_write_slice(slice)
}
#[inline]
fn write_u8(&mut self, value: u8) -> usize {
(**self).write_u8(value)
}
#[inline]
fn write_u8_checked(&mut self, value: u8) -> Option<usize> {
(**self).write_u8_checked(value)
}
#[inline]
fn try_write_u8(&mut self, value: u8) -> Result<usize, InsufficientSpace> {
(**self).try_write_u8(value)
}
#[inline]
fn write_i8(&mut self, value: i8) -> usize {
(**self).write_i8(value)
}
#[inline]
fn write_i8_checked(&mut self, value: i8) -> Option<usize> {
(**self).write_i8_checked(value)
}
#[inline]
fn try_write_i8(&mut self, value: i8) -> Result<usize, InsufficientSpace> {
(**self).try_write_i8(value)
}
write_fixed! {
@forward
u16, u32, u64, u128,
i16, i32, i64, i128,
f32, f64
}
};
}
impl<T: ChunkMut + ?Sized> ChunkMut for &mut T {
deref_forward_buf_mut!();
}
#[cfg(any(feature = "std", feature = "alloc"))]
const _: () = {
impl<T: ChunkMut + ?Sized> ChunkMut for std::boxed::Box<T> {
deref_forward_buf_mut!();
}
impl<T: EmptyChunk> EmptyChunk for std::boxed::Box<T> {
#[inline]
fn empty() -> Self
where
Self: Sized,
{
std::boxed::Box::new(T::empty())
}
}
};
impl EmptyChunk for &mut [u8] {
#[inline]
fn empty() -> Self
where
Self: Sized,
{
&mut []
}
}
impl ChunkMut for &mut [u8] {
#[inline]
fn advance_mut(&mut self, cnt: usize) {
if self.len() < cnt {
panic_advance(&TryAdvanceError::new(must_non_zero(cnt), self.len()));
}
let (_, b) = core::mem::take(self).split_at_mut(cnt);
*self = b;
}
#[inline]
fn truncate_mut(&mut self, len: usize) {
if len >= self.len() {
return;
}
let (a, _) = core::mem::take(self).split_at_mut(len);
*self = a;
}
#[inline]
fn buffer_mut(&mut self) -> &mut [u8] {
self
}
#[inline]
fn remaining_mut(&self) -> usize {
<[u8]>::len(self)
}
#[inline]
fn has_remaining_mut(&self) -> bool {
!self.is_empty()
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct ChunkWriter<B: ?Sized>(B);
impl<B> From<B> for ChunkWriter<B> {
#[inline]
fn from(value: B) -> Self {
Self(value)
}
}
impl<B: ?Sized> core::ops::Deref for ChunkWriter<B> {
type Target = B;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<B: ?Sized> core::ops::DerefMut for ChunkWriter<B> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<B: EmptyChunk> EmptyChunk for ChunkWriter<B> {
#[inline]
fn empty() -> Self
where
Self: Sized,
{
ChunkWriter(B::empty())
}
}
impl<B: ?Sized + ChunkMut> ChunkMut for ChunkWriter<B> {
deref_forward_buf_mut!();
}
impl<B: ?Sized> ChunkWriter<B> {
#[inline]
pub const fn as_mut(&mut self) -> ChunkWriter<&mut B> {
ChunkWriter(&mut self.0)
}
#[inline]
pub const fn as_ref(&self) -> ChunkWriter<&B> {
ChunkWriter(&self.0)
}
}
impl<B> ChunkWriter<B> {
#[inline]
pub const fn new(buf: B) -> Self {
ChunkWriter(buf)
}
#[inline]
pub fn into_inner(self) -> B {
self.0
}
}
const _: () = {
fn _assert_trait_object(_b: &dyn ChunkMut) {}
};
#[cfg(test)]
mod tests {
use super::*;
struct Wrapper<'a>(&'a mut [u8]);
impl ChunkMut for Wrapper<'_> {
fn remaining_mut(&self) -> usize {
self.0.len()
}
fn truncate_mut(&mut self, new_len: usize) {
self.0.truncate_mut(new_len);
}
fn buffer_mut(&mut self) -> &mut [u8] {
self.0
}
fn advance_mut(&mut self, cnt: usize) {
self.0.advance_mut(cnt);
}
}
#[test]
#[should_panic]
fn test_advance_mut_panic() {
let mut buf = [0u8; 5];
let mut slice = &mut buf[..];
slice.advance_mut(10);
}
#[test]
fn test_blanket_has_remaining_mut() {
let mut buf = [0u8; 5];
let slice = Wrapper(&mut buf[..]);
assert!(ChunkMut::has_remaining_mut(&slice));
let empty_slice = Wrapper(&mut []);
assert!(!ChunkMut::has_remaining_mut(&empty_slice));
}
#[test]
fn test_blanket_fill() {
let mut buf = [0u8; 5];
let mut slice = Wrapper(&mut buf[..]);
slice.fill(0xFF);
assert_eq!(slice.0, &[0xFF; 5]);
slice.fill(0x00);
assert_eq!(slice.0, &[0x00; 5]);
}
#[test]
fn test_blanket_split_at_mut() {
let mut buf = [1, 2, 3, 4, 5];
let mut slice = Wrapper(&mut buf[..]);
let (left, right) = slice.split_at_mut(2);
assert_eq!(left, &[1, 2]);
assert_eq!(right, &[3, 4, 5]);
}
#[test]
fn test_deref_write_buf() {
let mut buf = [0u8; 10];
let write_buf = ChunkWriter::from(&mut buf[..]);
let val = core::ops::Deref::deref(&write_buf);
assert_eq!(val[0], 0); }
#[test]
fn test_deref_mut_write_buf() {
let mut buf = [0u8; 10];
let mut write_buf = ChunkWriter::from(&mut buf[..]);
let val = core::ops::DerefMut::deref_mut(&mut write_buf);
val[0] = 42; assert_eq!(buf[0], 42);
}
#[test]
fn test_deref_forward_has_remaining_mut() {
let mut buf = [0u8; 5];
let slice = ChunkWriter::from(&mut buf[..]);
assert!(slice.has_remaining_mut());
let empty_slice: ChunkWriter<&mut [u8]> = ChunkWriter::from([].as_mut_slice());
assert!(!empty_slice.has_remaining_mut());
}
#[test]
fn test_deref_forward_advance_mut() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
slice.advance_mut(3);
assert_eq!(slice.buffer_mut(), &[0, 0]);
assert_eq!(slice.remaining_mut(), 2); }
#[test]
fn test_deref_forward_try_advance_mut() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert!(slice.try_advance_mut(3).is_ok());
assert_eq!(slice.buffer_mut(), &[0, 0]);
assert_eq!(slice.remaining_mut(), 2);
let err = slice.try_advance_mut(10);
assert!(err.is_err()); }
#[test]
fn test_deref_forward_truncate_mut() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
slice.truncate_mut(3);
assert_eq!(slice.buffer_mut(), &[0, 0, 0]);
assert_eq!(slice.remaining_mut(), 3); }
#[test]
fn test_deref_forward_buffer_mut() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
let buffer = slice.buffer_mut();
assert_eq!(buffer, &mut [0u8; 5]);
buffer[0] = 42; assert_eq!(slice.buffer_mut(), &[42, 0, 0, 0, 0]);
}
#[test]
fn test_deref_forward_fill() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
ChunkMut::fill(&mut slice, 0xFF); assert_eq!(slice.buffer_mut(), &[0xFF; 5]);
}
#[test]
fn test_deref_forward_prefix_mut() {
let mut buf = [1, 2, 3, 4, 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
let prefix = slice.prefix_mut(3);
assert_eq!(prefix, &mut [1, 2, 3]);
prefix[0] = 10; assert_eq!(slice.buffer_mut(), &[10, 2, 3, 4, 5]);
}
#[test]
fn test_deref_forward_prefix_mut_checked() {
let mut buf = [1, 2, 3, 4, 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert!(slice.prefix_mut_checked(3).is_some());
assert!(slice.prefix_mut_checked(10).is_none()); }
#[test]
fn test_deref_forward_suffix_mut() {
let mut buf = [1, 2, 3, 4, 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
let suffix = slice.suffix_mut(2);
assert_eq!(suffix, &mut [4, 5]);
}
#[test]
fn test_deref_forward_suffix_mut_checked() {
let mut buf = [1, 2, 3, 4, 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert!(slice.suffix_mut_checked(2).is_some());
assert!(slice.suffix_mut_checked(10).is_none()); }
#[test]
fn test_deref_forward_split_at_mut() {
let mut buf = [1, 2, 3, 4, 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
let (left, right) = slice.split_at_mut(2);
assert_eq!(left, &[1, 2]);
assert_eq!(right, &[3, 4, 5]);
}
#[test]
fn test_deref_forward_split_at_mut_checked() {
let mut buf = [1, 2, 3, 4, 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert!(slice.split_at_mut_checked(2).is_some());
assert!(slice.split_at_mut_checked(10).is_none()); }
#[test]
fn test_deref_forward_put_slice() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
let written = slice.put_slice(&[1, 2, 3]);
assert_eq!(written, 3);
assert_eq!(slice.buffer_mut(), &[1, 2, 3, 0, 0]);
}
#[test]
fn test_deref_forward_put_slice_checked() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.put_slice_checked(&[1, 2, 3]), Some(3));
assert_eq!(slice.put_slice_checked(&[1, 2, 3, 4, 5, 6]), None); assert_eq!(slice.buffer_mut(), &[1, 2, 3, 0, 0]);
}
#[test]
fn test_deref_forward_try_put_slice() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.try_put_slice(&[1, 2, 3]), Ok(3));
assert_eq!(
slice.try_put_slice(&[1, 2, 3, 4, 5, 6]),
Err(InsufficientSpace::new(must_non_zero(6), 5))
); assert_eq!(slice.buffer_mut(), &[1, 2, 3, 0, 0]);
}
#[test]
fn test_deref_forward_put_slice_at() {
let mut buf = [0u8; 10];
let mut slice = ChunkWriter::from(&mut buf[..]);
let written = slice.put_slice_at(&[1, 2, 3], 2);
assert_eq!(written, 3);
assert_eq!(slice.buffer_mut(), &[0, 0, 1, 2, 3, 0, 0, 0, 0, 0]);
assert_eq!(slice.remaining_mut(), 10);
}
#[test]
fn test_deref_forward_put_slice_at_checked() {
let mut buf = [0u8; 10];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.put_slice_at_checked(&[1, 2, 3], 2), Some(3));
assert_eq!(slice.put_slice_at_checked(&[1, 2, 3], 8), None); assert_eq!(slice.buffer_mut(), &[0, 0, 1, 2, 3, 0, 0, 0, 0, 0]);
assert_eq!(slice.remaining_mut(), 10);
}
#[test]
fn test_deref_forward_try_put_slice_at() {
let mut buf = [0u8; 10];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.try_put_slice_at(&[1, 2, 3], 2), Ok(3));
assert_eq!(
slice.try_put_slice_at(&[1, 2, 3], 8),
Err(TryPutAtError::insufficient_space(must_non_zero(3), 2, 8))
);
assert_eq!(slice.buffer_mut(), &[0, 0, 1, 2, 3, 0, 0, 0, 0, 0]);
assert_eq!(slice.remaining_mut(), 10);
}
macro_rules! deref_forward_put {
(@one $($ty:ident),+$(,)?) => {
paste::paste! {
$(
#[test]
fn [< test_deref_forward_put_ $ty >]() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
let written = slice.[< put_ $ty >](42);
assert_eq!(written, 1);
assert_eq!(slice.buffer_mut(), &[42, 0, 0, 0, 0]);
}
#[test]
fn [< test_deref_forward_put_ $ty _checked >]() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.[< put_ $ty _checked >](42), Some(1));
assert_eq!(slice.buffer_mut(), &[42, 0, 0, 0, 0]);
let mut empty: ChunkWriter<&mut [u8]> = ChunkWriter::from(&mut [][..]);
assert_eq!(empty.[< put_ $ty _checked >](42), None); assert_eq!(empty.buffer_mut(), &[]);
}
#[test]
fn [< test_deref_forward_try_put_ $ty >]() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.[< try_put_ $ty >](42), Ok(1));
assert_eq!(slice.buffer_mut(), &[42, 0, 0, 0, 0]);
let mut empty: ChunkWriter<&mut [u8]> = ChunkWriter::from(&mut [][..]);
assert_eq!(empty.[< try_put_ $ty >](42), Err(InsufficientSpace::new(crate::NON_ZERO_1, 0)));
assert_eq!(empty.buffer_mut(), &[]);
}
#[test]
fn [< test_deref_forward_put_ $ty _at >]() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.[< put_ $ty _at >](42, 1), 1);
assert_eq!(slice.buffer_mut(), &[0, 42, 0, 0, 0]);
assert_eq!(slice.remaining_mut(), 5);
}
#[test]
fn [< test_deref_forward_put_ $ty _at_checked >] () {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.[< put_ $ty _at_checked >](42, 1), Some(1));
assert_eq!(slice.buffer_mut(), &[0, 42, 0, 0, 0]);
assert_eq!(slice.remaining_mut(), 5);
assert_eq!(slice.[< put_ $ty _at_checked >](42, 5), None); assert_eq!(slice.buffer_mut(), &[0, 42, 0, 0, 0]);
}
#[test]
fn [< test_deref_forward_try_put_ $ty _at >]() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.[< try_put_ $ty _at >](42, 1), Ok(1));
assert_eq!(slice.buffer_mut(), &[0, 42, 0, 0, 0]);
assert_eq!(slice.remaining_mut(), 5);
assert_eq!(slice.[< try_put_ $ty _at >](42, 5), Err(TryPutAtError::out_of_bounds(5, 5)));
assert_eq!(slice.buffer_mut(), &[0, 42, 0, 0, 0]);
}
)*
}
};
($($ty:ident), +$(,)?) => {
$(deref_forward_put!(le $ty);)*
$(deref_forward_put!(be $ty);)*
$(deref_forward_put!(ne $ty);)*
};
($endian:ident $ty:ident) => {
paste::paste! {
#[test]
fn [< test_deref_forward_put_ $ty _ $endian >]() {
let mut buf = [0u8; size_of::<$ty>()];
let mut slice = ChunkWriter::from(&mut buf[..]);
let written = slice.[< put_ $ty _ $endian >](42 as $ty);
assert_eq!(written, size_of::<$ty>());
assert_eq!(slice.buffer_mut(), (42 as $ty).[< to_ $endian _bytes >]().as_slice());
}
#[test]
fn [< test_deref_forward_put_ $ty _ $endian _checked >]() {
let mut buf = [0u8; size_of::<$ty>()];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.[< put_ $ty _ $endian _checked >](42 as $ty), Some(size_of::<$ty>()));
assert_eq!(slice.buffer_mut(), (42 as $ty).[< to_ $endian _bytes >]().as_slice());
let mut empty: ChunkWriter<&mut [u8]> = ChunkWriter::from(&mut [][..]);
assert_eq!(empty.[< put_ $ty _ $endian _checked >](42 as $ty), None); }
#[test]
fn [< test_deref_forward_try_put_ $ty _ $endian >]() {
let mut buf = [0u8; size_of::<$ty>()];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.[< try_put_ $ty _ $endian >](42 as $ty), Ok(size_of::<$ty>()));
assert_eq!(slice.buffer_mut(), (42 as $ty).[< to_ $endian _bytes >]().as_slice());
let mut empty: ChunkWriter<&mut [u8]> = ChunkWriter::from(&mut [][..]);
assert_eq!(empty.[< try_put_ $ty _ $endian >](42 as $ty), Err(InsufficientSpace::new(must_non_zero(size_of::<$ty>()), 0)));
assert_eq!(empty.buffer_mut(), &[]);
}
#[test]
fn [< test_deref_forward_put_ $ty _ $endian _at >]() {
let mut buf = [0u8; { size_of::<$ty>() + 1 }];
let mut slice = ChunkWriter::from(&mut buf[..]);
let written = slice.[< put_ $ty _ $endian _at >](42 as $ty, 1);
assert_eq!(written, size_of::<$ty>());
assert_eq!(&slice.buffer_mut()[1..], (42 as $ty).[< to_ $endian _bytes >]().as_slice());
}
#[test]
fn [< test_deref_forward_put_ $ty _ $endian _at_checked >]() {
let mut buf = [0u8; { size_of::<$ty>() + 1 }];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.[< put_ $ty _ $endian _at_checked >](42 as $ty, 1), Some(size_of::<$ty>()));
assert_eq!(&slice.buffer_mut()[1..], (42 as $ty).[< to_ $endian _bytes >]().as_slice());
let mut empty: ChunkWriter<&mut [u8]> = ChunkWriter::from(&mut [][..]);
assert_eq!(empty.[< put_ $ty _ $endian _at_checked >](42 as $ty, 0), None); }
#[test]
fn [< test_deref_forward_try_put_ $ty _ $endian _at >]() {
let mut buf = [0u8; { size_of::<$ty>() + 1 }];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.[< try_put_ $ty _ $endian _at >](42 as $ty, 1), Ok(size_of::<$ty>()));
assert_eq!(&slice.buffer_mut()[1..], (42 as $ty).[< to_ $endian _bytes >]().as_slice());
let mut empty: ChunkWriter<&mut [u8]> = ChunkWriter::from(&mut [][..]);
assert_eq!(empty.[< try_put_ $ty _ $endian _at >](42 as $ty, 0), Err(TryPutAtError::out_of_bounds(0, 0)));
assert_eq!(empty.buffer_mut(), &[]);
}
}
};
}
deref_forward_put! {
@one u8, i8
}
deref_forward_put! {
u16, u32, u64, u128,
i16, i32, i64, i128,
f32, f64
}
#[test]
fn test_deref_forward_write_slice() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
let written = slice.write_slice(&[1, 2, 3]);
assert_eq!(written, 3);
assert_eq!(slice.buffer_mut(), &[0, 0]);
assert_eq!(slice.remaining_mut(), 2); assert_eq!(buf, [1, 2, 3, 0, 0]);
}
#[test]
fn test_deref_forward_write_slice_checked() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.write_slice_checked(&[1, 2, 3]), Some(3));
assert_eq!(slice.write_slice_checked(&[1, 2, 3, 4, 5, 6]), None); assert_eq!(slice.buffer_mut(), &[0, 0]);
assert_eq!(slice.remaining_mut(), 2);
assert_eq!(buf, [1, 2, 3, 0, 0]);
}
#[test]
fn test_deref_forward_try_write_slice() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.try_write_slice(&[1, 2, 3]), Ok(3));
assert_eq!(slice.buffer_mut(), &[0, 0]);
assert_eq!(slice.remaining_mut(), 2);
let err = slice.try_write_slice(&[1, 2, 3, 4, 5, 6]);
assert!(err.is_err()); assert_eq!(
err.unwrap_err(),
InsufficientSpace::new(must_non_zero(6), 2)
);
assert_eq!(slice.buffer_mut(), &[0, 0]);
assert_eq!(slice.remaining_mut(), 2);
assert_eq!(buf, [1, 2, 3, 0, 0]);
}
macro_rules! deref_forward_write {
(@one $($ty:ident),+$(,)?) => {
paste::paste! {
$(
#[test]
fn [< test_deref_forward_write_ $ty >]() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
let written = slice.[< write_ $ty >](42);
assert_eq!(written, 1);
assert_eq!(slice.buffer_mut(), &[0, 0, 0, 0]);
}
#[test]
fn [< test_deref_forward_write_ $ty _checked >]() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.[< write_ $ty _checked >](42), Some(1));
assert_eq!(slice.buffer_mut(), &[0, 0, 0, 0]);
let mut empty: ChunkWriter<&mut [u8]> = ChunkWriter::from(&mut [][..]);
assert_eq!(empty.[< write_ $ty _checked >](42), None); assert_eq!(empty.buffer_mut(), &[]);
}
#[test]
fn [< test_deref_forward_try_write_ $ty >]() {
let mut buf = [0u8; 5];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.[< try_write_ $ty >](42), Ok(1));
assert_eq!(slice.buffer_mut(), &[0, 0, 0, 0]);
let mut empty: ChunkWriter<&mut [u8]> = ChunkWriter::from(&mut [][..]);
assert_eq!(empty.[< try_write_ $ty >](42), Err(InsufficientSpace::new(crate::NON_ZERO_1, 0)));
assert_eq!(empty.buffer_mut(), &[]);
}
)*
}
};
($($ty:ident), +$(,)?) => {
$(deref_forward_write!(le $ty);)*
$(deref_forward_write!(be $ty);)*
$(deref_forward_write!(ne $ty);)*
};
($endian:ident $ty:ident) => {
paste::paste! {
#[test]
fn [< test_deref_forward_write_ $ty _ $endian >]() {
let mut buf = [0u8; size_of::<$ty>()];
let mut slice = ChunkWriter::from(&mut buf[..]);
let written = slice.[< write_ $ty _ $endian >](42 as $ty);
assert_eq!(written, size_of::<$ty>());
assert_eq!(slice.buffer_mut(), &[]);
assert_eq!(buf, (42 as $ty).[< to_ $endian _bytes >]().as_slice());
}
#[test]
fn [< test_deref_forward_write_ $ty _ $endian _checked >]() {
let mut buf = [0u8; size_of::<$ty>()];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.[< write_ $ty _ $endian _checked >](42 as $ty), Some(size_of::<$ty>()));
assert_eq!(slice.buffer_mut(), &[]);
assert_eq!(buf, (42 as $ty).[< to_ $endian _bytes >]().as_slice());
let mut empty: ChunkWriter<&mut [u8]> = ChunkWriter::from(&mut [][..]);
assert_eq!(empty.[< write_ $ty _ $endian _checked >](42 as $ty), None); assert_eq!(empty.buffer_mut(), &[]);
}
#[test]
fn [< test_deref_forward_try_write_ $ty _ $endian >]() {
let mut buf = [0u8; size_of::<$ty>()];
let mut slice = ChunkWriter::from(&mut buf[..]);
assert_eq!(slice.[< try_write_ $ty _ $endian >](42 as $ty), Ok(size_of::<$ty>()));
assert_eq!(slice.buffer_mut(), &[]);
assert_eq!(buf, (42 as $ty).[< to_ $endian _bytes >]().as_slice());
let mut empty: ChunkWriter<&mut [u8]> = ChunkWriter::from(&mut [][..]);
assert_eq!(empty.[< try_write_ $ty _ $endian >](42 as $ty), Err(InsufficientSpace::new(must_non_zero(size_of::<$ty>()), 0)));
assert_eq!(empty.buffer_mut(), &[]);
}
}
};
}
deref_forward_write! {
@one u8, i8
}
deref_forward_write! {
u16, u32, u64, u128,
i16, i32, i64, i128,
f32, f64
}
}