1use core::cell::Cell;
2#[cfg(feature = "alloc")]
3use dyn_clone::DynClone;
4use paste::paste;
5use spacepackets::MAX_SEQ_COUNT;
6#[cfg(feature = "std")]
7pub use stdmod::*;
8
9pub trait SequenceCountProviderCore<Raw> {
15 fn get(&self) -> Raw;
16
17 fn increment(&self);
18
19 fn get_and_increment(&self) -> Raw {
20 let val = self.get();
21 self.increment();
22 val
23 }
24}
25
26#[cfg(feature = "alloc")]
29pub trait SequenceCountProvider<Raw>: SequenceCountProviderCore<Raw> + DynClone {}
30#[cfg(feature = "alloc")]
31dyn_clone::clone_trait_object!(SequenceCountProvider<u16>);
32#[cfg(feature = "alloc")]
33impl<T, Raw> SequenceCountProvider<Raw> for T where T: SequenceCountProviderCore<Raw> + Clone {}
34
35#[derive(Default, Clone)]
36pub struct SeqCountProviderSimple<T: Copy> {
37 seq_count: Cell<T>,
38 max_val: T,
39}
40
41macro_rules! impl_for_primitives {
42 ($($ty: ident,)+) => {
43 $(
44 paste! {
45 impl SeqCountProviderSimple<$ty> {
46 pub fn [<new_ $ty _max_val>](max_val: $ty) -> Self {
47 Self {
48 seq_count: Cell::new(0),
49 max_val,
50 }
51 }
52
53 pub fn [<new_ $ty>]() -> Self {
54 Self {
55 seq_count: Cell::new(0),
56 max_val: $ty::MAX
57 }
58 }
59 }
60
61 impl SequenceCountProviderCore<$ty> for SeqCountProviderSimple<$ty> {
62 fn get(&self) -> $ty {
63 self.seq_count.get()
64 }
65
66 fn increment(&self) {
67 self.get_and_increment();
68 }
69
70 fn get_and_increment(&self) -> $ty {
71 let curr_count = self.seq_count.get();
72
73 if curr_count == self.max_val {
74 self.seq_count.set(0);
75 } else {
76 self.seq_count.set(curr_count + 1);
77 }
78 curr_count
79 }
80 }
81 }
82 )+
83 }
84}
85
86impl_for_primitives!(u8, u16, u32, u64,);
87
88pub struct CcsdsSimpleSeqCountProvider {
90 provider: SeqCountProviderSimple<u16>,
91}
92
93impl CcsdsSimpleSeqCountProvider {
94 pub fn new() -> Self {
95 Self {
96 provider: SeqCountProviderSimple::new_u16_max_val(MAX_SEQ_COUNT),
97 }
98 }
99}
100
101impl Default for CcsdsSimpleSeqCountProvider {
102 fn default() -> Self {
103 Self::new()
104 }
105}
106
107impl SequenceCountProviderCore<u16> for CcsdsSimpleSeqCountProvider {
108 delegate::delegate! {
109 to self.provider {
110 fn get(&self) -> u16;
111 fn increment(&self);
112 fn get_and_increment(&self) -> u16;
113 }
114 }
115}
116
117#[cfg(feature = "std")]
118pub mod stdmod {
119 use super::*;
120 use std::sync::{Arc, Mutex};
121
122 macro_rules! sync_clonable_seq_counter_impl {
123 ($($ty: ident,)+) => {
124 $(paste! {
125 #[derive(Clone, Default)]
130 pub struct [<SeqCountProviderSync $ty:upper>] {
131 seq_count: Arc<Mutex<$ty>>,
132 max_val: $ty
133 }
134
135 impl [<SeqCountProviderSync $ty:upper>] {
136 pub fn new() -> Self {
137 Self::new_with_max_val($ty::MAX)
138 }
139
140 pub fn new_with_max_val(max_val: $ty) -> Self {
141 Self {
142 seq_count: Arc::default(),
143 max_val
144 }
145 }
146 }
147 impl SequenceCountProviderCore<$ty> for [<SeqCountProviderSync $ty:upper>] {
148 fn get(&self) -> $ty {
149 match self.seq_count.lock() {
150 Ok(counter) => *counter,
151 Err(_) => 0
152 }
153 }
154
155 fn increment(&self) {
156 self.get_and_increment();
157 }
158
159 fn get_and_increment(&self) -> $ty {
160 match self.seq_count.lock() {
161 Ok(mut counter) => {
162 let val = *counter;
163 if val == self.max_val {
164 *counter = 0;
165 } else {
166 *counter += 1;
167 }
168 val
169 }
170 Err(_) => 0,
171 }
172 }
173 }
174 })+
175 }
176 }
177 sync_clonable_seq_counter_impl!(u8, u16, u32, u64,);
178}
179
180#[cfg(test)]
181mod tests {
182 use crate::seq_count::{
183 CcsdsSimpleSeqCountProvider, SeqCountProviderSimple, SeqCountProviderSyncU8,
184 SequenceCountProviderCore,
185 };
186 use spacepackets::MAX_SEQ_COUNT;
187
188 #[test]
189 fn test_u8_counter() {
190 let u8_counter = SeqCountProviderSimple::new_u8();
191 assert_eq!(u8_counter.get(), 0);
192 assert_eq!(u8_counter.get_and_increment(), 0);
193 assert_eq!(u8_counter.get_and_increment(), 1);
194 assert_eq!(u8_counter.get(), 2);
195 }
196
197 #[test]
198 fn test_u8_counter_overflow() {
199 let u8_counter = SeqCountProviderSimple::new_u8();
200 for _ in 0..256 {
201 u8_counter.increment();
202 }
203 assert_eq!(u8_counter.get(), 0);
204 }
205
206 #[test]
207 fn test_ccsds_counter() {
208 let ccsds_counter = CcsdsSimpleSeqCountProvider::default();
209 assert_eq!(ccsds_counter.get(), 0);
210 assert_eq!(ccsds_counter.get_and_increment(), 0);
211 assert_eq!(ccsds_counter.get_and_increment(), 1);
212 assert_eq!(ccsds_counter.get(), 2);
213 }
214
215 #[test]
216 fn test_ccsds_counter_overflow() {
217 let ccsds_counter = CcsdsSimpleSeqCountProvider::default();
218 for _ in 0..MAX_SEQ_COUNT + 1 {
219 ccsds_counter.increment();
220 }
221 assert_eq!(ccsds_counter.get(), 0);
222 }
223
224 #[test]
225 fn test_atomic_ref_counters() {
226 let sync_u8_counter = SeqCountProviderSyncU8::new();
227 assert_eq!(sync_u8_counter.get(), 0);
228 assert_eq!(sync_u8_counter.get_and_increment(), 0);
229 assert_eq!(sync_u8_counter.get_and_increment(), 1);
230 assert_eq!(sync_u8_counter.get(), 2);
231 }
232
233 #[test]
234 fn test_atomic_ref_counters_overflow() {
235 let sync_u8_counter = SeqCountProviderSyncU8::new();
236 for _ in 0..u8::MAX as u16 + 1 {
237 sync_u8_counter.increment();
238 }
239 assert_eq!(sync_u8_counter.get(), 0);
240 }
241
242 #[test]
243 fn test_atomic_ref_counters_overflow_custom_max_val() {
244 let sync_u8_counter = SeqCountProviderSyncU8::new_with_max_val(128);
245 for _ in 0..129 {
246 sync_u8_counter.increment();
247 }
248 assert_eq!(sync_u8_counter.get(), 0);
249 }
250}