kstring/
ref.rs

1use std::fmt;
2
3use crate::KString;
4use crate::KStringCow;
5
6type StdString = std::string::String;
7type BoxedStr = Box<str>;
8
9/// A reference to a UTF-8 encoded, immutable string.
10#[derive(Copy, Clone)]
11#[repr(transparent)]
12pub struct KStringRef<'s> {
13    pub(crate) inner: KStringRefInner<'s>,
14}
15
16#[derive(Copy, Clone, Debug)]
17pub(crate) enum KStringRefInner<'s> {
18    Borrowed(&'s str),
19    Singleton(&'static str),
20}
21
22impl<'s> KStringRef<'s> {
23    /// Create a new empty `KString`.
24    #[inline]
25    pub fn new() -> Self {
26        Default::default()
27    }
28
29    /// Create a reference to a borrowed data.
30    #[inline]
31    pub fn from_ref(other: &'s str) -> Self {
32        Self {
33            inner: KStringRefInner::Borrowed(other),
34        }
35    }
36
37    /// Create a reference to a `'static` data.
38    #[inline]
39    pub fn from_static(other: &'static str) -> Self {
40        Self {
41            inner: KStringRefInner::Singleton(other),
42        }
43    }
44
45    /// Clone the data into an owned-type.
46    #[inline]
47    #[allow(clippy::wrong_self_convention)]
48    pub fn to_owned(&self) -> KString {
49        self.inner.to_owned()
50    }
51
52    /// Extracts a string slice containing the entire `KStringRef`.
53    #[inline]
54    pub fn as_str(&self) -> &str {
55        self.inner.as_str()
56    }
57
58    /// Convert to a mutable string type, cloning the data if necessary.
59    #[inline]
60    pub fn into_mut(self) -> StdString {
61        self.inner.into_mut()
62    }
63}
64
65impl<'s> KStringRefInner<'s> {
66    #[inline]
67    #[allow(clippy::wrong_self_convention)]
68    fn to_owned(&self) -> KString {
69        match self {
70            Self::Borrowed(s) => KString::from_ref(s),
71            Self::Singleton(s) => KString::from_static(s),
72        }
73    }
74
75    #[inline]
76    fn as_str(&self) -> &str {
77        match self {
78            Self::Borrowed(s) => s,
79            Self::Singleton(s) => s,
80        }
81    }
82
83    #[inline]
84    fn into_mut(self) -> StdString {
85        self.as_str().to_owned()
86    }
87}
88
89impl<'s> std::ops::Deref for KStringRef<'s> {
90    type Target = str;
91
92    #[inline]
93    fn deref(&self) -> &str {
94        self.as_str()
95    }
96}
97
98impl<'s> Eq for KStringRef<'s> {}
99
100impl<'s> PartialEq<KStringRef<'s>> for KStringRef<'s> {
101    #[inline]
102    fn eq(&self, other: &KStringRef<'s>) -> bool {
103        PartialEq::eq(self.as_str(), other.as_str())
104    }
105}
106
107impl<'s> PartialEq<str> for KStringRef<'s> {
108    #[inline]
109    fn eq(&self, other: &str) -> bool {
110        PartialEq::eq(self.as_str(), other)
111    }
112}
113
114impl<'s> PartialEq<&'s str> for KStringRef<'s> {
115    #[inline]
116    fn eq(&self, other: &&str) -> bool {
117        PartialEq::eq(self.as_str(), *other)
118    }
119}
120
121impl<'s> PartialEq<String> for KStringRef<'s> {
122    #[inline]
123    fn eq(&self, other: &StdString) -> bool {
124        PartialEq::eq(self.as_str(), other.as_str())
125    }
126}
127
128impl<'s> Ord for KStringRef<'s> {
129    #[inline]
130    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
131        self.as_str().cmp(other.as_str())
132    }
133}
134
135impl<'s> PartialOrd for KStringRef<'s> {
136    #[inline]
137    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
138        self.as_str().partial_cmp(other.as_str())
139    }
140}
141
142impl<'s> std::hash::Hash for KStringRef<'s> {
143    #[inline]
144    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
145        self.as_str().hash(state);
146    }
147}
148
149impl<'s> fmt::Debug for KStringRef<'s> {
150    #[inline]
151    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152        fmt::Debug::fmt(&self.inner, f)
153    }
154}
155
156impl<'s> fmt::Display for KStringRef<'s> {
157    #[inline]
158    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159        fmt::Display::fmt(self.as_str(), f)
160    }
161}
162
163impl<'s> AsRef<str> for KStringRef<'s> {
164    #[inline]
165    fn as_ref(&self) -> &str {
166        self.as_str()
167    }
168}
169
170impl<'s> AsRef<[u8]> for KStringRef<'s> {
171    #[inline]
172    fn as_ref(&self) -> &[u8] {
173        self.as_bytes()
174    }
175}
176
177impl<'s> AsRef<std::ffi::OsStr> for KStringRef<'s> {
178    #[inline]
179    fn as_ref(&self) -> &std::ffi::OsStr {
180        (&**self).as_ref()
181    }
182}
183
184impl<'s> AsRef<std::path::Path> for KStringRef<'s> {
185    #[inline]
186    fn as_ref(&self) -> &std::path::Path {
187        std::path::Path::new(self)
188    }
189}
190
191impl<'s> std::borrow::Borrow<str> for KStringRef<'s> {
192    #[inline]
193    fn borrow(&self) -> &str {
194        self.as_str()
195    }
196}
197
198impl<'s> Default for KStringRef<'s> {
199    #[inline]
200    fn default() -> Self {
201        Self::from_static("")
202    }
203}
204
205impl<'s> From<&'s KString> for KStringRef<'s> {
206    #[inline]
207    fn from(other: &'s KString) -> Self {
208        other.as_ref()
209    }
210}
211
212impl<'s> From<&'s KStringCow<'s>> for KStringRef<'s> {
213    #[inline]
214    fn from(other: &'s KStringCow<'s>) -> Self {
215        other.as_ref()
216    }
217}
218
219impl<'s> From<&'s StdString> for KStringRef<'s> {
220    #[inline]
221    fn from(other: &'s StdString) -> Self {
222        KStringRef::from_ref(other.as_str())
223    }
224}
225
226impl<'s> From<&'s BoxedStr> for KStringRef<'s> {
227    #[inline]
228    fn from(other: &'s BoxedStr) -> Self {
229        Self::from_ref(other)
230    }
231}
232
233impl<'s> From<&'s str> for KStringRef<'s> {
234    #[inline]
235    fn from(other: &'s str) -> Self {
236        KStringRef::from_ref(other)
237    }
238}
239
240#[cfg(feature = "serde")]
241impl<'s> serde::Serialize for KStringRef<'s> {
242    #[inline]
243    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
244    where
245        S: serde::Serializer,
246    {
247        serializer.serialize_str(self.as_str())
248    }
249}
250
251#[cfg(feature = "serde")]
252impl<'de: 's, 's> serde::Deserialize<'de> for KStringRef<'s> {
253    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
254    where
255        D: serde::Deserializer<'de>,
256    {
257        let s: &'s str = serde::Deserialize::deserialize(deserializer)?;
258        let s = KStringRef::from_ref(s);
259        Ok(s)
260    }
261}
262
263#[cfg(test)]
264mod test {
265    use super::*;
266
267    #[test]
268    fn test_size() {
269        println!("KStringRef: {}", std::mem::size_of::<KStringRef<'static>>());
270    }
271}