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