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