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
use std::ops::Range;

use crate::{get_count, set_count};

pub trait AsRangeArg {
    fn start(&self) -> usize;
    fn end(&self) -> usize;
}

impl AsRangeArg for Range<usize> {
    fn start(&self) -> usize {
        self.start
    }

    fn end(&self) -> usize {
        self.end
    }
}

impl AsRangeArg for usize {
    fn start(&self) -> usize {
        0
    }

    fn end(&self) -> usize {
        *self
    }
}

impl AsRangeArg for (usize, usize) {
    fn start(&self) -> usize {
        self.0
    }

    fn end(&self) -> usize {
        self.1
    }
}

/// inclusive range
/// used to reset the cache count in loops as every operation increases the cache count, which would break the "cache cycle" if the cache count would not be reset.
///
/// # Example
/// ```
/// use custos::{get_count, range, Ident, bump_count};
///
/// for _ in range(100) {
///     Ident::new(10); // an 'Ident' is created if a Buffer is retrieved from cache.
///     bump_count();
///     assert!(get_count() == 1);
/// }
/// assert!(get_count() == 0);
/// ```
pub fn range<R: AsRangeArg>(range: R) -> Count {
    Count(range.start(), range.end())
}

/// used to reset the cache count
pub struct Count(usize, usize);

pub struct CountIntoIter {
    epoch: usize,
    idx: usize,
    end: usize,
}

impl Iterator for CountIntoIter {
    type Item = usize;

    fn next(&mut self) -> Option<Self::Item> {
        set_count(self.idx);
        if self.epoch > self.end {
            return None;
        }
        let epoch = Some(self.epoch);
        self.epoch += 1;
        epoch
    }
}

impl IntoIterator for Count {
    type Item = usize;

    type IntoIter = CountIntoIter;

    fn into_iter(self) -> Self::IntoIter {
        CountIntoIter {
            epoch: self.0,
            idx: get_count(),
            end: self.1,
        }
    }
}