1extern crate alloc;
2
3use alloc::{
4 borrow::ToOwned as _,
5 boxed::Box,
6 ffi::CString,
7 rc::Rc,
8 string::{String, ToString as _},
9 sync::Arc,
10 vec::Vec,
11};
12use core::ffi::CStr;
13
14pub trait FromRef<Borrowed: ?Sized> {
19 fn from_ref(val: &Borrowed) -> Self;
21}
22
23impl FromRef<str> for Box<str> {
25 fn from_ref(val: &str) -> Self {
26 Self::from(val)
27 }
28}
29impl FromRef<str> for Rc<str> {
30 fn from_ref(val: &str) -> Self {
31 Self::from(val)
32 }
33}
34impl FromRef<str> for Arc<str> {
35 fn from_ref(val: &str) -> Self {
36 Self::from(val)
37 }
38}
39impl FromRef<str> for String {
40 fn from_ref(val: &str) -> Self {
41 val.to_string()
42 }
43}
44
45impl FromRef<CStr> for Box<CStr> {
47 fn from_ref(val: &CStr) -> Self {
48 Self::from(val)
49 }
50}
51impl FromRef<CStr> for Rc<CStr> {
52 fn from_ref(val: &CStr) -> Self {
53 Self::from(val)
54 }
55}
56impl FromRef<CStr> for Arc<CStr> {
57 fn from_ref(val: &CStr) -> Self {
58 Self::from(val)
59 }
60}
61impl FromRef<CStr> for CString {
62 fn from_ref(val: &CStr) -> Self {
63 val.to_owned()
64 }
65}
66
67impl<T: Clone> FromRef<T> for T {
69 fn from_ref(val: &T) -> Self {
70 val.clone()
71 }
72}
73
74impl<T: Clone> FromRef<[T]> for Box<[T]> {
76 fn from_ref(val: &[T]) -> Self {
77 Self::from(val)
78 }
79}
80impl<T: Clone> FromRef<[T]> for Rc<[T]> {
81 fn from_ref(val: &[T]) -> Self {
82 Self::from(val)
83 }
84}
85impl<T: Clone> FromRef<[T]> for Arc<[T]> {
86 fn from_ref(val: &[T]) -> Self {
87 Self::from(val)
88 }
89}
90impl<T: Clone> FromRef<[T]> for Vec<T> {
91 fn from_ref(val: &[T]) -> Self {
92 val.to_vec()
93 }
94}
95
96#[cfg(feature = "std")]
98mod os_impls {
99 extern crate std;
100
101 use alloc::{boxed::Box, rc::Rc, sync::Arc};
102 use std::{
103 ffi::{OsStr, OsString},
104 path::{Path, PathBuf},
105 };
106
107 use super::FromRef;
108
109 impl FromRef<OsStr> for Box<OsStr> {
111 fn from_ref(val: &OsStr) -> Self {
112 Self::from(val)
113 }
114 }
115 impl FromRef<OsStr> for Rc<OsStr> {
116 fn from_ref(val: &OsStr) -> Self {
117 Self::from(val)
118 }
119 }
120 impl FromRef<OsStr> for Arc<OsStr> {
121 fn from_ref(val: &OsStr) -> Self {
122 Self::from(val)
123 }
124 }
125 impl FromRef<OsStr> for OsString {
126 fn from_ref(val: &OsStr) -> Self {
127 val.to_os_string()
128 }
129 }
130
131 impl FromRef<Path> for Box<Path> {
133 fn from_ref(val: &Path) -> Self {
134 Self::from(val)
135 }
136 }
137 impl FromRef<Path> for Rc<Path> {
138 fn from_ref(val: &Path) -> Self {
139 Self::from(val)
140 }
141 }
142 impl FromRef<Path> for Arc<Path> {
143 fn from_ref(val: &Path) -> Self {
144 Self::from(val)
145 }
146 }
147 impl FromRef<Path> for PathBuf {
148 fn from_ref(val: &Path) -> Self {
149 val.to_path_buf()
150 }
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use alloc::{boxed::Box, ffi::CString, rc::Rc, string::String, sync::Arc, vec::Vec};
157 use core::ffi::CStr;
158
159 use ahash::RandomState;
160
161 use crate::{FromRef, Interner};
162
163 #[cfg(feature = "std")]
164 #[test]
165 fn test_from_ref_system_types() {
166 extern crate std;
167 use std::{
168 ffi::{CString, OsStr, OsString},
169 path::{Path, PathBuf},
170 };
171
172 let mut interner = Interner::<PathBuf, RandomState>::new(RandomState::new());
173 let p = Path::new("/tmp/test");
174 let h = interner.intern_ref(p).unwrap();
175 assert_eq!(interner.resolve(h).unwrap(), p);
176
177 let mut os_interner = Interner::<OsString, RandomState>::new(RandomState::new());
178 let o = OsStr::new("test_os_str");
179 let h_os = os_interner.intern_ref(o).unwrap();
180 assert_eq!(os_interner.resolve(h_os).unwrap(), o);
181
182 let mut c_interner = Interner::<CString, RandomState>::new(RandomState::new());
184 let c = c"hello";
185 let h_c = c_interner.intern_ref(c).unwrap();
186 assert_eq!(c_interner.resolve(h_c).unwrap().as_c_str(), c);
187
188 let mut box_path_interner = Interner::<Box<Path>, RandomState>::new(RandomState::new());
190 let h_bp = box_path_interner.intern_ref(p).unwrap();
191 assert_eq!(&**box_path_interner.resolve(h_bp).unwrap(), p);
192 }
193
194 #[test]
195 fn test_from_ref_identity() {
196 let mut interner = Interner::<u32, RandomState>::new(RandomState::new());
199 let val = 42u32;
200 let h = interner.intern_ref(&val).unwrap();
203 assert_eq!(*interner.resolve(h).unwrap(), 42);
204 }
205
206 #[test]
207 fn test_from_ref_slices_generic() {
208 let mut interner = Interner::<Box<[u32]>, RandomState>::new(RandomState::new());
210 let slice: &[u32] = &[1, 2, 3];
211 let h = interner.intern_ref(slice).unwrap();
212 assert_eq!(&**interner.resolve(h).unwrap(), slice);
213
214 let mut rc_interner = Interner::<Rc<[u32]>, RandomState>::new(RandomState::new());
216 let h_rc = rc_interner.intern_ref(slice).unwrap();
217 assert_eq!(&**rc_interner.resolve(h_rc).unwrap(), slice);
218 }
219
220 fn assert_from_ref<
222 B: ?Sized + PartialEq + core::fmt::Debug,
223 O: FromRef<B> + core::borrow::Borrow<B> + core::fmt::Debug + PartialEq,
224 >(
225 borrowed: &B,
226 expected: &O,
227 ) {
228 let converted = O::from_ref(borrowed);
229 assert_eq!(&converted, expected);
230 assert_eq!(converted.borrow(), borrowed);
231 }
232
233 #[test]
234 fn test_str_permutations() {
235 let input = "hello";
236
237 assert_from_ref::<str, String>(input, &String::from("hello"));
239
240 let b: Box<str> = Box::from("hello");
242 assert_from_ref::<str, Box<str>>(input, &b);
243
244 let r: Rc<str> = Rc::from("hello");
246 assert_from_ref::<str, Rc<str>>(input, &r);
247
248 let a: Arc<str> = Arc::from("hello");
250 assert_from_ref::<str, Arc<str>>(input, &a);
251 }
252
253 #[test]
254 fn test_cstr_permutations() {
255 let input = c"hello";
256
257 assert_from_ref::<CStr, CString>(input, &CString::new("hello").unwrap());
259
260 let b: Box<CStr> = Box::from(input);
262 assert_from_ref::<CStr, Box<CStr>>(input, &b);
263
264 let r: Rc<CStr> = Rc::from(input);
266 assert_from_ref::<CStr, Rc<CStr>>(input, &r);
267
268 let a: Arc<CStr> = Arc::from(input);
270 assert_from_ref::<CStr, Arc<CStr>>(input, &a);
271 }
272
273 #[test]
274 fn test_slice_permutations() {
275 let input: &[u8] = &[1, 2, 3];
276
277 assert_from_ref::<[u8], Vec<u8>>(input, &Vec::from(input));
279
280 let b: Box<[u8]> = Box::from(input);
282 assert_from_ref::<[u8], Box<[u8]>>(input, &b);
283
284 let r: Rc<[u8]> = Rc::from(input);
286 assert_from_ref::<[u8], Rc<[u8]>>(input, &r);
287
288 let a: Arc<[u8]> = Arc::from(input);
290 assert_from_ref::<[u8], Arc<[u8]>>(input, &a);
291 }
292
293 #[test]
294 fn test_identity_t() {
295 let input = 42;
297 assert_from_ref::<i32, i32>(&input, &42);
298 }
299
300 #[cfg(feature = "std")]
301 #[test]
302 fn test_os_str_permutations() {
303 extern crate std;
304 use std::ffi::{OsStr, OsString};
305
306 let input = OsStr::new("hello");
307
308 assert_from_ref::<OsStr, OsString>(input, &OsString::from("hello"));
310
311 let b: Box<OsStr> = Box::from(input);
313 assert_from_ref::<OsStr, Box<OsStr>>(input, &b);
314
315 let r: Rc<OsStr> = Rc::from(input);
317 assert_from_ref::<OsStr, Rc<OsStr>>(input, &r);
318
319 let a: Arc<OsStr> = Arc::from(input);
321 assert_from_ref::<OsStr, Arc<OsStr>>(input, &a);
322 }
323
324 #[cfg(feature = "std")]
325 #[test]
326 fn test_path_permutations() {
327 extern crate std;
328 use std::path::{Path, PathBuf};
329
330 let input = Path::new("/tmp/hello");
331
332 assert_from_ref::<Path, PathBuf>(input, &PathBuf::from("/tmp/hello"));
334
335 let b: Box<Path> = Box::from(input);
337 assert_from_ref::<Path, Box<Path>>(input, &b);
338
339 let r: Rc<Path> = Rc::from(input);
341 assert_from_ref::<Path, Rc<Path>>(input, &r);
342
343 let a: Arc<Path> = Arc::from(input);
345 assert_from_ref::<Path, Arc<Path>>(input, &a);
346 }
347}