add first Add and AddAssign impl for CUC #11

Merged
muellerr merged 4 commits from cuc_time_extensions into main 2023-01-18 21:53:13 +01:00
Showing only changes of commit 1652567b8c - Show all commits

View File

@ -4,6 +4,8 @@
//! The core data structure to do this is the [TimeProviderCcsdsEpoch] struct.
use super::*;
use core::fmt::Debug;
use core::ops::{Add, AddAssign};
use core::time::Duration;
const MIN_CUC_LEN: usize = 2;
@ -579,6 +581,80 @@ impl CcsdsTimeProvider for TimeProviderCcsdsEpoch {
}
}
fn get_provider_values_after_duration_addition(
provider: &TimeProviderCcsdsEpoch,
duration: Duration,
) -> (u32, Option<FractionalPart>) {
let mut new_counter = provider.counter.1;
let subsec_nanos = duration.subsec_nanos();
let mut increment_counter = |amount: u32| {
let mut sum: u64 = 0;
let mut counter_inc_handler = |max_val: u64| {
sum = new_counter as u64 + amount as u64;
if sum >= max_val {
new_counter = (sum % max_val) as u32;
return;
}
new_counter = sum as u32;
};
match provider.counter.0 {
1 => counter_inc_handler(u8::MAX as u64),
2 => counter_inc_handler(u16::MAX as u64),
3 => counter_inc_handler((2_u32.pow(24) - 1) as u64),
4 => counter_inc_handler(u32::MAX as u64),
_ => {
// Should never happen
panic!("invalid counter width")
}
}
};
let fractional_part = if let Some(fractional_part) = &provider.fractions {
let fractional_increment =
fractional_part_from_subsec_ns(fractional_part.0, subsec_nanos as u64).unwrap();
let mut increment_fractions = |resolution| {
let mut new_fractions = fractional_part.1 + fractional_increment.1;
let max_fractions = fractional_res_to_div(resolution);
if new_fractions > max_fractions {
increment_counter(1);
new_fractions -= max_fractions;
}
Some(FractionalPart(resolution, new_fractions))
};
match fractional_increment.0 {
FractionalResolution::Seconds => None,
_ => increment_fractions(fractional_increment.0),
}
} else {
None
};
(new_counter, fractional_part)
}
impl AddAssign<Duration> for TimeProviderCcsdsEpoch {
fn add_assign(&mut self, duration: Duration) {
let (new_counter, new_fractional_part) =
get_provider_values_after_duration_addition(self, duration);
self.counter.1 = new_counter;
if self.fractions.is_some() {
self.fractions = new_fractional_part;
}
}
}
impl Add<Duration> for TimeProviderCcsdsEpoch {
type Output = Self;
fn add(self, duration: Duration) -> Self::Output {
let (new_counter, new_fractional_part) =
get_provider_values_after_duration_addition(&self, duration);
if let Some(fractional_part) = new_fractional_part {
// The generated fractional part should always be valid, so its okay to unwrap here.
return Self::new_with_fractions(new_counter, fractional_part).unwrap();
}
Self::new(new_counter)
}
}
#[cfg(test)]
mod tests {
use super::*;