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