#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DeviceModel {
IlumaOne,
Iluma,
IlumaPrime,
IlumaIOne,
IlumaI,
IlumaIPrime,
Unknown,
}
impl DeviceModel {
#[must_use]
pub fn from_local_name(value: &str) -> Self {
let normalized = value.trim().to_ascii_uppercase();
if normalized.contains("ILUMA I PRIME") {
Self::IlumaIPrime
} else if normalized.contains("ILUMA I ONE") {
Self::IlumaIOne
} else if normalized.contains("ILUMA I") {
Self::IlumaI
} else if normalized.contains("ILUMA PRIME") {
Self::IlumaPrime
} else if normalized.contains("ILUMA ONE") {
Self::IlumaOne
} else if normalized.contains("ILUMA") {
Self::Iluma
} else {
Self::Unknown
}
}
#[must_use]
pub const fn is_one_form_factor(self) -> bool {
matches!(self, Self::IlumaOne | Self::IlumaIOne)
}
#[must_use]
pub const fn is_iluma_family(self) -> bool {
matches!(self, Self::IlumaOne | Self::Iluma | Self::IlumaPrime)
}
#[must_use]
pub const fn is_iluma_i_family(self) -> bool {
matches!(self, Self::IlumaIOne | Self::IlumaI | Self::IlumaIPrime)
}
#[must_use]
pub const fn supports_holder_features(self) -> bool {
matches!(self, Self::Iluma | Self::IlumaPrime | Self::IlumaI | Self::IlumaIPrime)
}
#[must_use]
pub const fn supports(self, capability: DeviceCapability) -> bool {
match capability {
DeviceCapability::Brightness
| DeviceCapability::Vibration
| DeviceCapability::DeviceLock => !matches!(self, Self::Unknown),
DeviceCapability::FlexPuff | DeviceCapability::FlexBattery => {
matches!(self, Self::IlumaI | Self::IlumaIPrime)
}
DeviceCapability::SmartGesture => {
matches!(self, Self::Iluma | Self::IlumaPrime) || self.is_iluma_i_family()
}
DeviceCapability::AutoStart => self.is_iluma_i_family(),
DeviceCapability::ChargeStartVibration => self.supports_holder_features(),
}
}
#[must_use]
pub const fn supports_charge_start_vibration(self) -> bool {
self.supports(DeviceCapability::ChargeStartVibration)
}
}
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct DeviceInfo {
pub model_number: Option<String>,
pub serial_number: Option<String>,
pub software_revision: Option<String>,
pub manufacturer_name: Option<String>,
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DeviceCapability {
Brightness,
Vibration,
FlexPuff,
FlexBattery,
SmartGesture,
AutoStart,
DeviceLock,
ChargeStartVibration,
}
#[cfg(test)]
mod tests {
use super::{DeviceCapability, DeviceModel};
#[test]
fn detects_one_form_factor_models() {
assert!(DeviceModel::IlumaOne.is_one_form_factor());
assert!(DeviceModel::IlumaIOne.is_one_form_factor());
assert!(!DeviceModel::Iluma.is_one_form_factor());
assert!(!DeviceModel::Unknown.is_one_form_factor());
}
#[test]
fn detects_model_families() {
assert!(DeviceModel::IlumaPrime.is_iluma_family());
assert!(DeviceModel::IlumaIPrime.is_iluma_i_family());
assert!(!DeviceModel::IlumaIPrime.is_iluma_family());
assert!(!DeviceModel::Unknown.is_iluma_i_family());
}
#[test]
fn detects_holder_feature_models() {
for model in [
DeviceModel::Iluma,
DeviceModel::IlumaPrime,
DeviceModel::IlumaI,
DeviceModel::IlumaIPrime,
] {
assert!(model.supports_holder_features(), "{model:?} should support holder features");
}
for model in [DeviceModel::IlumaOne, DeviceModel::IlumaIOne, DeviceModel::Unknown] {
assert!(
!model.supports_holder_features(),
"{model:?} should not support holder features"
);
}
}
#[test]
fn maps_capabilities_by_model_variation() {
let models = [
DeviceModel::IlumaOne,
DeviceModel::Iluma,
DeviceModel::IlumaPrime,
DeviceModel::IlumaIOne,
DeviceModel::IlumaI,
DeviceModel::IlumaIPrime,
DeviceModel::Unknown,
];
let matrix = [
(DeviceCapability::Brightness, [true, true, true, true, true, true, false]),
(DeviceCapability::Vibration, [true, true, true, true, true, true, false]),
(DeviceCapability::DeviceLock, [true, true, true, true, true, true, false]),
(DeviceCapability::FlexPuff, [false, false, false, false, true, true, false]),
(DeviceCapability::FlexBattery, [false, false, false, false, true, true, false]),
(DeviceCapability::SmartGesture, [false, true, true, true, true, true, false]),
(DeviceCapability::AutoStart, [false, false, false, true, true, true, false]),
(DeviceCapability::ChargeStartVibration, [false, true, true, false, true, true, false]),
];
for (capability, expected_by_model) in matrix {
for (model, expected) in models.into_iter().zip(expected_by_model) {
assert_eq!(
model.supports(capability),
expected,
"{model:?} support for {capability:?}"
);
}
}
}
#[test]
fn gates_charge_start_vibration_to_holder_models() {
for model in [
DeviceModel::Iluma,
DeviceModel::IlumaPrime,
DeviceModel::IlumaI,
DeviceModel::IlumaIPrime,
] {
assert!(model.supports_charge_start_vibration());
assert!(model.supports(DeviceCapability::ChargeStartVibration));
}
assert!(!DeviceModel::IlumaOne.supports_charge_start_vibration());
assert!(!DeviceModel::IlumaIOne.supports_charge_start_vibration());
assert!(!DeviceModel::Unknown.supports_charge_start_vibration());
assert!(!DeviceModel::IlumaOne.supports(DeviceCapability::ChargeStartVibration));
assert!(!DeviceModel::IlumaIOne.supports(DeviceCapability::ChargeStartVibration));
assert!(!DeviceModel::Unknown.supports(DeviceCapability::ChargeStartVibration));
}
}