1use derive_more::{Deref, DerefMut};
2
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5use std::{
6 borrow::{Borrow, Cow},
7 sync::Arc,
8};
9use util::arc_cow::ArcCow;
10
11/// A shared string is an immutable string that can be cheaply cloned in GPUI
12/// tasks. Essentially an abstraction over an `Arc<str>` and `&'static str`,
13#[derive(Deref, DerefMut, Eq, PartialEq, PartialOrd, Ord, Hash, Clone)]
14pub struct SharedString(ArcCow<'static, str>);
15
16impl SharedString {
17 /// Creates a static [`SharedString`] from a `&'static str`.
18 pub const fn new_static(str: &'static str) -> Self {
19 Self(ArcCow::Borrowed(str))
20 }
21
22 /// Creates a [`SharedString`] from anything that can become an `Arc<str>`
23 pub fn new(str: impl Into<Arc<str>>) -> Self {
24 SharedString(ArcCow::Owned(str.into()))
25 }
26}
27
28impl JsonSchema for SharedString {
29 fn inline_schema() -> bool {
30 String::inline_schema()
31 }
32
33 fn schema_name() -> Cow<'static, str> {
34 String::schema_name()
35 }
36
37 fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
38 String::json_schema(generator)
39 }
40}
41
42impl Default for SharedString {
43 fn default() -> Self {
44 Self(ArcCow::Owned(Arc::default()))
45 }
46}
47
48impl AsRef<str> for SharedString {
49 fn as_ref(&self) -> &str {
50 &self.0
51 }
52}
53
54impl Borrow<str> for SharedString {
55 fn borrow(&self) -> &str {
56 self.as_ref()
57 }
58}
59
60impl std::fmt::Debug for SharedString {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 self.0.fmt(f)
63 }
64}
65
66impl std::fmt::Display for SharedString {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 write!(f, "{}", self.0.as_ref())
69 }
70}
71
72impl PartialEq<String> for SharedString {
73 fn eq(&self, other: &String) -> bool {
74 self.as_ref() == other
75 }
76}
77
78impl PartialEq<SharedString> for String {
79 fn eq(&self, other: &SharedString) -> bool {
80 self == other.as_ref()
81 }
82}
83
84impl PartialEq<str> for SharedString {
85 fn eq(&self, other: &str) -> bool {
86 self.as_ref() == other
87 }
88}
89
90impl<'a> PartialEq<&'a str> for SharedString {
91 fn eq(&self, other: &&'a str) -> bool {
92 self.as_ref() == *other
93 }
94}
95
96impl From<&SharedString> for SharedString {
97 fn from(value: &SharedString) -> Self {
98 value.clone()
99 }
100}
101
102impl From<SharedString> for Arc<str> {
103 fn from(val: SharedString) -> Self {
104 match val.0 {
105 ArcCow::Borrowed(borrowed) => Arc::from(borrowed),
106 ArcCow::Owned(owned) => owned.clone(),
107 }
108 }
109}
110
111impl<T: Into<ArcCow<'static, str>>> From<T> for SharedString {
112 fn from(value: T) -> Self {
113 Self(value.into())
114 }
115}
116
117impl From<SharedString> for String {
118 fn from(val: SharedString) -> Self {
119 val.0.to_string()
120 }
121}
122
123impl Serialize for SharedString {
124 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
125 where
126 S: serde::Serializer,
127 {
128 serializer.serialize_str(self.as_ref())
129 }
130}
131
132impl<'de> Deserialize<'de> for SharedString {
133 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
134 where
135 D: serde::Deserializer<'de>,
136 {
137 let s = String::deserialize(deserializer)?;
138 Ok(SharedString::from(s))
139 }
140}