clang_ast/
intern.rs

1use foldhash::HashSet;
2use serde::de::{DeserializeSeed, Deserializer, Error, Visitor};
3use std::cell::{Cell, RefCell};
4use std::fmt;
5use std::sync::Arc;
6
7const INTERN: ::std::thread::LocalKey<RefCell<HashSet<Arc<str>>>> =
    {
        #[inline]
        fn __init() -> RefCell<HashSet<Arc<str>>> {
            RefCell::new(HashSet::default())
        }
        unsafe {
            ::std::thread::LocalKey::new(const {
                        if ::std::mem::needs_drop::<RefCell<HashSet<Arc<str>>>>() {
                            |init|
                                {
                                    #[thread_local]
                                    static VAL:
                                        ::std::thread::local_impl::LazyStorage<RefCell<HashSet<Arc<str>>>,
                                        ()> =
                                        ::std::thread::local_impl::LazyStorage::new();
                                    VAL.get_or_init(init, __init)
                                }
                        } else {
                            |init|
                                {
                                    #[thread_local]
                                    static VAL:
                                        ::std::thread::local_impl::LazyStorage<RefCell<HashSet<Arc<str>>>,
                                        !> =
                                        ::std::thread::local_impl::LazyStorage::new();
                                    VAL.get_or_init(init, __init)
                                }
                        }
                    })
        }
    };thread_local! {
8    static REFCOUNT: Cell<usize> = const { Cell::new(0) };
9    static INTERN: RefCell<HashSet<Arc<str>>> = RefCell::new(HashSet::default());
10}
11
12fn borrowed(string: &str) -> Arc<str> {
13    do_intern(string)
14}
15
16fn owned(string: String) -> Arc<str> {
17    do_intern(string)
18}
19
20fn do_intern(string: impl AsRef<str> + Into<Arc<str>>) -> Arc<str> {
21    INTERN.with(|intern| {
22        let mut intern = intern.borrow_mut();
23        if let Some(arc) = intern.get(string.as_ref()) {
24            Arc::clone(arc)
25        } else {
26            let arc: Arc<str> = string.into();
27            intern.insert(Arc::clone(&arc));
28            arc
29        }
30    })
31}
32
33pub(crate) struct Guard {
34    _private: (),
35}
36
37pub(crate) fn activate() -> Guard {
38    REFCOUNT.with(|refcount| refcount.set(refcount.get() + 1));
39    Guard { _private: () }
40}
41
42impl Drop for Guard {
43    fn drop(&mut self) {
44        let prev = REFCOUNT.with(|refcount| refcount.replace(refcount.get() - 1));
45        if prev == 1 {
46            crate::loc::thread_local_reset();
47            INTERN.with(|intern| intern.borrow_mut().clear());
48        }
49    }
50}
51
52pub(crate) struct InternVisitor;
53
54impl<'de> Visitor<'de> for InternVisitor {
55    type Value = Arc<str>;
56
57    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
58        formatter.write_str("a string")
59    }
60
61    fn visit_str<E>(self, string: &str) -> Result<Self::Value, E>
62    where
63        E: Error,
64    {
65        Ok(borrowed(string))
66    }
67
68    fn visit_string<E>(self, string: String) -> Result<Self::Value, E>
69    where
70        E: Error,
71    {
72        Ok(owned(string))
73    }
74}
75
76impl<'de> DeserializeSeed<'de> for InternVisitor {
77    type Value = Arc<str>;
78
79    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
80    where
81        D: Deserializer<'de>,
82    {
83        deserializer.deserialize_str(self)
84    }
85}