error implementation
This commit is contained in:
parent
b5c84acc5c
commit
6230817405
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user