1#![allow(clippy::precedence)]
10
11use crate::cast::{Cast, Conv};
12use crate::window::WindowId;
13use hash_hasher::{HashBuildHasher, HashedMap};
14use std::cell::RefCell;
15use std::cmp::Ordering;
16use std::collections::hash_map::Entry;
17use std::hash::{DefaultHasher, Hash, Hasher};
18use std::iter::once;
19use std::marker::PhantomData;
20use std::mem::size_of;
21use std::num::NonZeroU64;
22use std::rc::Rc;
23use std::{fmt, slice};
24
25thread_local! {
26 static DB: RefCell<HashedMap<u64, *mut usize>> = const { RefCell::new(HashedMap::with_hasher(HashBuildHasher::new())) };
28}
29
30const INVALID: u64 = !0;
32
33const USE_MASK: u64 = 0x3;
35const USE_BITS: u64 = 0x01;
37const USE_PTR: u64 = 0x02;
39
40const MASK_LEN: u64 = 0xF0;
41const SHIFT_LEN: u8 = 4;
42const BLOCKS: u8 = 14;
43const MASK_BITS: u64 = 0xFFFF_FFFF_FFFF_FF00;
44
45const MASK_PTR: u64 = 0xFFFF_FFFF_FFFF_FFFC;
46
47const LEN_MASK: usize = 0xF_FFFF;
48const LEN_INCR: usize = LEN_MASK + 1;
49
50struct IntOrPtr(NonZeroU64, PhantomData<Rc<()>>);
61
62#[derive(Clone, Debug, PartialEq, Eq)]
63enum Variant<'a> {
64 Invalid,
65 Int(u64),
66 Slice(&'a [usize]),
67}
68
69fn hash(path: &[usize]) -> u64 {
70 let mut hasher = DefaultHasher::new();
71 path.hash(&mut hasher);
72 hasher.finish()
73}
74
75impl IntOrPtr {
76 const ROOT: Self = IntOrPtr(NonZeroU64::new(USE_BITS).unwrap(), PhantomData);
77 const INVALID: Self = IntOrPtr(NonZeroU64::new(INVALID).unwrap(), PhantomData);
78
79 #[inline]
80 fn get_ptr(&self) -> Option<*mut usize> {
81 if self.0.get() & USE_MASK == USE_PTR {
82 let p = usize::conv(self.0.get() & MASK_PTR);
83 Some(p as *mut usize)
84 } else {
85 None
86 }
87 }
88
89 fn get_slice(&self) -> Option<&[usize]> {
90 self.get_ptr().map(|p| unsafe {
91 let len = *p.offset(1) & LEN_MASK;
92 let p = p.offset(2);
93 slice::from_raw_parts(p, len)
94 })
95 }
96
97 fn new_int(x: u64) -> Self {
101 assert!(x & USE_MASK == USE_BITS);
102 let x = NonZeroU64::new(x).unwrap();
103 let u = IntOrPtr(x, PhantomData);
104 assert!(u.get_ptr().is_none());
105 u
106 }
107
108 fn new_iter<I: Clone + Iterator<Item = usize>>(iter: I) -> Self {
110 let ref_count = 1;
111 let len = iter.clone().count();
112 let mut v: Vec<usize> = once(ref_count).chain(once(len)).chain(iter).collect();
113
114 let mut p: Option<*mut usize> = None;
115 let pp = &mut p;
116 DB.with_borrow_mut(move |db| {
117 loop {
118 let x = hash(&v);
119 match db.entry(x) {
120 Entry::Occupied(entry) => {
121 let p = *entry.get();
122 let slice = unsafe { slice::from_raw_parts(p.offset(2), *p.offset(1)) };
123 if slice == &v[2..] {
124 unsafe { increment_rc(p) };
125 *pp = Some(p);
126 break;
127 } else {
128 v[1] = v[1].wrapping_add(LEN_INCR);
130 }
131 }
132 Entry::Vacant(entry) => {
133 let p = Box::leak(v.into_boxed_slice()) as *mut [usize] as *mut usize;
134 *pp = Some(p);
135 entry.insert(p);
136 break;
137 }
138 }
139 }
140 });
141
142 let p: u64 = (p.expect("failed to access Id DB") as usize).cast();
143 debug_assert_eq!(p & 3, 0);
144 let p = p | USE_PTR;
145 let u = IntOrPtr(NonZeroU64::new(p).unwrap(), PhantomData);
146 assert!(u.get_ptr().is_some());
147 u
148 }
149
150 fn get(&self) -> Variant<'_> {
151 if let Some(slice) = self.get_slice() {
152 Variant::Slice(slice)
153 } else if self.0.get() == INVALID {
154 Variant::Invalid
155 } else {
156 Variant::Int(self.0.get())
157 }
158 }
159
160 fn to_nzu64(&self) -> NonZeroU64 {
161 if let Some(slice) = self.get_slice() {
162 let x = hash(slice) & MASK_PTR;
163 NonZeroU64::new(x | USE_PTR).unwrap()
164 } else {
165 self.0
166 }
167 }
168
169 fn try_from_u64(n: u64) -> Option<IntOrPtr> {
170 match n & USE_MASK {
171 USE_BITS => {
172 Some(IntOrPtr(NonZeroU64::new(n).unwrap(), PhantomData))
174 }
175 USE_PTR => {
176 let mut result = None;
177 let r = &mut result;
178 DB.with_borrow(|db| {
179 if let Some(p) = db.get(&n) {
180 unsafe { increment_rc(*p) };
181 let p: u64 = (*p as usize).cast();
182 *r = Some(IntOrPtr(NonZeroU64::new(p).unwrap(), PhantomData))
183 }
184 });
185 result
186 }
187 _ if n == !0 => Some(IntOrPtr::INVALID),
188 _ => None,
189 }
190 }
191}
192
193unsafe fn increment_rc(p: *mut usize) {
197 unsafe {
198 let ref_count = *p;
199
200 if ref_count == 0 || ref_count == usize::MAX {
202 std::process::abort();
203 }
204
205 *p = ref_count + 1;
206 }
207}
208
209impl Clone for IntOrPtr {
210 fn clone(&self) -> Self {
211 if let Some(p) = self.get_ptr() {
212 unsafe { increment_rc(p) };
213 }
214 IntOrPtr(self.0, PhantomData)
215 }
216}
217
218impl Drop for IntOrPtr {
219 fn drop(&mut self) {
220 if let Some(p) = self.get_ptr() {
221 unsafe {
222 let ref_count = *p;
223 if ref_count > 1 {
224 *p = ref_count - 1;
225 } else {
226 let len = (*p.offset(1) & LEN_MASK) + 2;
228 let slice = slice::from_raw_parts_mut(p, len);
229
230 let x = hash(slice);
231 DB.with_borrow_mut(|db| db.remove(&x));
232
233 let _ = Box::<[usize]>::from_raw(slice);
234 }
235 }
236 }
237 }
238}
239
240enum PathIter<'a> {
241 Bits(BitsIter),
242 Slice(std::iter::Cloned<std::slice::Iter<'a, usize>>),
243}
244
245impl<'a> Iterator for PathIter<'a> {
246 type Item = usize;
247
248 #[inline]
249 fn next(&mut self) -> Option<usize> {
250 match self {
251 PathIter::Bits(bits) => bits.next(),
252 PathIter::Slice(slice) => slice.next(),
253 }
254 }
255
256 #[inline]
257 fn size_hint(&self) -> (usize, Option<usize>) {
258 match self {
259 PathIter::Bits(bits) => bits.size_hint(),
260 PathIter::Slice(slice) => slice.size_hint(),
261 }
262 }
263}
264
265pub struct WidgetPathIter<'a>(PathIter<'a>);
267impl<'a> Iterator for WidgetPathIter<'a> {
268 type Item = usize;
269
270 #[inline]
271 fn next(&mut self) -> Option<usize> {
272 self.0.next()
273 }
274
275 #[inline]
276 fn size_hint(&self) -> (usize, Option<usize>) {
277 self.0.size_hint()
278 }
279}
280
281#[allow(clippy::assigning_clones)]
320#[derive(Clone)]
321pub struct Id(IntOrPtr);
322
323fn encode(key: usize) -> (u64, u8) {
325 debug_assert!(8 * size_of::<usize>() as u32 - key.leading_zeros() <= 64);
326 let mut x = key as u64 & 0x0000_FFFF_FFFF_FFFF;
327 let mut y = x & 7;
328 x >>= 3;
329 let mut shift = 4;
330 while x != 0 {
331 y |= (8 | (x & 7)) << shift;
332 x >>= 3;
333 shift += 4;
334 }
335 (y, shift)
336}
337
338#[inline]
339fn block_len(x: u64) -> u8 {
340 ((x & MASK_LEN) >> SHIFT_LEN) as u8
341}
342
343fn next_from_bits(mut x: u64) -> (usize, u8) {
345 const TAKE: u64 = 0x7000_0000_0000_0000;
346 const HIGH: u64 = 0x8000_0000_0000_0000;
347 let mut y = (x & TAKE) >> 60;
348 let mut c = 1;
349 while (x & HIGH) != 0 {
350 x <<= 4;
351 y = (y << 3) | ((x & TAKE) >> 60);
352 c += 1;
353 }
354 (y.cast(), c)
355}
356
357#[derive(Clone, Debug)]
358struct BitsIter(u8, u64);
359impl BitsIter {
360 fn new(bits: u64) -> Self {
361 assert!((bits & USE_MASK) == USE_BITS);
362 let len = block_len(bits);
363 BitsIter(len, bits & MASK_BITS)
364 }
365}
366impl Iterator for BitsIter {
367 type Item = usize;
368 fn next(&mut self) -> Option<usize> {
369 if self.0 == 0 {
370 return None;
371 }
372 let (next, blocks) = next_from_bits(self.1);
373 self.0 -= blocks;
374 self.1 <<= 4 * blocks;
375 Some(next)
376 }
377 fn size_hint(&self) -> (usize, Option<usize>) {
378 ((self.0 != 0) as usize, Some(self.0 as usize))
379 }
380}
381
382impl Id {
383 pub(crate) const ROOT: Self = Id(IntOrPtr::ROOT);
385
386 const INVALID: Self = Id(IntOrPtr::INVALID);
387
388 pub fn is_valid(&self) -> bool {
394 self.0.get() != Variant::Invalid
395 }
396
397 pub fn iter(&self) -> WidgetPathIter<'_> {
399 match self.0.get() {
400 Variant::Invalid => panic!("Id::iter: invalid"),
401 Variant::Int(x) => WidgetPathIter(PathIter::Bits(BitsIter::new(x))),
402 Variant::Slice(path) => WidgetPathIter(PathIter::Slice(path.iter().cloned())),
403 }
404 }
405
406 pub fn path_len(&self) -> usize {
408 match self.0.get() {
409 Variant::Invalid => panic!("Id::path_len: invalid"),
410 Variant::Int(x) => BitsIter::new(x).count(),
411 Variant::Slice(path) => path.len(),
412 }
413 }
414
415 pub fn is_ancestor_of(&self, id: &Self) -> bool {
417 match (self.0.get(), id.0.get()) {
418 (Variant::Invalid, _) | (_, Variant::Invalid) => {
419 panic!("Id::is_ancestor_of: invalid")
420 }
421 (Variant::Slice(_), Variant::Int(_)) => {
422 false
424 }
425 (Variant::Int(self_x), Variant::Int(child_x)) => {
426 let self_blocks = block_len(self_x);
427 let child_blocks = block_len(child_x);
428 if self_blocks > child_blocks {
429 return false;
430 }
431
432 let shift = 4 * (BLOCKS - self_blocks) + 8;
434 shift == 64 || self_x >> shift == child_x >> shift
435 }
436 (Variant::Int(self_x), Variant::Slice(child)) => {
437 let iter = BitsIter::new(self_x);
438 iter.zip(child.iter()).all(|(a, b)| a == *b)
439 }
440 (Variant::Slice(self_path), Variant::Slice(child)) => child.starts_with(self_path),
441 }
442 }
443
444 pub fn common_ancestor(&self, id: &Self) -> Self {
446 let mut r = Id::ROOT;
447 for (a, b) in self.iter().zip(id.iter()) {
448 if a != b {
449 break;
450 }
451 r = r.make_child(a);
452 }
453 r
454 }
455
456 pub fn iter_keys_after(&self, id: &Self) -> WidgetPathIter<'_> {
457 let mut self_iter = self.iter();
458 for v in id.iter() {
459 if self_iter.next() != Some(v) {
460 return WidgetPathIter(PathIter::Bits(BitsIter(0, 0)));
461 }
462 }
463 self_iter
464 }
465
466 pub fn next_key_after(&self, id: &Self) -> Option<usize> {
472 match (id.0.get(), self.0.get()) {
473 (Variant::Invalid, _) | (_, Variant::Invalid) => {
474 panic!("Id::next_key_after: invalid")
475 }
476 (Variant::Slice(_), Variant::Int(_)) => None,
477 (Variant::Int(parent_x), Variant::Int(child_x)) => {
478 let parent_blocks = block_len(parent_x);
479 let child_blocks = block_len(child_x);
480 if parent_blocks >= child_blocks {
481 return None;
482 }
483
484 let shift = 4 * (BLOCKS - parent_blocks) + 8;
486 if shift != 64 && parent_x >> shift != child_x >> shift {
487 return None;
488 }
489
490 debug_assert!(child_blocks > 0);
491 let next_bits = (child_x & MASK_BITS) << (4 * parent_blocks);
492 Some(next_from_bits(next_bits).0)
493 }
494 (Variant::Int(parent_x), Variant::Slice(child_path)) => {
495 let iter = BitsIter::new(parent_x);
496 let mut child_iter = child_path.iter();
497 if iter.zip(&mut child_iter).all(|(a, b)| a == *b) {
498 child_iter.next().cloned()
499 } else {
500 None
501 }
502 }
503 (Variant::Slice(parent_path), Variant::Slice(child_path)) => {
504 if child_path.starts_with(parent_path) {
505 child_path[parent_path.len()..].iter().next().cloned()
506 } else {
507 None
508 }
509 }
510 }
511 }
512
513 pub fn parent(&self) -> Option<Id> {
515 match self.0.get() {
516 Variant::Invalid => None,
517 Variant::Int(x) => {
518 let mut bit_len = 4 * block_len(x);
519 while bit_len > 0 {
520 bit_len -= 4;
521 if bit_len > 0 && (x >> (64 - bit_len)) & 8 != 0 {
522 continue;
523 }
524
525 let len = ((bit_len / 4) as u64) << SHIFT_LEN;
526 let mask = MASK_BITS << (56 - bit_len);
527 let id = (x & mask) | len | USE_BITS;
528 return Some(Id(IntOrPtr::new_int(id)));
529 }
530 None
531 }
532 Variant::Slice(path) => {
533 if path.is_empty() {
534 return None;
535 }
536
537 let len = path.len();
538 let path = &path[0..len - 1];
539
540 if len > BLOCKS as usize {
541 Some(Id(IntOrPtr::new_iter(path.iter().cloned())))
542 } else {
543 Some(make_id(path))
544 }
545 }
546 }
547 }
548
549 #[must_use]
554 pub fn make_child(&self, key: usize) -> Self {
555 match self.0.get() {
556 Variant::Invalid => panic!("Id::make_child: invalid"),
557 Variant::Int(self_x) => {
558 let block_len = block_len(self_x);
561 let avail_blocks = BLOCKS - block_len;
562 let req_bits = (8 * size_of::<usize>() as u8 - key.leading_zeros() as u8).max(1);
564 if req_bits <= 3 * avail_blocks {
565 let (bits, bit_len) = encode(key);
566 let used_blocks = bit_len / 4;
567 debug_assert_eq!(used_blocks, req_bits.div_ceil(3));
568 let len = (block_len as u64 + used_blocks as u64) << SHIFT_LEN;
569 let rest = bits << 4 * avail_blocks - bit_len + 8;
570 let id = (self_x & MASK_BITS) | rest | len | USE_BITS;
571 Id(IntOrPtr::new_int(id))
572 } else {
573 Id(IntOrPtr::new_iter(BitsIter::new(self_x).chain(once(key))))
574 }
575 }
576 Variant::Slice(path) => Id(IntOrPtr::new_iter(path.iter().cloned().chain(once(key)))),
577 }
578 }
579
580 pub(crate) fn window_id(&self) -> Option<WindowId> {
584 let index = self.next_key_after(&Id::ROOT)?;
585 WindowId::try_from(index.cast())
586 }
587
588 pub fn to_nzu64(&self) -> NonZeroU64 {
596 self.0.to_nzu64()
597 }
598
599 pub fn try_from_u64(n: u64) -> Option<Id> {
625 IntOrPtr::try_from_u64(n).map(Id)
626 }
627}
628
629impl PartialEq for Id {
630 fn eq(&self, rhs: &Self) -> bool {
631 match (self.0.get(), rhs.0.get()) {
632 (Variant::Invalid, _) | (_, Variant::Invalid) => panic!("Id::eq: invalid id"),
633 (Variant::Int(x), Variant::Int(y)) => x == y,
634 _ => self.iter().eq(rhs.iter()),
635 }
636 }
637}
638impl Eq for Id {}
639
640impl PartialEq<str> for Id {
641 fn eq(&self, rhs: &str) -> bool {
642 let formatted = format!("{self}");
644 formatted == rhs
645 }
646}
647impl PartialEq<&str> for Id {
648 fn eq(&self, rhs: &&str) -> bool {
649 self == *rhs
650 }
651}
652
653impl PartialOrd for Id {
654 fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
655 Some(self.cmp(rhs))
656 }
657}
658
659impl Ord for Id {
660 fn cmp(&self, rhs: &Self) -> Ordering {
661 match (self.0.get(), rhs.0.get()) {
662 (Variant::Invalid, _) | (_, Variant::Invalid) => panic!("Id::cmp: invalid id"),
663 (Variant::Int(x), Variant::Int(y)) => x.cmp(&y),
664 _ => self.iter().cmp(rhs.iter()),
665 }
666 }
667}
668
669impl Hash for Id {
670 fn hash<H: Hasher>(&self, state: &mut H) {
671 match self.0.get() {
672 Variant::Invalid => (),
673 Variant::Int(x) => {
674 x.hash(state);
675 }
676 Variant::Slice(path) => {
677 path.hash(state);
678 }
679 }
680 }
681}
682
683impl PartialEq<Option<Id>> for Id {
684 #[inline]
685 fn eq(&self, rhs: &Option<Id>) -> bool {
686 rhs.as_ref().map(|id| id == self).unwrap_or(false)
687 }
688}
689
690impl<'a> PartialEq<Option<&'a Id>> for Id {
691 #[inline]
692 fn eq(&self, rhs: &Option<&'a Id>) -> bool {
693 rhs.map(|id| id == self).unwrap_or(false)
694 }
695}
696
697impl<'a> PartialEq<&'a Id> for Id {
698 #[inline]
699 fn eq(&self, rhs: &&Id) -> bool {
700 self == *rhs
701 }
702}
703
704impl<'a> PartialEq<&'a Option<Id>> for Id {
705 #[inline]
706 fn eq(&self, rhs: &&Option<Id>) -> bool {
707 self == *rhs
708 }
709}
710
711impl Default for Id {
712 fn default() -> Self {
713 Id::INVALID
714 }
715}
716
717impl fmt::Debug for Id {
718 #[inline]
719 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
720 write!(f, "Id({self})")
721 }
722}
723
724impl fmt::Display for Id {
725 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
726 match self.0.get() {
727 Variant::Invalid => write!(f, "#INVALID"),
728 Variant::Int(x) => {
729 let len = block_len(x);
730 if len == 0 {
731 write!(f, "#")
732 } else {
733 let bits = x >> (4 * (BLOCKS - len) + 8);
734 write!(f, "#{1:0>0$x}", len as usize, bits)
735 }
736 }
737 Variant::Slice(path) => {
738 write!(f, "#")?;
739 for key in path {
740 let (bits, bit_len) = encode(*key);
741 write!(f, "{1:0>0$x}", bit_len as usize / 4, bits)?;
742 }
743 Ok(())
744 }
745 }
746 }
747}
748
749#[cfg(feature = "accesskit")]
753impl From<Id> for accesskit::NodeId {
754 #[inline]
755 fn from(id: Id) -> Self {
756 accesskit::NodeId(id.to_nzu64().get())
757 }
758}
759
760#[cfg(feature = "accesskit")]
764impl From<&Id> for accesskit::NodeId {
765 #[inline]
766 fn from(id: &Id) -> Self {
767 accesskit::NodeId(id.to_nzu64().get())
768 }
769}
770
771pub trait HasId {
780 fn has_id(self) -> Id;
781}
782
783impl HasId for Id {
784 #[inline]
785 fn has_id(self) -> Id {
786 self
787 }
788}
789
790impl HasId for &Id {
791 #[inline]
792 fn has_id(self) -> Id {
793 self.clone()
794 }
795}
796
797impl HasId for &mut Id {
798 #[inline]
799 fn has_id(self) -> Id {
800 self.clone()
801 }
802}
803
804fn make_id(seq: &[usize]) -> Id {
805 let mut id = Id::ROOT;
806 for x in seq {
807 id = id.make_child(*x);
808 }
809 id
810}
811
812#[cfg(test)]
813mod test {
814 use super::*;
815
816 #[test]
817 fn size_of_option_widget_id() {
818 use std::mem::size_of;
819 assert_eq!(size_of::<Id>(), 8);
820 assert_eq!(size_of::<Id>(), size_of::<Option<Id>>());
821 }
822
823 #[test]
824 fn test_partial_eq() {
825 assert_eq!(Id::ROOT, Id::ROOT);
826 let c1 = Id::ROOT.make_child(0).make_child(15);
827 let c2 = Id::ROOT.make_child(1).make_child(15);
828 let c3 = Id::ROOT.make_child(0).make_child(14);
829 let c4 = Id::ROOT.make_child(0).make_child(15);
830 assert!(c1 != c2);
831 assert!(c1 != c3);
832 assert!(c2 != c3);
833 assert_eq!(c1, c4);
834 assert!(c1 != Id::ROOT);
835
836 let d1 = Id(IntOrPtr::new_iter([0, 15].iter().cloned()));
837 let d2 = Id(IntOrPtr::new_iter([1, 15].iter().cloned()));
838 assert_eq!(c1, d1);
839 assert_eq!(c2, d2);
840 assert!(d1 != d2);
841 assert!(d1 != Id::ROOT);
842 }
843
844 #[test]
845 #[should_panic]
846 fn test_partial_eq_invalid_1() {
847 let _ = Id::INVALID == Id::INVALID;
848 }
849
850 #[test]
851 #[should_panic]
852 fn test_partial_eq_invalid_2() {
853 let _ = Id::ROOT == Id::INVALID;
854 }
855
856 #[test]
857 #[should_panic]
858 fn test_partial_eq_invalid_3() {
859 let _ = Id::INVALID == Id::ROOT;
860 }
861
862 #[test]
863 fn test_partial_eq_str() {
864 assert_eq!(Id::ROOT, "#");
865 assert!(Id::ROOT != "#0");
866 assert_eq!(Id::ROOT.make_child(0).make_child(15), "#097");
867 assert_eq!(Id::ROOT.make_child(1).make_child(15), "#197");
868 let c3 = Id::ROOT.make_child(0).make_child(14);
869 assert_eq!(c3, "#096");
870 assert!(c3 != "#097");
871 }
872
873 #[test]
874 fn test_ord() {
875 let root = Id::ROOT;
876 let c_0 = root.make_child(0);
877 let c_0_0 = c_0.make_child(0);
878 assert!(root < c_0);
879 assert!(c_0 < c_0_0);
880
881 let c_1 = root.make_child(1);
882 assert!(c_0_0 < c_1);
883 assert!(c_1 < root.make_child(8));
884
885 let d_0 = Id(IntOrPtr::new_iter([0].iter().cloned()));
886 let d_0_0 = Id(IntOrPtr::new_iter([0, 0].iter().cloned()));
887 let d_1 = Id(IntOrPtr::new_iter([1].iter().cloned()));
888 assert_eq!(d_0.cmp(&c_0), Ordering::Equal);
889 assert_eq!(d_0_0.cmp(&c_0_0), Ordering::Equal);
890 assert_eq!(d_1.cmp(&c_1), Ordering::Equal);
891 assert!(d_0 < d_0_0);
892 assert!(d_0_0 < d_1);
893 }
894
895 #[test]
896 #[should_panic]
897 fn test_ord_invalid() {
898 let _ = Id::INVALID < Id::ROOT;
899 }
900
901 #[test]
902 fn test_next_from_bits() {
903 const REST: u64 = 0x0FFF_FFFF_FFFF_FFFF;
904 assert_eq!(next_from_bits(0), (0, 1));
905 assert_eq!(next_from_bits(REST), (0, 1));
906 assert_eq!(next_from_bits((7 << 60) | REST), (7, 1));
907 assert_eq!(next_from_bits((0xB << 60) | (3 << 56)), (27, 2));
908 assert_eq!(
909 next_from_bits(0xC9A4_F300_0000_0000),
910 ((4 << 9) + (1 << 6) + (2 << 3) + 4, 4)
911 );
912 }
913
914 #[test]
915 fn text_bits_iter() {
916 fn as_vec(x: u64) -> Vec<usize> {
917 BitsIter::new(x).collect()
918 }
919 assert_eq!(as_vec(USE_BITS), Vec::<usize>::new());
920 assert_eq!(as_vec(0x3100_0000_0000_0011), vec![3]);
921 assert_eq!(as_vec(0x1A93_007F_0000_0071), vec![1, 139, 0, 0, 7]);
922 }
923
924 #[test]
925 fn test_parent() {
926 fn test(seq: &[usize]) {
927 let len = seq.len();
928 let id = make_id(&seq[..len - 1]);
929
930 if len == 0 {
931 assert_eq!(id.parent(), None);
932 } else {
933 let id2 = id.make_child(seq[len - 1]);
934 assert_eq!(id2.parent(), Some(id));
935 }
936 }
937
938 test(&[4]);
939 test(&[4, 0]);
940 test(&[0, 0, 0]);
941 test(&[0, 1, 0]);
942 test(&[9, 0, 1, 300]);
943 test(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0]);
944 test(&[313553, 13513, 13511631]);
945 }
946
947 #[test]
948 fn test_make_child() {
949 fn test(seq: &[usize], x: u64) {
950 let id = make_id(seq);
951 let v = id.to_nzu64().get();
952 if v != x {
953 panic!("test({seq:?}, {x:x}): found {v:x}");
954 }
955
956 assert!(id.is_ancestor_of(&id));
958 }
959
960 test(&[], USE_BITS);
961 test(&[0, 0, 0], (3 << 4) | USE_BITS);
962 test(&[0, 1, 0], (3 << 4) | (1 << 56) | USE_BITS);
963 test(&[9, 0, 1, 300], 0x9101cd4000000071);
964 test(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0], 0x12345679091920e1);
965 }
966
967 #[test]
968 fn test_display() {
969 fn from_seq(seq: &[usize]) -> String {
970 format!("{}", make_id(seq))
971 }
972
973 assert_eq!(from_seq(&[]), "#");
974 assert_eq!(from_seq(&[0]), "#0");
975 assert_eq!(from_seq(&[1, 2, 3]), "#123");
976 assert_eq!(from_seq(&[5, 9, 13]), "#59195");
977 assert_eq!(from_seq(&[321]), "#d81");
978 assert_eq!(
979 from_seq(&[313553, 13513, 13511631]),
980 "#99ccba1bab91ebcadf97"
981 )
982 }
983
984 #[test]
985 fn test_is_ancestor() {
986 fn test(seq: &[usize], seq2: &[usize]) {
987 let id = make_id(seq);
988 let mut id2 = id.clone();
989 for x in seq2 {
990 id2 = id2.make_child(*x);
991 }
992 let next = seq2.iter().next().cloned();
993 assert_eq!(id.is_ancestor_of(&id2), next.is_some() || id == id2);
994 assert_eq!(id2.next_key_after(&id), next);
995 }
996
997 test(&[], &[]);
998 test(&[], &[1]);
999 test(&[], &[51930, 2, 18]);
1000 test(&[5, 6, 0, 1, 1], &[]);
1001 test(&[5, 6, 0, 1, 1], &[1, 1]);
1002 test(&[8, 26], &[0]);
1003 test(&[9, 9, 9, 9, 9, 9, 9], &[]);
1004 test(&[9, 9, 9, 9, 9, 9, 9], &[6]);
1005 test(&[9, 9, 9, 9, 9, 9, 9, 9], &[3]);
1006 test(&[0, 2, 2, 0, 17], &[0]);
1007 }
1008
1009 #[test]
1010 fn test_not_ancestor() {
1011 fn test(seq: &[usize], seq2: &[usize]) {
1012 let id = make_id(seq);
1013 let id2 = make_id(seq2);
1014 assert_eq!(id.is_ancestor_of(&id2), false);
1015 assert_eq!(id2.next_key_after(&id), None);
1016 }
1017
1018 test(&[0], &[]);
1019 test(&[0], &[1]);
1020 test(&[2, 10, 1], &[2, 10]);
1021 test(&[0, 5, 2], &[0, 1, 5]);
1022 }
1023
1024 #[test]
1025 fn common_ancestor() {
1026 fn test(seq: &[usize], seq2: &[usize], seq3: &[usize]) {
1027 let id = make_id(seq);
1028 let id2 = make_id(seq2);
1029 assert_eq!(id.common_ancestor(&id2), make_id(seq3));
1030 }
1031
1032 test(&[0], &[], &[]);
1033 test(&[0], &[1, 2], &[]);
1034 test(&[0], &[0, 2], &[0]);
1035 test(&[2, 10, 1], &[2, 10], &[2, 10]);
1036 test(&[0, 5, 2], &[0, 5, 1], &[0, 5]);
1037 }
1038
1039 #[test]
1040 fn deduplicate_allocations() {
1041 let id1 = make_id(&[2, 6, 1, 1, 0, 13, 0, 100, 1000]);
1042 let id2 = make_id(&[2, 6, 1, 1, 0, 13, 0, 100, 1000]);
1043 assert_eq!(id1.0.0, id2.0.0);
1044 }
1045}