diff --git a/src/extend/mod.rs b/src/extend/mod.rs new file mode 100644 index 0000000..fd616b8 --- /dev/null +++ b/src/extend/mod.rs @@ -0,0 +1,39 @@ +mod signal; + +use derive_getters::Getters; + +/// DBC value +#[derive(Debug, Clone, Getters)] +pub struct Value { + pub(crate) name: String, + #[getter(rename = "raw_value")] + #[getter(copy)] + pub(crate) raw: u64, + #[getter(copy)] + pub(crate) offset: f64, + #[getter(copy)] + pub(crate) factor: f64, + pub(crate) unit: String, +} + +unsafe impl Send for Value {} +unsafe impl Sync for Value {} + +impl Value { + /// Get the value of the signal + #[inline] + pub fn value(&self) -> T + where + T: num::NumCast + Default, + { + T::from(self.raw as f64 * self.factor + self.offset).unwrap_or_default() + } + /// Get the value and unit of the signal as a string + #[inline] + pub fn value_string(&self) -> String + where + T: num::NumCast + Default + std::fmt::Display, + { + format!("{} {}", self.value::(), self.unit) + } +} diff --git a/src/extend/signal.rs b/src/extend/signal.rs new file mode 100644 index 0000000..6994b4b --- /dev/null +++ b/src/extend/signal.rs @@ -0,0 +1,156 @@ +use super::Value; +use crate::{ByteOrder, Signal, ValueType}; + +impl Signal { + /// Decodes/Extracts a signal from the message data as a [`Value`] + /// + /// # Params + /// + /// * data: source data + /// + /// # Return + /// + /// [`Value`] if the size of signal is not zero + pub fn decode_value(&self, data: &[u8]) -> Option { + self.decode(data).map(|v| Value { + name: self.name.clone(), + raw: v, + offset: self.offset, + factor: self.factor, + unit: self.unit.clone(), + }) + } + + /// Decodes/Extracts a signal from the message data + /// + /// # Params + /// + /// * data: source data + /// + /// # Return + /// + /// Raw signal value if the size of signal is not zero + pub fn decode(&self, data: &[u8]) -> Option { + if self.signal_size == 0 { + return None; + } + + let len = data.len(); + let mut result = 0; + match self.byte_order { + ByteOrder::LittleEndian => { + let mut src_bit = self.start_bit as usize; + let mut dst_bit = 0; + for _ in 0..self.signal_size { + /* copy bit */ + let index = src_bit / 8; + if index >= len { + return None; + } + if (data[index] & (1 << (src_bit % 8))) > 0 { + result |= 1 << dst_bit; + } + + /* calculate next position */ + src_bit += 1; + dst_bit += 1; + } + } + ByteOrder::BigEndian => { + let mut src_bit = self.start_bit as usize; + let mut dst_bit = self.signal_size - 1; + for _ in 0..self.signal_size { + /* copy bit */ + let index = src_bit / 8; + if index >= len { + return None; + } + if (data[index] & (1 << (src_bit % 8))) > 0 { + result |= 1 << dst_bit; + } + + /* calculate next position */ + if (src_bit % 8) == 0 { + src_bit += 15; + } else { + src_bit -= 1; + } + dst_bit -= 1; + } + } + } + + match self.value_type() { + ValueType::Signed => { + if (result & (1 << (self.signal_size - 1))) > 0 { + for i in self.signal_size..64 { + result |= 1 << i; + } + } + } + ValueType::Unsigned => {} + } + + Some(result) + } + + /// Encodes a signal into the message data + /// + /// # Params + /// + /// * data: source data + /// + /// * value: Raw signal value + pub fn encode(&self, data: &mut Vec, value: u64) { + if self.signal_size == 0 { + return; + } + + match self.byte_order { + ByteOrder::LittleEndian => { + let mut src_bit = self.start_bit as usize; + let mut dst_bit = 0; + for _ in 0..self.signal_size { + /* copy bit */ + let index = src_bit / 8; + if index >= data.len() { + data.resize(index + 1, 0); + } + if (value & 1 << dst_bit) > 0 { + data[index] |= 1 << (src_bit % 8); + } else { + data[index] &= !(1 << (src_bit % 8)); + } + + /* calculate next position */ + src_bit += 1; + dst_bit += 1; + } + } + ByteOrder::BigEndian => { + let mut src_bit = self.start_bit as usize; + let mut dst_bit = self.signal_size - 1; + for _ in 0..self.signal_size { + /* copy bit */ + let index = src_bit / 8; + if index >= data.len() { + data.resize(index + 1, 0); + } + if (value & 1 << dst_bit) > 0 { + data[index] |= 1 << (dst_bit % 8); + } else { + data[index] &= !(1 << (src_bit % 8)); + } + + /* calculate next position */ + if (src_bit % 8) == 0 { + src_bit += 15; + } else { + src_bit -= 1; + } + dst_bit -= 1; + } + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 4412748..f22f25e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,9 @@ use std::convert::TryFrom; use derive_getters::Getters; +mod extend; pub mod parser; +pub use extend::*; #[cfg(test)] mod tests {