vertigo/dom/
dom_id.rs

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