1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3pub struct FrameNum(u8);
4
5impl FrameNum {
6 #[inline]
10 #[must_use]
11 pub const fn new(num: u8) -> Self {
12 Self(num & 0b0011_1111)
13 }
14
15 #[inline]
20 #[must_use]
21 pub const fn get(&self) -> u8 {
22 self.0
23 }
24}
25
26#[derive(Debug, Clone)]
33pub struct FrameNumSequence {
34 state: u8,
35}
36
37impl FrameNumSequence {
38 #[inline]
40 #[must_use]
41 pub const fn starting_at(x: u8) -> Self {
42 Self { state: x }
43 }
44
45 #[inline]
47 #[must_use]
48 pub const fn new() -> Self {
49 Self::starting_at(0)
50 }
51
52 #[inline]
54 #[must_use = "unused frame number"]
55 pub fn advance(&mut self) -> FrameNum {
56 let x = self.peek();
57 self.state = self.state.wrapping_add(1);
58 x
59 }
60
61 #[inline]
63 #[must_use]
64 pub const fn peek(&self) -> FrameNum {
65 self.peek_n(1)
66 }
67
68 #[allow(clippy::cast_possible_truncation)]
74 #[inline]
75 #[must_use]
76 pub const fn peek_n(&self, n: usize) -> FrameNum {
77 assert!(n >= 1, "n must be greater or equal to 1");
78 FrameNum::new(self.state.wrapping_add((n - 1) as u8))
79 }
80}
81
82impl Default for FrameNumSequence {
83 fn default() -> Self {
84 Self::new()
85 }
86}
87
88impl Iterator for FrameNumSequence {
89 type Item = FrameNum;
90
91 #[inline]
92 fn next(&mut self) -> Option<Self::Item> {
93 Some(self.advance())
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 const N: usize = 512;
102
103 #[test]
104 #[allow(clippy::cast_possible_truncation)]
105 fn test_sequence() {
106 let seq = FrameNumSequence::new().take(N);
107 let expected = (0..N).map(|x| x as u8).map(FrameNum::new);
108
109 assert!(seq.eq(expected));
110 }
111
112 #[test]
113 fn test_sequence_peek() {
114 let mut seq = FrameNumSequence::new();
115
116 for _ in 0..N {
117 let peeked = seq.peek();
118 let next = seq.advance();
119 assert_eq!(peeked, next);
120 }
121 }
122}