1use core::ops::{Range, RangeInclusive};
2
3pub trait AsRangeArg {
5 fn start(&self) -> usize;
7 fn end(&self) -> usize;
9}
10
11impl AsRangeArg for Range<usize> {
12 #[inline]
13 fn start(&self) -> usize {
14 self.start
15 }
16
17 #[inline]
18 fn end(&self) -> usize {
19 self.end
20 }
21}
22
23impl AsRangeArg for RangeInclusive<usize> {
24 #[inline]
25 fn start(&self) -> usize {
26 *self.start()
27 }
28
29 #[inline]
30 fn end(&self) -> usize {
31 *self.end() + 1
32 }
33}
34
35impl AsRangeArg for usize {
36 #[inline]
37 fn start(&self) -> usize {
38 0
39 }
40
41 #[inline]
42 fn end(&self) -> usize {
43 *self
44 }
45}
46
47impl AsRangeArg for (usize, usize) {
48 #[inline]
49 fn start(&self) -> usize {
50 self.0
51 }
52
53 #[inline]
54 fn end(&self) -> usize {
55 self.1
56 }
57}
58
59#[cfg_attr(not(feature = "no-std"), doc = "```")]
67#[cfg_attr(feature = "no-std", doc = "```ignore")]
68#[inline]
78pub fn range<R: AsRangeArg>(range: R) -> Count {
79 Count(range.start(), range.end())
80}
81
82#[derive(Debug, Clone, Copy)]
84pub struct Count(pub(super) usize, pub(super) usize);
85
86#[derive(Debug)]
88pub struct CountIntoIter {
89 epoch: usize,
90 #[cfg(not(feature = "no-std"))]
91 idx: usize,
92 end: usize,
93}
94
95impl Iterator for CountIntoIter {
96 type Item = usize;
97
98 fn next(&mut self) -> Option<Self::Item> {
99 #[cfg(not(feature = "no-std"))]
100 unsafe {
101 crate::set_count(self.idx)
102 };
103 if self.epoch >= self.end {
104 return None;
105 }
106 let epoch = Some(self.epoch);
107 self.epoch += 1;
108 epoch
109 }
110}
111
112impl IntoIterator for Count {
113 type Item = usize;
114
115 type IntoIter = CountIntoIter;
116
117 #[inline]
118 fn into_iter(self) -> Self::IntoIter {
119 CountIntoIter {
120 epoch: self.0,
121 #[cfg(not(feature = "no-std"))]
122 idx: crate::get_count(),
123 end: self.1,
124 }
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use crate::{range, Count, CountIntoIter};
131
132 fn count_iter(iter: &mut CountIntoIter) {
133 iter.next();
134 assert_eq!(iter.epoch, 1);
135 #[cfg(not(feature = "no-std"))]
136 assert_eq!(iter.idx, 0);
137 assert_eq!(iter.end, 10);
138
139 iter.next();
140 assert_eq!(iter.epoch, 2);
141 #[cfg(not(feature = "no-std"))]
142 assert_eq!(iter.idx, 0);
143 assert_eq!(iter.end, 10);
144 }
145
146 #[test]
147 fn test_count_into_iter() {
148 let mut iter = CountIntoIter {
149 epoch: 0,
150 #[cfg(not(feature = "no-std"))]
151 idx: 0,
152 end: 10,
153 };
154
155 count_iter(&mut iter);
156 }
157
158 #[test]
159 fn test_count() {
160 let count: Count = Count(0, 10);
161 count_iter(&mut count.into_iter());
162 }
163
164 #[test]
165 fn test_range_inclusive() {
166 let count: Count = range(0..=9);
167 count_iter(&mut count.into_iter());
168
169 for (idx, other) in count.into_iter().zip(0..=9) {
170 assert_eq!(idx, other)
171 }
172 }
173}