use crate::{DecodeValue, DerOrd, EncodeValue, Error, Header, Length, Reader, Result, Writer};
use core::cmp::Ordering;
#[derive(Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[repr(transparent)]
pub(crate) struct BytesRef([u8]);
impl BytesRef {
pub const EMPTY: &'static Self = Self::new_unchecked(&[]);
pub const fn new(slice: &[u8]) -> Result<&Self> {
match Length::new_usize(slice.len()) {
Ok(_) => Ok(Self::new_unchecked(slice)),
Err(err) => Err(err),
}
}
pub(crate) const fn new_unchecked(slice: &[u8]) -> &Self {
#[allow(unsafe_code)]
unsafe {
&*(core::ptr::from_ref::<[u8]>(slice) as *const Self)
}
}
pub(crate) const fn as_ptr(&self) -> *const BytesRef {
core::ptr::from_ref::<BytesRef>(self)
}
pub const fn as_slice(&self) -> &[u8] {
&self.0
}
pub fn len(&self) -> Length {
debug_assert!(u32::try_from(self.0.len()).is_ok());
#[allow(clippy::cast_possible_truncation)] Length::new(self.0.len() as u32)
}
pub const fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn prefix(&self, length: Length) -> Result<&Self> {
let inner = self
.as_slice()
.get(..usize::try_from(length)?)
.ok_or_else(|| Error::incomplete(self.len()))?;
Ok(Self::new_unchecked(inner))
}
}
impl AsRef<[u8]> for BytesRef {
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl<'a> DecodeValue<'a> for &'a BytesRef {
type Error = Error;
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
BytesRef::new(reader.read_slice(header.length())?)
}
}
impl EncodeValue for BytesRef {
fn value_len(&self) -> Result<Length> {
Ok(self.len())
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
writer.write(self.as_ref())
}
}
impl DerOrd for BytesRef {
fn der_cmp(&self, other: &Self) -> Result<Ordering> {
Ok(self.as_slice().cmp(other.as_slice()))
}
}
impl<'a> TryFrom<&'a [u8]> for &'a BytesRef {
type Error = Error;
fn try_from(slice: &'a [u8]) -> Result<Self> {
BytesRef::new(slice)
}
}
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for &'a BytesRef {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let length: Length = u.arbitrary()?;
Ok(BytesRef::new_unchecked(
u.bytes(u32::from(length) as usize)?,
))
}
fn size_hint(depth: usize) -> (usize, Option<usize>) {
arbitrary::size_hint::and(Length::size_hint(depth), (0, None))
}
}
#[cfg(feature = "alloc")]
pub(crate) mod allocating {
use super::BytesRef;
#[cfg(feature = "ber")]
use crate::{ErrorKind, length::indefinite::read_constructed_vec};
use crate::{
DecodeValue, DerOrd, EncodeValue, Error, Header, Length, Reader, Result, Tag, Writer,
};
use alloc::{borrow::ToOwned, boxed::Box, vec::Vec};
use core::{borrow::Borrow, cmp::Ordering, ops::Deref};
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub(crate) struct BytesOwned {
length: Length,
inner: Box<[u8]>,
}
impl BytesOwned {
pub fn new(data: impl Into<Box<[u8]>>) -> Result<Self> {
let inner: Box<[u8]> = data.into();
Ok(Self {
length: Length::try_from(inner.len())?,
inner,
})
}
pub fn decode_value_parts<'a, R: Reader<'a>>(
reader: &mut R,
header: Header,
inner_tag: Tag,
) -> Result<Self> {
#[cfg(feature = "ber")]
if header.is_constructed() {
if header.length().is_indefinite() && reader.encoding_rules().is_ber() {
return Self::new(read_constructed_vec(reader, header.length(), inner_tag)?);
} else {
return Err(Error::new(
ErrorKind::Noncanonical { tag: header.tag() },
reader.position().saturating_sub(Length::ONE),
));
}
}
#[cfg(not(feature = "ber"))]
let _ = inner_tag;
Self::decode_value(reader, header)
}
}
impl AsRef<[u8]> for BytesOwned {
fn as_ref(&self) -> &[u8] {
&self.inner
}
}
impl AsRef<BytesRef> for BytesOwned {
fn as_ref(&self) -> &BytesRef {
BytesRef::new_unchecked(&self.inner)
}
}
impl Borrow<[u8]> for BytesOwned {
fn borrow(&self) -> &[u8] {
&self.inner
}
}
impl Borrow<BytesRef> for BytesOwned {
fn borrow(&self) -> &BytesRef {
BytesRef::new_unchecked(&self.inner)
}
}
impl Deref for BytesOwned {
type Target = BytesRef;
fn deref(&self) -> &BytesRef {
self.borrow()
}
}
impl<'a> DecodeValue<'a> for BytesOwned {
type Error = Error;
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
reader.read_vec(header.length()).and_then(Self::new)
}
}
impl EncodeValue for BytesOwned {
fn value_len(&self) -> Result<Length> {
Ok(self.length)
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
writer.write(self.as_ref())
}
}
impl Default for BytesOwned {
fn default() -> Self {
Self {
length: Length::ZERO,
inner: Box::new([]),
}
}
}
impl DerOrd for BytesOwned {
fn der_cmp(&self, other: &Self) -> Result<Ordering> {
Ok(self.as_slice().cmp(other.as_slice()))
}
}
impl From<BytesOwned> for Box<[u8]> {
fn from(bytes: BytesOwned) -> Box<[u8]> {
bytes.inner
}
}
impl From<&BytesRef> for BytesOwned {
fn from(bytes: &BytesRef) -> BytesOwned {
BytesOwned {
length: bytes.len(),
inner: bytes.as_slice().into(),
}
}
}
impl TryFrom<&[u8]> for BytesOwned {
type Error = Error;
fn try_from(bytes: &[u8]) -> Result<Self> {
Self::new(bytes)
}
}
impl TryFrom<Box<[u8]>> for BytesOwned {
type Error = Error;
fn try_from(bytes: Box<[u8]>) -> Result<Self> {
Self::new(bytes)
}
}
impl TryFrom<Vec<u8>> for BytesOwned {
type Error = Error;
fn try_from(bytes: Vec<u8>) -> Result<Self> {
Self::new(bytes)
}
}
impl ToOwned for BytesRef {
type Owned = BytesOwned;
fn to_owned(&self) -> BytesOwned {
BytesOwned {
inner: self.as_slice().into(),
length: self.len(),
}
}
}
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for BytesOwned {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let length = u.arbitrary()?;
Ok(Self {
length,
inner: Box::from(u.bytes(u32::from(length) as usize)?),
})
}
fn size_hint(depth: usize) -> (usize, Option<usize>) {
arbitrary::size_hint::and(Length::size_hint(depth), (0, None))
}
}
}