Skip to main content

cstree/interning/lasso_compat/
traits.rs

1#![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
16// Safety: `InternKey` has the same invariant as `lasso::Key`
17unsafe 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}