use core::fmt::{Debug, Display, LowerHex, UpperHex};
#[cfg(feature = "std")]
use tracing::info;
#[derive(Clone, Copy, Eq)]
pub struct LogicalAddress(
pub u16,
);
impl LogicalAddress {
pub const MIN_CLIENT_ADDRESS: LogicalAddress = LogicalAddress(0x0E00);
pub const MAX_CLIENT_ADDRESS: LogicalAddress = LogicalAddress(0x0FFF);
pub const OBD_ADDRESS_RANGE: (LogicalAddress, LogicalAddress) =
(LogicalAddress(0x0F00), LogicalAddress(0x0F7F));
#[must_use]
pub fn is_valid_client_address(&self) -> bool {
if *self >= Self::MIN_CLIENT_ADDRESS && *self <= Self::MAX_CLIENT_ADDRESS {
if *self >= Self::OBD_ADDRESS_RANGE.0 && *self <= Self::OBD_ADDRESS_RANGE.1 {
#[cfg(feature = "std")]
info!(
"Logical addresses in the 0x0F00-0x0F7F range are intended for internal \
data collection/on-board diagnostics only. Ensure that this is the intended use case."
);
}
true
} else {
false
}
}
}
impl Display for LogicalAddress {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#06X}", self.0)
}
}
impl Debug for LogicalAddress {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#06X}", self.0)
}
}
impl UpperHex for LogicalAddress {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
UpperHex::fmt(&self.0, f)
}
}
impl LowerHex for LogicalAddress {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
LowerHex::fmt(&self.0, f)
}
}
impl From<u16> for LogicalAddress {
fn from(addr: u16) -> Self {
LogicalAddress(addr)
}
}
impl From<LogicalAddress> for u16 {
fn from(addr: LogicalAddress) -> Self {
addr.0
}
}
impl PartialOrd<u16> for LogicalAddress {
fn partial_cmp(&self, other: &u16) -> Option<core::cmp::Ordering> {
self.0.partial_cmp(other)
}
}
impl PartialOrd<LogicalAddress> for LogicalAddress {
fn partial_cmp(&self, other: &LogicalAddress) -> Option<core::cmp::Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl PartialEq<u16> for LogicalAddress {
fn eq(&self, other: &u16) -> bool {
self.0 == *other
}
}
impl PartialEq<LogicalAddress> for LogicalAddress {
fn eq(&self, other: &LogicalAddress) -> bool {
self.0 == other.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_logical_address() {
let addr = LogicalAddress(0x0E00);
assert!(addr.is_valid_client_address());
assert_eq!(addr.0, 0x0E00);
assert_eq!(addr, LogicalAddress(0x0E00));
assert_eq!(addr, 0x0E00);
}
}