1 //! Common handling for types backed by `str` slices with enforcement of a 2 //! library-level length limitation i.e. `Length::max()`. 3 4 use crate::{BytesRef, DecodeValue, EncodeValue, Header, Length, Reader, Result, Writer}; 5 use core::str; 6 7 /// String slice newtype which respects the [`Length::max`] limit. 8 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] 9 pub struct StrRef<'a> { 10 /// Inner value 11 pub(crate) inner: &'a str, 12 13 /// Precomputed `Length` (avoids possible panicking conversions) 14 pub(crate) length: Length, 15 } 16 17 impl<'a> StrRef<'a> { 18 /// Create a new [`StrRef`], ensuring that the byte representation of 19 /// the provided `str` value is shorter than `Length::max()`. new(s: &'a str) -> Result<Self>20 pub fn new(s: &'a str) -> Result<Self> { 21 Ok(Self { 22 inner: s, 23 length: Length::try_from(s.as_bytes().len())?, 24 }) 25 } 26 27 /// Parse a [`StrRef`] from UTF-8 encoded bytes. from_bytes(bytes: &'a [u8]) -> Result<Self>28 pub fn from_bytes(bytes: &'a [u8]) -> Result<Self> { 29 Self::new(str::from_utf8(bytes)?) 30 } 31 32 /// Borrow the inner `str` as_str(&self) -> &'a str33 pub fn as_str(&self) -> &'a str { 34 self.inner 35 } 36 37 /// Borrow the inner byte slice as_bytes(&self) -> &'a [u8]38 pub fn as_bytes(&self) -> &'a [u8] { 39 self.inner.as_bytes() 40 } 41 42 /// Get the [`Length`] of this [`StrRef`] len(self) -> Length43 pub fn len(self) -> Length { 44 self.length 45 } 46 47 /// Is this [`StrRef`] empty? is_empty(self) -> bool48 pub fn is_empty(self) -> bool { 49 self.len() == Length::ZERO 50 } 51 } 52 53 impl AsRef<str> for StrRef<'_> { as_ref(&self) -> &str54 fn as_ref(&self) -> &str { 55 self.as_str() 56 } 57 } 58 59 impl AsRef<[u8]> for StrRef<'_> { as_ref(&self) -> &[u8]60 fn as_ref(&self) -> &[u8] { 61 self.as_bytes() 62 } 63 } 64 65 impl<'a> DecodeValue<'a> for StrRef<'a> { decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self>66 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { 67 Self::from_bytes(BytesRef::decode_value(reader, header)?.as_slice()) 68 } 69 } 70 71 impl<'a> EncodeValue for StrRef<'a> { value_len(&self) -> Result<Length>72 fn value_len(&self) -> Result<Length> { 73 Ok(self.length) 74 } 75 encode_value(&self, writer: &mut impl Writer) -> Result<()>76 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { 77 writer.write(self.as_ref()) 78 } 79 } 80 81 #[cfg(feature = "alloc")] 82 mod allocating { 83 use super::StrRef; 84 use crate::{referenced::RefToOwned, StrOwned}; 85 86 impl<'a> RefToOwned<'a> for StrRef<'a> { 87 type Owned = StrOwned; ref_to_owned(&self) -> Self::Owned88 fn ref_to_owned(&self) -> Self::Owned { 89 StrOwned::from(*self) 90 } 91 } 92 } 93