1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
#[cfg(feature = "alloc")]
pub(crate) use lazy_collections::{
LazierIterator,
LazyVecQueue,
LazyVecStack,
};
pub(crate) use non_advancing_iterator::NonAdvancingIterator;
pub use ref_id::RefId;
mod ref_id
{
use core::{
cmp::Ordering,
hash::Hash,
ops::Deref,
ptr,
};
/// Compare and hash references by pointer.
///
/// This should be used as the [`Node::Id`](crate::Node::Id), instead of `*const U`, where
/// possible, where `T` is some type of reference to the primary inner type `U` of an `N:
/// Node` (and must not be a reference to an `N` itself). This is safer for avoiding logic
/// bugs, because it keeps any lifetimes of `T`. While `*const U` can be safely used for some
/// types, it is not guaranteed that some refactoring does not invalidate the (imaginary)
/// lifetime of such a pointer. (This crate is `forbid(unsafe_code)` but since such pointers
/// would only be used as identifiers (and never dereferenced), such lifetime logic bugs could
/// become hypothetically possible).
///
/// If the `T` type is a "fat" reference, the additional metadata is compared and hashed,
/// because such values with differing metadata could have different behavior and should be
/// considered distinct.
#[derive(Copy, Clone)]
#[allow(clippy::exhaustive_structs)]
pub struct RefId<T>(pub T);
impl<T: Deref> RefId<T>
{
#[inline]
fn as_ptr(&self) -> *const T::Target
{
let p: *const T::Target = {
let r: &T::Target = &*self.0;
r
};
p
}
}
impl<T: Deref> PartialEq for RefId<T>
{
#[inline]
fn eq(
&self,
other: &Self,
) -> bool
{
ptr::eq(self.as_ptr(), other.as_ptr())
}
}
impl<T: Deref> Eq for RefId<T> {}
impl<T: Deref> Hash for RefId<T>
{
#[inline]
fn hash<H: core::hash::Hasher>(
&self,
state: &mut H,
)
{
ptr::hash(self.as_ptr(), state);
}
}
impl<T: Deref> PartialOrd for RefId<T>
{
#[inline]
fn partial_cmp(
&self,
other: &Self,
) -> Option<Ordering>
{
Some(Ord::cmp(self, other))
}
#[inline]
fn lt(
&self,
other: &Self,
) -> bool
{
self.as_ptr() < other.as_ptr()
}
#[inline]
fn le(
&self,
other: &Self,
) -> bool
{
self.as_ptr() <= other.as_ptr()
}
#[inline]
fn gt(
&self,
other: &Self,
) -> bool
{
self.as_ptr() > other.as_ptr()
}
#[inline]
fn ge(
&self,
other: &Self,
) -> bool
{
self.as_ptr() >= other.as_ptr()
}
}
impl<T: Deref> Ord for RefId<T>
{
#[inline]
fn cmp(
&self,
other: &Self,
) -> Ordering
{
Ord::cmp(&self.as_ptr(), &other.as_ptr())
}
}
}
#[cfg(feature = "alloc")]
mod lazy_collections
{
extern crate alloc;
use {
super::NonAdvancingIterator,
alloc::{
collections::VecDeque,
vec::Vec,
},
};
/// A logical stack of items yielded by an internal stack of [`Iterator`]s. Enables lazily
/// generating items to reduce memory usage.
pub(crate) struct LazyVecStack<I>(Vec<I>);
/// A logical queue of items yielded by an internal queue of [`Iterator`]s. Enables lazily
/// generating items to reduce memory usage.
pub(crate) struct LazyVecQueue<I>(VecDeque<I>);
/// Somewhat similar to [`Flatten`](core::iter::Flatten) but designed to not consume ownership
/// and not hold a "current" sub-iterator so that mutating to `extend` with further items may
/// be done between `next` calls.
pub(crate) trait LazierIterator
{
type SubIter: NonAdvancingIterator;
fn extend(
&mut self,
subiter: Self::SubIter,
);
fn next_subiter_as_mut(&mut self) -> Option<&mut Self::SubIter>;
fn next_subiter(&mut self) -> Option<Self::SubIter>;
#[allow(clippy::inline_always)]
#[inline(always)] // Actually makes a big difference.
fn next(&mut self) -> Option<<Self::SubIter as Iterator>::Item>
{
while let Some(subiter) = self.next_subiter_as_mut() {
let next = subiter.next();
if !subiter.has_next() {
drop(self.next_subiter()); // Remove empty iterators, before returning `Some`.
}
if next.is_some() {
return next;
}
}
None
}
}
macro_rules! provided_impls {
{
$($t:ty {
$with_capacity:path,
$extend:ident,
$next_subiter_as_mut:ident,
$next_subiter:ident
},)*
} => {
$(
impl<I> $t
{
pub(crate) fn with_capacity(capacity: usize) -> Self
{
Self($with_capacity(capacity))
}
pub(crate) fn clear(&mut self)
{
self.0.clear()
}
}
impl<I: NonAdvancingIterator> LazierIterator for $t
{
type SubIter = I;
fn extend(
&mut self,
subiter: Self::SubIter,
)
{
self.0.$extend(subiter);
}
fn next_subiter_as_mut(&mut self) -> Option<&mut Self::SubIter>
{
self.0.$next_subiter_as_mut()
}
fn next_subiter(&mut self) -> Option<Self::SubIter>
{
self.0.$next_subiter()
}
}
)*
};
}
provided_impls! {
LazyVecStack<I> { Vec::with_capacity, push, last_mut, pop },
LazyVecQueue<I> { VecDeque::with_capacity, push_back, front_mut, pop_front },
}
}
mod non_advancing_iterator
{
/// An `Iterator` that can repeatedly yield the same next item without advancing.
///
/// Unlike [`Peekable`](core::iter::Peekable), this is not required to store and repeatedly
/// yield the same value. The logically-same next item may be dynamically regenerated as
/// distinct equivalent values.
pub(crate) trait NonAdvancingIterator: Iterator
{
/// Returns the next item without advancing the iterator.
///
/// Multiple calls return the logically-same item, when the iterator is not advanced by
/// some other means. In such case, this may or may not be the same value.
fn next_no_adv(&mut self) -> Option<Self::Item>;
/// Returns `true` if the iterator has a next item, without advancing the iterator.
fn has_next(&mut self) -> bool
{
self.next_no_adv().is_some()
}
}
}