#[non_exhaustive]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct RadioState {
pub enabled: bool,
pub hardware_enabled: bool,
pub present: bool,
}
impl RadioState {
#[must_use]
pub fn new(enabled: bool, hardware_enabled: bool) -> Self {
Self::with_presence(enabled, hardware_enabled, true)
}
#[must_use]
pub fn with_presence(enabled: bool, hardware_enabled: bool, present: bool) -> Self {
Self {
enabled,
hardware_enabled,
present,
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct AirplaneModeState {
pub wifi: RadioState,
pub wwan: RadioState,
pub bluetooth: RadioState,
}
impl AirplaneModeState {
#[must_use]
pub fn new(wifi: RadioState, wwan: RadioState, bluetooth: RadioState) -> Self {
Self {
wifi,
wwan,
bluetooth,
}
}
#[must_use]
pub fn is_airplane_mode(&self) -> bool {
let mut any_present = false;
for radio in [&self.wifi, &self.wwan, &self.bluetooth] {
if !radio.present {
continue;
}
any_present = true;
if radio.enabled {
return false;
}
}
any_present
}
#[must_use]
pub fn any_hardware_killed(&self) -> bool {
[&self.wifi, &self.wwan, &self.bluetooth]
.into_iter()
.any(|r| r.present && !r.hardware_enabled)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn all_off_is_airplane_mode() {
let state = AirplaneModeState::new(
RadioState::new(false, true),
RadioState::new(false, true),
RadioState::new(false, true),
);
assert!(state.is_airplane_mode());
assert!(!state.any_hardware_killed());
}
#[test]
fn any_on_is_not_airplane_mode() {
let state = AirplaneModeState::new(
RadioState::new(true, true),
RadioState::new(false, true),
RadioState::new(false, true),
);
assert!(!state.is_airplane_mode());
}
#[test]
fn hardware_killed_detected() {
let state = AirplaneModeState::new(
RadioState::new(true, true),
RadioState::new(true, false),
RadioState::new(true, true),
);
assert!(state.any_hardware_killed());
}
#[test]
fn no_hardware_kill() {
let state = AirplaneModeState::new(
RadioState::new(false, true),
RadioState::new(false, true),
RadioState::new(false, true),
);
assert!(!state.any_hardware_killed());
}
#[test]
fn radio_state_new() {
let rs = RadioState::new(true, false);
assert!(rs.enabled);
assert!(!rs.hardware_enabled);
assert!(rs.present, "RadioState::new defaults to present = true");
}
#[test]
fn radio_state_with_presence() {
let rs = RadioState::with_presence(true, true, false);
assert!(rs.enabled);
assert!(rs.hardware_enabled);
assert!(!rs.present);
}
#[test]
fn absent_radios_do_not_block_airplane_mode() {
let state = AirplaneModeState::new(
RadioState::new(false, true),
RadioState::with_presence(true, true, false),
RadioState::with_presence(true, false, false),
);
assert!(state.is_airplane_mode());
}
#[test]
fn absent_radios_do_not_count_as_hardware_killed() {
let state = AirplaneModeState::new(
RadioState::new(true, true),
RadioState::with_presence(true, false, false),
RadioState::with_presence(true, false, false),
);
assert!(!state.any_hardware_killed());
}
#[test]
fn no_radios_present_is_not_airplane_mode() {
let state = AirplaneModeState::new(
RadioState::with_presence(true, true, false),
RadioState::with_presence(true, true, false),
RadioState::with_presence(true, true, false),
);
assert!(
!state.is_airplane_mode(),
"with no controllable radios there is no airplane mode"
);
}
#[test]
fn one_radio_present_and_off_is_airplane_mode() {
let state = AirplaneModeState::new(
RadioState::new(false, true),
RadioState::with_presence(true, true, false),
RadioState::with_presence(true, true, false),
);
assert!(state.is_airplane_mode());
}
}