Skip to main content

cbor_core/
text.rs

1use std::borrow::Cow;
2
3use crate::Value;
4
5/// Conversion helper for [`Value::text_string`].
6///
7/// Wraps a `Cow<'a, str>` so that [`Value::text_string`] can accept
8/// owned and borrowed string inputs through a single
9/// `impl Into<TextString>` bound. This mirrors how [`Array`](crate::Array)
10/// and [`Map`](crate::Map) abstract their input shapes.
11///
12/// Supported source types:
13///
14/// - `&'a str` (and any `&'a T` with `T: AsRef<str>`) borrows zero-copy.
15/// - Owned `String` is moved without copying.
16/// - `Cow<'a, str>` is preserved as-is.
17/// - `char` allocates a one-character `String`.
18///
19/// ```
20/// # use cbor_core::Value;
21/// // Borrows from the literal:
22/// let v = Value::text_string("hello");
23/// assert_eq!(v.as_str().unwrap(), "hello");
24///
25/// // Owns its storage:
26/// let v = Value::text_string(String::from("hello"));
27/// assert_eq!(v.as_str().unwrap(), "hello");
28/// ```
29#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
30pub struct TextString<'a>(Cow<'a, str>);
31
32impl TextString<'_> {
33    /// Create an empty text string.
34    ///
35    /// The result is `Cow::Borrowed("")` and lives for any lifetime.
36    #[must_use]
37    pub const fn new() -> Self {
38        Self(Cow::Borrowed(""))
39    }
40
41    /// Borrow the contents as a `&str`.
42    #[must_use]
43    pub fn as_str(&self) -> &str {
44        self.0.as_ref()
45    }
46
47    /// Borrow the contents as a mutable `String`, cloning if the
48    /// inner `Cow` is currently borrowed.
49    pub fn as_string_mut(&mut self) -> &mut String {
50        self.0.to_mut()
51    }
52
53    /// Detach from any borrow, returning a `TextString` with an
54    /// independent lifetime.
55    ///
56    /// A borrowed `TextString<'a>` is copied into an owned `String`;
57    /// an already-owned one is returned unchanged. The result can
58    /// be assigned to any lifetime, in particular `TextString<'static>`.
59    #[must_use]
60    pub fn into_owned<'b>(self) -> TextString<'b> {
61        match self.0 {
62            Cow::Borrowed(text) => TextString(text.to_string().into()),
63            Cow::Owned(text) => TextString(text.into()),
64        }
65    }
66}
67
68impl From<char> for TextString<'_> {
69    fn from(value: char) -> Self {
70        Self(value.to_string().into())
71    }
72}
73
74impl<'a, T> From<&'a T> for TextString<'a>
75where
76    T: AsRef<str> + ?Sized,
77{
78    fn from(value: &'a T) -> Self {
79        Self(value.as_ref().into())
80    }
81}
82
83impl From<String> for TextString<'_> {
84    fn from(value: String) -> Self {
85        Self(value.into())
86    }
87}
88
89impl<'a> From<Cow<'a, str>> for TextString<'a> {
90    fn from(value: Cow<'a, str>) -> Self {
91        Self(value)
92    }
93}
94
95impl<'a> From<TextString<'a>> for Value<'a> {
96    fn from(value: TextString<'a>) -> Self {
97        Self::TextString(value.0)
98    }
99}
100
101/// Borrows the text rather than copying it.
102impl<'a> From<&'a TextString<'a>> for Value<'a> {
103    fn from(value: &'a TextString<'a>) -> Self {
104        Self::TextString(Cow::Borrowed(value.as_str()))
105    }
106}