use anyhow::Result; use serde::{Deserialize, Serialize}; use super::super::errors::*; use super::super::sps_datatypes::{BitPosition, DataEvaluation, UnparsedSPSDataType}; #[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq)] pub struct UDIntType { length: u32, position: BitPosition, } impl UDIntType { const LEN: usize = 4; pub fn new(byte: u32, bit: Option) -> Result { Ok(UDIntType { length: Self::LEN as u32, position: BitPosition { byte, bit }, }) } } impl DataEvaluation for UDIntType { 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 { "udint".to_string() } fn get_end_byte(&self) -> u32 { self.position.byte + self.length } fn get_byte_positon(&self) -> u32 { self.position.byte } fn get_length(&self) -> u32 { self.length } 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 bytes = data .get((self.position.byte) as usize..(self.position.byte + self.length) as usize) .ok_or_else(|| s7_read_error(self.into_string(), self.position.byte))?; let mut slice: [u8; Self::LEN] = Default::default(); slice.copy_from_slice(bytes); let parsed = u32::from_be_bytes(slice); Ok(parsed.to_string()) } fn sql_equivalent(&self) -> &str { r"BIGINT UNSIGNED DEFAULT 0" } } #[test] fn test() { const INTPOS: u32 = 5; const INT: u32 = 25890920; const LEN: usize = 4; let test_item = UDIntType::new(INTPOS, None).unwrap(); let raw_data: [u8; 50] = [255; 50]; let mut test_vec: Vec = raw_data.to_vec(); test_vec.splice( INTPOS as usize..INTPOS as usize + LEN, INT.to_be_bytes().iter().cloned(), ); let result = match test_item.parse_s7(&test_vec) { Ok(res) => res, Err(_) => "Error".to_string(), }; assert_eq!(result, INT.to_string()) }