1use std::{
2 borrow::Borrow,
3 cmp::Ordering,
4 ffi::{OsStr, OsString},
5 hash::{Hash, Hasher},
6 ops::Deref,
7 path::{Path, PathBuf},
8 sync::LazyLock,
9};
10
11use triomphe::Arc;
12
13use crate::{borrow::BorrowedInterned, pool::POOL};
14
15#[derive(Clone, Eq)]
16#[repr(transparent)]
17pub struct Interned(Arc<[u8]>);
19
20impl Interned {
21 pub fn new(value: &[u8]) -> Self {
34 Self(POOL.get_or_insert(value))
35 }
36
37 pub(crate) fn from_existing(value: Arc<[u8]>) -> Self {
38 Self(value)
39 }
40}
41
42pub(crate) static DEFAULT: LazyLock<Interned> = LazyLock::new(|| Interned::new(Default::default()));
43
44impl Default for Interned {
45 fn default() -> Self {
46 DEFAULT.clone()
47 }
48}
49
50impl Drop for Interned {
51 fn drop(&mut self) {
52 POOL.remove_if_needed(&self.0);
53 }
54}
55
56impl Deref for Interned {
57 type Target = BorrowedInterned;
58
59 fn deref(&self) -> &Self::Target {
60 BorrowedInterned::new(self.0.deref())
61 }
62}
63
64impl PartialEq for Interned {
65 fn eq(&self, other: &Self) -> bool {
66 self.deref().eq(other)
67 }
68}
69
70impl Hash for Interned {
71 fn hash<H: Hasher>(&self, state: &mut H) {
72 self.deref().hash(state)
73 }
74}
75
76impl PartialOrd for Interned {
77 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
78 Some(self.cmp(other))
79 }
80}
81
82impl Ord for Interned {
83 fn cmp(&self, other: &Self) -> Ordering {
84 self.deref().cmp(other)
85 }
86}
87
88impl From<&[u8]> for Interned {
89 fn from(value: &[u8]) -> Self {
90 Interned::new(value)
91 }
92}
93impl From<Vec<u8>> for Interned {
94 fn from(value: Vec<u8>) -> Self {
95 value.as_slice().into()
96 }
97}
98
99impl From<&str> for Interned {
100 fn from(value: &str) -> Self {
101 value.as_bytes().into()
102 }
103}
104
105impl From<String> for Interned {
106 fn from(value: String) -> Self {
107 value.as_bytes().into()
108 }
109}
110
111impl From<&String> for Interned {
112 fn from(value: &String) -> Self {
113 value.as_bytes().into()
114 }
115}
116
117impl From<&OsStr> for Interned {
118 fn from(value: &OsStr) -> Self {
119 value.as_encoded_bytes().into()
120 }
121}
122
123impl From<OsString> for Interned {
124 fn from(value: OsString) -> Self {
125 value.as_encoded_bytes().into()
126 }
127}
128
129impl From<&OsString> for Interned {
130 fn from(value: &OsString) -> Self {
131 value.as_encoded_bytes().into()
132 }
133}
134
135impl From<&Path> for Interned {
136 fn from(value: &Path) -> Self {
137 value.as_os_str().into()
138 }
139}
140
141impl From<PathBuf> for Interned {
142 fn from(value: PathBuf) -> Self {
143 value.as_os_str().into()
144 }
145}
146
147impl From<&PathBuf> for Interned {
148 fn from(value: &PathBuf) -> Self {
149 value.as_os_str().into()
150 }
151}
152
153impl Borrow<BorrowedInterned> for Interned {
154 fn borrow(&self) -> &BorrowedInterned {
155 self.deref()
156 }
157}
158
159impl AsRef<BorrowedInterned> for Interned {
160 fn as_ref(&self) -> &BorrowedInterned {
161 self.deref()
162 }
163}