hcl_primitives/
internal_string.rs

1//! Provides the `InternalString` type and associated functionality.
2
3use alloc::borrow::{Borrow, Cow};
4#[cfg(not(feature = "std"))]
5use alloc::boxed::Box;
6#[cfg(not(feature = "std"))]
7use alloc::string::String;
8use core::fmt;
9use core::ops::Deref;
10
11#[cfg(feature = "perf")]
12type Inner = kstring::KString;
13#[cfg(not(feature = "perf"))]
14type Inner = String;
15
16/// An opaque string storage which inlines small strings on the stack if the `perf` feature is
17/// enabled.
18#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
19pub struct InternalString(Inner);
20
21impl InternalString {
22    /// Create a new empty `InternalString`.
23    #[inline]
24    #[must_use]
25    pub const fn new() -> Self {
26        #[cfg(feature = "perf")]
27        let inner = kstring::KString::EMPTY;
28        #[cfg(not(feature = "perf"))]
29        let inner = String::new();
30
31        InternalString(inner)
32    }
33
34    /// Converts the `InternalString` into a mutable string type.
35    #[inline]
36    #[must_use]
37    pub fn into_string(self) -> String {
38        #[cfg(feature = "perf")]
39        let string = self.0.into_string();
40        #[cfg(not(feature = "perf"))]
41        let string = self.0;
42
43        string
44    }
45
46    /// Converts the `InternalString` into a copy-on-write string type.
47    #[inline]
48    #[must_use]
49    pub fn into_cow_str(self) -> Cow<'static, str> {
50        #[cfg(feature = "perf")]
51        let cow = self.0.into_cow_str();
52        #[cfg(not(feature = "perf"))]
53        let cow = self.0.into();
54
55        cow
56    }
57
58    /// Returns a reference to the underlying string.
59    #[inline]
60    pub fn as_str(&self) -> &str {
61        self.0.as_str()
62    }
63}
64
65impl Default for InternalString {
66    fn default() -> Self {
67        InternalString::new()
68    }
69}
70
71impl Deref for InternalString {
72    type Target = str;
73
74    #[inline]
75    fn deref(&self) -> &str {
76        self.as_str()
77    }
78}
79
80impl Borrow<str> for InternalString {
81    #[inline]
82    fn borrow(&self) -> &str {
83        self.as_str()
84    }
85}
86
87impl AsRef<str> for InternalString {
88    #[inline]
89    fn as_ref(&self) -> &str {
90        self.as_str()
91    }
92}
93
94impl From<&str> for InternalString {
95    #[inline]
96    fn from(s: &str) -> Self {
97        #[cfg(feature = "perf")]
98        let inner = kstring::KString::from_ref(s);
99        #[cfg(not(feature = "perf"))]
100        let inner = String::from(s);
101
102        InternalString(inner)
103    }
104}
105
106impl From<String> for InternalString {
107    #[inline]
108    fn from(s: String) -> Self {
109        #[cfg(feature = "perf")]
110        let inner = kstring::KString::from_string(s);
111        #[cfg(not(feature = "perf"))]
112        let inner = s;
113
114        InternalString(inner)
115    }
116}
117
118impl From<&String> for InternalString {
119    #[inline]
120    fn from(s: &String) -> Self {
121        InternalString(s.into())
122    }
123}
124
125impl From<&InternalString> for InternalString {
126    #[inline]
127    fn from(s: &InternalString) -> Self {
128        s.clone()
129    }
130}
131
132impl From<Box<str>> for InternalString {
133    #[inline]
134    fn from(s: Box<str>) -> Self {
135        InternalString(s.into())
136    }
137}
138
139impl<'a> From<Cow<'a, str>> for InternalString {
140    #[inline]
141    fn from(s: Cow<'a, str>) -> Self {
142        match s {
143            Cow::Borrowed(borrowed) => borrowed.into(),
144            Cow::Owned(owned) => owned.into(),
145        }
146    }
147}
148
149impl From<InternalString> for String {
150    #[inline]
151    fn from(is: InternalString) -> Self {
152        is.into_string()
153    }
154}
155
156impl<'a> From<InternalString> for Cow<'a, str> {
157    fn from(value: InternalString) -> Self {
158        value.into_cow_str()
159    }
160}
161
162impl<'a> From<&'a InternalString> for Cow<'a, str> {
163    fn from(value: &'a InternalString) -> Self {
164        Cow::Borrowed(value.as_str())
165    }
166}
167
168impl fmt::Debug for InternalString {
169    #[inline]
170    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171        write!(f, "InternalString({self})")
172    }
173}
174
175impl fmt::Display for InternalString {
176    #[inline]
177    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
178        f.write_str(self.as_str())
179    }
180}
181
182#[cfg(feature = "serde")]
183impl serde::Serialize for InternalString {
184    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
185    where
186        S: serde::Serializer,
187    {
188        self.0.serialize(serializer)
189    }
190}
191
192#[cfg(feature = "serde")]
193impl<'de> serde::Deserialize<'de> for InternalString {
194    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
195    where
196        D: serde::Deserializer<'de>,
197    {
198        Inner::deserialize(deserializer).map(InternalString)
199    }
200}