1use std::{
2 borrow::Cow,
3 fmt::{
4 Debug,
5 Display,
6 },
7 ops::Deref,
8 sync::LazyLock,
9};
10
11use internment::ArcIntern;
12use serde::{
13 Serialize,
14 Serializer,
15};
16
17#[repr(transparent)]
18#[derive(Clone)]
19pub struct ArcStr(ArcIntern<String>);
20
21impl ArcStr {
22 pub fn as_str(&self) -> &str {
23 &self.0
24 }
25}
26
27impl Deref for ArcStr {
28 type Target = str;
29
30 fn deref(&self) -> &Self::Target {
31 &self.0
32 }
33}
34
35impl AsRef<str> for ArcStr {
36 fn as_ref(&self) -> &str {
37 &self.0
38 }
39}
40
41impl<T> PartialEq<T> for ArcStr
42where
43 T: AsRef<str>,
44{
45 fn eq(&self, other: &T) -> bool {
46 *self.0 == other.as_ref()
47 }
48}
49
50impl Eq for ArcStr {}
51
52impl From<ArcStr> for Cow<'_, str> {
53 fn from(value: ArcStr) -> Self {
54 Self::Owned(value.to_string())
55 }
56}
57
58impl Serialize for ArcStr {
59 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
60 where
61 S: Serializer,
62 {
63 serializer.serialize_str(&self.0)
64 }
65}
66
67impl std::hash::Hash for ArcStr {
68 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
69 self.0.hash(state);
70 }
71}
72
73impl PartialOrd for ArcStr {
74 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
75 Some(self.cmp(other))
76 }
77}
78
79impl Ord for ArcStr {
80 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
81 self.0.cmp(&other.0)
82 }
83}
84
85impl Display for ArcStr {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 Display::fmt(&self.0, f)
88 }
89}
90
91impl Debug for ArcStr {
92 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93 Debug::fmt(&self.0, f)
94 }
95}
96
97impl From<&str> for ArcStr {
98 fn from(value: &str) -> Self {
99 Self(ArcIntern::from_ref(value))
100 }
101}
102
103impl Default for ArcStr {
104 fn default() -> Self {
105 DEFAULT_ARCSTR.clone()
106 }
107}
108
109static DEFAULT_ARCSTR: LazyLock<ArcStr> = LazyLock::new(|| ArcStr(ArcIntern::from_ref("")));
110
111#[derive(Default)]
112pub struct StringCache;
113
114impl StringCache {
115 pub fn new() -> Self {
116 Self
117 }
118
119 pub fn get_or_insert(&self, s: &str) -> ArcStr {
120 ArcStr(ArcIntern::from_ref(s))
121 }
122
123 pub fn get_or_insert_owned(&self, s: String) -> ArcStr {
126 ArcStr(ArcIntern::new(s))
127 }
128}