static_id/
static_id.rs

1use crate::symbol::Symbol;
2//use crate::IdCore;
3use once_cell::sync::Lazy;
4//use rustc_hash::AHashMap;
5use ahash::AHashMap;
6use std::{
7    hash::Hash, 
8    hash::Hasher,
9    ptr::eq as ptr_eq
10};
11
12use std::sync::Mutex;
13use serde::{Serialize, Deserialize, Serializer, Deserializer};
14use deepsize::DeepSizeOf;
15
16#[derive(PartialEq, Eq, Hash, Clone, Serialize, Deserialize, Debug, Default)]
17pub struct IdCoreNxM<const N: usize, const M: usize> {
18    pub code: Symbol<N>,
19    pub venue: Symbol<M>,
20}
21
22#[derive(Clone, Copy)]
23pub struct StaticIdNxM<const N: usize, const M: usize> {
24    pub id_ptr: *const IdCoreNxM<N, M>,
25}
26
27impl<const N: usize, const M: usize> DeepSizeOf for StaticIdNxM<N, M> {
28    fn deep_size_of_children(&self, _context: &mut deepsize::Context) -> usize {
29        0
30    }
31}
32// Safety implementations
33unsafe impl<const N: usize, const M: usize> Send for StaticIdNxM<N, M> {}
34unsafe impl<const N: usize, const M: usize> Sync for StaticIdNxM<N, M> {}
35
36// Implement key traits
37impl<const N: usize, const M: usize> std::fmt::Display for StaticIdNxM<N, M> {
38    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39        unsafe {
40            write!(f, "{}@{}", (*self.id_ptr).code, (*self.id_ptr).venue)
41        }
42    }
43}
44
45impl<const N: usize, const M: usize> std::fmt::Debug for StaticIdNxM<N, M> {
46    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47        unsafe {
48            write!(f, "{}@{}", (*self.id_ptr).code, (*self.id_ptr).venue)
49        }
50    }
51}
52
53impl<const N: usize, const M: usize> PartialEq for StaticIdNxM<N, M> {
54    #[inline]
55    fn eq(&self, other: &Self) -> bool {
56        ptr_eq(self.id_ptr, other.id_ptr)
57    }
58}
59
60impl<const N: usize, const M: usize> Eq for StaticIdNxM<N, M> {}
61
62impl<const N: usize, const M: usize> Hash for StaticIdNxM<N, M> {
63    #[inline]
64    fn hash<H: Hasher>(&self, state: &mut H) {
65        self.id_ptr.hash(state);
66    }
67}
68
69impl<const N: usize, const M: usize> StaticIdNxM<N, M> {
70    #[inline]  
71    pub fn len(&self) -> usize {
72        unsafe { (*self.id_ptr).code.len() + (*self.id_ptr).venue.len() }
73    }
74
75    #[inline]
76    pub fn is_empty(&self) -> bool {
77        unsafe { (*self.id_ptr).code.is_empty() && (*self.id_ptr).venue.is_empty() }
78    }
79
80    #[inline]
81    pub fn upper_bound_len(&self) -> usize {
82        unsafe { (*self.id_ptr).code.upper_bound() + (*self.id_ptr).venue.upper_bound() }
83    }
84
85    #[inline]
86    #[must_use]
87    pub fn code_str(&self) -> &str {
88        unsafe { (*self.id_ptr).code.as_str() }
89    }
90
91    #[inline]
92    #[must_use]
93    pub fn venue_str(&self) -> &str {
94        unsafe { (*self.id_ptr).venue.as_str() }
95    }
96}
97
98impl<const N: usize, const M: usize> Serialize for StaticIdNxM<N, M> {
99    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
100    where
101        S: Serializer,
102    {
103        serializer.serialize_str(&self.to_string())
104    }
105}
106
107pub type IdCore16x0 = IdCoreNxM<16, 0>;
108pub type IdCore16x16 = IdCoreNxM<16, 16>;
109pub type IdCore16x32 = IdCoreNxM<16, 32>;
110pub type IdCore16x64 = IdCoreNxM<16, 64>;
111pub type IdCore32x0 = IdCoreNxM<32, 0>;
112pub type IdCore32x16 = IdCoreNxM<32, 16>;
113pub type IdCore32x32 = IdCoreNxM<32, 32>;
114pub type IdCore32x64 = IdCoreNxM<32, 64>;
115pub type IdCore64x0 = IdCoreNxM<64, 0>;
116pub type IdCore64x16 = IdCoreNxM<64, 16>;
117pub type IdCore64x32 = IdCoreNxM<64, 32>;
118pub type IdCore64x64 = IdCoreNxM<64, 64>;
119pub type IdCore = IdCoreNxM<32, 32>;
120
121pub type StaticId16x0 = StaticIdNxM<16, 0>;
122pub type StaticId16x16 = StaticIdNxM<16, 16>;
123pub type StaticId16x32 = StaticIdNxM<16, 32>;
124pub type StaticId16x64 = StaticIdNxM<16, 64>;
125pub type StaticId32x0 = StaticIdNxM<32, 0>;
126pub type StaticId32x16 = StaticIdNxM<32, 16>;
127pub type StaticId32x32 = StaticIdNxM<32, 32>;
128pub type StaticId32x64 = StaticIdNxM<32, 64>;
129pub type StaticId64x0 = StaticIdNxM<64, 0>;
130pub type StaticId64x16 = StaticIdNxM<64, 16>;
131pub type StaticId64x32 = StaticIdNxM<64, 32>;
132pub type StaticId64x64 = StaticIdNxM<64, 64>;
133pub type StaticId = StaticIdNxM<32, 32>;
134
135static ID_CACHE_16X0: Lazy<Mutex<AHashMap<IdCore16x0, &'static IdCore16x0>>> = Lazy::new(|| Mutex::new(AHashMap::default()));
136static DEFAULT_ID_16X0: Lazy<StaticId16x0> = Lazy::new(|| StaticId16x0::from_str(""));
137
138static ID_CACHE_16X16: Lazy<Mutex<AHashMap<IdCore16x16, &'static IdCore16x16>>> = Lazy::new(|| Mutex::new(AHashMap::default()));
139static DEFAULT_ID_16X16: Lazy<StaticId16x16> = Lazy::new(|| StaticId16x16::from_str("", ""));
140
141static ID_CACHE_16X32: Lazy<Mutex<AHashMap<IdCore16x32, &'static IdCore16x32>>> = Lazy::new(|| Mutex::new(AHashMap::default()));
142static DEFAULT_ID_16X32: Lazy<StaticId16x32> = Lazy::new(|| StaticId16x32::from_str("", ""));
143
144static ID_CACHE_16X64: Lazy<Mutex<AHashMap<IdCore16x64, &'static IdCore16x64>>> = Lazy::new(|| Mutex::new(AHashMap::default()));
145static DEFAULT_ID_16X64: Lazy<StaticId16x64> = Lazy::new(|| StaticId16x64::from_str("", ""));
146
147static ID_CACHE_32X0: Lazy<Mutex<AHashMap<IdCore32x0, &'static IdCore32x0>>> = Lazy::new(|| Mutex::new(AHashMap::default()));
148static DEFAULT_ID_32X0: Lazy<StaticId32x0> = Lazy::new(|| StaticId32x0::from_str(""));
149
150static ID_CACHE_32X16: Lazy<Mutex<AHashMap<IdCore32x16, &'static IdCore32x16>>> = Lazy::new(|| Mutex::new(AHashMap::default()));
151static DEFAULT_ID_32X16: Lazy<StaticId32x16> = Lazy::new(|| StaticId32x16::from_str("", ""));
152
153static ID_CACHE_32X32: Lazy<Mutex<AHashMap<IdCore32x32, &'static IdCore32x32>>> = Lazy::new(|| Mutex::new(AHashMap::default()));
154static DEFAULT_ID_32X32: Lazy<StaticId32x32> = Lazy::new(|| StaticId32x32::from_str("", ""));
155
156static ID_CACHE_32X64: Lazy<Mutex<AHashMap<IdCore32x64, &'static IdCore32x64>>> = Lazy::new(|| Mutex::new(AHashMap::default()));
157static DEFAULT_ID_32X64: Lazy<StaticId32x64> = Lazy::new(|| StaticId32x64::from_str("", ""));
158
159static ID_CACHE_64X0: Lazy<Mutex<AHashMap<IdCore64x0, &'static IdCore64x0>>> = Lazy::new(|| Mutex::new(AHashMap::default()));
160static DEFAULT_ID_64X0: Lazy<StaticId64x0> = Lazy::new(|| StaticId64x0::from_str(""));
161
162static ID_CACHE_64X16: Lazy<Mutex<AHashMap<IdCore64x16, &'static IdCore64x16>>> = Lazy::new(|| Mutex::new(AHashMap::default()));
163static DEFAULT_ID_64X16: Lazy<StaticId64x16> = Lazy::new(|| StaticId64x16::from_str("", ""));
164
165static ID_CACHE_64X32: Lazy<Mutex<AHashMap<IdCore64x32, &'static IdCore64x32>>> = Lazy::new(|| Mutex::new(AHashMap::default()));
166static DEFAULT_ID_64X32: Lazy<StaticId64x32> = Lazy::new(|| StaticId64x32::from_str("", ""));
167
168static ID_CACHE_64X64: Lazy<Mutex<AHashMap<IdCore64x64, &'static IdCore64x64>>> = Lazy::new(|| Mutex::new(AHashMap::default()));
169static DEFAULT_ID_64X64: Lazy<StaticId64x64> = Lazy::new(|| StaticId64x64::from_str("", ""));
170
171impl StaticId16x0 {
172    #[inline]
173    #[must_use]
174    pub fn from_str(code: &str) -> Self {
175        let id = IdCore16x0 {
176            code: Symbol::from(code),
177            venue: Symbol::from(""),
178
179        };
180        let mut cache = ID_CACHE_16X0.lock().unwrap();
181        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
182        StaticId16x0 { id_ptr: interned as *const IdCore16x0 }
183    }
184
185    #[inline]
186    #[must_use]
187    pub fn from_bytes(code: &[u8]) -> Self {
188        let id = IdCore16x0 {
189            code: Symbol::from(code),
190            venue: Symbol::from(""),
191        };
192        let mut cache = ID_CACHE_16X0.lock().unwrap();
193        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
194        StaticId16x0 { id_ptr: interned as *const IdCore16x0 }
195    }
196
197    #[inline]
198    pub fn cache_len() -> usize {
199        ID_CACHE_16X0.lock().unwrap().len()
200    }
201
202    #[inline]
203    pub fn get_id(&self) -> &IdCore16x0 {
204        unsafe { &*self.id_ptr }
205    }
206}
207
208impl Default for StaticId16x0 {
209    fn default() -> Self {
210        *DEFAULT_ID_16X0
211    }
212}
213
214impl StaticId32x0 {
215    #[inline]
216    #[must_use]
217    pub fn from_str(code: &str) -> Self {
218        let id = IdCore32x0 {
219            code: Symbol::from(code),
220            venue: Symbol::from(""),
221        };
222
223        let mut cache = ID_CACHE_32X0.lock().unwrap();
224        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
225        StaticId32x0 { id_ptr: interned as *const IdCore32x0 }
226    }
227
228    #[inline]
229    #[must_use]
230    pub fn from_bytes(code: &[u8]) -> Self {
231        let id = IdCore32x0 {
232            code: Symbol::from(code),
233            venue: Symbol::from(""),
234        };
235        let mut cache = ID_CACHE_32X0.lock().unwrap();
236        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
237        StaticId32x0 { id_ptr: interned as *const IdCore32x0 }
238    }
239
240    #[inline]
241    pub fn cache_len() -> usize {
242        ID_CACHE_32X0.lock().unwrap().len()
243    }
244
245    #[inline]
246    pub fn get_id(&self) -> &IdCore32x0 {
247        unsafe { &*self.id_ptr }
248    }
249}
250
251impl Default for StaticId32x0 {
252    fn default() -> Self {
253        *DEFAULT_ID_32X0
254    }
255}
256
257impl StaticId64x0 {
258    #[inline]
259    #[must_use]
260    pub fn from_str(code: &str) -> Self {
261        let id = IdCore64x0 {
262            code: Symbol::from(code),
263            venue: Symbol::from(""),
264        };
265        let mut cache = ID_CACHE_64X0.lock().unwrap();
266        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
267        StaticId64x0 { id_ptr: interned as *const IdCore64x0 }
268    }
269
270    #[inline]
271    #[must_use]
272    pub fn from_bytes(code: &[u8]) -> Self {
273        let id = IdCore64x0 {
274            code: Symbol::from(code),
275            venue: Symbol::from(""),
276        };
277        let mut cache = ID_CACHE_64X0.lock().unwrap();
278        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
279        StaticId64x0 { id_ptr: interned as *const IdCore64x0 }
280    }
281
282    #[inline]
283    pub fn cache_len() -> usize {
284        ID_CACHE_64X0.lock().unwrap().len()
285    }
286
287    #[inline]
288    pub fn get_id(&self) -> &IdCore64x0 {
289        unsafe { &*self.id_ptr }
290    }
291}
292
293impl Default for StaticId64x0 {
294    fn default() -> Self {
295        *DEFAULT_ID_64X0
296    }
297}
298
299impl StaticId16x16 {
300    #[inline]
301    #[must_use]
302    pub fn from_str(code: &str, venue: &str) -> Self {
303        let id = IdCore16x16 {
304            code: Symbol::from(code),
305            venue: Symbol::from(venue),
306        };
307        let mut cache = ID_CACHE_16X16.lock().unwrap();
308        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
309        StaticId16x16 { id_ptr: interned as *const IdCore16x16 }
310    }
311
312    #[inline]
313    #[must_use]
314    pub fn from_bytes(code: &[u8], venue: &[u8]) -> Self {
315        let id = IdCore16x16 {
316            code: Symbol::from(code),
317            venue: Symbol::from(venue),
318        };
319        let mut cache = ID_CACHE_16X16.lock().unwrap();
320        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
321        StaticId16x16 { id_ptr: interned as *const IdCore16x16 }
322    }
323
324    #[inline]
325    #[must_use]
326    pub fn from_combined_str(combined: &str) -> Self {
327        let (code, venue) = combined.split_at(combined.find('@').unwrap());
328        let venue = &venue[1..];
329        Self::from_str(code, venue)
330    }
331
332    #[inline]
333    pub fn cache_len() -> usize {
334        ID_CACHE_16X16.lock().unwrap().len()
335    }
336
337    #[inline]
338    pub fn get_id(&self) -> &IdCore16x16 {
339        unsafe { &*self.id_ptr }
340    }
341}
342
343impl Default for StaticId16x16 {
344    fn default() -> Self {
345        *DEFAULT_ID_16X16
346    }
347}
348
349impl<'de> Deserialize<'de> for StaticId16x16 {
350    fn deserialize<D>(deserializer: D) -> Result<StaticId16x16, D::Error>
351    where
352        D: Deserializer<'de>,
353    {
354        let s = String::deserialize(deserializer)?;
355        Ok(StaticId16x16::from_combined_str(&s))
356    }
357}
358
359// 16x32
360
361impl StaticId16x32 {
362    #[inline]
363    #[must_use]
364    pub fn from_str(code: &str, venue: &str) -> Self {
365        let id = IdCore16x32 {
366            code: Symbol::from(code),
367            venue: Symbol::from(venue),
368        };
369        let mut cache = ID_CACHE_16X32.lock().unwrap();
370        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
371        StaticId16x32 { id_ptr: interned as *const IdCore16x32 }
372    }
373
374    #[inline]
375    #[must_use]
376    pub fn from_bytes(code: &[u8], venue: &[u8]) -> Self {
377        let id = IdCore16x32 {
378            code: Symbol::from(code),
379            venue: Symbol::from(venue),
380        };
381        let mut cache = ID_CACHE_16X32.lock().unwrap();
382        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
383        StaticId16x32 { id_ptr: interned as *const IdCore16x32 }
384    }
385
386    #[inline]
387    #[must_use]
388    pub fn from_combined_str(combined: &str) -> Self {
389        let (code, venue) = combined.split_at(combined.find('@').unwrap());
390        let venue = &venue[1..];
391        Self::from_str(code, venue)
392    }
393
394    #[inline]
395    pub fn cache_len() -> usize {
396        ID_CACHE_16X32.lock().unwrap().len()
397    }
398
399    #[inline]
400    pub fn get_id(&self) -> &IdCore16x32 {
401        unsafe { &*self.id_ptr }
402    }
403}
404
405impl Default for StaticId16x32 {
406    fn default() -> Self {
407        *DEFAULT_ID_16X32
408    }
409}
410
411impl<'de> Deserialize<'de> for StaticId16x32 {
412    fn deserialize<D>(deserializer: D) -> Result<StaticId16x32, D::Error>
413    where
414        D: Deserializer<'de>,
415    {
416        let s = String::deserialize(deserializer)?;
417        Ok(StaticId16x32::from_combined_str(&s))
418    }
419}
420// 16x64
421impl StaticId16x64 {
422    #[inline]
423    #[must_use]
424    pub fn from_str(code: &str, venue: &str) -> Self {
425        let id = IdCore16x64 {
426            code: Symbol::from(code),
427            venue: Symbol::from(venue),
428        };
429        let mut cache = ID_CACHE_16X64.lock().unwrap();
430        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
431        StaticId16x64 { id_ptr: interned as *const IdCore16x64 }
432    }
433
434    #[inline]
435    #[must_use]
436    pub fn from_bytes(code: &[u8], venue: &[u8]) -> Self {
437        let id = IdCore16x64 {
438            code: Symbol::from(code),
439            venue: Symbol::from(venue),
440        };
441        let mut cache = ID_CACHE_16X64.lock().unwrap();
442        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
443        StaticId16x64 { id_ptr: interned as *const IdCore16x64 }
444    }
445
446    #[inline]
447    #[must_use]
448    pub fn from_combined_str(combined: &str) -> Self {
449        let (code, venue) = combined.split_at(combined.find('@').unwrap());
450        let venue = &venue[1..];
451        Self::from_str(code, venue)
452    }
453
454    #[inline]
455    pub fn cache_len() -> usize {
456        ID_CACHE_16X64.lock().unwrap().len()
457    }
458
459    #[inline]
460    pub fn get_id(&self) -> &IdCore16x64 {
461        unsafe { &*self.id_ptr }
462    }
463}
464
465impl Default for StaticId16x64 {
466    fn default() -> Self {
467        *DEFAULT_ID_16X64
468    }
469}
470
471impl<'de> Deserialize<'de> for StaticId16x64 {
472    fn deserialize<D>(deserializer: D) -> Result<StaticId16x64, D::Error>
473    where
474        D: Deserializer<'de>,
475    {
476        let s = String::deserialize(deserializer)?;
477        Ok(StaticId16x64::from_combined_str(&s))
478    }
479}
480
481// 32x16
482impl StaticId32x16 {
483    #[inline]
484    #[must_use]
485    pub fn from_str(code: &str, venue: &str) -> Self {
486        let id = IdCore32x16 {
487            code: Symbol::from(code),
488            venue: Symbol::from(venue),
489        };
490        let mut cache = ID_CACHE_32X16.lock().unwrap();
491        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
492        StaticId32x16 { id_ptr: interned as *const IdCore32x16 }
493    }
494
495    #[inline]
496    #[must_use]
497    pub fn from_bytes(code: &[u8], venue: &[u8]) -> Self {
498        let id = IdCore32x16 {
499            code: Symbol::from(code),
500            venue: Symbol::from(venue),
501        };
502        let mut cache = ID_CACHE_32X16.lock().unwrap();
503        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
504        StaticId32x16 { id_ptr: interned as *const IdCore32x16 }
505    }
506
507    #[inline]
508    #[must_use]
509    pub fn from_combined_str(combined: &str) -> Self {
510        let (code, venue) = combined.split_at(combined.find('@').unwrap());
511        let venue = &venue[1..];
512        Self::from_str(code, venue)
513    }
514
515    #[inline]
516    pub fn cache_len() -> usize {
517        ID_CACHE_32X16.lock().unwrap().len()
518    }
519
520    #[inline]
521    pub fn get_id(&self) -> &IdCore32x16 {
522        unsafe { &*self.id_ptr }
523    }
524}
525
526impl Default for StaticId32x16 {
527    fn default() -> Self {
528        *DEFAULT_ID_32X16
529    }
530}
531
532impl<'de> Deserialize<'de> for StaticId32x16 {
533    fn deserialize<D>(deserializer: D) -> Result<StaticId32x16, D::Error>
534    where
535        D: Deserializer<'de>,
536    {
537        let s = String::deserialize(deserializer)?;
538        Ok(StaticId32x16::from_combined_str(&s))
539    }
540}
541
542// 32x32
543
544impl StaticId32x32 {
545    #[inline]
546    #[must_use]
547    pub fn from_str(code: &str, venue: &str) -> Self {
548        let id = IdCore32x32 {
549            code: Symbol::from(code),
550            venue: Symbol::from(venue),
551        };
552        let mut cache = ID_CACHE_32X32.lock().unwrap();
553        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
554        StaticId32x32 { id_ptr: interned as *const IdCore32x32 }
555    }
556
557    #[inline]
558    #[must_use]
559    pub fn from_bytes(code: &[u8], venue: &[u8]) -> Self {
560        let id = IdCore32x32 {
561            code: Symbol::from(code),
562            venue: Symbol::from(venue),
563        };
564        let mut cache = ID_CACHE_32X32.lock().unwrap();
565        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
566        StaticId32x32 { id_ptr: interned as *const IdCore32x32 }
567    }
568
569    #[inline]
570    #[must_use]
571    pub fn from_combined_str(combined: &str) -> Self {
572        let (code, venue) = combined.split_at(combined.find('@').unwrap());
573        let venue = &venue[1..];
574        Self::from_str(code, venue)
575    }
576
577    #[inline]
578    pub fn cache_len() -> usize {
579        ID_CACHE_32X32.lock().unwrap().len()
580    }
581
582    #[inline]
583    pub fn get_id(&self) -> &IdCore32x32 {
584        unsafe { &*self.id_ptr }
585    }
586}
587
588impl Default for StaticId32x32 {
589    fn default() -> Self {
590        *DEFAULT_ID_32X32
591    }
592}
593
594impl<'de> Deserialize<'de> for StaticId32x32 {
595    fn deserialize<D>(deserializer: D) -> Result<StaticId32x32, D::Error>
596    where
597        D: Deserializer<'de>,
598    {
599        let s = String::deserialize(deserializer)?;
600        Ok(StaticId32x32::from_combined_str(&s))
601    }
602}
603
604// 32x64
605
606impl StaticId32x64 {
607    #[inline]
608    #[must_use]
609    pub fn from_str(code: &str, venue: &str) -> Self {
610        let id = IdCore32x64 {
611            code: Symbol::from(code),
612            venue: Symbol::from(venue),
613        };
614        let mut cache = ID_CACHE_32X64.lock().unwrap();
615        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
616        StaticId32x64 { id_ptr: interned as *const IdCore32x64 }
617    }
618
619    #[inline]
620    #[must_use]
621    pub fn from_bytes(code: &[u8], venue: &[u8]) -> Self {
622        let id = IdCore32x64 {
623            code: Symbol::from(code),
624            venue: Symbol::from(venue),
625        };
626        let mut cache = ID_CACHE_32X64.lock().unwrap();
627        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
628        StaticId32x64 { id_ptr: interned as *const IdCore32x64 }
629    }
630
631    #[inline]
632    #[must_use]
633    pub fn from_combined_str(combined: &str) -> Self {
634        let (code, venue) = combined.split_at(combined.find('@').unwrap());
635        let venue = &venue[1..];
636        Self::from_str(code, venue)
637    }
638
639    #[inline]
640    pub fn cache_len() -> usize {
641        ID_CACHE_32X64.lock().unwrap().len()
642    }
643
644    #[inline]
645    pub fn get_id(&self) -> &IdCore32x64 {
646        unsafe { &*self.id_ptr }
647    }
648}
649
650impl Default for StaticId32x64 {
651    fn default() -> Self {
652        *DEFAULT_ID_32X64
653    }
654}
655
656impl<'de> Deserialize<'de> for StaticId32x64 {
657    fn deserialize<D>(deserializer: D) -> Result<StaticId32x64, D::Error>
658    where
659        D: Deserializer<'de>,
660    {
661        let s = String::deserialize(deserializer)?;
662        Ok(StaticId32x64::from_combined_str(&s))
663    }
664}
665
666// 64x16
667
668impl StaticId64x16 {
669    #[inline]
670    #[must_use]
671    pub fn from_str(code: &str, venue: &str) -> Self {
672        let id = IdCore64x16 {
673            code: Symbol::from(code),
674            venue: Symbol::from(venue),
675        };
676        let mut cache = ID_CACHE_64X16.lock().unwrap();
677        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
678        StaticId64x16 { id_ptr: interned as *const IdCore64x16 }
679    }
680
681    #[inline]
682    #[must_use]
683    pub fn from_bytes(code: &[u8], venue: &[u8]) -> Self {
684        let id = IdCore64x16 {
685            code: Symbol::from(code),
686            venue: Symbol::from(venue),
687        };
688        let mut cache = ID_CACHE_64X16.lock().unwrap();
689        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
690        StaticId64x16 { id_ptr: interned as *const IdCore64x16 }
691    }
692
693    #[inline]
694    #[must_use]
695    pub fn from_combined_str(combined: &str) -> Self {
696        let (code, venue) = combined.split_at(combined.find('@').unwrap());
697        let venue = &venue[1..];
698        Self::from_str(code, venue)
699    }
700
701    #[inline]
702    pub fn cache_len() -> usize {
703        ID_CACHE_64X16.lock().unwrap().len()
704    }
705
706    #[inline]
707    pub fn get_id(&self) -> &IdCore64x16 {
708        unsafe { &*self.id_ptr }
709    }
710}
711
712impl Default for StaticId64x16 {
713    fn default() -> Self {
714        *DEFAULT_ID_64X16
715    }
716}
717
718impl<'de> Deserialize<'de> for StaticId64x16 {
719    fn deserialize<D>(deserializer: D) -> Result<StaticId64x16, D::Error>
720    where
721        D: Deserializer<'de>,
722    {
723        let s = String::deserialize(deserializer)?;
724        Ok(StaticId64x16::from_combined_str(&s))
725    }
726}
727
728// 64x32
729
730impl StaticId64x32 {
731    #[inline]
732    #[must_use]
733    pub fn from_str(code: &str, venue: &str) -> Self {
734        let id = IdCore64x32 {
735            code: Symbol::from(code),
736            venue: Symbol::from(venue),
737        };
738        let mut cache = ID_CACHE_64X32.lock().unwrap();
739        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
740        StaticId64x32 { id_ptr: interned as *const IdCore64x32 }
741    }
742
743    #[inline]
744    #[must_use]
745    pub fn from_bytes(code: &[u8], venue: &[u8]) -> Self {
746        let id = IdCore64x32 {
747            code: Symbol::from(code),
748            venue: Symbol::from(venue),
749        };
750        let mut cache = ID_CACHE_64X32.lock().unwrap();
751        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
752        StaticId64x32 { id_ptr: interned as *const IdCore64x32 }
753    }
754
755    #[inline]
756    #[must_use]
757    pub fn from_combined_str(combined: &str) -> Self {
758        let (code, venue) = combined.split_at(combined.find('@').unwrap());
759        let venue = &venue[1..];
760        Self::from_str(code, venue)
761    }
762
763    #[inline]
764    pub fn cache_len() -> usize {
765        ID_CACHE_64X32.lock().unwrap().len()
766    }
767
768    #[inline]
769    pub fn get_id(&self) -> &IdCore64x32 {
770        unsafe { &*self.id_ptr }
771    }
772}
773
774impl Default for StaticId64x32 {
775    fn default() -> Self {
776        *DEFAULT_ID_64X32
777    }
778}
779
780impl<'de> Deserialize<'de> for StaticId64x32 {
781    fn deserialize<D>(deserializer: D) -> Result<StaticId64x32, D::Error>
782    where
783        D: Deserializer<'de>,
784    {
785        let s = String::deserialize(deserializer)?;
786        Ok(StaticId64x32::from_combined_str(&s))
787    }
788}
789
790// 64x64
791
792impl StaticId64x64 {
793    #[inline]
794    #[must_use]
795    pub fn from_str(code: &str, venue: &str) -> Self {
796        let id = IdCore64x64 {
797            code: Symbol::from(code),
798            venue: Symbol::from(venue),
799        };
800        let mut cache = ID_CACHE_64X64.lock().unwrap();
801        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
802        StaticId64x64 { id_ptr: interned as *const IdCore64x64 }
803    }
804
805    #[inline]
806    #[must_use]
807    pub fn from_bytes(code: &[u8], venue: &[u8]) -> Self {
808        let id = IdCore64x64 {
809            code: Symbol::from(code),
810            venue: Symbol::from(venue),
811        };
812        let mut cache = ID_CACHE_64X64.lock().unwrap();
813        let interned = *cache.entry(id.clone()).or_insert_with(|| Box::leak(Box::new(id)));
814        StaticId64x64 { id_ptr: interned as *const IdCore64x64 }
815    }
816
817    #[inline]
818    #[must_use]
819    pub fn from_combined_str(combined: &str) -> Self {
820        let (code, venue) = combined.split_at(combined.find('@').unwrap());
821        let venue = &venue[1..];
822        Self::from_str(code, venue)
823    }
824
825    #[inline]
826    pub fn cache_len() -> usize {
827        ID_CACHE_64X64.lock().unwrap().len()
828    }
829
830    #[inline]
831    pub fn get_id(&self) -> &IdCore64x64 {
832        unsafe { &*self.id_ptr }
833    }
834}
835
836impl Default for StaticId64x64 {
837    fn default() -> Self {
838        *DEFAULT_ID_64X64
839    }
840}
841
842impl<'de> Deserialize<'de> for StaticId64x64 {
843    fn deserialize<D>(deserializer: D) -> Result<StaticId64x64, D::Error>
844    where
845        D: Deserializer<'de>,
846    {
847        let s = String::deserialize(deserializer)?;
848        Ok(StaticId64x64::from_combined_str(&s))
849    }
850}