#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Address(u8);
impl Address {
#[must_use]
pub const fn new(value: u8) -> Self {
Self(value)
}
#[must_use]
pub const fn value(self) -> u8 {
self.0
}
#[must_use]
pub const fn kind(self) -> AddressKind {
match self.0 {
0 => AddressKind::Unconfigured,
1..=250 => AddressKind::Primary,
251 => AddressKind::PrimaryMasterRepeater,
252 => AddressKind::Reserved,
253 => AddressKind::Secondary,
254 => AddressKind::Test,
255 => AddressKind::Broadcast,
}
}
#[must_use]
pub const fn expects_response(self) -> bool {
!matches!(self.kind(), AddressKind::Reserved | AddressKind::Broadcast)
}
}
impl From<u8> for Address {
fn from(value: u8) -> Self {
Self::new(value)
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum AddressKind {
Unconfigured,
Primary,
PrimaryMasterRepeater,
Reserved,
Secondary,
Test,
Broadcast,
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use super::*;
#[test]
fn classifies_every_address_range() {
let cases = [
(0, AddressKind::Unconfigured, true),
(1, AddressKind::Primary, true),
(250, AddressKind::Primary, true),
(251, AddressKind::PrimaryMasterRepeater, true),
(252, AddressKind::Reserved, false),
(253, AddressKind::Secondary, true),
(254, AddressKind::Test, true),
(255, AddressKind::Broadcast, false),
];
for (value, kind, expects_response) in cases {
let address = Address::from(value);
assert_eq!(address.value(), value);
assert_eq!(address.kind(), kind);
assert_eq!(address.expects_response(), expects_response);
}
}
#[test]
fn reserved_address_remains_representable() {
assert_eq!(Address::new(252).value(), 252);
assert_eq!(Address::new(252).kind(), AddressKind::Reserved);
}
}