use crate::Word;
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct Field {
mask: u16,
offset: u32,
}
impl Field {
pub const fn new() -> Self {
Self { mask: 0, offset: 0 }
}
pub const fn with_mask(mut self, mask: u16) -> Self {
self.mask = mask;
self
}
pub const fn with_offset(mut self) -> Self {
self.offset = self.mask.trailing_zeros();
self
}
pub const fn from(mask: u16) -> Self {
Self::new().with_mask(mask).with_offset()
}
pub fn get<T: Word, F: From<u16>>(&self, word: &T) -> F {
let value = word.as_value() & self.mask;
F::from(value >> self.offset)
}
pub fn set<T: Word>(&self, word: &mut T, value: u8) {
let value = (value as u16) << self.offset;
let data = word.as_value() & !self.mask;
word.set_value(data | (value & self.mask));
}
}
pub(crate) const COMMAND_ADDRESS: u16 = 0b1111100000000000;
pub(crate) const COMMAND_ADDRESS_FIELD: Field = Field::from(COMMAND_ADDRESS);
pub(crate) const COMMAND_TRANSMIT_RECEIVE: u16 = 0b0000010000000000;
pub(crate) const COMMAND_TRANSMIT_RECEIVE_FIELD: Field = Field::from(COMMAND_TRANSMIT_RECEIVE);
pub(crate) const COMMAND_SUBADDRESS: u16 = 0b0000001111100000;
pub(crate) const COMMAND_SUBADDRESS_FIELD: Field = Field::from(COMMAND_SUBADDRESS);
pub(crate) const COMMAND_MODE_CODE: u16 = 0b0000000000011111;
pub(crate) const COMMAND_MODE_CODE_FIELD: Field = Field::from(COMMAND_MODE_CODE);
pub(crate) const COMMAND_WORD_COUNT: u16 = 0b0000000000011111;
pub(crate) const COMMAND_WORD_COUNT_FIELD: Field = Field::from(COMMAND_WORD_COUNT);
pub(crate) const STATUS_ADDRESS: u16 = 0b1111100000000000;
pub(crate) const STATUS_ADDRESS_FIELD: Field = Field::from(STATUS_ADDRESS);
pub(crate) const STATUS_MESSAGE_ERROR: u16 = 0b0000010000000000;
pub(crate) const STATUS_MESSAGE_ERROR_FIELD: Field = Field::from(STATUS_MESSAGE_ERROR);
pub(crate) const STATUS_INSTRUMENTATION: u16 = 0b0000001000000000;
pub(crate) const STATUS_INSTRUMENTATION_FIELD: Field = Field::from(STATUS_INSTRUMENTATION);
pub(crate) const STATUS_SERVICE_REQUEST: u16 = 0b0000000100000000;
pub(crate) const STATUS_SERVICE_REQUEST_FIELD: Field = Field::from(STATUS_SERVICE_REQUEST);
pub(crate) const STATUS_RESERVED: u16 = 0b0000000011100000;
pub(crate) const STATUS_RESERVED_FIELD: Field = Field::from(STATUS_RESERVED);
pub(crate) const STATUS_BROADCAST_RECEIVED: u16 = 0b0000000000010000;
pub(crate) const STATUS_BROADCAST_RECEIVED_FIELD: Field = Field::from(STATUS_BROADCAST_RECEIVED);
pub(crate) const STATUS_TERMINAL_BUSY: u16 = 0b0000000000001000;
pub(crate) const STATUS_TERMINAL_BUSY_FIELD: Field = Field::from(STATUS_TERMINAL_BUSY);
pub(crate) const STATUS_SUBSYSTEM_ERROR: u16 = 0b0000000000000100;
pub(crate) const STATUS_SUBSYSTEM_ERROR_FIELD: Field = Field::from(STATUS_SUBSYSTEM_ERROR);
pub(crate) const STATUS_DYNAMIC_BUS_ACCEPTANCE: u16 = 0b0000000000000010;
pub(crate) const STATUS_DYNAMIC_BUS_ACCEPTANCE_FIELD: Field =
Field::from(STATUS_DYNAMIC_BUS_ACCEPTANCE);
pub(crate) const STATUS_TERMINAL_ERROR: u16 = 0b0000000000000001;
pub(crate) const STATUS_TERMINAL_ERROR_FIELD: Field = Field::from(STATUS_TERMINAL_ERROR);
#[cfg(test)]
mod tests {
use super::*;
use crate::DataWord;
#[test]
fn test_field_clone() {
let field1 = Field::from(0b1010101010101010);
let field2 = field1.clone();
assert_eq!(field1, field2);
}
#[test]
fn test_field_new() {
let field = Field::new();
assert_eq!(field.mask, 0);
assert_eq!(field.offset, 0);
}
#[test]
fn test_field_with_mask() {
let field = Field::new().with_mask(0b1010101010101010);
assert_eq!(field.mask, 0b1010101010101010);
assert_eq!(field.offset, 0);
}
#[test]
fn test_field_with_offset_0() {
let field = Field::new().with_mask(0b1010101010101010).with_offset();
assert_eq!(field.offset, 1);
}
#[test]
fn test_field_with_offset_1() {
let field = Field::new().with_mask(0b1010101010101000).with_offset();
assert_eq!(field.offset, 3);
}
#[test]
fn test_field_with_offset_2() {
let field = Field::new().with_mask(0b1010101010100000).with_offset();
assert_eq!(field.offset, 5);
}
#[test]
fn test_field_with_offset_3() {
let field = Field::new().with_mask(0b1010101010000000).with_offset();
assert_eq!(field.offset, 7);
}
#[test]
fn test_field_from_u16_0() {
let input = 0b1010101010101010;
let expected = 1;
let field = Field::from(input);
assert_eq!(field.mask, input);
assert_eq!(field.offset, expected);
}
#[test]
fn test_field_from_u16_1() {
let input = 0b1010101010101000;
let expected = 3;
let field = Field::from(input);
assert_eq!(field.mask, input);
assert_eq!(field.offset, expected);
}
#[test]
fn test_field_from_u16_2() {
let input = 0b1010101010100000;
let expected = 5;
let field = Field::from(input);
assert_eq!(field.mask, input);
assert_eq!(field.offset, expected);
}
#[test]
fn test_field_from_u16_3() {
let input = 0b1010101010000000;
let expected = 7;
let field = Field::from(input);
assert_eq!(field.mask, input);
assert_eq!(field.offset, expected);
}
#[test]
fn test_field_get_0() {
let mask = 0b1110000000000000;
let input = 0b1010000000000000;
let expected = 0b101;
let field = Field::from(mask);
let word = DataWord::from(input);
let value: u16 = field.get(&word);
assert_eq!(value, expected);
}
#[test]
fn test_field_get_1() {
let mask = 0b0011110000000000;
let input = 0b0010110000000000;
let expected = 0b1011;
let field = Field::from(mask);
let word = DataWord::from(input);
let value: u16 = field.get(&word);
assert_eq!(value, expected);
}
#[test]
fn test_field_get_2() {
let mask = 0b0000011111000000;
let input = 0b0000010101000000;
let expected = 0b10101;
let field = Field::from(mask);
let word = DataWord::from(input);
let value: u16 = field.get(&word);
assert_eq!(value, expected);
}
#[test]
fn test_field_get_3() {
let mask = 0b0000000001111110;
let input = 0b0000000001011010;
let expected = 0b101101;
let field = Field::from(mask);
let word = DataWord::from(input);
let value: u16 = field.get(&word);
assert_eq!(value, expected);
}
#[test]
fn test_field_get_4() {
let mask = 0b0000000000000011;
let input = 0b0000000000000011;
let expected = 0b0000011;
let field = Field::from(mask);
let word = DataWord::from(input);
let value: u16 = field.get(&word);
assert_eq!(value, expected);
}
#[test]
fn test_field_set_0() {
let mask = 0b1110000000000000;
let input = 0b101;
let expected = 0b1010000000000000;
let field = Field::from(mask);
let mut word = DataWord::from(0);
field.set(&mut word, input);
assert_eq!(word.as_value(), expected);
}
#[test]
fn test_field_set_1() {
let mask = 0b0011110000000000;
let input = 0b1011;
let expected = 0b0010110000000000;
let field = Field::from(mask);
let mut word = DataWord::from(0);
field.set(&mut word, input);
assert_eq!(word.as_value(), expected);
}
#[test]
fn test_field_set_2() {
let mask = 0b0000011111000000;
let input = 0b10101;
let expected = 0b0000010101000000;
let field = Field::from(mask);
let mut word = DataWord::from(0);
field.set(&mut word, input);
assert_eq!(word.as_value(), expected);
}
#[test]
fn test_field_set_3() {
let mask = 0b0000000001111110;
let input = 0b101101;
let expected = 0b0000000001011010;
let field = Field::from(mask);
let mut word = DataWord::from(0);
field.set(&mut word, input);
assert_eq!(word.as_value(), expected);
}
#[test]
fn test_field_set_4() {
let mask = 0b0000000000000011;
let input = 0b0000011;
let expected = 0b0000000000000011;
let field = Field::from(mask);
let mut word = DataWord::from(0);
field.set(&mut word, input);
assert_eq!(word.as_value(), expected);
}
}