der/
str_owned.rs

1//! Common handling for types backed by `String` with enforcement of a
2//! library-level length limitation i.e. `Length::max()`.
3
4use crate::{
5    referenced::OwnedToRef, BytesRef, DecodeValue, EncodeValue, Header, Length, Reader, Result,
6    StrRef, Writer,
7};
8use alloc::string::String;
9use core::str;
10
11/// String newtype which respects the [`Length::max`] limit.
12#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
13pub 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
21impl StrOwned {
22    /// Create a new [`StrOwned`], ensuring that the byte representation of
23    /// the provided `str` value is shorter than `Length::max()`.
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.
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`
39    pub fn as_str(&self) -> &str {
40        &self.inner
41    }
42
43    /// Borrow the inner byte slice
44    pub fn as_bytes(&self) -> &[u8] {
45        self.inner.as_bytes()
46    }
47
48    /// Get the [`Length`] of this [`StrOwned`]
49    pub fn len(&self) -> Length {
50        self.length
51    }
52
53    /// Is this [`StrOwned`] empty?
54    pub fn is_empty(&self) -> bool {
55        self.len() == Length::ZERO
56    }
57}
58
59impl AsRef<str> for StrOwned {
60    fn as_ref(&self) -> &str {
61        self.as_str()
62    }
63}
64
65impl AsRef<[u8]> for StrOwned {
66    fn as_ref(&self) -> &[u8] {
67        self.as_bytes()
68    }
69}
70
71impl<'a> DecodeValue<'a> for StrOwned {
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
77impl EncodeValue for StrOwned {
78    fn value_len(&self) -> Result<Length> {
79        Ok(self.length)
80    }
81
82    fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
83        writer.write(self.as_ref())
84    }
85}
86
87impl From<StrRef<'_>> for StrOwned {
88    fn from(s: StrRef<'_>) -> StrOwned {
89        Self {
90            inner: String::from(s.inner),
91            length: s.length,
92        }
93    }
94}
95
96impl OwnedToRef for StrOwned {
97    type Borrowed<'a> = StrRef<'a>;
98    fn owned_to_ref(&self) -> Self::Borrowed<'_> {
99        StrRef {
100            length: self.length,
101            inner: self.inner.as_ref(),
102        }
103    }
104}