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
17static 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}