1use std::{
2 cell::RefCell,
3 collections::HashMap,
4 hash::Hash,
5 ptr,
6 sync::atomic::{AtomicU16, Ordering},
7};
8
9#[derive(Debug, Default)]
15pub struct DomRef(AtomicU16);
16
17thread_local! {
18 static HTML_ELEMENT_MAP: RefCell<HashMap<u16, web_sys::Node>> = RefCell::new(HashMap::new());
19}
20
21impl DomRef {
22 pub fn set(&self, element: web_sys::Node) {
23 HTML_ELEMENT_MAP.with(|map| {
24 let mut map = map.borrow_mut();
25 let current_key = self.0.load(Ordering::Relaxed);
26 let key = if current_key != 0 {
27 current_key
28 } else {
29 let mut key = 1;
30 while map.contains_key(&key) {
31 key += 1;
32 if key == u16::MAX {
33 panic!("Element Map Overflow");
34 }
35 }
36 self.0.store(key, Ordering::Relaxed);
37 key
38 };
39 map.insert(key, element);
40 });
41 }
42
43 pub fn get(&self) -> Option<web_sys::Node> {
52 HTML_ELEMENT_MAP.with(|map| {
53 map.borrow()
54 .get(&self.0.load(Ordering::Relaxed))
55 .map(|element| element.clone())
56 })
57 }
58}
59
60impl Drop for DomRef {
61 fn drop(&mut self) {
62 HTML_ELEMENT_MAP.with(|map| {
63 map.borrow_mut().remove(&self.0.load(Ordering::Relaxed));
64 });
65 }
66}
67
68impl Hash for DomRef {
69 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
70 self.0.load(Ordering::Relaxed).hash(state);
71 }
72}
73
74impl PartialEq for DomRef {
75 fn eq(&self, other: &Self) -> bool {
76 ptr::addr_eq(self.0.as_ptr(), other.0.as_ptr())
77 }
78}