1use crate::Set;
2use std::{
3 borrow, fmt, ops,
4 rc::Rc,
5 sync::{Arc, LazyLock, RwLock},
6};
7
8static STR_FACTORY: LazyLock<RwLock<Set<Arc<str>>>> = LazyLock::new(|| RwLock::new(Set::default()));
9
10#[derive(Clone, Eq, Hash)]
12pub struct Str(Arc<str>);
13
14impl Str {
15 fn create_or_get(input: &str) -> Self {
16 let mut factory = STR_FACTORY.write().unwrap();
17 if let Some(s) = factory.get(input) {
18 Self(s.clone())
19 } else {
20 let arc: Arc<str> = Arc::from(input);
21 factory.insert(Arc::clone(&arc));
22 Self(arc)
23 }
24 }
25
26 pub fn as_str(&self) -> &str {
27 self.as_ref()
28 }
29}
30
31impl Default for Str {
32 fn default() -> Self {
33 Self::create_or_get("")
34 }
35}
36
37impl ops::Deref for Str {
38 type Target = str;
39
40 fn deref(&self) -> &Self::Target {
41 &self.0
42 }
43}
44
45impl Drop for Str {
46 fn drop(&mut self) {
47 let is_last_one = Arc::strong_count(&self.0) == 2; if is_last_one {
49 if let Ok(mut factory) = STR_FACTORY.write() {
50 factory.remove(self.as_str());
51 }
52 }
53 }
54}
55
56impl From<&str> for Str {
57 fn from(value: &str) -> Self {
58 Self::create_or_get(value)
59 }
60}
61
62impl From<String> for Str {
63 fn from(value: String) -> Self {
64 Self::from(value.as_str())
65 }
66}
67
68impl From<Box<str>> for Str {
69 fn from(value: Box<str>) -> Self {
70 Self::from(value.as_ref())
71 }
72}
73
74impl From<Rc<str>> for Str {
75 fn from(value: Rc<str>) -> Self {
76 Self::from(value.as_ref())
77 }
78}
79
80impl From<Arc<str>> for Str {
81 fn from(value: Arc<str>) -> Self {
82 Self(value)
83 }
84}
85
86impl AsRef<str> for Str {
87 fn as_ref(&self) -> &str {
88 self.0.as_ref()
89 }
90}
91
92impl borrow::Borrow<str> for Str {
93 fn borrow(&self) -> &str {
94 self.0.as_ref()
95 }
96}
97
98impl<T: AsRef<str> + ?Sized> PartialEq<T> for Str {
99 fn eq(&self, other: &T) -> bool {
100 self.as_ref() == other.as_ref()
101 }
102}
103
104impl fmt::Display for Str {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 self.0.as_ref().fmt(f)
107 }
108}
109
110impl fmt::Debug for Str {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 self.0.as_ref().fmt(f)
113 }
114}
115
116#[derive(PartialEq, Eq, Hash, Debug, Clone)]
117pub struct StrPath<'a> {
118 pub is_absolute: bool,
119 pub path: &'a str,
120}
121
122impl<'a> StrPath<'a> {
123 pub const fn absolute(path: &'a str) -> Self {
124 Self {
125 is_absolute: true,
126 path,
127 }
128 }
129
130 pub const fn relative(path: &'a str) -> Self {
131 Self {
132 is_absolute: false,
133 path,
134 }
135 }
136}
137
138impl ops::Deref for StrPath<'_> {
139 type Target = str;
140
141 fn deref(&self) -> &Self::Target {
142 self.path
143 }
144}