use anyhow::{anyhow, Result}; use bit::BitIndex; use serde::{Deserialize, Serialize}; use super::super::errors::*; use super::super::sps_datatypes::{BitPosition, DataEvaluation, UnparsedSPSDataType}; #[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash)] pub struct BooleanType { position: BitPosition, } impl BooleanType { pub fn new(byte: u32, bit: Option) -> Result { match bit { Some(bit_) => { if bit_ < 8 { Ok(BooleanType { position: BitPosition { byte, bit }, }) } else { Err(Errors::InvalidBit) } } None => Err(Errors::MissingBit), } } } impl DataEvaluation for BooleanType { fn into_unparsed(&self) -> UnparsedSPSDataType { UnparsedSPSDataType { data_type: self.into_string(), data_byte: self.position.byte, data_bit: self.position.bit, data_length: None, } } fn into_string(&self) -> String { "boolean".to_string() } fn get_end_byte(&self) -> u32 { self.position.byte } fn get_byte_positon(&self) -> u32 { self.position.byte } fn get_length(&self) -> u32 { 1 } fn parse_serial(&self, data: &[&str]) -> Result { Ok(data .get((self.position.byte) as usize) .ok_or_else(|| serial_error(self.into_string(), self.position.byte))? .to_string()) } fn parse_s7(&self, data: &[u8]) -> Result { let byte = data .get((self.position.byte) as usize) .ok_or_else(|| s7_read_error(self.into_string(), self.position.byte))?; Ok(match byte.bit(self.position.bit.ok_or_else(|| { anyhow!( "Cannot read Bit {}.{}.", self.position.byte, self.position.bit.unwrap() ) })? as usize) { true => 1, false => 0, } .to_string()) } fn sql_equivalent(&self) -> &str { "BOOLEAN DEFAULT false" } } #[test] fn test() { const BYTEPOS: u32 = 5; const BITPOS: u32 = 4; const VAL: bool = false; let test_item = BooleanType::new(BYTEPOS, Some(BITPOS)).unwrap(); let raw_data: [u8; 50] = [0; 50]; let mut test_vec: Vec = raw_data.to_vec(); test_vec[BYTEPOS as usize].set_bit(BITPOS as usize, VAL); let result = match test_item.parse_s7(&test_vec) { Ok(res) => res, Err(_) => "Error".to_string(), }; assert_eq!( result, match VAL { true => 1, false => 0, } .to_string() ) }