use core::fmt;
use core::convert::Infallible;
#[cfg(feature = "bytes")] use bytes::{Bytes, BytesMut};
#[cfg(feature = "std")] use std::borrow::Cow;
#[cfg(feature = "std")] use std::vec::Vec;
pub trait OctetsBuilder {
type AppendError: Into<ShortBuf>;
fn append_slice(
&mut self, slice: &[u8]
) -> Result<(), Self::AppendError>;
}
impl<'a, T: OctetsBuilder> OctetsBuilder for &'a mut T {
type AppendError = T::AppendError;
fn append_slice(
&mut self, slice: &[u8]
) -> Result<(), Self::AppendError> {
(*self).append_slice(slice)
}
}
#[cfg(feature = "std")]
impl OctetsBuilder for Vec<u8> {
type AppendError = Infallible;
fn append_slice(
&mut self, slice: &[u8]
) -> Result<(), Self::AppendError> {
self.extend_from_slice(slice);
Ok(())
}
}
#[cfg(feature = "std")]
impl<'a> OctetsBuilder for Cow<'a, [u8]> {
type AppendError = Infallible;
fn append_slice(
&mut self, slice: &[u8]
) -> Result<(), Self::AppendError> {
if let Cow::Owned(ref mut vec) = *self {
vec.extend_from_slice(slice);
} else {
let mut vec = std::mem::replace(
self, Cow::Borrowed(b"")
).into_owned();
vec.extend_from_slice(slice);
*self = Cow::Owned(vec);
}
Ok(())
}
}
#[cfg(feature = "bytes")]
impl OctetsBuilder for BytesMut {
type AppendError = Infallible;
fn append_slice(
&mut self, slice: &[u8]
) -> Result<(), Self::AppendError> {
self.extend_from_slice(slice);
Ok(())
}
}
#[cfg(feature = "smallvec")]
impl<A: smallvec::Array<Item = u8>> OctetsBuilder for smallvec::SmallVec<A> {
type AppendError = Infallible;
fn append_slice(
&mut self, slice: &[u8]
) -> Result<(), Self::AppendError> {
self.extend_from_slice(slice);
Ok(())
}
}
#[cfg(feature = "heapless")]
impl<const N: usize> OctetsBuilder for heapless::Vec<u8, N> {
type AppendError = ShortBuf;
fn append_slice(
&mut self, slice: &[u8]
) -> Result<(), Self::AppendError> {
self.extend_from_slice(slice).map_err(|_| ShortBuf)
}
}
pub trait Truncate {
fn truncate(&mut self, len: usize);
}
impl<'a, T: Truncate> Truncate for &'a mut T {
fn truncate(&mut self, len: usize) {
(*self).truncate(len)
}
}
impl<'a> Truncate for &'a [u8] {
fn truncate(&mut self, len: usize) {
if len < self.len() {
*self = &self[..len]
}
}
}
#[cfg(feature = "std")]
impl<'a> Truncate for Cow<'a, [u8]> {
fn truncate(&mut self, len: usize) {
match *self {
Cow::Borrowed(ref mut slice) => *slice = &slice[..len],
Cow::Owned(ref mut vec) => vec.truncate(len),
}
}
}
#[cfg(feature = "std")]
impl Truncate for Vec<u8> {
fn truncate(&mut self, len: usize) {
self.truncate(len)
}
}
#[cfg(feature = "bytes")]
impl Truncate for Bytes {
fn truncate(&mut self, len: usize) {
self.truncate(len)
}
}
#[cfg(feature = "bytes")]
impl Truncate for BytesMut {
fn truncate(&mut self, len: usize) {
self.truncate(len)
}
}
#[cfg(feature = "smallvec")]
impl<A: smallvec::Array<Item = u8>> Truncate for smallvec::SmallVec<A> {
fn truncate(&mut self, len: usize) {
self.truncate(len)
}
}
#[cfg(feature = "heapless")]
impl<const N: usize> Truncate for heapless::Vec<u8, N> {
fn truncate(&mut self, len: usize) {
self.truncate(len)
}
}
pub trait EmptyBuilder {
fn empty() -> Self;
fn with_capacity(capacity: usize) -> Self;
}
#[cfg(feature = "std")]
impl EmptyBuilder for Vec<u8> {
fn empty() -> Self {
Vec::new()
}
fn with_capacity(capacity: usize) -> Self {
Vec::with_capacity(capacity)
}
}
#[cfg(feature = "bytes")]
impl EmptyBuilder for BytesMut {
fn empty() -> Self {
BytesMut::new()
}
fn with_capacity(capacity: usize) -> Self {
BytesMut::with_capacity(capacity)
}
}
#[cfg(feature = "smallvec")]
impl<A: smallvec::Array<Item = u8>> EmptyBuilder for smallvec::SmallVec<A> {
fn empty() -> Self {
smallvec::SmallVec::new()
}
fn with_capacity(capacity: usize) -> Self {
smallvec::SmallVec::with_capacity(capacity)
}
}
#[cfg(feature = "heapless")]
impl<const N: usize> EmptyBuilder for heapless::Vec<u8, N> {
fn empty() -> Self {
Self::new()
}
fn with_capacity(capacity: usize) -> Self {
debug_assert!(capacity <= N);
heapless::Vec::new()
}
}
pub trait FreezeBuilder {
type Octets;
fn freeze(self) -> Self::Octets;
}
#[cfg(feature = "std")]
impl FreezeBuilder for Vec<u8> {
type Octets = Self;
fn freeze(self) -> Self::Octets {
self
}
}
#[cfg(feature = "std")]
impl<'a> FreezeBuilder for Cow<'a, [u8]> {
type Octets = Self;
fn freeze(self) -> Self::Octets {
self
}
}
#[cfg(feature = "bytes")]
impl FreezeBuilder for BytesMut {
type Octets = Bytes;
fn freeze(self) -> Self::Octets {
BytesMut::freeze(self)
}
}
#[cfg(feature = "smallvec")]
impl<A: smallvec::Array<Item = u8>> FreezeBuilder for smallvec::SmallVec<A> {
type Octets = Self;
fn freeze(self) -> Self::Octets {
self
}
}
#[cfg(feature = "heapless")]
impl<const N: usize> FreezeBuilder for heapless::Vec<u8, N> {
type Octets = Self;
fn freeze(self) -> Self::Octets {
self
}
}
pub trait IntoBuilder {
type Builder: OctetsBuilder;
fn into_builder(self) -> Self::Builder;
}
#[cfg(feature = "std")]
impl IntoBuilder for Vec<u8> {
type Builder = Self;
fn into_builder(self) -> Self::Builder {
self
}
}
#[cfg(feature = "std")]
impl<'a> IntoBuilder for &'a [u8] {
type Builder = Vec<u8>;
fn into_builder(self) -> Self::Builder {
self.into()
}
}
#[cfg(feature = "std")]
impl<'a> IntoBuilder for Cow<'a, [u8]> {
type Builder = Self;
fn into_builder(self) -> Self::Builder {
self
}
}
#[cfg(feature = "bytes")]
impl IntoBuilder for Bytes {
type Builder = BytesMut;
fn into_builder(self) -> Self::Builder {
BytesMut::from(self.as_ref())
}
}
#[cfg(feature = "smallvec")]
impl<A: smallvec::Array<Item = u8>> IntoBuilder for smallvec::SmallVec<A> {
type Builder = Self;
fn into_builder(self) -> Self::Builder {
self
}
}
#[cfg(feature = "heapless")]
impl<const N: usize> IntoBuilder for heapless::Vec<u8, N> {
type Builder = Self;
fn into_builder(self) -> Self::Builder {
self
}
}
pub trait FromBuilder: AsRef<[u8]> + Sized {
type Builder: OctetsBuilder + FreezeBuilder<Octets = Self>;
fn from_builder(builder: Self::Builder) -> Self;
}
#[cfg(feature = "std")]
impl FromBuilder for Vec<u8> {
type Builder = Self;
fn from_builder(builder: Self::Builder) -> Self {
builder
}
}
#[cfg(feature = "std")]
impl<'a> FromBuilder for Cow<'a, [u8]> {
type Builder = Self;
fn from_builder(builder: Self::Builder) -> Self {
builder
}
}
#[cfg(feature = "bytes")]
impl FromBuilder for Bytes {
type Builder = BytesMut;
fn from_builder(builder: Self::Builder) -> Self {
builder.freeze()
}
}
#[cfg(feature = "smallvec")]
impl<A: smallvec::Array<Item = u8>> FromBuilder for smallvec::SmallVec<A> {
type Builder = Self;
fn from_builder(builder: Self::Builder) -> Self {
builder
}
}
#[cfg(feature = "heapless")]
impl<const N: usize> FromBuilder for heapless::Vec<u8, N> {
type Builder = Self;
fn from_builder(builder: Self::Builder) -> Self {
builder
}
}
pub type BuilderAppendError<Octets>
= <<Octets as FromBuilder>::Builder as OctetsBuilder>::AppendError;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ShortBuf;
impl From<Infallible> for ShortBuf {
fn from(_: Infallible) -> ShortBuf {
unreachable!()
}
}
impl fmt::Display for ShortBuf {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("buffer size exceeded")
}
}
#[cfg(feature = "std")]
impl std::error::Error for ShortBuf {}
pub fn infallible<T, E: Into<Infallible>>(src: Result<T, E>) -> T {
match src {
Ok(ok) => ok,
Err(_) => unreachable!(),
}
}
pub fn with_infallible<F, T, E>(op: F) -> T
where
F: FnOnce() -> Result<T, E>,
E: Into<Infallible>,
{
infallible(op())
}