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}