syntree/
pointer.rs

1//! Pointer-related types and traits.
2
3use core::fmt;
4use core::hash;
5
6mod sealed {
7    pub trait Sealed {}
8}
9
10/// A pointer type that is derived from the pointer [Width].
11pub trait Pointer: Sized + Copy + hash::Hash + Eq + fmt::Debug + self::sealed::Sealed {
12    #[doc(hidden)]
13    unsafe fn new_unchecked(value: usize) -> Self;
14
15    /// Safe constructor for the pointer.
16    ///
17    /// Returns [`None`] if the value provided is out of bounds for the pointer type.
18    ///
19    /// # Examples
20    ///
21    /// ```
22    /// use syntree::pointer::{Pointer, PointerU32};
23    ///
24    /// let v = PointerU32::new(0).ok_or("out of bounds")?;
25    /// assert_eq!(v.get(), 0);
26    /// let v = PointerU32::new(42).ok_or("out of bounds")?;
27    /// assert_eq!(v.get(), 42);
28    /// # Ok::<_, Box<dyn core::error::Error>>(())
29    /// ```
30    fn new(value: usize) -> Option<Self>;
31
32    /// Get the index of a pointer.
33    ///
34    /// # Examples
35    ///
36    /// ```
37    /// use syntree::pointer::{Pointer, PointerU32};
38    ///
39    /// let v = PointerU32::new(0).ok_or("out of bounds")?;
40    /// assert_eq!(v.get(), 0);
41    /// let v = PointerU32::new(42).ok_or("out of bounds")?;
42    /// assert_eq!(v.get(), 42);
43    /// # Ok::<_, Box<dyn core::error::Error>>(())
44    /// ```
45    fn get(self) -> usize;
46}
47
48/// A pointer width that can be used to reference other nodes.
49///
50/// This is determined by a primitive unsigned types such as `u32` or `usize`.
51pub trait Width: self::sealed::Sealed {
52    #[doc(hidden)]
53    const EMPTY: Self;
54
55    /// The pointer type associated with a specific width.
56    ///
57    /// # Examples
58    ///
59    /// ```
60    /// use syntree::pointer::Width;
61    ///
62    /// let tree = syntree::tree! {
63    ///     "root1",
64    ///     "root2",
65    /// };
66    ///
67    /// let root1: <usize as Width>::Pointer = tree.first().ok_or("missing root")?.id();
68    /// let root2: <usize as Width>::Pointer = tree.last().ok_or("missing root")?.id();
69    ///
70    /// assert_ne!(root1, root2);
71    ///
72    /// # Ok::<_, Box<dyn core::error::Error>>(())
73    /// ```
74    type Pointer: Pointer;
75}
76
77macro_rules! implement {
78    ($ty:ident, $non_zero:ident, $e:ident) => {
79        impl Width for $ty {
80            const EMPTY: Self = 0;
81            type Pointer = $e;
82        }
83
84        use core::num::$non_zero;
85
86        impl self::sealed::Sealed for $ty {}
87        impl self::sealed::Sealed for $e {}
88
89        #[doc = concat!(" [`Pointer`] implementation for `", stringify!($ty), "`.")]
90        #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
91        #[repr(transparent)]
92        pub struct $e($non_zero);
93
94        impl $e {
95            #[doc = concat!(" Safe constructor for the pointer.")]
96            ///
97            #[doc = concat!(" Returns [`None`] if the value provided is out of bounds for the pointer type.")]
98            ///
99            /// # Examples
100            ///
101            /// ```
102            /// use syntree::pointer::Pointer;
103            #[doc = concat!("use syntree::pointer::", stringify!($e), ";")]
104            ///
105            #[doc = concat!(" let v = ", stringify!($e), "::new(0).ok_or(\"out of bounds\")?;")]
106            /// assert_eq!(v.get(), 0);
107            #[doc = concat!(" let v = ", stringify!($e), "::new(42).ok_or(\"out of bounds\")?;")]
108            /// assert_eq!(v.get(), 42);
109            /// # Ok::<_, Box<dyn core::error::Error>>(())
110            /// ```
111            #[inline]
112            pub fn new(value: usize) -> Option<Self> {
113                let value = <$ty>::try_from(value).ok()?;
114                $non_zero::new(value.wrapping_add(1)).map(Self)
115            }
116
117            #[doc = concat!(" Get the index of a pointer.")]
118            ///
119            /// # Examples
120            ///
121            /// ```
122            /// use syntree::pointer::Pointer;
123            #[doc = concat!("use syntree::pointer::", stringify!($e), ";")]
124            ///
125            #[doc = concat!(" let v = ", stringify!($e), "::new(0).ok_or(\"out of bounds\")?;")]
126            /// assert_eq!(v.get(), 0);
127            #[doc = concat!(" let v = ", stringify!($e), "::new(42).ok_or(\"out of bounds\")?;")]
128            /// assert_eq!(v.get(), 42);
129            /// # Ok::<_, Box<dyn core::error::Error>>(())
130            /// ```
131            #[inline]
132            pub fn get(self) -> usize {
133                self.0.get().wrapping_sub(1) as usize
134            }
135        }
136
137        #[doc = concat!(" Pointer used for `", stringify!($ty), "` type.")]
138        ///
139        /// ```
140        /// use syntree::pointer::Pointer;
141        #[doc = concat!("use syntree::pointer::", stringify!($e), ";")]
142        ///
143        #[doc = concat!(" let v = ", stringify!($e), "::new(0).ok_or(\"out of bounds\")?;")]
144        /// assert_eq!(v.get(), 0);
145        #[doc = concat!(" let v = ", stringify!($e), "::new(42).ok_or(\"out of bounds\")?;")]
146        /// assert_eq!(v.get(), 42);
147        /// # Ok::<_, Box<dyn core::error::Error>>(())
148        /// ```
149        impl crate::pointer::Pointer for $e {
150            /// Unsafely construct a pointer value.
151            ///
152            /// # Safety
153            ///
154            /// Caller must ensure that the value is a legal value for the
155            /// target pointer type.
156            #[inline]
157            unsafe fn new_unchecked(value: usize) -> Self {
158                let value = value as $ty;
159                Self($non_zero::new_unchecked(value.wrapping_add(1)))
160            }
161
162            #[inline]
163            fn new(value: usize) -> Option<Self> {
164                $e::new(value)
165            }
166
167            #[inline]
168            fn get(self) -> usize {
169                $e::get(self)
170            }
171        }
172
173        /// Construct a default value.
174        ///
175        /// ```
176        /// use syntree::pointer::Pointer;
177        #[doc = concat!("use syntree::pointer::", stringify!($e), ";")]
178        ///
179        #[doc = concat!(" let v = ", stringify!($e), "::default();")]
180        /// assert_eq!(v.get(), 0);
181        /// ```
182        impl Default for $e {
183            #[inline]
184            fn default() -> Self {
185                // SAFETY: we know that 1 is a legal value and that it
186                // corresponds to zero.
187                unsafe { Self($non_zero::new_unchecked(1)) }
188            }
189        }
190
191        impl fmt::Debug for $e {
192            #[inline]
193            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194                self.get().fmt(f)
195            }
196        }
197    };
198}
199
200implement!(usize, NonZeroUsize, PointerUsize);
201implement!(u8, NonZeroU8, PointerU8);
202implement!(u16, NonZeroU16, PointerU16);
203implement!(u32, NonZeroU32, PointerU32);
204implement!(u64, NonZeroU64, PointerU64);
205implement!(u128, NonZeroU128, PointerU128);