use num_traits::{One, SaturatingAdd, Zero};
use crate::{index_decoder::IndexDecoder, Change, Error, IncrementalDecoder, StepMode};
#[derive(Debug)]
pub struct IndexedIncrementalDecoder<Mode, T = i32> {
decoder: IncrementalDecoder<Mode, T>,
indexer: IndexDecoder,
}
impl<Mode, T> Default for IndexedIncrementalDecoder<Mode, T>
where
Mode: StepMode,
IncrementalDecoder<Mode, T>: Default,
{
fn default() -> Self {
Self::new(IncrementalDecoder::default())
}
}
impl<Mode, T> IndexedIncrementalDecoder<Mode, T>
where
Mode: StepMode,
{
pub(crate) fn new(decoder: IncrementalDecoder<Mode, T>) -> Self {
Self {
decoder,
indexer: Default::default(),
}
}
}
impl<Mode, T> IndexedIncrementalDecoder<Mode, T>
where
Mode: StepMode,
T: Copy + Zero + One + SaturatingAdd + From<i8>,
{
pub fn update(&mut self, a: bool, b: bool, z: bool) -> Result<Option<Change>, Error> {
let result = self.decoder.update(a, b);
if self.indexer.update(z) {
self.decoder.set_counter(Zero::zero());
}
result
}
pub fn reset(&mut self) {
self.decoder.reset();
self.indexer.reset();
}
pub fn counter(&self) -> T {
self.decoder.counter()
}
pub fn set_counter(&mut self, counter: T) {
self.decoder.set_counter(counter);
}
}
#[cfg(test)]
mod tests {
use crate::HalfStep;
use super::*;
#[test]
fn index() {
let a: Vec<bool> = vec![false, false, true, true, false, false, true, true];
let b: Vec<bool> = vec![true, false, false, true, true, false, false, true];
let z: Vec<bool> = vec![false, false, false, false, true, false, false, false];
let pulse_trains = a.into_iter().zip(b).zip(z);
let changes: Vec<Option<Change>> = vec![
None,
Some(Change::Positive),
None,
Some(Change::Positive),
None,
Some(Change::Positive),
None,
Some(Change::Positive),
];
let counters: Vec<i32> = vec![0, 1, 1, 2, 0, 1, 1, 2];
let expected = changes.into_iter().zip(counters);
let mut decoder: IndexedIncrementalDecoder<HalfStep> = Default::default();
for (input, expected) in pulse_trains.zip(expected) {
let ((a, b), z) = input;
let (expected_change, expected_counter) = expected;
let change = decoder.update(a, b, z).unwrap();
assert_eq!(change, expected_change);
assert_eq!(decoder.counter(), expected_counter);
}
}
}