makepad_live_id/
live_id.rs

1#![allow(dead_code)]
2
3use {
4    std::{
5        sync::atomic::{AtomicU64, Ordering},
6        ops::{Index, IndexMut, Deref, DerefMut},
7        collections::{HashMap},
8        sync::Once,
9        sync::Mutex,
10        fmt,
11    }
12};
13
14
15impl LiveIdInterner {
16    pub fn add(&mut self, val: &str) {
17        self.id_to_string.insert(LiveId::from_str(val), val.to_string());
18    }
19    
20    pub fn contains(&mut self, val: &str) -> bool {
21        self.id_to_string.contains_key(&LiveId::from_str(val))
22    }
23    
24    pub fn with<F, R>(f: F) -> R
25    where
26    F: FnOnce(&mut Self) -> R,
27    {
28        static IDMAP: Mutex<Option<LiveIdInterner>> = Mutex::new(None);
29        static ONCE: Once = Once::new();
30        ONCE.call_once( ||{
31            let mut map = LiveIdInterner {
32                //alloc: 0,
33                id_to_string: HashMap::new()
34            };
35            // pre-seed list for debugging purposes
36            let fill = [
37                "default",
38                "exp",
39                "void",
40                "true",
41                "false",
42                "use",
43                "#",
44                "$",
45                "@",
46                "^",
47                "^=",
48                "|",
49                "||",
50                "|=",
51                "%",
52                "%=",
53                "!=",
54                "!",
55                "&&",
56                "*=",
57                "*",
58                "+=",
59                "+",
60                ",",
61                "-=",
62                "->",
63                "-",
64                "..",
65                "...",
66                "..=",
67                ".",
68                "/=",
69                "/",
70                "::",
71                ":",
72                ";",
73                "<=",
74                "<",
75                "<<",
76                "<<=",
77                "==",
78                "=",
79                ">=",
80                "=>",
81                ">",
82                ">>",
83                ">>=",
84                "?",
85                "tracks",
86                "state",
87                "state_id",
88                "user",
89                "play",
90                "ended",
91                "geom_pos",
92                "geom_id",
93                "geom_uv",
94            ];
95            for item in &fill {
96                if map.contains(item) {
97                    eprintln!("WE HAVE AN ID COLLISION!");
98                }
99                map.add(item);
100            }
101            *IDMAP.lock().unwrap() = Some(map)
102        });
103        let mut idmap = IDMAP.lock().unwrap();
104        f(idmap.as_mut().unwrap())
105    }
106}
107
108#[derive(Clone, Default, Eq, Hash, Copy, Ord, PartialOrd, PartialEq)]
109pub struct LiveId(pub u64);
110
111pub const LIVE_ID_SEED:u64 = 0xd6e8_feb8_6659_fd93;
112
113impl LiveId {
114    pub fn empty() -> Self {
115        Self (0)
116    }
117    pub fn from_lo_hi(lo:u32, hi:u32)->Self{
118        Self( (lo as u64) | ((hi as u64)<<32) )
119    }
120    pub fn lo(&self)->u32{
121        (self.0&0xffff_ffff) as u32
122    }
123    pub fn hi(&self)->u32{
124        (self.0>>32) as u32
125    }
126    
127    pub fn seeded()->Self{
128        Self(LIVE_ID_SEED)
129    }
130    
131    pub fn is_unique(&self) -> bool {
132        (self.0 & 0x8000_0000_0000_0000) == 0 && self.0 != 0
133    }
134    
135    pub fn is_ident(&self) -> bool {
136        (self.0 & 0x8000_0000_0000_0000) != 0
137    }
138    
139    pub fn is_empty(&self) -> bool {
140        self.0 == 0
141    }
142
143    pub fn get_value(&self) -> u64 {
144        self.0
145    }
146    
147    // from https://nullprogram.com/blog/2018/07/31/
148    // i have no idea what im doing with start value and finalisation.
149    pub const fn from_bytes(seed:u64, id_bytes: &[u8], start: usize, end: usize) -> Self {
150        let mut x = seed;
151        let mut i = start;
152        while i < end {
153            x = x.overflowing_add(id_bytes[i] as u64).0;
154            x ^= x >> 32;
155            x = x.overflowing_mul(0xd6e8_feb8_6659_fd93).0;
156            x ^= x >> 32;
157            x = x.overflowing_mul(0xd6e8_feb8_6659_fd93).0;
158            x ^= x >> 32;
159            i += 1;
160        }
161        // mark high bit as meaning that this is a hash id
162        Self ((x & 0x7fff_ffff_ffff_ffff) | 0x8000_0000_0000_0000)
163    }
164    
165    pub fn add(&self, what:u64)->Self{
166        Self(self.0 + what)
167    }
168    
169    pub fn xor(&self, what:u64)->Self{
170        Self((self.0 ^ what)| 0x8000_0000_0000_0000)
171    }
172    
173    pub fn sub(&self, what:u64)->Self{
174        Self(self.0 - what)
175    }
176        
177    pub const fn from_str(id_str: &str) -> Self {
178        let bytes = id_str.as_bytes();
179        Self::from_bytes(LIVE_ID_SEED, bytes, 0, bytes.len())
180    }
181    
182    pub const fn from_bytes_lc(seed:u64, id_bytes: &[u8], start: usize, end: usize) -> Self {
183        let mut x = seed;
184        let mut i = start;
185        while i < end {
186            let byte = id_bytes[i];
187            let byte = if byte >= 65 && byte <=90{
188                byte + 32
189            }
190            else{
191                byte
192            };
193            x = x.overflowing_add(byte as u64).0;
194            x ^= x >> 32;
195            x = x.overflowing_mul(0xd6e8_feb8_6659_fd93).0;
196            x ^= x >> 32;
197            x = x.overflowing_mul(0xd6e8_feb8_6659_fd93).0;
198            x ^= x >> 32;
199            i += 1;
200        }
201        // mark high bit as meaning that this is a hash id
202        Self ((x & 0x7fff_ffff_ffff_ffff) | 0x8000_0000_0000_0000)
203    }
204        
205    pub const fn from_str_lc(id_str: &str) -> Self {
206        let bytes = id_str.as_bytes();
207        Self::from_bytes_lc(LIVE_ID_SEED, bytes, 0, bytes.len())
208    }
209    
210    pub const fn str_append(self, id_str: &str) -> Self {
211        let bytes = id_str.as_bytes();
212        Self::from_bytes(self.0, bytes, 0, bytes.len())
213    }
214
215    pub const fn bytes_append(self, bytes: &[u8]) -> Self {
216        Self::from_bytes(self.0, bytes, 0, bytes.len())
217    }
218    
219    pub const fn id_append(self, id: LiveId) -> Self {
220        let bytes = id.0.to_be_bytes();
221        Self::from_bytes(self.0, &bytes, 0, bytes.len())
222    }
223    
224    pub const fn from_str_num(id_str: &str, num:u64) -> Self {
225        let bytes = id_str.as_bytes();
226        let id = Self::from_bytes(LIVE_ID_SEED, bytes, 0, bytes.len());
227        Self::from_bytes(id.0, &num.to_be_bytes(), 0, 8)
228    }
229    
230    pub const fn from_num(seed:u64, num:u64) -> Self {
231        Self::from_bytes(seed, &num.to_be_bytes(), 0, 8)
232    }
233    
234    pub fn from_str_with_lut(id_str: &str) -> Result<Self,
235    String> {
236        let id = Self::from_str(id_str);
237        LiveIdInterner::with( | idmap | {
238            if let Some(stored) = idmap.id_to_string.get(&id) {
239                if stored != id_str {
240                    return Err(stored.clone())
241                }
242            }
243            else {
244                idmap.id_to_string.insert(id, id_str.to_string());
245            }
246            Ok(id)
247        })
248    }
249    
250    pub fn from_str_with_intern(id_str: &str, intern:InternLiveId) -> Self{
251        let id = Self::from_str(id_str);
252        if let InternLiveId::Yes = intern{
253            LiveIdInterner::with( | idmap | {idmap.id_to_string.insert(id, id_str.to_string())});
254        }
255        id
256    }
257    
258    pub fn from_str_num_with_lut(id_str: &str, num:u64) -> Result<Self,
259    String> {
260        let id = Self::from_str_num(id_str, num);
261        LiveIdInterner::with( | idmap | {
262            idmap.id_to_string.insert(id, format!("{}{}",id_str, num));
263            Ok(id)
264        })
265    }
266    
267    pub fn as_string<F, R>(&self, f: F) -> R
268    where F: FnOnce(Option<&str>) -> R
269    {
270        LiveIdInterner::with( | idmap | {
271            match idmap.id_to_string.get(self){
272                Some(v)=>f(Some(v)),
273                None=>f(None)
274            }
275        })
276    }
277
278    pub fn unique() -> Self {
279        LiveId(UNIQUE_LIVE_ID.fetch_add(1, Ordering::SeqCst))
280    }
281}
282 
283#[derive(Clone, Copy)]
284pub enum InternLiveId{
285    Yes,
286    No
287}
288
289pub (crate) static UNIQUE_LIVE_ID: AtomicU64 = AtomicU64::new(1);
290/*
291impl Ord for LiveId {
292    fn cmp(&self, other: &LiveId) -> cmp::Ordering {
293        LiveIdInterner::with( | idmap | {
294            if let Some(id1) = idmap.id_to_string.get(self) {
295                if let Some(id2) = idmap.id_to_string.get(other) {
296                    return id1.cmp(id2)
297                }
298            }
299            cmp::Ordering::Equal
300        })
301    }
302}
303
304impl PartialOrd for LiveId {
305    fn partial_cmp(&self, other: &LiveId) -> Option<cmp::Ordering> {
306        Some(self.cmp(other))
307    }
308}*/
309
310impl fmt::Debug for LiveId {
311    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
312        fmt::Display::fmt(self, f)
313    }
314}
315
316impl fmt::Display for LiveId {
317    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
318        if *self == LiveId::empty() {
319            write!(f, "0")
320        }
321        else if self.is_unique(){
322            write!(f, "UniqueId {}", self.0)
323        }
324        else{
325            self.as_string( | string | {
326                if let Some(id) = string {
327                    write!(f, "{}", id)
328                }
329                else {
330                    write!(f, "{:016x}", self.0)
331                }
332            })
333        }
334    }
335}
336
337impl fmt::LowerHex for LiveId {
338    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
339        fmt::Display::fmt(self, f)
340    }
341}
342
343
344pub struct LiveIdInterner {
345    //alloc: u64,
346    id_to_string: HashMap<LiveId, String>,
347}
348
349// ----------------------------------------------------------------------------
350
351// Idea taken from the `nohash_hasher` crate.
352#[derive(Default)]
353pub struct LiveIdHasher(u64);
354
355impl std::hash::Hasher for LiveIdHasher {
356    fn write(&mut self, _: &[u8]) {
357        unreachable!("Invalid use of IdHasher");
358    }
359    
360    fn write_u8(&mut self, _n: u8) {
361        unreachable!("Invalid use of IdHasher");
362    }
363    fn write_u16(&mut self, _n: u16) {
364        unreachable!("Invalid use of IdHasher");
365    }
366    fn write_u32(&mut self, _n: u32) {
367        unreachable!("Invalid use of IdHasher");
368    }
369    
370    #[inline(always)]
371    fn write_u64(&mut self, n: u64) {
372        self.0 = n;
373    }
374    
375    fn write_usize(&mut self, _n: usize) {
376        unreachable!("Invalid use of IdHasher");
377    }
378    
379    fn write_i8(&mut self, _n: i8) {
380        unreachable!("Invalid use of IdHasher");
381    }
382    fn write_i16(&mut self, _n: i16) {
383        unreachable!("Invalid use of IdHasher");
384    }
385    fn write_i32(&mut self, _n: i32) {
386        unreachable!("Invalid use of IdHasher");
387    }
388    fn write_i64(&mut self, _n: i64) {
389        unreachable!("Invalid use of IdHasher");
390    }
391    fn write_isize(&mut self, _n: isize) {
392        unreachable!("Invalid use of IdHasher");
393    }
394    
395    #[inline(always)]
396    fn finish(&self) -> u64 {
397        self.0
398    }
399}
400
401#[derive(Copy, Clone, Default)]
402pub struct LiveIdHasherBuilder {}
403
404impl std::hash::BuildHasher for LiveIdHasherBuilder {
405    type Hasher = LiveIdHasher;
406    
407    #[inline(always)]
408    fn build_hasher(&self) -> LiveIdHasher {
409        LiveIdHasher::default()
410    }
411}
412
413#[derive(Clone, Debug)]
414pub struct LiveIdMap<K, V> {
415    map: HashMap<K, V, LiveIdHasherBuilder>,
416    //alloc_set: HashSet<K, LiveIdHasherBuilder>
417}
418
419impl<K, V> Default for LiveIdMap<K, V>
420where K: std::cmp::Eq + std::hash::Hash + Copy + From<LiveId> + std::fmt::Debug {
421    fn default() -> Self {
422        Self {
423            map: HashMap::with_hasher(LiveIdHasherBuilder {}),
424            //alloc_set: HashSet::with_hasher(LiveIdHasherBuilder {})
425        }
426    }
427}
428/*
429impl<K, V> LiveIdMap<K, V>
430where K: std::cmp::Eq + std::hash::Hash + Copy + From<LiveId> + std::fmt::Debug
431{
432    pub fn new() -> Self {Self::default()}
433    
434    pub fn alloc_key(&mut self) -> K {
435        loop {
436            let new_id = LiveId::unique().into();
437            if self.map.get(&new_id).is_none() && !self.alloc_set.contains(&new_id) {
438                self.alloc_set.insert(new_id);
439                return new_id
440            }
441        }
442    }
443    
444    pub fn insert_unique(&mut self, value: V) -> K {
445        loop {
446            let new_id = LiveId::unique().into();
447            if self.alloc_set.contains(&new_id) {
448                continue
449            }
450            match self.map.entry(new_id) {
451                Entry::Occupied(_) => continue,
452                Entry::Vacant(v) => {
453                    
454                    v.insert(value);
455                    return new_id
456                }
457            }
458        }
459    }
460    
461    pub fn insert(&mut self, k: impl Into<K>, value: V) {
462        let k = k.into();
463        self.alloc_set.remove(&k);
464        match self.map.entry(k) {
465            Entry::Occupied(_) => panic!("Item {:?} already inserted",k),
466            Entry::Vacant(v) => v.insert(value)
467        };
468    }
469}
470*/
471impl<K, V> Deref for LiveIdMap<K, V>
472where K: std::cmp::Eq + std::hash::Hash + Copy + From<LiveId>
473{
474    type Target = HashMap<K, V, LiveIdHasherBuilder>;
475    fn deref(&self) -> &Self::Target {&self.map}
476}
477
478impl<K, V> DerefMut for LiveIdMap<K, V>
479where K: std::cmp::Eq + std::hash::Hash + Copy + From<LiveId>
480{
481    fn deref_mut(&mut self) -> &mut Self::Target {&mut self.map}
482}
483
484impl<K, V> Index<K> for LiveIdMap<K, V>
485where K: std::cmp::Eq + std::hash::Hash + Copy + From<LiveId>
486{
487    type Output = V;
488    fn index(&self, index: K) -> &Self::Output {
489        self.map.get(&index).unwrap()
490    }
491}
492
493impl<K, V> IndexMut<K> for LiveIdMap<K, V>
494where K: std::cmp::Eq + std::hash::Hash + Copy + From<LiveId>
495{
496    fn index_mut(&mut self, index: K) -> &mut Self::Output {
497        self.map.get_mut(&index).unwrap()
498    }
499}