use alloc::string::String;
use alloc::vec::Vec;
#[derive(Debug, Clone, PartialEq, Default)]
pub struct A2lProject {
pub project: String,
pub modules: Vec<A2lModule>,
}
impl A2lProject {
pub fn parse(input: &str) -> Result<Self, crate::A2lError> {
crate::parser::parse(input)
}
#[must_use]
pub fn module_by_name(&self, name: &str) -> Option<&A2lModule> {
self.modules.iter().find(|m| m.name == name)
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct A2lModule {
pub name: String,
pub characteristics: Vec<Characteristic>,
pub measurements: Vec<Measurement>,
pub record_layouts: Vec<RecordLayout>,
pub compu_methods: Vec<CompuMethod>,
}
impl A2lModule {
#[must_use]
pub fn characteristic_by_name(&self, name: &str) -> Option<&Characteristic> {
self.characteristics.iter().find(|c| c.name == name)
}
#[must_use]
pub fn measurement_by_name(&self, name: &str) -> Option<&Measurement> {
self.measurements.iter().find(|m| m.name == name)
}
#[must_use]
pub fn record_layout_by_name(&self, name: &str) -> Option<&RecordLayout> {
self.record_layouts.iter().find(|r| r.name == name)
}
#[must_use]
pub fn compu_method_by_name(&self, name: &str) -> Option<&CompuMethod> {
self.compu_methods.iter().find(|c| c.name == name)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Characteristic {
pub name: String,
pub r#type: CharType,
pub address: u32,
pub deposit: String,
pub max_diff: f64,
pub conversion: String,
pub lower_limit: f64,
pub upper_limit: f64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[allow(clippy::exhaustive_enums)]
pub enum CharType {
Value,
Curve,
Map,
ValBlk,
Ascii,
}
impl CharType {
#[must_use]
pub fn from_keyword(keyword: &str) -> Option<Self> {
Some(match keyword {
"VALUE" => Self::Value,
"CURVE" => Self::Curve,
"MAP" => Self::Map,
"VAL_BLK" => Self::ValBlk,
"ASCII" => Self::Ascii,
_ => return None,
})
}
#[must_use]
pub const fn keyword(self) -> &'static str {
match self {
Self::Value => "VALUE",
Self::Curve => "CURVE",
Self::Map => "MAP",
Self::ValBlk => "VAL_BLK",
Self::Ascii => "ASCII",
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Measurement {
pub name: String,
pub datatype: DataType,
pub address: u32,
pub conversion: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[allow(clippy::exhaustive_enums)]
pub enum DataType {
Ubyte,
Sbyte,
Uword,
Sword,
Ulong,
Slong,
Uint64,
Int64,
Float32,
Float64,
}
impl DataType {
#[must_use]
pub fn from_keyword(keyword: &str) -> Option<Self> {
Some(match keyword {
"UBYTE" => Self::Ubyte,
"SBYTE" => Self::Sbyte,
"UWORD" => Self::Uword,
"SWORD" => Self::Sword,
"ULONG" => Self::Ulong,
"SLONG" => Self::Slong,
"A_UINT64" => Self::Uint64,
"A_INT64" => Self::Int64,
"FLOAT32_IEEE" => Self::Float32,
"FLOAT64_IEEE" => Self::Float64,
_ => return None,
})
}
#[must_use]
pub const fn keyword(self) -> &'static str {
match self {
Self::Ubyte => "UBYTE",
Self::Sbyte => "SBYTE",
Self::Uword => "UWORD",
Self::Sword => "SWORD",
Self::Ulong => "ULONG",
Self::Slong => "SLONG",
Self::Uint64 => "A_UINT64",
Self::Int64 => "A_INT64",
Self::Float32 => "FLOAT32_IEEE",
Self::Float64 => "FLOAT64_IEEE",
}
}
#[must_use]
pub const fn size_bytes(self) -> usize {
match self {
Self::Ubyte | Self::Sbyte => 1,
Self::Uword | Self::Sword => 2,
Self::Ulong | Self::Slong | Self::Float32 => 4,
Self::Uint64 | Self::Int64 | Self::Float64 => 8,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct RecordLayout {
pub name: String,
pub fnc_values: Option<FncValues>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct FncValues {
pub position: u8,
pub datatype: DataType,
}
#[derive(Debug, Clone, PartialEq)]
pub struct CompuMethod {
pub name: String,
pub conversion_type: ConversionType,
pub coeffs: Coeffs,
pub tab_ref: Option<String>,
pub unit: String,
}
impl CompuMethod {
#[must_use]
pub fn to_linear(&self) -> Option<LinearFn> {
match self.conversion_type {
ConversionType::Identity => Some(LinearFn {
slope: 1.0,
intercept: 0.0,
}),
ConversionType::Linear => match self.coeffs {
Coeffs::Linear([a, b]) => Some(LinearFn {
slope: a,
intercept: b,
}),
_ => None,
},
ConversionType::RatFunc => match self.coeffs {
Coeffs::RatFunc([a, b, c, d, e, f])
if a == 0.0 && d == 0.0 && e == 0.0 && f != 0.0 =>
{
Some(LinearFn {
slope: b / f,
intercept: c / f,
})
}
_ => None,
},
ConversionType::Table => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct LinearFn {
pub slope: f64,
pub intercept: f64,
}
impl LinearFn {
#[must_use]
pub fn apply(&self, raw: f64) -> f64 {
self.slope * raw + self.intercept
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
#[allow(clippy::exhaustive_enums)]
pub enum Coeffs {
RatFunc([f64; 6]),
Linear([f64; 2]),
#[default]
None,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[allow(clippy::exhaustive_enums)]
pub enum ConversionType {
Linear,
RatFunc,
Table,
Identity,
}
impl ConversionType {
#[must_use]
pub fn from_keyword(keyword: &str) -> Option<Self> {
Some(match keyword {
"LINEAR" => Self::Linear,
"RAT_FUNC" => Self::RatFunc,
"TABLE" => Self::Table,
"IDENTITY" | "IDENTICAL" => Self::Identity,
_ => return None,
})
}
#[must_use]
pub const fn keyword(self) -> &'static str {
match self {
Self::Linear => "LINEAR",
Self::RatFunc => "RAT_FUNC",
Self::Table => "TABLE",
Self::Identity => "IDENTITY",
}
}
}