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);