#![allow(clippy::result_unit_err)]
use core::{mem::MaybeUninit, ops::Deref};
pub trait PbString {
unsafe fn pb_set_len(&mut self, len: usize);
fn pb_reserve(&mut self, _additional: usize) {}
fn pb_clear(&mut self);
fn pb_spare_cap(&mut self) -> &mut [MaybeUninit<u8>];
}
impl<T: PbString> PbString for &mut T {
unsafe fn pb_set_len(&mut self, len: usize) {
(*self).pb_set_len(len);
}
fn pb_clear(&mut self) {
(*self).pb_clear();
}
fn pb_spare_cap(&mut self) -> &mut [MaybeUninit<u8>] {
(*self).pb_spare_cap()
}
fn pb_reserve(&mut self, additional: usize) {
(*self).pb_reserve(additional);
}
}
pub trait PbBytes: PbString {}
impl<T: PbBytes> PbBytes for &mut T {}
pub trait PbVec<T> {
fn pb_push(&mut self, elem: T) -> Result<(), ()>;
}
impl<T, V: PbVec<T>> PbVec<T> for &mut V {
fn pb_push(&mut self, elem: T) -> Result<(), ()> {
(*self).pb_push(elem)
}
}
pub trait PbMap<K, V> {
fn pb_insert(&mut self, key: K, val: V) -> Result<(), ()>;
}
impl<K, V, M: PbMap<K, V>> PbMap<K, V> for &mut M {
fn pb_insert(&mut self, key: K, val: V) -> Result<(), ()> {
(*self).pb_insert(key, val)
}
}
pub(crate) mod impl_fixed_len {
use core::{array::TryFromSliceError, ops::DerefMut};
use super::*;
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct FixedLenString<const N: usize>([u8; N]);
impl<const N: usize> Default for FixedLenString<N> {
#[inline]
fn default() -> Self {
Self([0; N])
}
}
impl<const N: usize> PbString for FixedLenString<N> {
#[inline]
unsafe fn pb_set_len(&mut self, _len: usize) {}
#[inline]
fn pb_clear(&mut self) {
self.0 = [0; N];
}
#[inline]
fn pb_spare_cap(&mut self) -> &mut [MaybeUninit<u8>] {
unsafe {
core::slice::from_raw_parts_mut(self.0.as_mut_ptr() as *mut MaybeUninit<u8>, N)
}
}
}
impl<const N: usize> Deref for FixedLenString<N> {
type Target = str;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { core::str::from_utf8_unchecked(self.0.as_slice()) }
}
}
impl<const N: usize> DerefMut for FixedLenString<N> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { core::str::from_utf8_unchecked_mut(self.0.as_mut_slice()) }
}
}
impl<const N: usize> AsRef<str> for FixedLenString<N> {
fn as_ref(&self) -> &str {
self
}
}
impl<const N: usize> AsMut<str> for FixedLenString<N> {
fn as_mut(&mut self) -> &mut str {
self
}
}
impl<const N: usize> TryFrom<&str> for FixedLenString<N> {
type Error = TryFromSliceError;
fn try_from(s: &str) -> Result<Self, Self::Error> {
Ok(Self(s.as_bytes().try_into()?))
}
}
impl<const N: usize> From<FixedLenString<N>> for [u8; N] {
fn from(value: FixedLenString<N>) -> Self {
value.0
}
}
impl<const N: usize> PbBytes for [u8; N] {}
impl<const N: usize> PbString for [u8; N] {
#[inline]
unsafe fn pb_set_len(&mut self, _len: usize) {}
#[inline]
fn pb_clear(&mut self) {}
#[inline]
fn pb_spare_cap(&mut self) -> &mut [MaybeUninit<u8>] {
unsafe { core::slice::from_raw_parts_mut(self.as_mut_ptr() as *mut MaybeUninit<u8>, N) }
}
}
}
#[cfg(feature = "container-arrayvec-0-7")]
mod impl_arrayvec {
use core::ops::DerefMut;
use super::*;
use arrayvec::{ArrayString, ArrayVec};
impl<const N: usize> PbBytes for ArrayVec<u8, N> {}
impl<const N: usize> PbString for ArrayVec<u8, N> {
#[inline]
unsafe fn pb_set_len(&mut self, len: usize) {
self.set_len(len)
}
#[inline]
fn pb_clear(&mut self) {
self.clear()
}
#[inline]
fn pb_spare_cap(&mut self) -> &mut [MaybeUninit<u8>] {
let len = self.len();
let slice = unsafe {
core::slice::from_raw_parts_mut(self.as_mut_ptr() as *mut MaybeUninit<u8>, N)
};
slice.get_mut(len..).unwrap_or(&mut [])
}
}
impl<const N: usize> PbString for ArrayString<N> {
#[inline]
unsafe fn pb_set_len(&mut self, len: usize) {
self.set_len(len)
}
#[inline]
fn pb_clear(&mut self) {
self.clear()
}
#[inline]
fn pb_spare_cap(&mut self) -> &mut [MaybeUninit<u8>] {
let len = self.len();
self.clear();
let s = self.deref_mut().as_mut_ptr();
let slice = unsafe { core::slice::from_raw_parts_mut(s as *mut MaybeUninit<u8>, N) };
slice.get_mut(len..).unwrap_or(&mut [])
}
}
impl<T, const N: usize> PbVec<T> for ArrayVec<T, N> {
#[inline]
fn pb_push(&mut self, elem: T) -> Result<(), ()> {
self.try_push(elem).map_err(drop)
}
}
}
#[allow(unused)]
macro_rules! impl_heapless {
($mod_name:ident, $pkg_name:ident) => {
mod $mod_name {
use super::*;
use core::hash::{BuildHasher, Hash};
use $pkg_name::{IndexMap, String, Vec};
impl<const N: usize> PbBytes for Vec<u8, N> {}
impl<const N: usize> PbString for Vec<u8, N> {
#[inline]
fn pb_clear(&mut self) {
self.clear()
}
#[inline]
unsafe fn pb_set_len(&mut self, len: usize) {
self.set_len(len)
}
#[inline]
fn pb_spare_cap(&mut self) -> &mut [MaybeUninit<u8>] {
let len = self.len();
let slice = unsafe {
core::slice::from_raw_parts_mut(self.as_mut_ptr() as *mut MaybeUninit<u8>, N)
};
slice.get_mut(len..).unwrap_or(&mut [])
}
}
impl<const N: usize> PbString for String<N> {
#[inline]
fn pb_clear(&mut self) {
self.clear()
}
#[inline]
unsafe fn pb_set_len(&mut self, len: usize) {
self.as_mut_vec().set_len(len)
}
#[inline]
fn pb_spare_cap(&mut self) -> &mut [MaybeUninit<u8>] {
let len = self.len();
let slice = unsafe {
core::slice::from_raw_parts_mut(
self.as_mut_vec().as_mut_ptr() as *mut MaybeUninit<u8>,
N,
)
};
slice.get_mut(len..).unwrap_or(&mut [])
}
}
impl<T, const N: usize> PbVec<T> for Vec<T, N> {
#[inline]
fn pb_push(&mut self, elem: T) -> Result<(), ()> {
self.push(elem).map_err(drop)
}
}
impl<K: Eq + Hash, V, S: BuildHasher, const N: usize> PbMap<K, V> for IndexMap<K, V, S, N> {
#[inline]
fn pb_insert(&mut self, key: K, val: V) -> Result<(), ()> {
self.insert(key, val).map_err(drop)?;
Ok(())
}
}
}
};
}
#[cfg(feature = "container-heapless-0-8")]
impl_heapless!(impl_heapless_0_8, heapless_0_8);
#[cfg(feature = "container-heapless-0-9")]
impl_heapless!(impl_heapless_0_9, heapless_0_9);
#[cfg(feature = "alloc")]
mod impl_alloc {
use super::*;
use alloc::{borrow::Cow, collections::BTreeMap, string::String, vec::Vec};
impl PbBytes for Vec<u8> {}
impl PbString for Vec<u8> {
#[inline]
fn pb_clear(&mut self) {
self.clear()
}
#[inline]
unsafe fn pb_set_len(&mut self, len: usize) {
self.set_len(len)
}
#[inline]
fn pb_reserve(&mut self, additional: usize) {
self.reserve(additional)
}
#[inline]
fn pb_spare_cap(&mut self) -> &mut [MaybeUninit<u8>] {
self.spare_capacity_mut()
}
}
impl PbBytes for Cow<'_, [u8]> {}
impl PbString for Cow<'_, [u8]> {
#[inline]
unsafe fn pb_set_len(&mut self, len: usize) {
self.to_mut().set_len(len);
}
#[inline]
fn pb_clear(&mut self) {
self.to_mut().clear()
}
#[inline]
fn pb_reserve(&mut self, additional: usize) {
self.to_mut().reserve(additional)
}
#[inline]
fn pb_spare_cap(&mut self) -> &mut [MaybeUninit<u8>] {
self.to_mut().spare_capacity_mut()
}
}
impl PbString for String {
#[inline]
fn pb_clear(&mut self) {
self.clear()
}
#[inline]
unsafe fn pb_set_len(&mut self, len: usize) {
self.as_mut_vec().set_len(len)
}
#[inline]
fn pb_reserve(&mut self, additional: usize) {
self.reserve(additional)
}
#[inline]
fn pb_spare_cap(&mut self) -> &mut [MaybeUninit<u8>] {
unsafe { self.as_mut_vec().spare_capacity_mut() }
}
}
impl PbString for Cow<'_, str> {
#[inline]
unsafe fn pb_set_len(&mut self, len: usize) {
self.to_mut().as_mut_vec().set_len(len);
}
#[inline]
fn pb_clear(&mut self) {
self.to_mut().clear()
}
#[inline]
fn pb_reserve(&mut self, additional: usize) {
self.to_mut().reserve(additional)
}
#[inline]
fn pb_spare_cap(&mut self) -> &mut [MaybeUninit<u8>] {
unsafe { self.to_mut().as_mut_vec() }.spare_capacity_mut()
}
}
impl<T> PbVec<T> for Vec<T> {
#[inline]
fn pb_push(&mut self, elem: T) -> Result<(), ()> {
self.push(elem);
Ok(())
}
}
impl<T> PbVec<T> for Cow<'_, [T]>
where
[T]: alloc::borrow::ToOwned<Owned = Vec<T>>,
{
fn pb_push(&mut self, elem: T) -> Result<(), ()> {
self.to_mut().push(elem);
Ok(())
}
}
impl<K: Ord, V> PbMap<K, V> for BTreeMap<K, V> {
#[inline]
fn pb_insert(&mut self, key: K, val: V) -> Result<(), ()> {
self.insert(key, val);
Ok(())
}
}
#[cfg(feature = "std")]
impl<K: Eq + core::hash::Hash, V> PbMap<K, V> for std::collections::HashMap<K, V> {
#[inline]
fn pb_insert(&mut self, key: K, val: V) -> Result<(), ()> {
self.insert(key, val);
Ok(())
}
}
}