#![allow(clippy::bool_comparison)]
#![no_std]
#[cfg(test)]
extern crate alloc;
#[cfg(test)]
extern crate proptest;
#[cfg(any(feature = "std", test))]
extern crate std;
#[cfg(test)]
#[macro_use]
extern crate assert_matches;
mod dlt_extended_header;
pub use dlt_extended_header::*;
mod dlt_header;
pub use dlt_header::*;
mod dlt_typed_payload;
pub use dlt_typed_payload::*;
mod dlt_message_info;
pub use dlt_message_info::*;
mod dlt_packet_slice;
pub use dlt_packet_slice::*;
mod dlt_slice_iterator;
pub use dlt_slice_iterator::*;
mod nv_payload;
pub use nv_payload::*;
pub mod control;
pub mod error;
pub mod verbose;
pub mod storage;
#[cfg(test)]
use alloc::{format, vec, vec::Vec};
use arrayvec::ArrayVec;
use core::slice::from_raw_parts;
#[cfg(feature = "std")]
use std::io;
#[cfg(test)]
mod proptest_generators;
const MAX_VERSION: u8 = 0b111;
const EXTDENDED_HEADER_FLAG: u8 = 0b1;
const BIG_ENDIAN_FLAG: u8 = 0b10;
const ECU_ID_FLAG: u8 = 0b100;
const SESSION_ID_FLAG: u8 = 0b1000;
const TIMESTAMP_FLAG: u8 = 0b10000;
pub const EXT_MSIN_VERB_FLAG: u8 = 0b0000_0001;
const EXT_MSIN_MSTP_TYPE_LOG: u8 = 0x0 << 1;
const EXT_MSIN_MSTP_TYPE_TRACE: u8 = 0x1 << 1;
const EXT_MSIN_MSTP_TYPE_NW_TRACE: u8 = 0x2 << 1;
const EXT_MSIN_MSTP_TYPE_CONTROL: u8 = 0x3 << 1;
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum DltLogLevel {
Fatal = 0x1,
Error = 0x2,
Warn = 0x3,
Info = 0x4,
Debug = 0x5,
Verbose = 0x6,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum DltTraceType {
Variable = 0x1,
FunctionIn = 0x2,
FunctionOut = 0x3,
State = 0x4,
Vfb = 0x5,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum DltNetworkType {
Ipc,
Can,
Flexray,
Most,
Ethernet,
SomeIp,
UserDefined(u8),
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum DltControlMessageType {
Request = 0x1,
Response = 0x2,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum DltMessageType {
Log(DltLogLevel),
Trace(DltTraceType),
NetworkTrace(DltNetworkType),
Control(DltControlMessageType),
}
impl DltMessageType {
fn from_byte(value: u8) -> Option<DltMessageType> {
use DltMessageType::*;
const MSIN_MASK: u8 = 0b1111_0000;
match value & 0b0000_1110 {
EXT_MSIN_MSTP_TYPE_LOG => {
use DltLogLevel::*;
match (value & MSIN_MASK) >> 4 {
0x1 => Some(Log(Fatal)),
0x2 => Some(Log(Error)),
0x3 => Some(Log(Warn)),
0x4 => Some(Log(Info)),
0x5 => Some(Log(Debug)),
0x6 => Some(Log(Verbose)),
_ => None,
}
}
EXT_MSIN_MSTP_TYPE_TRACE => {
use DltTraceType::*;
match (value & MSIN_MASK) >> 4 {
0x1 => Some(Trace(Variable)),
0x2 => Some(Trace(FunctionIn)),
0x3 => Some(Trace(FunctionOut)),
0x4 => Some(Trace(State)),
0x5 => Some(Trace(Vfb)),
_ => None,
}
}
EXT_MSIN_MSTP_TYPE_NW_TRACE => {
use DltNetworkType::*;
match (value & MSIN_MASK) >> 4 {
0x1 => Some(NetworkTrace(Ipc)),
0x2 => Some(NetworkTrace(Can)),
0x3 => Some(NetworkTrace(Flexray)),
0x4 => Some(NetworkTrace(Most)),
0x5 => Some(NetworkTrace(Ethernet)),
0x6 => Some(NetworkTrace(SomeIp)),
other => Some(NetworkTrace(UserDefined(other))),
}
}
EXT_MSIN_MSTP_TYPE_CONTROL => {
use DltControlMessageType::*;
match (value & MSIN_MASK) >> 4 {
0x1 => Some(Control(Request)),
0x2 => Some(Control(Response)),
_ => None,
}
}
_ => None,
}
}
pub fn to_byte(&self) -> Result<u8, error::RangeError> {
use error::RangeError::NetworkTypekUserDefinedOutsideOfRange;
use DltMessageType::*;
use DltNetworkType::UserDefined;
if let NetworkTrace(UserDefined(user_defined_value)) = *self {
if !(7..=0xf).contains(&user_defined_value) {
return Err(NetworkTypekUserDefinedOutsideOfRange(user_defined_value));
}
}
let (message_type, message_type_info) = match self {
Log(ref level) => (EXT_MSIN_MSTP_TYPE_LOG, *level as u8),
Trace(ref trace_type) => (EXT_MSIN_MSTP_TYPE_TRACE, *trace_type as u8),
NetworkTrace(ref nw_trace_type) => {
use DltNetworkType::*;
(
EXT_MSIN_MSTP_TYPE_NW_TRACE,
match *nw_trace_type {
Ipc => 0x1,
Can => 0x2,
Flexray => 0x3,
Most => 0x4,
Ethernet => 0x5,
SomeIp => 0x6,
UserDefined(value) => value,
},
)
}
Control(ref control_msg_type) => (EXT_MSIN_MSTP_TYPE_CONTROL, *control_msg_type as u8),
};
Ok(message_type | ((message_type_info << 4) & 0b1111_0000))
}
}
#[cfg(test)]
mod tests {
use super::*;
mod dlt_log_level {
use super::*;
use DltLogLevel::*;
#[test]
fn clone_eq() {
const VALUES: [(DltLogLevel, u8); 6] = [
(Fatal, 1),
(Error, 2),
(Warn, 3),
(Info, 4),
(Debug, 5),
(Verbose, 6),
];
for v0 in &VALUES {
assert_eq!(v0.0, v0.0.clone());
assert_eq!(v0.0 as u8, v0.1);
for v1 in &VALUES {
assert_eq!(v0.0 != v1.0, v0.1 != v1.1,);
}
}
}
#[test]
fn debug() {
const VALUES: [(DltLogLevel, &str); 6] = [
(Fatal, "Fatal"),
(Error, "Error"),
(Warn, "Warn"),
(Info, "Info"),
(Debug, "Debug"),
(Verbose, "Verbose"),
];
for v in &VALUES {
assert_eq!(v.1, format!("{:?}", v.0));
}
}
}
mod dlt_trace_type {
use super::*;
use DltTraceType::*;
#[test]
fn clone_eq() {
const VALUES: [(DltTraceType, u8); 5] = [
(Variable, 1),
(FunctionIn, 2),
(FunctionOut, 3),
(State, 4),
(Vfb, 5),
];
for v0 in &VALUES {
assert_eq!(v0.0, v0.0.clone());
assert_eq!(v0.0 as u8, v0.1);
for v1 in &VALUES {
assert_eq!(v0.0 != v1.0, v0.1 != v1.1,);
}
}
}
#[test]
fn debug() {
const VALUES: [(DltTraceType, &str); 5] = [
(Variable, "Variable"),
(FunctionIn, "FunctionIn"),
(FunctionOut, "FunctionOut"),
(State, "State"),
(Vfb, "Vfb"),
];
for v in &VALUES {
assert_eq!(v.1, format!("{:?}", v.0));
}
}
}
mod dlt_network_type {
use super::*;
use DltNetworkType::*;
#[test]
fn clone_eq() {
const VALUES: [(DltNetworkType, u8); 8] = [
(Ipc, 1),
(Can, 2),
(Flexray, 3),
(Most, 4),
(Ethernet, 5),
(SomeIp, 6),
(UserDefined(0x7), 0x7),
(UserDefined(0xf), 0xf),
];
for v0 in &VALUES {
assert_eq!(v0.0, v0.0.clone());
for v1 in &VALUES {
assert_eq!(v0.0 != v1.0, v0.1 != v1.1,);
}
}
}
#[test]
fn debug() {
const VALUES: [(DltNetworkType, &str); 8] = [
(Ipc, "Ipc"),
(Can, "Can"),
(Flexray, "Flexray"),
(Most, "Most"),
(Ethernet, "Ethernet"),
(SomeIp, "SomeIp"),
(UserDefined(0x7), "UserDefined(7)"),
(UserDefined(0xf), "UserDefined(15)"),
];
for v in &VALUES {
assert_eq!(v.1, format!("{:?}", v.0));
}
}
}
mod dlt_control_message_type {
use super::*;
use DltControlMessageType::*;
#[test]
fn clone_eq() {
const VALUES: [(DltControlMessageType, u8); 2] = [(Request, 1), (Response, 2)];
for v0 in &VALUES {
assert_eq!(v0.0, v0.0.clone());
assert_eq!(v0.0.clone() as u8, v0.1);
for v1 in &VALUES {
assert_eq!(v0.0 != v1.0, v0.1 != v1.1,);
}
}
}
#[test]
fn debug() {
const VALUES: [(DltControlMessageType, &str); 2] =
[(Request, "Request"), (Response, "Response")];
for v in &VALUES {
assert_eq!(v.1, format!("{:?}", v.0));
}
}
}
mod dlt_message_type {
use super::*;
use DltControlMessageType::*;
use DltLogLevel::*;
use DltMessageType::*;
use DltNetworkType::*;
use DltTraceType::*;
const VALUES: [(DltMessageType, u8); 28] = [
(Log(Fatal), 0b0001_0000),
(Log(Error), 0b0010_0000),
(Log(Warn), 0b0011_0000),
(Log(Info), 0b0100_0000),
(Log(Debug), 0b0101_0000),
(Log(Verbose), 0b0110_0000),
(Trace(Variable), 0b0001_0010),
(Trace(FunctionIn), 0b0010_0010),
(Trace(FunctionOut), 0b0011_0010),
(Trace(State), 0b0100_0010),
(Trace(Vfb), 0b0101_0010),
(NetworkTrace(Ipc), 0b0001_0100),
(NetworkTrace(Can), 0b0010_0100),
(NetworkTrace(Flexray), 0b0011_0100),
(NetworkTrace(Most), 0b0100_0100),
(NetworkTrace(Ethernet), 0b0101_0100),
(NetworkTrace(SomeIp), 0b0110_0100),
(NetworkTrace(UserDefined(0x7)), 0b0111_0100),
(NetworkTrace(UserDefined(0x8)), 0b1000_0100),
(NetworkTrace(UserDefined(0x9)), 0b1001_0100),
(NetworkTrace(UserDefined(0xA)), 0b1010_0100),
(NetworkTrace(UserDefined(0xB)), 0b1011_0100),
(NetworkTrace(UserDefined(0xC)), 0b1100_0100),
(NetworkTrace(UserDefined(0xD)), 0b1101_0100),
(NetworkTrace(UserDefined(0xE)), 0b1110_0100),
(NetworkTrace(UserDefined(0xF)), 0b1111_0100),
(Control(Request), 0b0001_0110),
(Control(Response), 0b0010_0110),
];
#[test]
fn clone_eq() {
for v0 in &VALUES {
assert_eq!(v0.0, v0.0.clone());
for v1 in &VALUES {
assert_eq!(v0.0 != v1.0, v0.1 != v1.1,);
}
}
}
#[test]
fn debug() {
const DBG_VALUES: [(DltMessageType, &str); 5] = [
(Log(Fatal), "Log(Fatal)"),
(Trace(Variable), "Trace(Variable)"),
(NetworkTrace(Ipc), "NetworkTrace(Ipc)"),
(
NetworkTrace(UserDefined(0x7)),
"NetworkTrace(UserDefined(7))",
),
(Control(Request), "Control(Request)"),
];
for v in &DBG_VALUES {
assert_eq!(v.1, format!("{:?}", v.0));
}
}
#[test]
fn from_byte() {
for value in &VALUES {
assert_eq!(value.0, DltMessageType::from_byte(value.1).unwrap());
assert_eq!(value.0, DltMessageType::from_byte(value.1 | 1).unwrap());
}
assert!(DltMessageType::from_byte(0).is_none());
assert!(DltMessageType::from_byte(1).is_none()); for i in 7..=0b1111 {
assert!(DltMessageType::from_byte(i << 4).is_none());
assert!(DltMessageType::from_byte((i << 4) | 1).is_none());
}
assert!(DltMessageType::from_byte(0b0000_0010).is_none());
assert!(DltMessageType::from_byte(0b0000_0011).is_none());
for i in 6..=0b1111 {
assert!(DltMessageType::from_byte((i << 4) | 0b0010).is_none());
assert!(DltMessageType::from_byte((i << 4) | 0b0011).is_none());
}
assert!(DltMessageType::from_byte(0b0000_0110).is_none());
assert!(DltMessageType::from_byte(0b0000_0111).is_none());
for i in 3..=0b1111 {
assert!(DltMessageType::from_byte((i << 4) | 0b0110).is_none());
assert!(DltMessageType::from_byte((i << 4) | 0b0111).is_none());
}
}
#[test]
fn to_byte() {
for value in &VALUES {
assert_eq!(value.0.to_byte().unwrap(), value.1);
}
use error::RangeError::NetworkTypekUserDefinedOutsideOfRange;
assert_matches!(
NetworkTrace(UserDefined(0)).to_byte().unwrap_err(),
NetworkTypekUserDefinedOutsideOfRange(0)
);
assert_matches!(
NetworkTrace(UserDefined(1)).to_byte().unwrap_err(),
NetworkTypekUserDefinedOutsideOfRange(1)
);
for value in 0..7 {
assert_matches!(
NetworkTrace(UserDefined(value)).to_byte().unwrap_err(),
NetworkTypekUserDefinedOutsideOfRange(_)
);
}
for value in 16..=0xff {
assert_matches!(
NetworkTrace(UserDefined(value)).to_byte().unwrap_err(),
NetworkTypekUserDefinedOutsideOfRange(_)
);
}
}
}
}