use crate::channels::{CHANNEL_COUNT, CHANNEL_MAX, CHANNEL_MID, CHANNEL_MIN};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BankError {
BadIndex(usize),
BadValue(u16),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ChannelBank {
values: [u16; CHANNEL_COUNT],
}
impl Default for ChannelBank {
fn default() -> Self {
let mut values = [CHANNEL_MIN; CHANNEL_COUNT];
values[0] = CHANNEL_MID; values[1] = CHANNEL_MID; values[3] = CHANNEL_MID; Self { values }
}
}
impl ChannelBank {
pub fn values(&self) -> [u16; CHANNEL_COUNT] {
self.values
}
fn check(value: u16) -> Result<(), BankError> {
if (CHANNEL_MIN..=CHANNEL_MAX).contains(&value) {
Ok(())
} else {
Err(BankError::BadValue(value))
}
}
pub fn set_all(&mut self, values: [u16; CHANNEL_COUNT]) -> Result<(), BankError> {
for &v in &values {
Self::check(v)?;
}
self.values = values;
Ok(())
}
pub fn set_one(&mut self, index: usize, value: u16) -> Result<(), BankError> {
if index >= CHANNEL_COUNT {
return Err(BankError::BadIndex(index));
}
Self::check(value)?;
self.values[index] = value;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_bank_is_stick_neutral_throttle_low() {
let bank = ChannelBank::default();
let v = bank.values();
assert_eq!(v[0], CHANNEL_MID);
assert_eq!(v[1], CHANNEL_MID);
assert_eq!(v[2], CHANNEL_MIN, "throttle low");
assert_eq!(v[3], CHANNEL_MID);
assert!(v[4..].iter().all(|&x| x == CHANNEL_MIN));
}
#[test]
fn set_all_applies() {
let mut bank = ChannelBank::default();
let values = [CHANNEL_MID; CHANNEL_COUNT];
bank.set_all(values).unwrap();
assert_eq!(bank.values(), values);
}
#[test]
fn set_all_rejects_any_out_of_range_value_atomically() {
let mut bank = ChannelBank::default();
let before = bank.values();
let mut values = [CHANNEL_MID; CHANNEL_COUNT];
values[9] = CHANNEL_MAX + 1;
assert_eq!(
bank.set_all(values),
Err(BankError::BadValue(CHANNEL_MAX + 1))
);
assert_eq!(bank.values(), before, "no partial apply");
}
#[test]
fn set_one_bounds_index_and_value() {
let mut bank = ChannelBank::default();
bank.set_one(4, 1500).unwrap();
assert_eq!(bank.values()[4], 1500);
assert_eq!(bank.set_one(16, CHANNEL_MID), Err(BankError::BadIndex(16)));
assert_eq!(
bank.set_one(0, CHANNEL_MIN - 1),
Err(BankError::BadValue(CHANNEL_MIN - 1))
);
}
}