105 lines
2.7 KiB
Rust
105 lines
2.7 KiB
Rust
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<u32>) -> Result<Self, Errors> {
|
|
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<String> {
|
|
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<String> {
|
|
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<u8> = 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()
|
|
)
|
|
}
|