javascript_globals/
lib.rs1pub use generated::{GLOBALS, GLOBALS_BUILTIN, GLOBALS_ES2026};
25
26pub struct GlobalSet {
28 members: &'static [u8; generated::GLOBAL_NAME_BYTES],
30 writable: &'static [u16],
32}
33
34impl GlobalSet {
35 pub fn contains_key(&self, key: &str) -> bool {
37 self.global_id(key).is_some()
38 }
39
40 pub fn get(&self, key: &str) -> Option<&'static bool> {
42 let id = self.global_id(key)?;
43 Some(self.writable_value(id))
44 }
45
46 pub fn keys(&self) -> impl Iterator<Item = &'static &'static str> + '_ {
48 self.into_iter().map(|entry| entry.0)
49 }
50}
51
52impl<'a> IntoIterator for &'a GlobalSet {
53 type Item = (&'static &'static str, &'static bool);
54 type IntoIter = GlobalEntries<'a>;
55
56 fn into_iter(self) -> Self::IntoIter {
57 GlobalEntries { set: self, ids: 0..generated::GLOBAL_NAME_COUNT }
58 }
59}
60
61pub struct GlobalEntries<'a> {
63 set: &'a GlobalSet,
64 ids: core::ops::Range<usize>,
65}
66
67impl Iterator for GlobalEntries<'_> {
68 type Item = (&'static &'static str, &'static bool);
69
70 fn next(&mut self) -> Option<Self::Item> {
71 while self.ids.start < self.ids.end {
72 let byte_index = self.ids.start / 8;
73 let byte = self.set.members[byte_index] & (u8::MAX << (self.ids.start % 8));
75 if byte != 0 {
76 let id = byte_index * 8 + byte.trailing_zeros() as usize;
77 if id < self.ids.end {
78 self.ids.start = id + 1;
79 return Some(self.set.entry(id as u16));
80 }
81 }
82 self.ids.start = ((byte_index + 1) * 8).min(self.ids.end);
83 }
84 None
85 }
86}
87
88pub struct Globals;
90
91impl Globals {
92 pub fn entries(&self) -> impl Iterator<Item = (&'static str, &'static GlobalSet)> + '_ {
94 generated::ENVIRONMENTS.iter().copied()
95 }
96
97 pub fn get(&self, key: &str) -> Option<&'static GlobalSet> {
99 generated::get_environment(key)
100 }
101}
102
103mod generated;
104
105struct GlobalNames {
107 seed: u64,
108 pilots: &'static [u8],
109 remap: &'static [u32],
110 names: &'static [u8],
112 offsets: &'static [u16],
114}
115
116impl GlobalNames {
117 fn get(&self, name: &str) -> Option<u16> {
119 let hash = phf_shared::ptrhash::hash(name, &self.seed);
120 let index = phf_shared::ptrhash::get_index(
121 self.seed,
122 hash,
123 self.pilots,
124 self.remap,
125 generated::GLOBAL_NAME_COUNT,
126 ) as usize;
127 (self.name(index) == name).then_some(index as u16)
128 }
129
130 fn name(&self, id: usize) -> &'static str {
131 unsafe {
135 let start = usize::from(*self.offsets.get_unchecked(id));
136 let end = usize::from(*self.offsets.get_unchecked(id + 1));
137 core::str::from_utf8_unchecked(self.names.get_unchecked(start..end))
138 }
139 }
140}
141
142impl GlobalSet {
143 fn global_id(&self, key: &str) -> Option<u16> {
145 let id = generated::GLOBAL_NAMES.get(key)?;
146 self.contains_id(id).then_some(id)
147 }
148
149 fn contains_id(&self, id: u16) -> bool {
150 let id = usize::from(id);
151 self.members[id / 8] & (1 << (id % 8)) != 0
152 }
153
154 fn writable_value(&self, id: u16) -> &'static bool {
155 if self.writable.binary_search(&id).is_ok() { &true } else { &false }
156 }
157
158 fn entry(&self, id: u16) -> (&'static &'static str, &'static bool) {
159 (&generated::GLOBAL_NAME_REFS[usize::from(id)], self.writable_value(id))
160 }
161}