use core::{mem, slice, str};
pub trait DecodeBuf {
type Output;
unsafe fn allocate(&mut self, len: usize) -> *mut u8;
unsafe fn commit(self, len: usize) -> Self::Output;
}
impl<'a, const N: usize> DecodeBuf for &'a mut mem::MaybeUninit<[u8; N]> {
type Output = &'a [u8];
unsafe fn allocate(&mut self, len: usize) -> *mut u8 {
if len > N {
buffer_too_small();
}
self.as_mut_ptr() as *mut u8
}
unsafe fn commit(self, len: usize) -> Self::Output {
debug_assert!(len <= N);
slice::from_raw_parts(self.as_ptr() as *const u8, len)
}
}
impl<'a, const N: usize> DecodeBuf for &'a mut [mem::MaybeUninit<u8>; N] {
type Output = &'a [u8];
unsafe fn allocate(&mut self, len: usize) -> *mut u8 {
if len > N {
buffer_too_small();
}
self.as_mut_ptr() as *mut u8
}
unsafe fn commit(self, len: usize) -> Self::Output {
debug_assert!(len <= N);
slice::from_raw_parts(self.as_ptr() as *const u8, len)
}
}
impl<'a, const N: usize> DecodeBuf for &'a mut [u8; N] {
type Output = &'a [u8];
unsafe fn allocate(&mut self, len: usize) -> *mut u8 {
if len > N {
buffer_too_small();
}
self.as_mut_ptr()
}
unsafe fn commit(self, len: usize) -> Self::Output {
debug_assert!(len <= N);
slice::from_raw_parts(self.as_ptr(), len)
}
}
impl<'a> DecodeBuf for &'a mut [mem::MaybeUninit<u8>] {
type Output = &'a [u8];
unsafe fn allocate(&mut self, len: usize) -> *mut u8 {
if len > self.len() {
buffer_too_small();
}
self.as_mut_ptr() as *mut u8
}
unsafe fn commit(self, len: usize) -> Self::Output {
debug_assert!(len <= self.len());
slice::from_raw_parts(self.as_ptr() as *const u8, len)
}
}
impl<'a> DecodeBuf for &'a mut [u8] {
type Output = &'a [u8];
unsafe fn allocate(&mut self, len: usize) -> *mut u8 {
if len > self.len() {
buffer_too_small();
}
self.as_mut_ptr()
}
unsafe fn commit(self, len: usize) -> Self::Output {
debug_assert!(len <= self.len());
slice::from_raw_parts(self.as_ptr(), len)
}
}
#[cfg(any(test, feature = "std"))]
impl DecodeBuf for ::std::vec::Vec<u8> {
type Output = ::std::vec::Vec<u8>;
unsafe fn allocate(&mut self, len: usize) -> *mut u8 {
self.reserve(len);
self.as_mut_ptr().add(self.len())
}
unsafe fn commit(mut self, len: usize) -> Self::Output {
let new_len = self.len() + len;
self.set_len(new_len);
self
}
}
#[cfg(any(test, feature = "std"))]
impl<'a> DecodeBuf for &'a mut ::std::vec::Vec<u8> {
type Output = &'a [u8];
unsafe fn allocate(&mut self, len: usize) -> *mut u8 {
self.reserve(len);
self.as_mut_ptr().add(self.len())
}
unsafe fn commit(self, len: usize) -> Self::Output {
let start = self.len();
self.set_len(start + len);
slice::from_raw_parts(self.as_ptr().add(start), len)
}
}
pub trait EncodeBuf {
type Output;
unsafe fn allocate(&mut self, len: usize) -> *mut u8;
unsafe fn commit(self, len: usize) -> Self::Output;
}
impl<'a, const N: usize> EncodeBuf for &'a mut mem::MaybeUninit<[u8; N]> {
type Output = &'a str;
unsafe fn allocate(&mut self, len: usize) -> *mut u8 {
if len > N {
buffer_too_small();
}
self.as_mut_ptr() as *mut u8
}
unsafe fn commit(self, len: usize) -> Self::Output {
debug_assert!(len <= N);
let bytes = slice::from_raw_parts(self.as_ptr() as *const u8, len);
str::from_utf8_unchecked(bytes)
}
}
impl<'a, const N: usize> EncodeBuf for &'a mut [mem::MaybeUninit<u8>; N] {
type Output = &'a str;
unsafe fn allocate(&mut self, len: usize) -> *mut u8 {
if len > N {
buffer_too_small();
}
self.as_mut_ptr() as *mut u8
}
unsafe fn commit(self, len: usize) -> Self::Output {
debug_assert!(len <= N);
let bytes = slice::from_raw_parts(self.as_ptr() as *const u8, len);
str::from_utf8_unchecked(bytes)
}
}
impl<'a, const N: usize> EncodeBuf for &'a mut [u8; N] {
type Output = &'a str;
unsafe fn allocate(&mut self, len: usize) -> *mut u8 {
if len > N {
buffer_too_small();
}
self.as_mut_ptr()
}
unsafe fn commit(self, len: usize) -> Self::Output {
debug_assert!(len <= N);
let bytes = slice::from_raw_parts(self.as_ptr(), len);
str::from_utf8_unchecked(bytes)
}
}
impl<'a> EncodeBuf for &'a mut [mem::MaybeUninit<u8>] {
type Output = &'a str;
unsafe fn allocate(&mut self, len: usize) -> *mut u8 {
if len > self.len() {
buffer_too_small();
}
self.as_mut_ptr() as *mut u8
}
unsafe fn commit(self, len: usize) -> Self::Output {
debug_assert!(len <= self.len());
let bytes = slice::from_raw_parts(self.as_ptr() as *const u8, len);
str::from_utf8_unchecked(bytes)
}
}
impl<'a> EncodeBuf for &'a mut [u8] {
type Output = &'a str;
unsafe fn allocate(&mut self, len: usize) -> *mut u8 {
if len > self.len() {
buffer_too_small();
}
self.as_mut_ptr()
}
unsafe fn commit(self, len: usize) -> Self::Output {
debug_assert!(len <= self.len());
let bytes = slice::from_raw_parts(self.as_ptr(), len);
str::from_utf8_unchecked(bytes)
}
}
#[cfg(any(test, feature = "std"))]
impl EncodeBuf for ::std::string::String {
type Output = ::std::string::String;
unsafe fn allocate(&mut self, len: usize) -> *mut u8 {
let vec = self.as_mut_vec();
vec.reserve(len);
vec.as_mut_ptr().add(vec.len())
}
unsafe fn commit(mut self, len: usize) -> Self::Output {
{
let vec = self.as_mut_vec();
let new_len = vec.len() + len;
vec.set_len(new_len);
}
self
}
}
#[cfg(any(test, feature = "std"))]
impl<'a> EncodeBuf for &'a mut ::std::string::String {
type Output = &'a str;
unsafe fn allocate(&mut self, len: usize) -> *mut u8 {
let vec = self.as_mut_vec();
vec.reserve(len);
vec.as_mut_ptr().add(vec.len())
}
unsafe fn commit(self, len: usize) -> Self::Output {
let vec = self.as_mut_vec();
let start = vec.len();
vec.set_len(start + len);
let bytes = slice::from_raw_parts(vec.as_ptr().add(start), len);
str::from_utf8_unchecked(bytes)
}
}
#[cfg(any(test, feature = "std"))]
impl<'a> EncodeBuf for &'a mut ::std::vec::Vec<u8> {
type Output = &'a str;
unsafe fn allocate(&mut self, len: usize) -> *mut u8 {
self.reserve(len);
self.as_mut_ptr().add(self.len())
}
unsafe fn commit(self, len: usize) -> Self::Output {
let start = self.len();
self.set_len(start + len);
let bytes = slice::from_raw_parts(self.as_ptr().add(start), len);
str::from_utf8_unchecked(bytes)
}
}
#[cold]
const fn buffer_too_small() {
panic!("buffer too small");
}