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