Skip to main content

gpui_core/
shared_string.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3use smol_str::SmolStr;
4use std::{
5    borrow::{Borrow, Cow},
6    ops::Deref,
7    sync::Arc,
8};
9
10/// A shared string is an immutable string that can be cheaply cloned in GPUI
11/// tasks. Uses SmolStr for efficient storage with inline optimization for small strings.
12#[derive(Eq, PartialEq, PartialOrd, Ord, Hash, Clone, Default)]
13pub struct SharedString(SmolStr);
14
15impl SharedString {
16    /// Creates a static [`SharedString`] from a `&'static str`.
17    pub const fn new_static(str: &'static str) -> Self {
18        Self(SmolStr::new_static(str))
19    }
20
21    /// Creates a [`SharedString`] from anything that can become a SmolStr
22    pub fn new(str: impl Into<SmolStr>) -> Self {
23        SharedString(str.into())
24    }
25
26    /// Get a &str from the underlying string.
27    pub fn as_str(&self) -> &str {
28        self.0.as_str()
29    }
30}
31
32impl Deref for SharedString {
33    type Target = str;
34
35    fn deref(&self) -> &Self::Target {
36        self.0.as_str()
37    }
38}
39
40impl JsonSchema for SharedString {
41    fn inline_schema() -> bool {
42        String::inline_schema()
43    }
44
45    fn schema_name() -> Cow<'static, str> {
46        String::schema_name()
47    }
48
49    fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
50        String::json_schema(generator)
51    }
52}
53
54impl AsRef<str> for SharedString {
55    fn as_ref(&self) -> &str {
56        &self.0
57    }
58}
59
60impl Borrow<str> for SharedString {
61    fn borrow(&self) -> &str {
62        self.as_ref()
63    }
64}
65
66impl std::fmt::Debug for SharedString {
67    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68        self.0.fmt(f)
69    }
70}
71
72impl std::fmt::Display for SharedString {
73    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74        write!(f, "{}", self.0.as_str())
75    }
76}
77
78impl PartialEq<String> for SharedString {
79    fn eq(&self, other: &String) -> bool {
80        self.as_ref() == other
81    }
82}
83
84impl PartialEq<SharedString> for String {
85    fn eq(&self, other: &SharedString) -> bool {
86        self == other.as_ref()
87    }
88}
89
90impl PartialEq<str> for SharedString {
91    fn eq(&self, other: &str) -> bool {
92        self.as_ref() == other
93    }
94}
95
96impl<'a> PartialEq<&'a str> for SharedString {
97    fn eq(&self, other: &&'a str) -> bool {
98        self.as_ref() == *other
99    }
100}
101
102impl From<&SharedString> for SharedString {
103    fn from(value: &SharedString) -> Self {
104        value.clone()
105    }
106}
107
108impl From<SharedString> for Arc<str> {
109    fn from(val: SharedString) -> Self {
110        // Reuses the underlying Arc when SmolStr is in its Heap variant (zero-copy).
111        Arc::<str>::from(val.0)
112    }
113}
114
115impl From<&str> for SharedString {
116    fn from(value: &str) -> Self {
117        Self(SmolStr::from(value))
118    }
119}
120
121impl From<String> for SharedString {
122    fn from(value: String) -> Self {
123        Self(SmolStr::from(value))
124    }
125}
126
127impl From<Arc<str>> for SharedString {
128    fn from(value: Arc<str>) -> Self {
129        // SmolStr's `From<Arc<str>>` keeps the original Arc on the heap path,
130        // avoiding an allocation+copy for long strings.
131        Self(SmolStr::from(value))
132    }
133}
134
135impl From<&String> for SharedString {
136    fn from(value: &String) -> Self {
137        Self(SmolStr::from(value))
138    }
139}
140
141impl From<SharedString> for String {
142    fn from(val: SharedString) -> Self {
143        val.0.to_string()
144    }
145}
146
147impl Serialize for SharedString {
148    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
149    where
150        S: serde::Serializer,
151    {
152        serializer.serialize_str(self.as_ref())
153    }
154}
155
156impl<'de> Deserialize<'de> for SharedString {
157    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
158    where
159        D: serde::Deserializer<'de>,
160    {
161        let s = String::deserialize(deserializer)?;
162        Ok(SharedString::from(s))
163    }
164}