polars_utils/
pl_ref_str.rs

1use std::borrow::{Borrow, Cow};
2use std::fmt::Debug;
3use std::hash::Hash;
4use std::ops::Deref;
5use std::sync::{Arc, LazyLock};
6
7#[macro_export]
8macro_rules! format_pl_refstr {
9    ($($arg:tt)*) => {{
10        use std::fmt::Write;
11
12        let mut string = String::new();
13        write!(string, $($arg)*).unwrap();
14        $crate::pl_str::PlRefStr::from_string(string)
15    }}
16}
17
18type Inner = Arc<str>;
19
20/// Reference-counted string.
21#[derive(Clone, Eq, Hash, PartialOrd, Ord)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23pub struct PlRefStr(Inner);
24
25impl PlRefStr {
26    pub fn empty() -> Self {
27        return EMPTY.clone();
28        static EMPTY: LazyLock<PlRefStr> = LazyLock::new(|| PlRefStr::from_str(""));
29    }
30
31    #[inline(always)]
32    #[allow(clippy::should_implement_trait)]
33    pub fn from_str(s: &str) -> Self {
34        Self(Inner::from(s))
35    }
36
37    #[inline(always)]
38    pub fn from_string(s: String) -> Self {
39        Self(Inner::from(s))
40    }
41
42    #[inline(always)]
43    pub fn from_arc_str(arc: Arc<str>) -> Self {
44        Self(arc)
45    }
46
47    #[inline(always)]
48    pub fn as_str(&self) -> &str {
49        self.0.as_ref()
50    }
51
52    #[inline(always)]
53    #[allow(clippy::inherent_to_string_shadow_display)] // This is faster.
54    pub fn to_string(&self) -> String {
55        self.as_str().to_string()
56    }
57
58    #[inline(always)]
59    pub fn into_string(self) -> String {
60        self.as_str().to_string()
61    }
62
63    #[inline(always)]
64    pub fn into_arc_str(self) -> Arc<str> {
65        self.0
66    }
67
68    /// Checks if references point to the same allocation.
69    #[inline(always)]
70    pub fn ptr_eq(this: &Self, other: &Self) -> bool {
71        Inner::ptr_eq(&this.0, &other.0)
72    }
73
74    #[inline(always)]
75    pub fn get_mut(&mut self) -> Option<&mut str> {
76        Inner::get_mut(&mut self.0)
77    }
78
79    #[inline(always)]
80    pub fn make_mut(&mut self) -> &mut str {
81        Inner::make_mut(&mut self.0)
82    }
83}
84
85impl Default for PlRefStr {
86    #[inline(always)]
87    fn default() -> Self {
88        Self::empty()
89    }
90}
91
92// AsRef, Deref and Borrow impls to &str
93
94impl AsRef<str> for PlRefStr {
95    #[inline(always)]
96    fn as_ref(&self) -> &str {
97        self.as_str()
98    }
99}
100
101impl Deref for PlRefStr {
102    type Target = str;
103
104    #[inline(always)]
105    fn deref(&self) -> &Self::Target {
106        self.as_str()
107    }
108}
109
110impl Borrow<str> for PlRefStr {
111    #[inline(always)]
112    fn borrow(&self) -> &str {
113        self.as_str()
114    }
115}
116
117// AsRef impls for other types
118
119impl AsRef<std::path::Path> for PlRefStr {
120    #[inline(always)]
121    fn as_ref(&self) -> &std::path::Path {
122        self.as_str().as_ref()
123    }
124}
125
126impl AsRef<[u8]> for PlRefStr {
127    #[inline(always)]
128    fn as_ref(&self) -> &[u8] {
129        self.as_bytes()
130    }
131}
132
133impl AsRef<std::ffi::OsStr> for PlRefStr {
134    #[inline(always)]
135    fn as_ref(&self) -> &std::ffi::OsStr {
136        self.as_str().as_ref()
137    }
138}
139
140// From impls
141
142impl From<&str> for PlRefStr {
143    #[inline(always)]
144    fn from(value: &str) -> Self {
145        Self::from_str(value)
146    }
147}
148
149impl From<String> for PlRefStr {
150    #[inline(always)]
151    fn from(value: String) -> Self {
152        Self::from_string(value)
153    }
154}
155
156impl From<PlRefStr> for String {
157    #[inline(always)]
158    fn from(value: PlRefStr) -> Self {
159        value.into_string()
160    }
161}
162
163impl From<Cow<'_, str>> for PlRefStr {
164    #[inline(always)]
165    fn from(value: Cow<str>) -> Self {
166        match value {
167            Cow::Owned(s) => Self::from_string(s),
168            Cow::Borrowed(s) => Self::from_str(s),
169        }
170    }
171}
172
173impl From<&String> for PlRefStr {
174    #[inline(always)]
175    fn from(value: &String) -> Self {
176        Self::from_str(value.as_str())
177    }
178}
179
180impl From<Arc<str>> for PlRefStr {
181    #[inline(always)]
182    fn from(value: Arc<str>) -> Self {
183        Self::from_arc_str(value)
184    }
185}
186
187// FromIterator impls
188impl FromIterator<char> for PlRefStr {
189    #[inline(always)]
190    fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> PlRefStr {
191        Self::from_string(String::from_iter(iter))
192    }
193}
194
195impl<'a> FromIterator<&'a char> for PlRefStr {
196    #[inline(always)]
197    fn from_iter<I: IntoIterator<Item = &'a char>>(iter: I) -> PlRefStr {
198        Self::from_string(String::from_iter(iter))
199    }
200}
201
202impl<'a> FromIterator<&'a str> for PlRefStr {
203    #[inline(always)]
204    fn from_iter<I: IntoIterator<Item = &'a str>>(iter: I) -> PlRefStr {
205        Self::from_string(String::from_iter(iter))
206    }
207}
208
209impl FromIterator<String> for PlRefStr {
210    #[inline(always)]
211    fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> PlRefStr {
212        Self::from_string(String::from_iter(iter))
213    }
214}
215
216impl FromIterator<Box<str>> for PlRefStr {
217    #[inline(always)]
218    fn from_iter<I: IntoIterator<Item = Box<str>>>(iter: I) -> PlRefStr {
219        Self::from_string(String::from_iter(iter))
220    }
221}
222
223impl<'a> FromIterator<std::borrow::Cow<'a, str>> for PlRefStr {
224    #[inline(always)]
225    fn from_iter<I: IntoIterator<Item = std::borrow::Cow<'a, str>>>(iter: I) -> PlRefStr {
226        Self::from_string(String::from_iter(iter))
227    }
228}
229
230impl<T> PartialEq<T> for PlRefStr
231where
232    T: AsRef<str> + ?Sized,
233{
234    #[inline(always)]
235    fn eq(&self, other: &T) -> bool {
236        self.as_str() == other.as_ref()
237    }
238}
239
240impl PartialEq<PlRefStr> for &str {
241    #[inline(always)]
242    fn eq(&self, other: &PlRefStr) -> bool {
243        *self == other.as_str()
244    }
245}
246
247impl PartialEq<PlRefStr> for String {
248    #[inline(always)]
249    fn eq(&self, other: &PlRefStr) -> bool {
250        self.as_str() == other.as_str()
251    }
252}
253
254// Debug, Display
255
256impl Debug for PlRefStr {
257    #[inline(always)]
258    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
259        Debug::fmt(self.as_str(), f)
260    }
261}
262
263impl core::fmt::Display for PlRefStr {
264    #[inline(always)]
265    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
266        core::fmt::Display::fmt(self.as_str(), f)
267    }
268}
269
270#[cfg(feature = "dsl-schema")]
271impl schemars::JsonSchema for PlRefStr {
272    fn inline_schema() -> bool {
273        str::inline_schema()
274    }
275    fn schema_name() -> std::borrow::Cow<'static, str> {
276        str::schema_name()
277    }
278    fn schema_id() -> std::borrow::Cow<'static, str> {
279        str::schema_id()
280    }
281    fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
282        str::json_schema(generator)
283    }
284}