sid/
id_range.rs

1use {Id, IntegerHandle, FromUsize};
2use core::marker::PhantomData;
3use core::fmt;
4use core::ops;
5use core::cmp;
6use num_traits::Zero;
7
8pub struct IdRange<T, H = u32> {
9    pub start: H,
10    pub end: H,
11    _marker: PhantomData<T>,
12}
13
14impl<T, H: fmt::Display> fmt::Debug for IdRange<T, H> {
15    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16        write!(f, "Id#[{}..{}]", self.start, self.end)
17    }
18}
19
20impl<T, H: Copy> Copy for IdRange<T, H> {}
21
22impl<T, H: Copy> Clone for IdRange<T, H> {
23    fn clone(&self) -> IdRange<T, H> {
24        *self
25    }
26}
27
28impl<T, H: PartialEq> PartialEq for IdRange<T, H> {
29    fn eq(&self, other: &IdRange<T, H>) -> bool {
30        self.start.eq(&other.start) && self.end.eq(&other.end)
31    }
32}
33
34impl<T, H: Copy + Eq> Eq for IdRange<T, H> {}
35
36impl<T, H: IntegerHandle> IdRange<T, H> {
37    #[inline]
38    pub fn new(range: ops::Range<H>) -> Self {
39        IdRange {
40            start: range.start,
41            end: range.end,
42            _marker: PhantomData,
43        }
44    }
45
46    #[inline]
47    pub fn len(self) -> H {
48        self.end - self.start
49    }
50
51    #[inline]
52    pub fn empty() -> Self {
53        IdRange::new(Zero::zero()..Zero::zero())
54    }
55
56    #[inline]
57    pub fn is_empty(self) -> bool
58    where
59        H: Zero,
60    {
61        self.len() == Zero::zero()
62    }
63
64    #[inline]
65    pub fn nth(self, i: H) -> Id<T, H> {
66        debug_assert!(i < self.len());
67        return Id {
68            handle: self.start + i,
69            _marker: PhantomData,
70        };
71    }
72
73    #[inline]
74    pub fn start(&self) -> Id<T, H> {
75        Id::new(self.start)
76    }
77
78    #[inline]
79    pub fn usize_start(&self) -> usize {
80        self.start.to_usize()
81    }
82
83    #[inline]
84    pub fn usize_end(&self) -> usize {
85        self.end.to_usize()
86    }
87
88    #[inline]
89    pub fn usize_range(&self) -> ops::Range<usize> {
90        self.usize_start()..self.usize_end()
91    }
92
93    #[inline]
94    pub fn untyped(&self) -> ops::Range<H> {
95        self.start..self.end
96    }
97
98    #[inline]
99    /// Return a range with the front element popped, or None if the range is empty.
100    pub fn shrinked_left(self) -> Option<IdRange<T, H>> {
101        if self.is_empty() {
102            return None;
103        }
104        return Some(IdRange::new((self.start + H::one())..self.end));
105    }
106
107    #[inline]
108    /// Return a range with the back element popped, or None if the range is empty.
109    pub fn shrinked_right(self) -> Option<IdRange<T, H>> {
110        if self.is_empty() {
111            return None;
112        }
113        return Some(IdRange::new(
114            self.start..FromUsize::from_usize(self.end.to_usize() - 1),
115        ));
116    }
117
118    #[inline]
119    pub fn intersection(&self, other: Self) -> Self {
120        let start = cmp::max(self.start, other.start);
121        let end = cmp::min(self.end, other.end);
122        if end < start {
123            return IdRange::empty();
124        }
125        return IdRange::new(start..end);
126    }
127}
128
129impl<T, H: IntegerHandle> Iterator for IdRange<T, H> {
130    type Item = Id<T, H>;
131    fn next(&mut self) -> Option<Id<T, H>> {
132        if let Some(new_range) = self.shrinked_left() {
133            let first = self.start();
134            *self = new_range;
135            return Some(first);
136        }
137        return None;
138    }
139
140    fn size_hint(&self) -> (usize, Option<usize>) {
141        return (self.len().to_usize(), Some(self.len().to_usize()));
142    }
143
144    fn count(self) -> usize {
145        self.len().to_usize()
146    }
147}
148
149pub struct ReverseIdRange<T, H> {
150    range: IdRange<T, H>,
151}
152
153impl<T, H: fmt::Display> fmt::Debug for ReverseIdRange<T, H> {
154    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
155        write!(f, "ReverseId#[{}..{}]", self.range.start, self.range.end)
156    }
157}
158
159impl<T, H: Copy> Copy for ReverseIdRange<T, H> {}
160
161impl<T, H: Copy> Clone for ReverseIdRange<T, H> {
162    fn clone(&self) -> ReverseIdRange<T, H> {
163        *self
164    }
165}
166
167impl<T, H: PartialEq> PartialEq for ReverseIdRange<T, H> {
168    fn eq(&self, other: &ReverseIdRange<T, H>) -> bool {
169        self.range.eq(&other.range)
170    }
171}
172
173impl<T, H: Copy + Eq> Eq for ReverseIdRange<T, H> {}
174
175impl<T, H: IntegerHandle> ReverseIdRange<T, H> {
176    pub fn new(range: IdRange<T, H>) -> ReverseIdRange<T, H> {
177        ReverseIdRange { range: range }
178    }
179
180    pub fn len(&self) -> H {
181        self.range.len()
182    }
183
184    pub fn is_empty(self) -> bool {
185        self.len() == Zero::zero()
186    }
187
188    pub fn nth(self, i: H) -> Id<T, H> {
189        self.range.nth(i)
190    }
191}
192
193impl<T, H: IntegerHandle> Iterator for ReverseIdRange<T, H> {
194    type Item = Id<T, H>;
195    fn next(&mut self) -> Option<Id<T, H>> {
196        if let Some(new_range) = self.range.shrinked_right() {
197            self.range = new_range;
198            return Some(Id::new(self.range.end));
199        }
200        return None;
201    }
202
203    fn size_hint(&self) -> (usize, Option<usize>) {
204        self.range.size_hint()
205    }
206
207    fn count(self) -> usize {
208        self.range.count()
209    }
210}