#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum AdapterKeyName {
NoneAdapter,
LabView,
LabViewStdPrototype,
LabViewNxg,
Cvi,
CviStdPrototype,
DllFlex,
Sequence,
Automation,
DotNet,
Python,
HtBasic,
}
impl AdapterKeyName {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::NoneAdapter => "None Adapter",
Self::LabView => "G Flexible VI Adapter",
Self::LabViewStdPrototype => "G Std Prototype Adapter",
Self::LabViewNxg => "LabVIEW NXG Adapter",
Self::Cvi => "C/CVI Flexible Prototype Adapter",
Self::CviStdPrototype => "C/CVI Std Prototype Adapter",
Self::DllFlex => "DLL Flexible Prototype Adapter",
Self::Sequence => "Sequence Adapter",
Self::Automation => "Automation Adapter",
Self::DotNet => "DotNet Adapter",
Self::Python => "Python Adapter",
Self::HtBasic => "HTBasic Adapter",
}
}
#[must_use]
pub fn from_key(key: &str) -> Option<Self> {
[
Self::NoneAdapter,
Self::LabViewStdPrototype,
Self::LabView,
Self::LabViewNxg,
Self::CviStdPrototype,
Self::Cvi,
Self::DllFlex,
Self::Sequence,
Self::Automation,
Self::DotNet,
Self::Python,
Self::HtBasic,
]
.into_iter()
.find(|candidate| candidate.as_str() == key)
}
#[must_use]
pub const fn is_obsolete(self) -> bool {
matches!(self, Self::LabViewStdPrototype | Self::CviStdPrototype)
}
#[must_use]
pub const fn replacement(self) -> Option<Self> {
match self {
Self::LabViewStdPrototype => Some(Self::LabView),
Self::CviStdPrototype => Some(Self::Cvi),
_ => None,
}
}
}
impl std::fmt::Display for AdapterKeyName {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str(self.as_str())
}
}
#[cfg(test)]
mod tests {
use super::AdapterKeyName;
#[test]
fn every_key_round_trips() {
for adapter in [
AdapterKeyName::NoneAdapter,
AdapterKeyName::LabViewStdPrototype,
AdapterKeyName::LabView,
AdapterKeyName::LabViewNxg,
AdapterKeyName::CviStdPrototype,
AdapterKeyName::Cvi,
AdapterKeyName::DllFlex,
AdapterKeyName::Sequence,
AdapterKeyName::Automation,
AdapterKeyName::DotNet,
AdapterKeyName::Python,
AdapterKeyName::HtBasic,
] {
assert_eq!(AdapterKeyName::from_key(adapter.as_str()), Some(adapter));
}
}
#[test]
fn an_unrecognised_key_is_reported_rather_than_guessed() {
assert_eq!(AdapterKeyName::from_key("Some Future Adapter"), None);
assert_eq!(AdapterKeyName::from_key(""), None);
}
#[test]
fn the_obsolete_keys_point_at_their_replacements() {
assert_eq!(
AdapterKeyName::LabViewStdPrototype.replacement(),
Some(AdapterKeyName::LabView)
);
assert_eq!(
AdapterKeyName::CviStdPrototype.replacement(),
Some(AdapterKeyName::Cvi)
);
assert!(AdapterKeyName::LabViewStdPrototype.is_obsolete());
assert!(AdapterKeyName::CviStdPrototype.is_obsolete());
for current in [
AdapterKeyName::LabView,
AdapterKeyName::Cvi,
AdapterKeyName::LabViewNxg,
AdapterKeyName::DllFlex,
AdapterKeyName::NoneAdapter,
] {
assert!(!current.is_obsolete(), "{current:?} is not obsolete");
assert_eq!(current.replacement(), None);
}
}
#[test]
fn the_maintained_labview_adapter_is_the_flexible_one() {
assert_eq!(AdapterKeyName::LabView.as_str(), "G Flexible VI Adapter");
assert_eq!(
AdapterKeyName::LabViewStdPrototype.as_str(),
"G Std Prototype Adapter"
);
assert_ne!(AdapterKeyName::LabViewNxg, AdapterKeyName::LabView);
}
#[test]
fn keys_are_distinct() {
let keys = [
AdapterKeyName::NoneAdapter.as_str(),
AdapterKeyName::LabViewStdPrototype.as_str(),
AdapterKeyName::LabView.as_str(),
AdapterKeyName::LabViewNxg.as_str(),
AdapterKeyName::CviStdPrototype.as_str(),
AdapterKeyName::Cvi.as_str(),
AdapterKeyName::DllFlex.as_str(),
AdapterKeyName::Sequence.as_str(),
AdapterKeyName::Automation.as_str(),
AdapterKeyName::DotNet.as_str(),
AdapterKeyName::Python.as_str(),
AdapterKeyName::HtBasic.as_str(),
];
let mut sorted = keys.to_vec();
sorted.sort_unstable();
sorted.dedup();
assert_eq!(sorted.len(), keys.len());
}
}