cstree/interning/lasso_compat/
traits.rs1#![cfg(feature = "lasso_compat")]
2
3extern crate alloc;
4
5use alloc::format;
6use core::{
7 fmt,
8 hash::{BuildHasher, Hash},
9};
10
11use crate::interning::{
12 TokenKey,
13 traits::{InternKey, Interner, Resolver},
14};
15
16unsafe impl lasso::Key for TokenKey {
18 fn into_usize(self) -> usize {
19 self.into_u32() as usize
20 }
21
22 fn try_from_usize(int: usize) -> Option<Self> {
23 let raw_key = u32::try_from(int).ok()?;
24 Self::try_from_u32(raw_key)
25 }
26}
27
28#[derive(Debug, Clone, PartialEq, Eq, Hash)]
29pub enum LassoCompatError {
30 LassoError(lasso::LassoError),
31 KeyConversionError { lasso_key: usize },
32}
33
34impl From<lasso::LassoError> for LassoCompatError {
35 #[inline]
36 fn from(error: lasso::LassoError) -> Self {
37 Self::LassoError(error)
38 }
39}
40
41impl fmt::Display for LassoCompatError {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 match self {
44 LassoCompatError::LassoError(lasso_error) => write!(f, "{lasso_error}"),
45 LassoCompatError::KeyConversionError { lasso_key } => write!(
46 f,
47 "invalid key: failed to convert `lasso::Key` `{lasso_key}` to `InternKey`"
48 ),
49 }
50 }
51}
52
53impl core::error::Error for LassoCompatError {}
54
55macro_rules! compat_resolver {
56 ($resolver:ident<K$(, $hasher:ident)?> $(where $($t:ident : $bound:ident),+)? $(if #[cfg(feature = $feature:literal)])?) => {
57 $(#[cfg_attr(doc_cfg, doc(cfg(feature = $feature)))])?
58 impl<K$(, $hasher)?> Resolver<TokenKey> for lasso::$resolver<K$(, $hasher)?>
59 where
60 K: lasso::Key,
61 $($($t: $bound),+)?
62 {
63 fn try_resolve(&self, key: TokenKey) -> Option<&str> {
64 let raw_key = TokenKey::into_u32(key);
65 let lasso_key = K::try_from_usize(raw_key as usize)?;
66 <Self as lasso::Resolver<K>>::try_resolve(self, &lasso_key)
67 }
68
69 fn resolve(&self, key: TokenKey) -> &str {
70 let raw_key = TokenKey::into_u32(key);
71 let lasso_key = K::try_from_usize(raw_key as usize).expect(&format!(
72 "invalid key: failed to convert `{key:?}` to `lasso::Key`"
73 ));
74 <Self as lasso::Resolver<K>>::resolve(self, &lasso_key)
75 }
76 }
77 };
78}
79
80macro_rules! compat_interner {
81 ($interner:ident<K, S> $(where $($t:ident : $bound:ident),+)? if #[cfg(feature = $feature:literal)]) => {
82 #[cfg_attr(doc_cfg, doc(cfg(feature = $feature)))]
83 impl<K, S> Interner<TokenKey> for lasso::$interner<K, S>
84 where
85 K: lasso::Key,
86 S: BuildHasher,
87 $($($t: $bound),+)?
88 {
89 type Error = LassoCompatError;
90
91 fn try_get_or_intern(&mut self, text: &str) -> Result<TokenKey, Self::Error> {
92 let lasso_key = <Self as lasso::Interner<K>>::try_get_or_intern(self, text)?;
93 let raw_key = K::into_usize(lasso_key);
94 u32::try_from(raw_key)
95 .ok()
96 .and_then(TokenKey::try_from_u32)
97 .ok_or(LassoCompatError::KeyConversionError { lasso_key: raw_key })
98 }
99
100 fn get_or_intern(&mut self, text: &str) -> TokenKey {
101 let lasso_key = <Self as lasso::Interner<K>>::get_or_intern(self, text);
102 let raw_key = K::into_usize(lasso_key);
103 u32::try_from(raw_key)
104 .ok()
105 .and_then(TokenKey::try_from_u32)
106 .ok_or(LassoCompatError::KeyConversionError { lasso_key: raw_key })
107 .unwrap_or_else(|_| panic!("invalid key: failed to convert `lasso::Key` `{raw_key}` to `InternKey` (failed to intern {text:?})"))
108 }
109 }
110 };
111}
112
113compat_resolver!(RodeoReader<K, S> if #[cfg(feature = "lasso_compat")]);
114compat_resolver!(RodeoResolver<K> if #[cfg(feature = "lasso_compat")]);
115
116compat_resolver!(Rodeo<K, S> if #[cfg(feature = "lasso_compat")]);
117compat_interner!(Rodeo<K, S> if #[cfg(feature = "lasso_compat")]);
118
119#[cfg(feature = "multi_threaded_interning")]
120mod multi_threaded {
121 use super::*;
122
123 compat_resolver!(ThreadedRodeo<K, S> where K: Hash, S: BuildHasher, S: Clone if #[cfg(feature = "multi_threaded_interning")]);
124
125 compat_interner!(ThreadedRodeo<K, S> where K: Hash, S: Clone if #[cfg(feature = "multi_threaded_interning")]);
126
127 #[cfg_attr(doc_cfg, doc(cfg(feature = "multi_threaded_interning")))]
128 impl<K, S> Interner<TokenKey> for &lasso::ThreadedRodeo<K, S>
129 where
130 K: lasso::Key + Hash,
131 S: BuildHasher + Clone,
132 {
133 type Error = <lasso::ThreadedRodeo<K, S> as Interner<TokenKey>>::Error;
134
135 fn try_get_or_intern(&mut self, text: &str) -> Result<TokenKey, Self::Error> {
136 let lasso_key = <Self as lasso::Interner<K>>::try_get_or_intern(self, text)?;
137 let raw_key = K::into_usize(lasso_key);
138 u32::try_from(raw_key)
139 .ok()
140 .and_then(TokenKey::try_from_u32)
141 .ok_or(LassoCompatError::KeyConversionError { lasso_key: raw_key })
142 }
143
144 fn get_or_intern(&mut self, text: &str) -> TokenKey {
145 let lasso_key = <Self as lasso::Interner<K>>::get_or_intern(self, text);
146 let raw_key = K::into_usize(lasso_key);
147 u32::try_from(raw_key)
148 .ok()
149 .and_then(TokenKey::try_from_u32)
150 .ok_or(LassoCompatError::KeyConversionError { lasso_key: raw_key })
151 .unwrap_or_else(|_| panic!("invalid key: failed to convert `lasso::Key` `{raw_key}` to `InternKey` (failed to intern {text:?})"))
152 }
153 }
154}