vertigo/dom/
dom_id.rs

1use std::{
2    hash::Hash,
3    sync::atomic::{AtomicBool, Ordering},
4};
5
6use vertigo_macro::AutoJsJson;
7
8const HTML_ID: u64 = 1;
9const HEAD_ID: u64 = 2;
10const BODY_ID: u64 = 3;
11const START_ID: u64 = 4;
12
13fn get_unique_id() -> u64 {
14    use std::sync::atomic::{AtomicU64, Ordering};
15    static COUNTER: AtomicU64 = AtomicU64::new(START_ID);
16    COUNTER.fetch_add(1, Ordering::Relaxed)
17}
18
19// Flags to ensure we have only 1 instance of these elements with predefined id
20static HAD_HTML: AtomicBool = AtomicBool::new(false);
21static HAD_HEAD: AtomicBool = AtomicBool::new(false);
22static HAD_BODY: AtomicBool = AtomicBool::new(false);
23
24#[derive(AutoJsJson, Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
25pub struct DomId(u64);
26
27impl Default for DomId {
28    fn default() -> Self {
29        Self(get_unique_id())
30    }
31}
32
33impl DomId {
34    pub fn from_name(name: &str) -> DomId {
35        let new_id = match name {
36            "html" => maybe_static_id("html", &HAD_HTML, HTML_ID),
37            "head" => maybe_static_id("head", &HAD_HEAD, HEAD_ID),
38            "body" => maybe_static_id("body", &HAD_BODY, BODY_ID),
39            _ => get_unique_id(),
40        };
41
42        DomId(new_id)
43    }
44
45    pub fn root_id() -> DomId {
46        DomId(HTML_ID)
47    }
48
49    pub fn from_u64(id: u64) -> DomId {
50        DomId(id)
51    }
52
53    pub fn to_u64(&self) -> u64 {
54        self.0
55    }
56}
57
58impl std::fmt::Display for DomId {
59    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60        write!(f, "RealDomNodeId={}", self.0)
61    }
62}
63
64fn maybe_static_id(name: &'static str, flag: &'static AtomicBool, static_id: u64) -> u64 {
65    if flag.load(Ordering::Relaxed) {
66        log::error!("Multiple <{name}> elements!");
67        get_unique_id()
68    } else {
69        flag.store(true, Ordering::Relaxed);
70        static_id
71    }
72}