Merge pull request 'sequence counter improvements' (#140) from seq-counter-improvements into main

Reviewed-on: #140
This commit was merged in pull request #140.
This commit is contained in:
2025-09-09 10:27:08 +02:00
2 changed files with 35 additions and 22 deletions

View File

@@ -17,6 +17,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `pus_version` API now returns a `Result<PusVersion, u8>` instead of a `PusVersion` to allow - `pus_version` API now returns a `Result<PusVersion, u8>` instead of a `PusVersion` to allow
modelling invalid version numbers properly. modelling invalid version numbers properly.
- Renamed `CcsdsPacket::total_len` to `CcsdsPacket::packet_len` - Renamed `CcsdsPacket::total_len` to `CcsdsPacket::packet_len`
- Renamed `SequenceCountProvider` to `SequenceCounter`
- Renamed `SeqCountProviderSimple` to `SequenceCounterSimple`
- Renamed `CcsdsSimpleSeqCountProvider` to `SequenceCounterCcsdsSimple`
- Renamed `SeqCountProviderSync` to `SequenceCounterSync`
## Removed ## Removed
@@ -25,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Added ## Added
- Added PUS A legacy support for telecommands inside the `ecss.tc_pus_a` module - Added PUS A legacy support for telecommands inside the `ecss.tc_pus_a` module
- Added `SequenceCounter::increment_mut` and `SequenceCounter::get_and_increment_mut`
# [v0.15.0] 2025-07-18 # [v0.15.0] 2025-07-18

View File

@@ -9,7 +9,7 @@ pub use stdmod::*;
/// The core functions are not mutable on purpose to allow easier usage with /// The core functions are not mutable on purpose to allow easier usage with
/// static structs when using the interior mutability pattern. This can be achieved by using /// static structs when using the interior mutability pattern. This can be achieved by using
/// [Cell], [core::cell::RefCell] or atomic types. /// [Cell], [core::cell::RefCell] or atomic types.
pub trait SequenceCountProvider { pub trait SequenceCounter {
type Raw: Into<u64>; type Raw: Into<u64>;
const MAX_BIT_WIDTH: usize; const MAX_BIT_WIDTH: usize;
@@ -17,16 +17,25 @@ pub trait SequenceCountProvider {
fn increment(&self); fn increment(&self);
fn increment_mut(&mut self) {
self.increment();
}
fn get_and_increment(&self) -> Self::Raw { fn get_and_increment(&self) -> Self::Raw {
let val = self.get(); let val = self.get();
self.increment(); self.increment();
val val
} }
fn get_and_increment_mut(&mut self) -> Self::Raw {
self.get_and_increment()
}
} }
#[derive(Clone)] #[derive(Clone)]
pub struct SeqCountProviderSimple<T: Copy> { pub struct SequenceCounterSimple<T: Copy> {
seq_count: Cell<T>, seq_count: Cell<T>,
// The maximum value
max_val: T, max_val: T,
} }
@@ -34,7 +43,7 @@ macro_rules! impl_for_primitives {
($($ty: ident,)+) => { ($($ty: ident,)+) => {
$( $(
paste! { paste! {
impl SeqCountProviderSimple<$ty> { impl SequenceCounterSimple<$ty> {
pub fn [<new_custom_max_val_ $ty>](max_val: $ty) -> Self { pub fn [<new_custom_max_val_ $ty>](max_val: $ty) -> Self {
Self { Self {
seq_count: Cell::new(0), seq_count: Cell::new(0),
@@ -49,13 +58,13 @@ macro_rules! impl_for_primitives {
} }
} }
impl Default for SeqCountProviderSimple<$ty> { impl Default for SequenceCounterSimple<$ty> {
fn default() -> Self { fn default() -> Self {
Self::[<new_ $ty>]() Self::[<new_ $ty>]()
} }
} }
impl SequenceCountProvider for SeqCountProviderSimple<$ty> { impl SequenceCounter for SequenceCounterSimple<$ty> {
type Raw = $ty; type Raw = $ty;
const MAX_BIT_WIDTH: usize = core::mem::size_of::<Self::Raw>() * 8; const MAX_BIT_WIDTH: usize = core::mem::size_of::<Self::Raw>() * 8;
@@ -87,19 +96,19 @@ impl_for_primitives!(u8, u16, u32, u64,);
/// This is a sequence count provider which wraps around at [MAX_SEQ_COUNT]. /// This is a sequence count provider which wraps around at [MAX_SEQ_COUNT].
#[derive(Clone)] #[derive(Clone)]
pub struct CcsdsSimpleSeqCountProvider { pub struct SequenceCounterCcsdsSimple {
provider: SeqCountProviderSimple<u16>, provider: SequenceCounterSimple<u16>,
} }
impl Default for CcsdsSimpleSeqCountProvider { impl Default for SequenceCounterCcsdsSimple {
fn default() -> Self { fn default() -> Self {
Self { Self {
provider: SeqCountProviderSimple::new_custom_max_val_u16(MAX_SEQ_COUNT), provider: SequenceCounterSimple::new_custom_max_val_u16(MAX_SEQ_COUNT),
} }
} }
} }
impl SequenceCountProvider for CcsdsSimpleSeqCountProvider { impl SequenceCounter for SequenceCounterCcsdsSimple {
type Raw = u16; type Raw = u16;
const MAX_BIT_WIDTH: usize = core::mem::size_of::<Self::Raw>() * 8; const MAX_BIT_WIDTH: usize = core::mem::size_of::<Self::Raw>() * 8;
delegate::delegate! { delegate::delegate! {
@@ -124,12 +133,12 @@ pub mod stdmod {
/// that the API provided by this class will not panic und [Mutex] lock errors, /// that the API provided by this class will not panic und [Mutex] lock errors,
/// but it will yield 0 for the getter functions. /// but it will yield 0 for the getter functions.
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct [<SeqCountProviderSync $ty:upper>] { pub struct [<SequenceCounterSync $ty:upper>] {
seq_count: Arc<Mutex<$ty>>, seq_count: Arc<Mutex<$ty>>,
max_val: $ty max_val: $ty
} }
impl [<SeqCountProviderSync $ty:upper>] { impl [<SequenceCounterSync $ty:upper>] {
pub fn new() -> Self { pub fn new() -> Self {
Self::new_with_max_val($ty::MAX) Self::new_with_max_val($ty::MAX)
} }
@@ -141,7 +150,7 @@ pub mod stdmod {
} }
} }
} }
impl SequenceCountProvider for [<SeqCountProviderSync $ty:upper>] { impl SequenceCounter for [<SequenceCounterSync $ty:upper>] {
type Raw = $ty; type Raw = $ty;
const MAX_BIT_WIDTH: usize = core::mem::size_of::<Self::Raw>() * 8; const MAX_BIT_WIDTH: usize = core::mem::size_of::<Self::Raw>() * 8;
@@ -180,14 +189,13 @@ pub mod stdmod {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::seq_count::{ use crate::seq_count::{
CcsdsSimpleSeqCountProvider, SeqCountProviderSimple, SeqCountProviderSyncU8, SequenceCounter, SequenceCounterCcsdsSimple, SequenceCounterSimple, SequenceCounterSyncU8,
SequenceCountProvider,
}; };
use crate::MAX_SEQ_COUNT; use crate::MAX_SEQ_COUNT;
#[test] #[test]
fn test_u8_counter() { fn test_u8_counter() {
let u8_counter = SeqCountProviderSimple::<u8>::default(); let u8_counter = SequenceCounterSimple::<u8>::default();
assert_eq!(u8_counter.get(), 0); assert_eq!(u8_counter.get(), 0);
assert_eq!(u8_counter.get_and_increment(), 0); assert_eq!(u8_counter.get_and_increment(), 0);
assert_eq!(u8_counter.get_and_increment(), 1); assert_eq!(u8_counter.get_and_increment(), 1);
@@ -196,7 +204,7 @@ mod tests {
#[test] #[test]
fn test_u8_counter_overflow() { fn test_u8_counter_overflow() {
let u8_counter = SeqCountProviderSimple::new_u8(); let u8_counter = SequenceCounterSimple::new_u8();
for _ in 0..256 { for _ in 0..256 {
u8_counter.increment(); u8_counter.increment();
} }
@@ -205,7 +213,7 @@ mod tests {
#[test] #[test]
fn test_ccsds_counter() { fn test_ccsds_counter() {
let ccsds_counter = CcsdsSimpleSeqCountProvider::default(); let ccsds_counter = SequenceCounterCcsdsSimple::default();
assert_eq!(ccsds_counter.get(), 0); assert_eq!(ccsds_counter.get(), 0);
assert_eq!(ccsds_counter.get_and_increment(), 0); assert_eq!(ccsds_counter.get_and_increment(), 0);
assert_eq!(ccsds_counter.get_and_increment(), 1); assert_eq!(ccsds_counter.get_and_increment(), 1);
@@ -214,7 +222,7 @@ mod tests {
#[test] #[test]
fn test_ccsds_counter_overflow() { fn test_ccsds_counter_overflow() {
let ccsds_counter = CcsdsSimpleSeqCountProvider::default(); let ccsds_counter = SequenceCounterCcsdsSimple::default();
for _ in 0..MAX_SEQ_COUNT + 1 { for _ in 0..MAX_SEQ_COUNT + 1 {
ccsds_counter.increment(); ccsds_counter.increment();
} }
@@ -223,7 +231,7 @@ mod tests {
#[test] #[test]
fn test_atomic_ref_counters() { fn test_atomic_ref_counters() {
let sync_u8_counter = SeqCountProviderSyncU8::new(); let sync_u8_counter = SequenceCounterSyncU8::new();
assert_eq!(sync_u8_counter.get(), 0); assert_eq!(sync_u8_counter.get(), 0);
assert_eq!(sync_u8_counter.get_and_increment(), 0); assert_eq!(sync_u8_counter.get_and_increment(), 0);
assert_eq!(sync_u8_counter.get_and_increment(), 1); assert_eq!(sync_u8_counter.get_and_increment(), 1);
@@ -232,7 +240,7 @@ mod tests {
#[test] #[test]
fn test_atomic_ref_counters_overflow() { fn test_atomic_ref_counters_overflow() {
let sync_u8_counter = SeqCountProviderSyncU8::new(); let sync_u8_counter = SequenceCounterSyncU8::new();
for _ in 0..u8::MAX as u16 + 1 { for _ in 0..u8::MAX as u16 + 1 {
sync_u8_counter.increment(); sync_u8_counter.increment();
} }
@@ -241,7 +249,7 @@ mod tests {
#[test] #[test]
fn test_atomic_ref_counters_overflow_custom_max_val() { fn test_atomic_ref_counters_overflow_custom_max_val() {
let sync_u8_counter = SeqCountProviderSyncU8::new_with_max_val(128); let sync_u8_counter = SequenceCounterSyncU8::new_with_max_val(128);
for _ in 0..129 { for _ in 0..129 {
sync_u8_counter.increment(); sync_u8_counter.increment();
} }