1 //! Common handling for types backed by byte slices with enforcement of a 2 //! library-level length limitation i.e. `Length::max()`. 3 4 use crate::{ 5 DecodeValue, DerOrd, EncodeValue, Error, Header, Length, Reader, Result, StrRef, Writer, 6 }; 7 use core::cmp::Ordering; 8 9 #[cfg(feature = "alloc")] 10 use crate::StrOwned; 11 12 /// Byte slice newtype which respects the `Length::max()` limit. 13 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] 14 pub(crate) struct BytesRef<'a> { 15 /// Precomputed `Length` (avoids possible panicking conversions) 16 pub length: Length, 17 18 /// Inner value 19 pub inner: &'a [u8], 20 } 21 22 impl<'a> BytesRef<'a> { 23 /// Constant value representing an empty byte slice. 24 pub const EMPTY: Self = Self { 25 length: Length::ZERO, 26 inner: &[], 27 }; 28 29 /// Create a new [`BytesRef`], ensuring that the provided `slice` value 30 /// is shorter than `Length::max()`. new(slice: &'a [u8]) -> Result<Self>31 pub fn new(slice: &'a [u8]) -> Result<Self> { 32 Ok(Self { 33 length: Length::try_from(slice.len())?, 34 inner: slice, 35 }) 36 } 37 38 /// Borrow the inner byte slice as_slice(&self) -> &'a [u8]39 pub fn as_slice(&self) -> &'a [u8] { 40 self.inner 41 } 42 43 /// Get the [`Length`] of this [`BytesRef`] len(self) -> Length44 pub fn len(self) -> Length { 45 self.length 46 } 47 48 /// Is this [`BytesRef`] empty? is_empty(self) -> bool49 pub fn is_empty(self) -> bool { 50 self.len() == Length::ZERO 51 } 52 } 53 54 impl AsRef<[u8]> for BytesRef<'_> { as_ref(&self) -> &[u8]55 fn as_ref(&self) -> &[u8] { 56 self.as_slice() 57 } 58 } 59 60 impl<'a> DecodeValue<'a> for BytesRef<'a> { decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self>61 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { 62 reader.read_slice(header.length).and_then(Self::new) 63 } 64 } 65 66 impl EncodeValue for BytesRef<'_> { value_len(&self) -> Result<Length>67 fn value_len(&self) -> Result<Length> { 68 Ok(self.length) 69 } 70 encode_value(&self, writer: &mut impl Writer) -> Result<()>71 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { 72 writer.write(self.as_ref()) 73 } 74 } 75 76 impl Default for BytesRef<'_> { default() -> Self77 fn default() -> Self { 78 Self { 79 length: Length::ZERO, 80 inner: &[], 81 } 82 } 83 } 84 85 impl DerOrd for BytesRef<'_> { der_cmp(&self, other: &Self) -> Result<Ordering>86 fn der_cmp(&self, other: &Self) -> Result<Ordering> { 87 Ok(self.as_slice().cmp(other.as_slice())) 88 } 89 } 90 91 impl<'a> From<StrRef<'a>> for BytesRef<'a> { from(s: StrRef<'a>) -> BytesRef<'a>92 fn from(s: StrRef<'a>) -> BytesRef<'a> { 93 let bytes = s.as_bytes(); 94 debug_assert_eq!(bytes.len(), usize::try_from(s.length).expect("overflow")); 95 96 BytesRef { 97 inner: bytes, 98 length: s.length, 99 } 100 } 101 } 102 103 #[cfg(feature = "alloc")] 104 impl<'a> From<&'a StrOwned> for BytesRef<'a> { from(s: &'a StrOwned) -> BytesRef<'a>105 fn from(s: &'a StrOwned) -> BytesRef<'a> { 106 let bytes = s.as_bytes(); 107 debug_assert_eq!(bytes.len(), usize::try_from(s.length).expect("overflow")); 108 109 BytesRef { 110 inner: bytes, 111 length: s.length, 112 } 113 } 114 } 115 116 impl<'a> TryFrom<&'a [u8]> for BytesRef<'a> { 117 type Error = Error; 118 try_from(slice: &'a [u8]) -> Result<Self>119 fn try_from(slice: &'a [u8]) -> Result<Self> { 120 Self::new(slice) 121 } 122 } 123 124 // Implement by hand because the derive would create invalid values. 125 // Make sure the length and the inner.len matches. 126 #[cfg(feature = "arbitrary")] 127 impl<'a> arbitrary::Arbitrary<'a> for BytesRef<'a> { arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self>128 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> { 129 let length = u.arbitrary()?; 130 Ok(Self { 131 length, 132 inner: u.bytes(u32::from(length) as usize)?, 133 }) 134 } 135 size_hint(depth: usize) -> (usize, Option<usize>)136 fn size_hint(depth: usize) -> (usize, Option<usize>) { 137 arbitrary::size_hint::and(Length::size_hint(depth), (0, None)) 138 } 139 } 140 141 #[cfg(feature = "alloc")] 142 mod allocating { 143 use super::BytesRef; 144 use crate::{referenced::RefToOwned, BytesOwned}; 145 146 impl<'a> RefToOwned<'a> for BytesRef<'a> { 147 type Owned = BytesOwned; ref_to_owned(&self) -> Self::Owned148 fn ref_to_owned(&self) -> Self::Owned { 149 BytesOwned::from(*self) 150 } 151 } 152 } 153