intern_mint/
interned.rs

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)]
17/// The main type offered by this crate, responsible for interning slices
18pub struct Interned(Arc<[u8]>);
19
20impl Interned {
21    /// Constructs a new [Interned] for a given `value`
22    ///
23    /// # Example
24    ///
25    /// ```
26    /// use intern_mint::Interned;
27    ///
28    /// let a = Interned::new(b"hello");
29    /// let b = Interned::new(b"hello");
30    ///
31    /// assert_eq!(a.as_ptr(), b.as_ptr());
32    /// ```
33    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}