use alloc::vec::Vec;
pub struct AddressTable {
data: Vec<u8>,
}
impl Default for AddressTable {
fn default() -> Self {
Self::new()
}
}
impl AddressTable {
pub const fn new() -> Self {
Self { data: Vec::new() }
}
pub fn load(&mut self, data: &[u8]) {
self.data = data.to_vec();
}
pub fn entry_count(&self) -> u16 {
if self.data.len() < 2 {
return 0;
}
u16::from_be_bytes([self.data[0], self.data[1]])
}
pub fn get_group_address(&self, tsap: u16) -> Option<u16> {
if tsap == 0 || tsap > self.entry_count() {
return None;
}
let offset = (tsap as usize) * 2;
if offset + 2 > self.data.len() {
return None;
}
Some(u16::from_be_bytes([
self.data[offset],
self.data[offset + 1],
]))
}
pub fn get_tsap(&self, group_address: u16) -> Option<u16> {
(1..=self.entry_count()).find(|&i| self.get_group_address(i) == Some(group_address))
}
pub fn contains(&self, group_address: u16) -> bool {
self.get_tsap(group_address).is_some()
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::*;
fn sample_table() -> AddressTable {
let mut t = AddressTable::new();
t.load(&[
0x00, 0x03, 0x08, 0x01, 0x08, 0x02, 0x09, 0x01, ]);
t
}
#[test]
fn entry_count() {
assert_eq!(sample_table().entry_count(), 3);
assert_eq!(AddressTable::new().entry_count(), 0);
}
#[test]
fn get_group_address() {
let t = sample_table();
assert_eq!(t.get_group_address(1), Some(0x0801));
assert_eq!(t.get_group_address(3), Some(0x0901));
assert_eq!(t.get_group_address(0), None);
assert_eq!(t.get_group_address(4), None);
}
#[test]
fn get_tsap() {
let t = sample_table();
assert_eq!(t.get_tsap(0x0801), Some(1));
assert_eq!(t.get_tsap(0x0901), Some(3));
assert_eq!(t.get_tsap(0xFFFF), None);
}
#[test]
fn contains() {
let t = sample_table();
assert!(t.contains(0x0801));
assert!(!t.contains(0xFFFF));
}
}