use core::convert::Infallible;
use core::ops::{Index, RangeBounds};
#[cfg(feature = "bytes")] use bytes::{Bytes, BytesMut};
#[cfg(feature = "std")] use std::borrow::Cow;
#[cfg(feature = "std")] use std::vec::Vec;
use crate::builder::ShortBuf;
pub trait Octets: AsRef<[u8]> {
type Range<'a>: Octets where Self: 'a;
fn range(&self, range: impl RangeBounds<usize>) -> Self::Range<'_>;
}
impl<'t, T: Octets + ?Sized> Octets for &'t T {
type Range<'a> = <T as Octets>::Range<'t> where Self: 'a;
fn range(&self, range: impl RangeBounds<usize>) -> Self::Range<'_> {
(*self).range(range)
}
}
impl Octets for [u8] {
type Range<'a> = &'a [u8];
fn range(&self, range: impl RangeBounds<usize>) -> Self::Range<'_> {
self.index(
(range.start_bound().cloned(), range.end_bound().cloned())
)
}
}
#[cfg(feature = "std")]
impl<'c> Octets for Cow<'c, [u8]> {
type Range<'a> = &'a [u8] where Self: 'a;
fn range(&self, range: impl RangeBounds<usize>) -> Self::Range<'_> {
self.as_ref().range(range)
}
}
#[cfg(feature = "std")]
impl Octets for Vec<u8> {
type Range<'a> = &'a [u8];
fn range(&self, range: impl RangeBounds<usize>) -> Self::Range<'_> {
self.as_slice().range(range)
}
}
#[cfg(feature = "std")]
impl Octets for std::sync::Arc<[u8]> {
type Range<'a> = &'a [u8];
fn range(&self, range: impl RangeBounds<usize>) -> Self::Range<'_> {
self.as_ref().range(range)
}
}
#[cfg(feature = "bytes")]
impl Octets for Bytes {
type Range<'a> = Bytes;
fn range(&self, range: impl RangeBounds<usize>) -> Self::Range<'_> {
self.slice(range)
}
}
#[cfg(feature = "smallvec")]
impl<A: smallvec::Array<Item = u8>> Octets for smallvec::SmallVec<A> {
type Range<'a> = &'a [u8] where A: 'a;
fn range(&self, range: impl RangeBounds<usize>) -> Self::Range<'_> {
self.as_slice().range(range)
}
}
#[cfg(feature = "heapless")]
impl<const N: usize> Octets for heapless::Vec<u8, N> {
type Range<'a> = &'a [u8] where Self: 'a;
fn range(&self, range: impl RangeBounds<usize>) -> Self::Range<'_> {
self.index(
(range.start_bound().cloned(), range.end_bound().cloned())
)
}
}
pub trait OctetsFrom<Source>: Sized {
type Error: Into<ShortBuf>;
fn try_octets_from(source: Source) -> Result<Self, Self::Error>;
fn octets_from(source: Source) -> Self
where Self::Error: Into<Infallible> {
match Self::try_octets_from(source) {
Ok(ok) => ok,
Err(_) => unreachable!()
}
}
}
impl<'a, Source: AsRef<[u8]> + 'a> OctetsFrom<&'a Source> for &'a [u8] {
type Error = Infallible;
fn try_octets_from(source: &'a Source) -> Result<Self, Self::Error> {
Ok(source.as_ref())
}
}
#[cfg(feature = "std")]
impl<Source> OctetsFrom<Source> for Vec<u8>
where
Self: From<Source>,
{
type Error = Infallible;
fn try_octets_from(source: Source) -> Result<Self, Self::Error> {
Ok(From::from(source))
}
}
#[cfg(feature = "bytes")]
impl<Source> OctetsFrom<Source> for Bytes
where
Self: From<Source>,
{
type Error = Infallible;
fn try_octets_from(source: Source) -> Result<Self, Self::Error> {
Ok(From::from(source))
}
}
#[cfg(feature = "bytes")]
impl<Source> OctetsFrom<Source> for BytesMut
where
Self: From<Source>,
{
type Error = Infallible;
fn try_octets_from(source: Source) -> Result<Self, Self::Error> {
Ok(From::from(source))
}
}
#[cfg(feature = "smallvec")]
impl<Source, A> OctetsFrom<Source> for smallvec::SmallVec<A>
where
Source: AsRef<[u8]>,
A: smallvec::Array<Item = u8>,
{
type Error = Infallible;
fn try_octets_from(source: Source) -> Result<Self, Self::Error> {
Ok(smallvec::ToSmallVec::to_smallvec(source.as_ref()))
}
}
#[cfg(feature = "heapless")]
impl<Source, const N: usize> OctetsFrom<Source> for heapless::Vec<u8, N>
where
Source: AsRef<[u8]>,
{
type Error = ShortBuf;
fn try_octets_from(source: Source) -> Result<Self, ShortBuf> {
heapless::Vec::from_slice(source.as_ref()).map_err(|_| ShortBuf)
}
}
pub trait OctetsInto<Target>: Sized {
type Error: Into<ShortBuf>;
fn try_octets_into(self) -> Result<Target, Self::Error>;
fn octets_into(self) -> Target
where Self::Error: Into<Infallible> {
match self.try_octets_into() {
Ok(ok) => ok,
Err(_) => unreachable!()
}
}
}
impl<Source, Target: OctetsFrom<Source>> OctetsInto<Target> for Source {
type Error = <Target as OctetsFrom<Source>>::Error;
fn try_octets_into(self) -> Result<Target, Self::Error> {
Target::try_octets_from(self)
}
}
#[cfg(feature = "smallvec")]
pub type SmallOctets = smallvec::SmallVec<[u8; 24]>;