error implementation

This commit is contained in:
Hlars 2021-10-22 17:59:36 +02:00
parent b5c84acc5c
commit 6230817405
10 changed files with 149 additions and 50 deletions

View File

@ -1,6 +1,48 @@
use anyhow::{anyhow, Error};
use std::fmt;
use std::error::Error;
use anyhow::{anyhow};
pub fn serial_error(name: String, pos: u32) -> Error {
#[derive(Debug)]
pub enum Errors {
MissingBit,
InvalidBit,
MissingLength,
InvalidLength,
UnknownType,
ConversionError{
byte: u32,
type_string: String,
}
}
impl Errors {
fn conversion(&self) -> &str {
match self {
Self::MissingBit => "Missing bit position.",
Self::InvalidBit => "Invalid value for bit. Expecting u8 between 0 and 7.",
Self::MissingLength => "Missing data length.",
Self::InvalidLength => "Invalid value for data_length in DBItem. Expecting u32.",
Self::UnknownType => "Unknown datatype",
Self::ConversionError{byte: _, type_string: _} => "Cannot convert data into type.",
}
}
}
impl fmt::Display for Errors {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let err_msg = self.conversion();
write!(f, "{}", err_msg)
}
}
impl Error for Errors {
fn description(&self) -> &str {
self.conversion()
}
}
pub fn serial_error(name: String, pos: u32) -> anyhow::Error {
anyhow!(
"Cannot convert Serial data for type '{}' at position {}.",
name,
@ -8,6 +50,6 @@ pub fn serial_error(name: String, pos: u32) -> Error {
)
}
pub fn s7_read_error(name: String, pos: u32) -> Error {
pub fn s7_read_error(name: String, pos: u32) -> anyhow::Error {
anyhow!("Cannot read Byte for type '{}' at position {}.", name, pos)
}

View File

@ -7,10 +7,19 @@ use super::types::string::*;
use super::types::time::*;
use super::types::udint::*;
use super::types::uint::*;
use super::errors::Errors;
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
use anyhow::Result;
pub struct DataInfo {
pub type_string: String,
pub byte: u32,
pub length: Option<u32>,
pub bit: Option<u32>,
}
#[derive(Debug, Serialize, Deserialize, Copy, Clone)]
pub enum SPSDataTypes {
Boolean(BooleanType),
@ -24,6 +33,29 @@ pub enum SPSDataTypes {
String(StringType),
}
impl TryFrom<DataInfo> for SPSDataTypes {
type Error = Errors;
fn try_from(data: DataInfo) -> Result<Self, Self::Error> {
match data.type_string.to_lowercase().as_str() {
"boolean" => Ok(Self::Boolean(BooleanType::new(data.byte, data.bit)?)),
"int" => Ok(Self::Int(IntType::new(data.byte, data.bit)?)),
"dint" => Ok(Self::DInt(DIntType::new(data.byte, data.bit)?)),
"real" => Ok(Self::Real(RealType::new(data.byte, data.bit)?)),
"time" => Ok(Self::Time(TimeType::new(data.byte, data.bit)?)),
"udint" => Ok(Self::UDInt(UDIntType::new(data.byte, data.bit)?)),
"uint" => Ok(Self::UInt(UIntType::new(data.byte, data.bit)?)),
"string" => {
match data.length {
Some(number) => Ok(Self::String(StringType::new(number, data.byte, data.bit)?)),
None => Err(Errors::MissingLength)
}
}
_ => Err(Errors::UnknownType)
}
}
}
impl SPSDataTypes {
fn into(self) -> Box<dyn DataEvaluation> {
match self {

View File

@ -11,9 +11,20 @@ pub struct BooleanType {
}
impl BooleanType {
pub fn new(byte: u32, bit: Option<u32>) -> Self {
BooleanType {
position: BitPosition { byte, bit },
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)
}
}
fn into_string(self) -> String {
@ -74,7 +85,7 @@ fn test() {
const BITPOS: u32 = 4;
const VAL: bool = false;
let test_item = BooleanType::new(BYTEPOS, Some(BITPOS));
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();

View File

@ -13,11 +13,13 @@ pub struct DIntType {
impl DIntType {
const LEN: usize = 4;
pub fn new(byte: u32, bit: Option<u32>) -> Self {
DIntType {
length: Self::LEN as u32,
position: BitPosition { byte, bit },
}
pub fn new(byte: u32, bit: Option<u32>) -> Result<Self, Errors> {
Ok(
DIntType {
length: Self::LEN as u32,
position: BitPosition { byte, bit },
}
)
}
fn into_string(self) -> String {
@ -69,7 +71,7 @@ fn test() {
const INTPOS: u32 = 5;
const INT: i32 = -2589090;
const LEN: usize = 4;
let test_item = DIntType::new(INTPOS, None);
let test_item = DIntType::new(INTPOS, None).unwrap();
let raw_data: [u8; 50] = [255; 50];
let mut test_vec: Vec<u8> = raw_data.to_vec();
test_vec.splice(

View File

@ -12,11 +12,13 @@ pub struct IntType {
impl IntType {
const LEN: usize = 2;
pub fn new(byte: u32, bit: Option<u32>) -> Self {
IntType {
length: Self::LEN as u32,
position: BitPosition { byte, bit },
}
pub fn new(byte: u32, bit: Option<u32>) -> Result<Self, Errors> {
Ok(
IntType {
length: Self::LEN as u32,
position: BitPosition { byte, bit },
}
)
}
fn into_string(self) -> String {
"int".to_string()
@ -67,7 +69,7 @@ fn test() {
const INTPOS: u32 = 3;
const INT: i16 = -12;
const LEN: usize = 2;
let test_item = IntType::new(INTPOS, None);
let test_item = IntType::new(INTPOS, None).unwrap();
let raw_data: [u8; 50] = [255; 50];
let mut test_vec: Vec<u8> = raw_data.to_vec();
test_vec.splice(

View File

@ -12,11 +12,13 @@ pub struct RealType {
impl RealType {
const LEN: usize = 4;
pub fn new(byte: u32, bit: Option<u32>) -> Self {
RealType {
length: Self::LEN as u32,
position: BitPosition { byte, bit },
}
pub fn new(byte: u32, bit: Option<u32>) -> Result<Self, Errors> {
Ok(
RealType {
length: Self::LEN as u32,
position: BitPosition { byte, bit },
}
)
}
fn into_string(self) -> String {
"real".to_string()
@ -67,7 +69,7 @@ fn test() {
const INTPOS: u32 = 5;
const INT: f32 = 2.522529;
const LEN: usize = 4;
let test_item = RealType::new(INTPOS, None);
let test_item = RealType::new(INTPOS, None).unwrap();
let raw_data: [u8; 50] = [255; 50];
let mut test_vec: Vec<u8> = raw_data.to_vec();
test_vec.splice(

View File

@ -10,11 +10,13 @@ pub struct StringType {
position: BitPosition,
}
impl StringType {
pub fn new(length: u32, byte: u32, bit: Option<u32>) -> Self {
StringType {
length,
position: BitPosition { byte, bit },
}
pub fn new(length: u32, byte: u32, bit: Option<u32>) -> Result<Self, Errors> {
Ok(
StringType {
length,
position: BitPosition { byte, bit },
}
)
}
fn into_string(self) -> String {
"string".to_string()
@ -42,7 +44,7 @@ impl DataEvaluation for StringType {
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))?
.ok_or(Errors::ConversionError{type_string: self.into_string(), byte: self.position.byte})?
.to_string())
}
fn parse_s7(&self, data: &[u8]) -> Result<String> {
@ -51,7 +53,7 @@ impl DataEvaluation for StringType {
// Byte 3: 1. Nutzzeichen
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))?;
.ok_or(Errors::ConversionError{type_string: self.into_string(), byte: self.position.byte})?;
match String::from_utf8(bytes[2..bytes[1] as usize + 2].to_vec()) {
Ok(string) => Ok(string),
Err(err) => Err(anyhow!(
@ -74,7 +76,7 @@ fn test() {
const LEN: u32 = 20;
const VAL: &str = "ich bin ein pfau";
let test_item = StringType::new(LEN + 2, BYTEPOS, None);
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;

View File

@ -11,11 +11,13 @@ pub struct TimeType {
}
impl TimeType {
const LEN: usize = 4;
pub fn new(byte: u32, bit: Option<u32>) -> Self {
TimeType {
length: Self::LEN as u32,
position: BitPosition { byte, bit },
}
pub fn new(byte: u32, bit: Option<u32>) -> Result<Self, Errors> {
Ok(
TimeType {
length: Self::LEN as u32,
position: BitPosition { byte, bit },
}
)
}
fn into_string(self) -> String {
"time".to_string()

View File

@ -11,11 +11,13 @@ pub struct UDIntType {
}
impl UDIntType {
const LEN: usize = 4;
pub fn new(byte: u32, bit: Option<u32>) -> Self {
UDIntType {
length: Self::LEN as u32,
position: BitPosition { byte, bit },
}
pub fn new(byte: u32, bit: Option<u32>) -> Result<Self, Errors> {
Ok(
UDIntType {
length: Self::LEN as u32,
position: BitPosition { byte, bit },
}
)
}
fn into_string(self) -> String {
"udint".to_string()
@ -65,7 +67,7 @@ fn test() {
const INTPOS: u32 = 5;
const INT: u32 = 25890920;
const LEN: usize = 4;
let test_item = UDIntType::new(INTPOS, None);
let test_item = UDIntType::new(INTPOS, None).unwrap();
let raw_data: [u8; 50] = [255; 50];
let mut test_vec: Vec<u8> = raw_data.to_vec();
test_vec.splice(

View File

@ -11,11 +11,13 @@ pub struct UIntType {
}
impl UIntType {
const LEN: usize = 2;
pub fn new(byte: u32, bit: Option<u32>) -> Self {
UIntType {
length: Self::LEN as u32,
position: BitPosition { byte, bit },
}
pub fn new(byte: u32, bit: Option<u32>) -> Result<Self, Errors> {
Ok(
UIntType {
length: Self::LEN as u32,
position: BitPosition { byte, bit },
}
)
}
fn into_string(self) -> String {
"uint".to_string()
@ -65,7 +67,7 @@ fn test() {
const INTPOS: u32 = 15;
const INT: u16 = 8209;
const LEN: usize = 2;
let test_item = UIntType::new(INTPOS, None);
let test_item = UIntType::new(INTPOS, None).unwrap();
let raw_data: [u8; 50] = [255; 50];
let mut test_vec: Vec<u8> = raw_data.to_vec();
test_vec.splice(