syntree/
index.rs

1//! Types that can be used to refer to indexes in a [Span][crate::Span].
2
3use core::cmp;
4
5use crate::flavor::Flavor;
6
7mod sealed {
8    pub trait Sealed {}
9
10    impl Sealed for u32 {}
11    impl Sealed for usize {}
12    impl Sealed for crate::empty::Empty {}
13}
14
15/// A type that can be used when referring to an index in a tree.
16///
17/// An index is a valid single component of a [Span][crate::Span], valid indexes
18/// are types such as `u32` and `usize`, but also [`Empty`][crate::Empty] in
19/// case indexing is not required.
20///
21/// See [Builder::new_with][crate::Builder::new_with].
22pub trait Index: Sized + Copy + cmp::Ord + cmp::Eq + self::sealed::Sealed {
23    #[doc(hidden)]
24    const EMPTY: Self;
25
26    #[doc(hidden)]
27    type Length: Length;
28
29    #[doc(hidden)]
30    fn is_empty(&self) -> bool;
31
32    #[doc(hidden)]
33    fn as_usize(self) -> usize;
34
35    #[doc(hidden)]
36    fn checked_add_len(self, other: Self::Length) -> Option<Self>;
37
38    #[doc(hidden)]
39    fn len_to(self, other: Self) -> Self::Length;
40
41    #[doc(hidden)]
42    fn from_usize(value: usize) -> Option<Self>;
43}
44
45#[doc(hidden)]
46pub trait Length: Copy + self::sealed::Sealed {
47    #[doc(hidden)]
48    const EMPTY: Self;
49
50    #[doc(hidden)]
51    fn is_empty(&self) -> bool;
52}
53
54impl Length for usize {
55    const EMPTY: Self = 0;
56
57    #[inline]
58    fn is_empty(&self) -> bool {
59        *self == 0
60    }
61}
62
63/// Ensure u32 is smaller or equal to usize.
64const _: () = assert!(core::mem::size_of::<u32>() <= core::mem::size_of::<usize>());
65
66impl Index for u32 {
67    const EMPTY: Self = 0;
68
69    type Length = usize;
70
71    #[inline]
72    fn is_empty(&self) -> bool {
73        *self == 0
74    }
75
76    #[inline]
77    fn as_usize(self) -> usize {
78        self as usize
79    }
80
81    #[inline]
82    fn checked_add_len(self, other: Self::Length) -> Option<Self> {
83        u32::checked_add(self, u32::try_from(other).ok()?)
84    }
85
86    #[inline]
87    fn len_to(self, other: Self) -> Self::Length {
88        other.saturating_sub(self) as usize
89    }
90
91    #[inline]
92    fn from_usize(value: usize) -> Option<Self> {
93        u32::try_from(value).ok()
94    }
95}
96
97impl Index for usize {
98    const EMPTY: Self = 0;
99
100    type Length = usize;
101
102    #[inline]
103    fn is_empty(&self) -> bool {
104        *self == 0
105    }
106
107    #[inline]
108    fn as_usize(self) -> usize {
109        self
110    }
111
112    #[inline]
113    fn checked_add_len(self, other: Self::Length) -> Option<Self> {
114        usize::checked_add(self, other)
115    }
116
117    #[inline]
118    fn len_to(self, other: Self) -> Self::Length {
119        other.saturating_sub(self)
120    }
121
122    #[inline]
123    fn from_usize(value: usize) -> Option<Self> {
124        Some(value)
125    }
126}
127
128/// A single span index entry for the given [Flavor] `F`.
129#[derive(Debug, Clone, Copy)]
130#[doc(hidden)]
131pub struct TreeIndex<F>
132where
133    F: ?Sized + Flavor,
134{
135    pub(crate) index: F::Index,
136    pub(crate) id: F::Pointer,
137}