naga/arena/
range.rs

1//! Well-typed ranges of [`Arena`]s.
2//!
3//! This module defines the [`Range`] type, representing a contiguous range of
4//! entries in an [`Arena`].
5//!
6//! [`Arena`]: super::Arena
7
8use super::{
9    handle::{Handle, Index},
10    Arena,
11};
12
13use std::{fmt, marker::PhantomData, ops};
14
15/// A strongly typed range of handles.
16#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
17#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
18#[cfg_attr(
19    any(feature = "serialize", feature = "deserialize"),
20    serde(transparent)
21)]
22#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
23#[cfg_attr(test, derive(PartialEq))]
24pub struct Range<T> {
25    pub(super) inner: ops::Range<u32>,
26    #[cfg_attr(any(feature = "serialize", feature = "deserialize"), serde(skip))]
27    marker: PhantomData<T>,
28}
29
30impl<T> Range<T> {
31    pub(crate) const fn erase_type(self) -> Range<()> {
32        let Self { inner, marker: _ } = self;
33        Range {
34            inner,
35            marker: PhantomData,
36        }
37    }
38}
39
40// NOTE: Keep this diagnostic in sync with that of [`BadHandle`].
41#[derive(Clone, Debug, thiserror::Error)]
42#[cfg_attr(test, derive(PartialEq))]
43#[error("Handle range {range:?} of {kind} is either not present, or inaccessible yet")]
44pub struct BadRangeError {
45    // This error is used for many `Handle` types, but there's no point in making this generic, so
46    // we just flatten them all to `Handle<()>` here.
47    kind: &'static str,
48    range: Range<()>,
49}
50
51impl BadRangeError {
52    pub fn new<T>(range: Range<T>) -> Self {
53        Self {
54            kind: std::any::type_name::<T>(),
55            range: range.erase_type(),
56        }
57    }
58}
59
60impl<T> Clone for Range<T> {
61    fn clone(&self) -> Self {
62        Range {
63            inner: self.inner.clone(),
64            marker: self.marker,
65        }
66    }
67}
68
69impl<T> fmt::Debug for Range<T> {
70    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
71        write!(formatter, "[{}..{}]", self.inner.start, self.inner.end)
72    }
73}
74
75impl<T> Iterator for Range<T> {
76    type Item = Handle<T>;
77    fn next(&mut self) -> Option<Self::Item> {
78        if self.inner.start < self.inner.end {
79            let next = self.inner.start;
80            self.inner.start += 1;
81            Some(Handle::new(Index::new(next).unwrap()))
82        } else {
83            None
84        }
85    }
86}
87
88impl<T> Range<T> {
89    /// Return a range enclosing handles `first` through `last`, inclusive.
90    pub fn new_from_bounds(first: Handle<T>, last: Handle<T>) -> Self {
91        Self {
92            inner: (first.index() as u32)..(last.index() as u32 + 1),
93            marker: Default::default(),
94        }
95    }
96
97    /// Return a range covering all handles with indices from `0` to `size`.
98    pub(super) fn full_range_from_size(size: usize) -> Self {
99        Self {
100            inner: 0..size as u32,
101            marker: Default::default(),
102        }
103    }
104
105    /// return the first and last handles included in `self`.
106    ///
107    /// If `self` is an empty range, there are no handles included, so
108    /// return `None`.
109    pub fn first_and_last(&self) -> Option<(Handle<T>, Handle<T>)> {
110        if self.inner.start < self.inner.end {
111            Some((
112                // `Range::new_from_bounds` expects a start- and end-inclusive
113                // range, but `self.inner` is an end-exclusive range.
114                Handle::new(Index::new(self.inner.start).unwrap()),
115                Handle::new(Index::new(self.inner.end - 1).unwrap()),
116            ))
117        } else {
118            None
119        }
120    }
121
122    /// Return the index range covered by `self`.
123    pub fn index_range(&self) -> ops::Range<u32> {
124        self.inner.clone()
125    }
126
127    /// Construct a `Range` that covers the indices in `inner`.
128    pub fn from_index_range(inner: ops::Range<u32>, arena: &Arena<T>) -> Self {
129        // Since `inner` is a `Range<u32>`, we only need to check that
130        // the start and end are well-ordered, and that the end fits
131        // within `arena`.
132        assert!(inner.start <= inner.end);
133        assert!(inner.end as usize <= arena.len());
134        Self {
135            inner,
136            marker: Default::default(),
137        }
138    }
139}