logic_eval_util/
str.rs

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/// Use [`From::from`] to create this type.
11#[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; // This + key in the factory
48        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}