rust-s7-datatypes/src/types/string.rs
2021-11-09 21:32:53 +01:00

97 lines
3.0 KiB
Rust

use anyhow::{anyhow, Result};
use serde::{Deserialize, Serialize};
use super::super::errors::*;
use super::super::sps_datatypes::{BitPosition, DataEvaluation, UnparsedSPSDataType};
#[derive(Debug, Serialize, Deserialize, Copy, Clone)]
pub struct StringType {
length: u32,
position: BitPosition,
}
impl StringType {
pub fn new(length: u32, byte: u32, bit: Option<u32>) -> Result<Self, Errors> {
Ok(
StringType {
length,
position: BitPosition { byte, bit },
}
)
}
}
impl DataEvaluation for StringType {
fn into_unparsed(&self) -> UnparsedSPSDataType {
UnparsedSPSDataType {
data_type: self.into_string(),
data_byte: self.position.byte,
data_bit: self.position.bit,
data_length: Some(self.length),
}
}
fn into_string(&self) -> String {
"string".to_string()
}
fn get_end_byte(&self) -> u32 {
// first two bytes are header bytes
self.position.byte + self.length + 2
}
fn get_byte_positon(&self) -> u32 {
self.position.byte
}
fn get_length(&self) -> u32 {
self.length
}
fn parse_serial(&self, data: &[&str]) -> Result<String> {
Ok(data
.get((self.position.byte) as usize)
.ok_or(Errors::ConversionError{type_string: self.into_string(), byte: self.position.byte})?
.to_string())
}
fn parse_s7(&self, data: &[u8]) -> Result<String> {
// Headerbyte 1: Reservierte Stringlänge in Byte [0…254]
// Headerbyte 2: Anzahl der zu interpretierenden Zeichen im String ab Byte 3
// Byte 3: 1. Nutzzeichen
let bytes = data
.get((self.position.byte) as usize..(self.position.byte + self.length) as usize)
.ok_or(Errors::ConversionError{type_string: self.into_string(), byte: self.position.byte})?;
// let bytes = bytes.unwrap();
match String::from_utf8(bytes[2..bytes[1] as usize + 2].to_vec()) {
Ok(string) => Ok(string),
Err(err) => Err(anyhow!(
"Could not convert data at byte {} with length {} into string: {}.",
self.position.byte,
self.length,
err
)),
}
}
fn sql_equivalent(&self) -> &str {
r"VARCHAR(255)"
}
}
#[test]
fn test2() {
const BYTEPOS: u32 = 5;
const LEN: u32 = 20;
const VAL: &str = "ich bin ein pfau";
let test_item = StringType::new(LEN + 2, BYTEPOS, None).unwrap();
let raw_data: [u8; 50] = [0; 50];
let mut test_vec: Vec<u8> = raw_data.to_vec();
test_vec[BYTEPOS as usize] = LEN as u8 + 2;
test_vec[BYTEPOS as usize + 1] = VAL.len() as u8;
test_vec.splice(
BYTEPOS as usize + 2..BYTEPOS as usize + LEN as usize,
VAL.as_bytes().iter().cloned(),
);
let result = match test_item.parse_s7(&test_vec) {
Ok(res) => res,
Err(_) => "Error".to_string(),
};
println!("{:?}", result);
assert_eq!(result, VAL.to_string())
}