granular_id/lib.rs
1//! This crate contains the type `GranularId`, which is a data type which can provide ID numbers in
2//! a sequential order, where between any two ID:s, there are infinitely many *more granular* ID:s.
3//! You can think of this as version numbers with an infinite granularity, so if there are versions
4//! 1 and 2, there are ID:s 1.1, 1.2, 1.3 etc in-between them. Additionally, in-between ID 1.1 and
5//! 1.2, there are infinitely many ID:s 1.1.1, 1.1.2 and so on.
6//!
7//! `GranularId`s is best used with any unsized integer type, where each component of the ID:s may
8//! range from the minimum bound to the maximum bound of that integer type. The `GranularId` that
9//! starts with the upper bound of the integer type is the very maximum `GranularId`. This means
10//! that, using `u8`, all these `GranularId<u8>`s exist, in increasing order:
11//! * `254`
12//! * `254.0`
13//! * `254.1`
14//! * `254.1.0`
15//! * `254.1.1`
16//! * `254.1.*`
17//! * ...
18//! * `254.2`
19//! * `254.3`
20//! * `255`
21//! `255` is the highest ID available of this type (i.e. there is no `255.0`, `255.1` etc), and is
22//! the upper bound for this type. This constraint is added so that there is an upper bound to the
23//! `GranularId<T>` type if `T` has an upper bound.
24//!
25//! Even though it is recommended to use unsized integers for ID components, any types conforming
26//! to the appropriate [`num_traits`](https://docs.rs/num-traits/latest/num_traits/index.html) may
27//! be used.
28//!
29//! You may also think of the ID:s as a tree structure, where `3` has the children `3.0`, `3.1` etc
30//! up to `3.T::max`, and `5.3` having the siblings `5.4`, `5.5`, `5.6` etc following it. For this
31//! reason, [`GranularId<T>::children`], [`GranularId<T>::next_siblings`],
32//! [`GranularId<T>::previous_siblings`] and [`GranularId<T>::all_siblings`], as well as
33//! [`GranularId<T>::parent`] exist. If you were to build a tree structure, you may have a
34//! [`root`](GranularId<T>::root) ID from which you assign all nodes living in the root ID:s from
35//! the children of that root, and in turn assign each child of each children an ID derived from its
36//! own ID. In that way, you are maintaining a total ordering of the children (assuming the
37//! component type is totally ordered) while being able to easily find the parent ID of any node.
38//! The [`root`](GranularId<T>::root) ID is a special ID since it doesn't have any components, and
39//! is always the lowest ID.
40
41use std::{cmp, fmt, iter::Iterator};
42
43pub use num_traits::bounds::{LowerBounded, UpperBounded};
44use num_traits::{Bounded, CheckedAdd, CheckedSub, One};
45
46/// The data type `GranularId` represents any ID which can have an arbitrary granularity,
47/// meaning that there is indefinitely many `GranularId`s in-between any two `GranularId`s. It is
48/// best used with unsized integer types such as `u8`, `u16`, `u32`, `u64` and `usize`, but may be
49/// used with other data types implementing the required
50/// [`num_traits`](https://docs.rs/num-traits/latest/num_traits/index.html) bounds.
51///
52/// An ID basically consists of multiple *components*
53#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
54pub struct GranularId<T> {
55 id: Vec<T>,
56}
57
58impl<T: fmt::Display> fmt::Display for GranularId<T> {
59 /// A `GranularId` is displayed similarly to a version string, where the `GranularId` created
60 /// from the vector `[1, 2, 3]` is displayed as `1.2.3`. If the `GranularId` is the root ID
61 /// (doesn't have any components), it is displayed as `<root>`.
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 let mut iter = self.id.iter();
64 if let Some(x) = iter.next() {
65 write!(f, "{x}")?;
66 for x in iter {
67 write!(f, ".{x}")?;
68 }
69 } else {
70 write!(f, "<root>")?;
71 }
72 Ok(())
73 }
74}
75
76impl<T> PartialOrd for GranularId<T>
77where
78 T: Ord,
79{
80 /// Since `GranularId`s does have a total ordering if and only if its type has a total ordering,
81 /// this function never returns `None` and just returns the value [`GranularId<T>::cmp`] would
82 /// return
83 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
84 Some(self.cmp(other))
85 }
86}
87
88impl<T> Ord for GranularId<T>
89where
90 T: Ord,
91{
92 /// When comparing two [`GranularId`]s, their relative positioning is determined by its first
93 /// non-matching component. All ID:s starting with `1` is less than all ID:s starting with a `2`
94 /// and `1.2` is ordered before `1.2.0`. Here is an example of some ordered `GranularId`s:
95 ///
96 /// ```rust
97 /// use num_traits::bounds::LowerBounded;
98 /// use granular_id::GranularId;
99 /// let vec: Vec<GranularId<u8>> = vec![
100 /// vec![1].into(), // id 1
101 /// vec![1, 0].into(), // id 1.0
102 /// vec![1, 1].into(), // id 1.1
103 /// vec![1, 1, 0].into(), // id 1.1.0
104 /// vec![1, 1, 1].into(), // id 1.1.1
105 /// vec![1, 1, 2].into(), // id 1.1.2
106 /// vec![1, 2].into(), // id 1.2
107 /// vec![2].into(), // id 2
108 /// ];
109 /// let mut min = GranularId::min_value();
110 /// for id in vec {
111 /// assert!(id > min);
112 /// min = id;
113 /// }
114 /// ```
115 ///
116 /// For a [`GranularId`] to have a total ordering, the component type must also have a total
117 /// ordering.
118 fn cmp(&self, other: &Self) -> cmp::Ordering {
119 Iterator::zip(self.id.iter(), &other.id)
120 .map(|(a, b)| a.cmp(b))
121 .find(|x| *x != cmp::Ordering::Equal)
122 .unwrap_or_else(|| self.id.len().cmp(&other.id.len()))
123 }
124}
125
126impl<T> LowerBounded for GranularId<T> {
127 /// The lower bound for any [`GranularId`] (the smallest ID) is the empty ID which contains no
128 /// components.
129 fn min_value() -> Self {
130 Self { id: vec![] }
131 }
132}
133
134impl<T> UpperBounded for GranularId<T>
135where
136 T: UpperBounded,
137{
138 /// The upper bound for any [`GranularId`] (the largest ID) is the empty ID which contains one
139 /// component, containing the upper bound of the component type.
140 fn max_value() -> Self {
141 Self {
142 id: vec![T::max_value()],
143 }
144 }
145}
146
147impl<T> From<Vec<T>> for GranularId<T>
148where
149 T: PartialEq + UpperBounded,
150{
151 /// A vector of components may be turned into a `GranularId`. Keep in mind that the maximum
152 /// `GranularId` of any type `T` is the one containing just the component `T::max`, attempting
153 /// to convert any vector starting with `T::max` will result in the
154 /// [`upper bound`](GranularId<T>::max_value) `GranularId` for that type.
155 fn from(other: Vec<T>) -> Self {
156 if other.first().map_or(false, |x| x == &T::max_value()) {
157 Self {
158 id: vec![T::max_value()],
159 }
160 } else {
161 Self { id: other }
162 }
163 }
164}
165
166impl<T> From<&[T]> for GranularId<T>
167where
168 T: PartialEq + UpperBounded + Clone,
169{
170 /// A slice of components may be turned into a `GranularId`. Keep in mind that the maximum
171 /// `GranularId` of any type `T` is the one containing just the component `T::max`, attempting
172 /// to convert any vector starting with `T::max` will result in the
173 /// [`upper bound`](GranularId<T>::max_value) `GranularId` for that type.
174 fn from(other: &[T]) -> Self {
175 if other.first().map_or(false, |x| x == &T::max_value()) {
176 Self {
177 id: vec![T::max_value()],
178 }
179 } else {
180 Self { id: other.to_vec() }
181 }
182 }
183}
184
185impl<T> From<GranularId<T>> for Vec<T> {
186 /// Turns a `GranularId` into a vector of its components.
187 fn from(other: GranularId<T>) -> Vec<T> {
188 other.id
189 }
190}
191
192impl<T> GranularId<T>
193where
194 T: SequentialId,
195{
196 /// Gets all the siblings of this `GranularId`, ordered from the smallest sibling to the largest
197 /// sibling. This is all the `GranularId`s which starts the same as this `GranularId` but has
198 /// its last component changed.
199 ///
200 /// ```rust
201 /// use granular_id::GranularId;
202 /// let id = GranularId::from(vec![1u8, 2, 2]); // id 1.2.2
203 /// let mut all_siblings = id.all_siblings();
204 /// assert_eq!(all_siblings.next().unwrap(), vec![1, 2, 0].into()); // id 1.2.0
205 /// assert_eq!(all_siblings.next().unwrap(), vec![1, 2, 1].into()); // id 1.2.1
206 /// assert_eq!(all_siblings.next().unwrap(), vec![1, 2, 2].into()); // id 1.2.2
207 /// assert_eq!(all_siblings.next().unwrap(), vec![1, 2, 3].into()); // id 1.2.3
208 /// ```
209 #[must_use]
210 pub fn all_siblings(&self) -> SequentialIds<T>
211 where
212 T: LowerBounded,
213 {
214 let mut id = self.id.clone();
215 id.pop();
216 SequentialIds {
217 current: Some(T::min_value()),
218 base: id,
219 }
220 }
221
222 /// Gets all the next siblings of this `GranularId`, ordered from the smallest sibling larger
223 /// than this ID to the largest sibling. This is all the `GranularId`s which starts the same as
224 /// this `GranularId` but has its last component changed to any larger value.
225 ///
226 /// ```rust
227 /// use granular_id::GranularId;
228 /// let id = GranularId::from(vec![1u8, 2, 2]); // id 1.2.2
229 /// let mut next_siblings = id.next_siblings();
230 /// assert_eq!(next_siblings.next().unwrap(), vec![1, 2, 3].into()); // id 1.2.3
231 /// assert_eq!(next_siblings.next().unwrap(), vec![1, 2, 4].into()); // id 1.2.4
232 /// assert_eq!(next_siblings.next().unwrap(), vec![1, 2, 5].into()); // id 1.2.5
233 /// assert_eq!(next_siblings.next().unwrap(), vec![1, 2, 6].into()); // id 1.2.6
234 /// ```
235 #[must_use]
236 pub fn next_siblings(&self) -> SequentialIds<T>
237 where
238 T: CheckedAdd,
239 {
240 let mut id = self.id.clone();
241 let current = id.pop().and_then(|x| x.checked_add(&T::one()));
242 SequentialIds { current, base: id }
243 }
244
245 /// Gets all direct children of this `GranularId`, ordered from the smallest child (which is
246 /// larger than this ID, but smallest out of all children) to the largest child. This is all
247 /// the `GranularId`s which starts with this `GranularId` but has one additional component.
248 ///
249 /// ```rust
250 /// use granular_id::GranularId;
251 /// let id = GranularId::from(vec![1u8, 2]); // id 1.2
252 /// let mut children = id.children();
253 /// assert_eq!(children.next().unwrap(), vec![1, 2, 0].into()); // id 1.2.0
254 /// assert_eq!(children.next().unwrap(), vec![1, 2, 1].into()); // id 1.2.1
255 /// assert_eq!(children.next().unwrap(), vec![1, 2, 2].into()); // id 1.2.2
256 /// assert_eq!(children.next().unwrap(), vec![1, 2, 3].into()); // id 1.2.3
257 /// ```
258 #[must_use]
259 pub fn children(&self) -> SequentialIds<T>
260 where
261 T: LowerBounded,
262 {
263 SequentialIds {
264 current: Some(T::min_value()),
265 base: self.id.clone(),
266 }
267 }
268}
269
270impl<T> GranularId<T>
271where
272 T: BackSequentialId,
273{
274 /// Gets all the previous siblings of this `GranularId`, ordered from the largest sibling
275 /// smaller than this ID to the smallest sibling. This is all the `GranularId`s which starts the
276 /// same as this `GranularId` but has its last component changed to any smaller value.
277 ///
278 /// ```rust
279 /// use granular_id::GranularId;
280 /// let id = GranularId::from(vec![1u8, 2, 3]); // id 1.2.3
281 /// let mut previous_siblings = id.previous_siblings();
282 /// assert_eq!(previous_siblings.next().unwrap(), vec![1, 2, 2].into()); // id 1.2.2
283 /// assert_eq!(previous_siblings.next().unwrap(), vec![1, 2, 1].into()); // id 1.2.1
284 /// assert_eq!(previous_siblings.next().unwrap(), vec![1, 2, 0].into()); // id 1.2.0
285 /// assert_eq!(previous_siblings.next(), None); // No more smaller siblings
286 /// ```
287 #[must_use]
288 pub fn previous_siblings(&self) -> BackSequentialIds<T>
289 where
290 T: Bounded + One + Clone + CheckedSub,
291 {
292 let mut id = self.id.clone();
293 let current = id.pop().and_then(|x| x.checked_sub(&T::one()));
294 BackSequentialIds { current, base: id }
295 }
296}
297
298impl<T> GranularId<T> {
299 /// Checks whether this `GranularId` is the maximum value of this type. If it is, no
300 /// other larger `GranularId`s exist of the same type.
301 ///
302 /// ```rust
303 /// use granular_id::GranularId;
304 /// let not_max: GranularId<u8> = vec![254].into();
305 /// let max: GranularId<u8> = vec![255].into();
306 /// assert!(!not_max.is_max_value());
307 /// assert!(max.is_max_value());
308 /// ```
309 #[must_use]
310 pub fn is_max_value(&self) -> bool
311 where
312 T: UpperBounded + PartialEq,
313 {
314 self == &Self::max_value()
315 }
316
317 /// Gets the granularity of this `GranularId`, which is the number of components it contains,
318 /// or the "precision" it has
319 ///
320 /// ```rust
321 ///
322 /// use granular_id::GranularId;
323 /// let id: GranularId<u8> = vec![1, 2, 3, 4].into(); // id 1.2.3.4, granularity 4
324 /// assert_eq!(id.granularity(), 4);
325 /// // Its children should have granularity 5:
326 /// assert_eq!(id.children().next().unwrap().granularity(), 5);
327 /// ```
328 #[must_use]
329 pub fn granularity(&self) -> usize {
330 self.id.len()
331 }
332
333 /// Checks whether this `GranularId` is the root, which means not having any components.
334 ///
335 /// ```rust
336 /// use granular_id::GranularId;
337 /// let not_root: GranularId<u8> = vec![254].into();
338 /// let root: GranularId<u8> = vec![].into();
339 /// assert!(!not_root.is_root());
340 /// assert!(root.is_root());
341 /// ```
342 #[must_use]
343 pub fn is_root(&self) -> bool {
344 self.id.is_empty()
345 }
346
347 /// Turns this `GranularId` into its parent, that is, the same `GranularId` with the last
348 /// component removed. If this `GranularId` is the root (has no components), this function
349 /// returns the root. For a mutating version, see [`GranularId::pop`], and for a copying
350 /// version, see [`GranularId::parent`]. If this `GranularId` doesn't have any components (is
351 /// the root ID), this function returns `None` since the root ID doesn't have a parent.
352 ///
353 /// ```rust
354 /// use granular_id::GranularId;
355 /// let id: GranularId<u8> = vec![1, 2, 3].into(); // id 1.2.3
356 /// assert_eq!(id.into_parent(), Some(vec![1, 2].into())); // id 1.2
357 /// ```
358 #[must_use]
359 pub fn into_parent(mut self) -> Option<Self> {
360 if self.id.is_empty() {
361 return None;
362 }
363 self.id.pop();
364 Some(self)
365 }
366
367 /// Gets the parent of this `GranularId`, that is, the same `GranularId` with the last component
368 /// removed. If this `GranularId` doesn't have any components (is the root ID), this function
369 /// returns `None` since the root ID doesn't have a parent.
370 ///
371 /// ```rust
372 /// use granular_id::GranularId;
373 /// let id: GranularId<u8> = vec![1, 2, 3].into(); // id 1.2.3
374 /// assert_eq!(id.parent(), Some(vec![1, 2].into())); // id 1.2
375 /// ```
376 #[must_use]
377 pub fn parent(&self) -> Option<Self>
378 where
379 T: Clone,
380 {
381 if self.id.is_empty() {
382 return None;
383 }
384 let mut id = self.id.clone();
385 id.pop();
386 Some(Self { id })
387 }
388
389 /// Returns an iterator over the ancestors of this `GranularId`. The iterator will yield all the
390 /// ancestors, in order from the next-most parent until the root `GranularId`. This will give the
391 /// same results as iteratively calling [`GranularId::parent`]. This function consumes the
392 /// `GranularId`.
393 ///
394 ///```rust
395 /// use granular_id::GranularId;
396 /// let id: GranularId<u8> = vec![1, 2, 3].into(); // id 1.2.3
397 /// let mut ancestors = id.into_ancestors();
398 /// assert_eq!(ancestors.next(), Some(vec![1, 2].into())); // id 1.2
399 /// assert_eq!(ancestors.next(), Some(vec![1].into())); // id 1
400 /// assert_eq!(ancestors.next(), Some(vec![].into())); // root id
401 /// assert_eq!(ancestors.next(), None); // There are no more ancestors at this point
402 ///```
403 #[must_use]
404 pub fn into_ancestors(self) -> Ancestors<T> {
405 Ancestors {
406 current: Some(self),
407 }
408 }
409
410 /// Returns an iterator over the ancestors of this `GranularId`. The iterator will yield all the
411 /// ancestors, in order from the next-most parent until the root `GranularId`. This will give the
412 /// same results as iteratively calling [`GranularId::parent`].
413 ///
414 ///```rust
415 /// use granular_id::GranularId;
416 /// let id: GranularId<u8> = vec![1, 2, 3].into(); // id 1.2.3
417 /// let mut ancestors = id.ancestors();
418 /// assert_eq!(ancestors.next(), Some(vec![1, 2].into())); // id 1.2
419 /// assert_eq!(ancestors.next(), Some(vec![1].into())); // id 1
420 /// assert_eq!(ancestors.next(), Some(vec![].into())); // root id
421 /// assert_eq!(ancestors.next(), None); // There are no more parents at this point
422 ///```
423 #[must_use]
424 pub fn ancestors(&self) -> Ancestors<T>
425 where
426 T: Clone,
427 {
428 Ancestors {
429 current: Some(self.clone()),
430 }
431 }
432
433 /// Removes the last component of this `GranularId`. To get the parent of any `GranularId`
434 /// without mutating it, see [`GranularId::parent`]. The function returns the component popped,
435 /// akin to [`Vec::pop`], which is `None` if this `GranularId` doesn't have a parent. In that
436 /// case, this `GranularId` will remain unchanged as the root.
437 ///
438 /// ```rust
439 /// use granular_id::GranularId;
440 /// let mut id: GranularId<u8> = vec![1, 2, 3].into(); // id 1.2.3
441 /// assert_eq!(id.pop(), Some(3)); // popping the last component '3'
442 /// assert_eq!(id, vec![1, 2].into()); // id 1.2
443 /// ```
444 pub fn pop(&mut self) -> Option<T> {
445 self.id.pop()
446 }
447
448 /// Pushes a new component to the `GranularId`, adding it as a new last component. Since the
449 /// maximum bound for a `GranularId` of type `T` is `[T::max]`, if any component is pushed to
450 /// such an ID, the call doesn't do anything.
451 ///
452 /// ```rust
453 /// use granular_id::GranularId;
454 /// let mut id: GranularId<u8> = vec![1, 2, 3].into(); // id 1.2.3
455 /// id.push(4);
456 /// assert_eq!(id, vec![1, 2, 3, 4].into()); // id 1.2.3.4
457 /// ```
458 pub fn push(&mut self, component: T)
459 where
460 T: UpperBounded + PartialEq,
461 {
462 if self != &Self::max_value() {
463 self.id.push(component);
464 }
465 }
466
467 /// Makes a new `GranularId`, adding the given component as its new last component. Since the
468 /// maximum bound for a `GranularId` of type `T` is `[T::max]`, if any component is pushed to
469 /// such an ID, the call returns a plain copy of the original `GranularId`.
470 ///
471 /// ```rust
472 /// use granular_id::GranularId;
473 /// let mut id: GranularId<u8> = vec![1, 2, 3].into(); // id 1.2.3
474 /// assert_eq!(id.pushing(4), vec![1, 2, 3, 4].into()); // id 1.2.3.4
475 /// ```
476 #[must_use]
477 pub fn pushing(&self, component: T) -> Self
478 where
479 T: UpperBounded + PartialEq + Clone,
480 {
481 if self == &Self::max_value() {
482 self.clone()
483 } else {
484 let mut id = self.id.clone();
485 id.push(component);
486 Self { id }
487 }
488 }
489
490 /// Appends all components from another `GranularId` to this `GranularId`, adding them as a new
491 /// last components. Since the maximum bound for a `GranularId` of type `T` is `[T::max]`, if
492 /// any components is appended to such an ID, the call doesn't do anything.
493 ///
494 /// ```rust
495 /// use granular_id::GranularId;
496 /// let mut id: GranularId<u8> = vec![1, 2, 3].into(); // id 1.2.3
497 /// let id_2 = vec![4, 5, 6].into(); // id 4.5.6
498 /// id.append(id_2);
499 /// assert_eq!(id, vec![1, 2, 3, 4, 5, 6].into()); // id 1.2.3.4.5.6
500 /// ```
501 pub fn append(&mut self, mut other: GranularId<T>)
502 where
503 T: UpperBounded + PartialEq,
504 {
505 if self != &Self::max_value() {
506 self.id.append(&mut other.id);
507 }
508 }
509
510 /// Makes a new `GranularId`, appending all components from another `GranularId` to that
511 /// `GranularId`, adding them as a new last components. Since the maximum bound for a
512 /// `GranularId` of type `T` is `[T::max]`, if any components is appended to such an ID, the
513 /// call returns a copy of the original `GranularId`.
514 ///
515 /// ```rust
516 /// use granular_id::GranularId;
517 /// let mut id: GranularId<u8> = vec![1, 2, 3].into(); // id 1.2.3
518 /// let id_2 = vec![4, 5, 6].into(); // id 4.5.6
519 /// assert_eq!(id.appending(id_2), vec![1, 2, 3, 4, 5, 6].into()); // id 1.2.3.4.5.6
520 /// ```
521 #[must_use]
522 pub fn appending(&self, mut other: GranularId<T>) -> GranularId<T>
523 where
524 T: UpperBounded + PartialEq + Clone,
525 {
526 if self == &Self::max_value() {
527 self.clone()
528 } else {
529 let mut id = self.id.clone();
530 id.append(&mut other.id);
531 Self { id }
532 }
533 }
534
535 /// Appends all components from a `Vec` to this `GranularId`, adding them as a new
536 /// last components. Since the maximum bound for a `GranularId` of type `T` is `[T::max]`, if
537 /// any components is appended to such an ID, the call doesn't do anything.
538 ///
539 /// ```rust
540 /// use granular_id::GranularId;
541 /// let mut id: GranularId<u8> = vec![1, 2, 3].into(); // id 1.2.3
542 /// id.append_vec(vec![4, 5, 6]);
543 /// assert_eq!(id, vec![1, 2, 3, 4, 5, 6].into()); // id 1.2.3.4.5.6
544 /// ```
545 pub fn append_vec(&mut self, mut other: Vec<T>)
546 where
547 T: UpperBounded + PartialEq,
548 {
549 if self.id.is_empty() {
550 // If this is empty, replace the internal vec, making sure to use into() to not
551 // exceed max
552 let other_id: GranularId<T> = other.into();
553 self.id = other_id.id;
554 } else if self != &Self::max_value() {
555 self.id.append(&mut other);
556 }
557 }
558
559 /// Makes a new `GranularId`, appending all components from a `Vec` to that
560 /// `GranularId`, adding them as a new last components. Since the maximum bound for a
561 /// `GranularId` of type `T` is `[T::max]`, if any components is appended to such an ID, the
562 /// call returns a copy of the original `GranularId`.
563 ///
564 /// ```rust
565 /// use granular_id::GranularId;
566 /// let mut id: GranularId<u8> = vec![1, 2, 3].into(); // id 1.2.3
567 /// assert_eq!(id.appending_vec(vec![4, 5, 6]), vec![1, 2, 3, 4, 5, 6].into()); // id 1.2.3.4.5.6
568 /// ```
569 #[must_use]
570 pub fn appending_vec(&self, mut other: Vec<T>) -> GranularId<T>
571 where
572 T: UpperBounded + PartialEq + Clone,
573 {
574 if self.id.is_empty() {
575 other.into()
576 } else if self != &Self::max_value() {
577 let mut id = self.id.clone();
578 id.append(&mut other);
579 Self { id }
580 } else {
581 self.clone()
582 }
583 }
584
585 /// Gets the root `GranularId` of any type, that is, a `GranularId` without any components.
586 /// That `GranularId` is the smallest one of that type.
587 ///
588 /// ```rust
589 /// use granular_id::GranularId;
590 /// let id: GranularId<u8> = GranularId::root(); // id <root>
591 /// assert_eq!(Into::<Vec<u8>>::into(id), vec![]);
592 /// ```
593 #[must_use]
594 pub fn root() -> Self {
595 Self { id: vec![] }
596 }
597}
598
599impl<T> IntoIterator for GranularId<T> {
600 type Item = T;
601 type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
602
603 /// Turns this `GranularId` into an iterator over its components, consuming them.
604 fn into_iter(self) -> Self::IntoIter {
605 self.id.into_iter()
606 }
607}
608
609pub struct SequentialIds<T> {
610 current: Option<T>,
611 base: Vec<T>,
612}
613
614pub trait SequentialId: UpperBounded + One + Clone + PartialEq + Ord + CheckedAdd {}
615
616impl<T: UpperBounded + One + Clone + PartialEq + Ord + CheckedAdd> SequentialId for T {}
617
618impl<T> Iterator for SequentialIds<T>
619where
620 T: SequentialId,
621{
622 type Item = GranularId<T>;
623
624 fn next(&mut self) -> Option<Self::Item> {
625 if self.base.first().map_or(false, |x| x >= &T::max_value()) {
626 return None;
627 }
628
629 let x = self.current.as_ref()?;
630 let mut id = self.base.clone();
631 id.push(x.clone());
632 self.current = x.checked_add(&T::one());
633 Some(GranularId { id })
634 }
635}
636
637pub trait BackSequentialId: Bounded + One + Clone + CheckedSub {}
638
639impl<T: Bounded + One + Clone + CheckedSub> BackSequentialId for T {}
640
641pub struct BackSequentialIds<T> {
642 current: Option<T>,
643 base: Vec<T>,
644}
645
646impl<T> Iterator for BackSequentialIds<T>
647where
648 T: BackSequentialId,
649{
650 type Item = GranularId<T>;
651
652 fn next(&mut self) -> Option<Self::Item> {
653 let x = self.current.as_ref()?;
654 let mut id = self.base.clone();
655 id.push(x.clone());
656 self.current = x.checked_sub(&T::one());
657 Some(GranularId { id })
658 }
659}
660
661pub struct Ancestors<T> {
662 current: Option<GranularId<T>>,
663}
664
665impl<T> Iterator for Ancestors<T>
666where
667 T: Clone,
668{
669 type Item = GranularId<T>;
670
671 fn next(&mut self) -> Option<Self::Item> {
672 self.current = self.current.as_ref().and_then(GranularId::parent);
673 self.current.clone()
674 }
675}
676
677#[cfg(test)]
678mod tests {
679 use std::collections::HashMap;
680
681 use super::*;
682
683 #[test]
684 fn keys_in_hm() {
685 // Create a HM
686 let mut hm: HashMap<GranularId<u8>, &'static str> = HashMap::new();
687
688 // Create three sample keys
689 let id_1: GranularId<u8> = vec![1].into();
690 let id_1_1: GranularId<u8> = vec![1, 1].into();
691 let id_2: GranularId<u8> = vec![2].into();
692
693 // Inserting sample values
694 hm.insert(id_1.clone(), "abc");
695 hm.insert(id_1_1.clone(), "def");
696 hm.insert(id_2.clone(), "ghi");
697
698 // Checking that they work as expected
699 assert_eq!(hm.get(&id_1).unwrap(), &"abc");
700 assert_eq!(hm.get(&id_1_1).unwrap(), &"def");
701 assert_eq!(hm.get(&id_2).unwrap(), &"ghi");
702 }
703
704 #[test]
705 fn readme_example() {
706 // Create a new GranularId from a vec of u8 (id: 1.2.3)
707 let id: GranularId<u8> = vec![1, 2, 3].into();
708
709 // Get the parent ID (id: 1.2)
710 let parent = id.parent().unwrap();
711 assert_eq!(parent, vec![1, 2].into());
712
713 // Iterate over the following siblings of 1.2.3
714 let mut next_siblings = id.next_siblings();
715 // First one is 1.2.4
716 assert_eq!(next_siblings.next().unwrap(), vec![1, 2, 4].into());
717 // Then, 1.2.5, etc
718 assert_eq!(next_siblings.next().unwrap(), vec![1, 2, 5].into());
719 assert_eq!(next_siblings.next().unwrap(), vec![1, 2, 6].into());
720
721 // Get an iterator over childrens of 1.2.3
722 let mut children = id.children();
723 // First one is 1.2.3.0
724 assert_eq!(children.next().unwrap(), vec![1, 2, 3, 0].into());
725 // Then, 1.2.3.1, etc
726 assert_eq!(children.next().unwrap(), vec![1, 2, 3, 1].into());
727 assert_eq!(children.next().unwrap(), vec![1, 2, 3, 2].into());
728
729 // Each parent is always smaller than all of its children
730 assert!(parent < id);
731 }
732}