Skip to content

Commit d99005f

Browse files
committed
Nested Parsers: Architectures proposal...
* Resolver will be passed to resolve method instead of parser returning a template. * Parsing log message is returning an error which is defined by each type implementing LogMessage trait. * Types with no errors sets the error to infallible for compiler optimizations. * This approach enables saving parsing errors. * Nested errors are ignored for now
1 parent 51352e8 commit d99005f

File tree

13 files changed

+428
-66
lines changed

13 files changed

+428
-66
lines changed

application/apps/indexer/Cargo.lock

+7-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

application/apps/indexer/Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ thiserror = "1.0"
2222
lazy_static = "1.4"
2323
tokio = { version = "1", features = ["full"] }
2424
tokio-stream = "0.1"
25-
dlt-core = "0.14"
25+
# dlt-core = "0.14"
26+
# TODO https://github.com/esrlabs/dlt-core/pull/24
27+
dlt-core = { git = "https://github.com/kruss/dlt-core.git", branch = "dlt_network_traces" }
2628
crossbeam-channel = "0.5"
2729
futures = "0.3"
2830
tokio-util = "0.7"

application/apps/indexer/indexer_cli/src/interactive.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
use crate::{duration_report, Instant};
22
use futures::{pin_mut, stream::StreamExt};
3-
use parsers::{dlt::DltParser, MessageStreamItem, ParseYield};
3+
use parsers::{
4+
dlt::DltParser,
5+
nested_parser::{resolve_log_msg, ParseRestResolver},
6+
MessageStreamItem, ParseYield,
7+
};
48
use processor::grabber::LineRange;
59
use rustyline::{error::ReadlineError, DefaultEditor};
610
use session::session::Session;
@@ -46,6 +50,7 @@ pub(crate) async fn handle_interactive_session(input: Option<PathBuf>) {
4650
let udp_source = UdpSource::new(RECEIVER, vec![]).await.unwrap();
4751
let dlt_parser = DltParser::new(None, None, None, false);
4852
let mut dlt_msg_producer = MessageProducer::new(dlt_parser, udp_source, None);
53+
let mut parse_reslover = ParseRestResolver::new();
4954
let msg_stream = dlt_msg_producer.as_stream();
5055
pin_mut!(msg_stream);
5156
loop {
@@ -56,10 +61,12 @@ pub(crate) async fn handle_interactive_session(input: Option<PathBuf>) {
5661
}
5762
item = msg_stream.next() => {
5863
match item {
59-
Some((_, MessageStreamItem::Item(ParseYield::Message(msg)))) => {
64+
Some((_, MessageStreamItem::Item(ParseYield::Message(item)))) => {
65+
let msg = resolve_log_msg(item, &mut parse_reslover);
6066
println!("msg: {msg}");
6167
}
62-
Some((_, MessageStreamItem::Item(ParseYield::MessageAndAttachment((msg, attachment))))) => {
68+
Some((_, MessageStreamItem::Item(ParseYield::MessageAndAttachment((item, attachment))))) => {
69+
let msg = resolve_log_msg(item, &mut parse_reslover);
6370
println!("msg: {msg}, attachment: {attachment:?}");
6471
}
6572
Some((_, MessageStreamItem::Item(ParseYield::Attachment(attachment)))) => {

application/apps/indexer/parsers/Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ rand.workspace = true
1818
# someip-messages = { path = "../../../../../someip"}
1919
someip-messages = { git = "https://github.com/esrlabs/someip" }
2020
# someip-payload = { path = "../../../../../someip-payload" }
21-
someip-payload = { git = "https://github.com/esrlabs/someip-payload" }
21+
# someip-payload = { git = "https://github.com/esrlabs/someip-payload" }
22+
# TODO
23+
someip-payload = { git = "https://github.com/kruss/someip-payload.git", branch = "robustness" }
2224

2325
[dev-dependencies]
2426
stringreader = "0.1.1"

application/apps/indexer/parsers/src/dlt/fmt.rs

+116-20
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,15 @@ use log::trace;
2828
use serde::ser::{Serialize, SerializeStruct, Serializer};
2929

3030
use std::{
31-
fmt::{self, Formatter},
31+
fmt::{self, Display, Formatter, Write},
3232
str,
3333
};
3434

35+
use crate::{
36+
nested_parser::ParseRestResolver, GeneralParseLogError, LogMessage, ParseLogSeverity,
37+
ResolveParseHint,
38+
};
39+
3540
const DLT_COLUMN_SENTINAL: char = '\u{0004}';
3641
const DLT_ARGUMENT_SENTINAL: char = '\u{0005}';
3742
const DLT_NEWLINE_SENTINAL_SLICE: &[u8] = &[0x6];
@@ -281,6 +286,17 @@ impl<'a> Serialize for FormattableMessage<'a> {
281286
None => state.serialize_field("payload", "[Unknown CtrlCommand]")?,
282287
}
283288
}
289+
PayloadContent::NetworkTrace(slices) => {
290+
state.serialize_field("app-id", &ext_header_app_id)?;
291+
state.serialize_field("context-id", &ext_header_context_id)?;
292+
state.serialize_field("message-type", &ext_header_msg_type)?;
293+
let arg_string = slices
294+
.iter()
295+
.map(|slice| format!("{:02X?}", slice))
296+
.collect::<Vec<String>>()
297+
.join("|");
298+
state.serialize_field("payload", &arg_string)?;
299+
}
284300
}
285301
state.end()
286302
}
@@ -386,12 +402,25 @@ impl<'a> FormattableMessage<'a> {
386402
payload_string,
387403
))
388404
}
405+
PayloadContent::NetworkTrace(slices) => {
406+
let payload_string = slices
407+
.iter()
408+
.map(|slice| format!("{:02X?}", slice))
409+
.collect::<Vec<String>>()
410+
.join("|");
411+
Ok(PrintableMessage::new(
412+
ext_h_app_id,
413+
eh_ctx_id,
414+
ext_h_msg_type,
415+
payload_string,
416+
))
417+
}
389418
}
390419
}
391420

392421
fn write_app_id_context_id_and_message_type(
393422
&self,
394-
f: &mut fmt::Formatter,
423+
f: &mut impl std::fmt::Write,
395424
) -> Result<(), fmt::Error> {
396425
match self.message.extended_header.as_ref() {
397426
Some(ext) => {
@@ -419,7 +448,7 @@ impl<'a> FormattableMessage<'a> {
419448
&self,
420449
id: u32,
421450
data: &[u8],
422-
f: &mut fmt::Formatter,
451+
f: &mut impl std::fmt::Write,
423452
) -> fmt::Result {
424453
trace!("format_nonverbose_data");
425454
let mut fibex_info_added = false;
@@ -511,7 +540,16 @@ impl<'a> FormattableMessage<'a> {
511540
}
512541
}
513542

514-
impl<'a> fmt::Display for FormattableMessage<'a> {
543+
impl LogMessage for FormattableMessage<'_> {
544+
type ParseError = GeneralParseLogError;
545+
546+
fn to_writer<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
547+
let bytes = self.message.as_bytes();
548+
let len = bytes.len();
549+
writer.write_all(&bytes)?;
550+
Ok(len)
551+
}
552+
515553
/// will format dlt Message with those fields:
516554
/// ********* storage-header ********
517555
/// date-time
@@ -528,43 +566,101 @@ impl<'a> fmt::Display for FormattableMessage<'a> {
528566
/// context-id
529567
///
530568
/// payload
531-
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
569+
fn try_resolve(
570+
&self,
571+
resolver: Option<&mut ParseRestResolver>,
572+
) -> Result<impl Display, Self::ParseError> {
573+
let mut msg = String::new();
574+
// Taken from Documentation: string formatting is considered an infallible operation.
575+
// Thus we can ignore `fmt::Error` errors.
576+
// Link from Clippy: 'https://rust-lang.github.io/rust-clippy/master/index.html#/format_push_string'
577+
// TODO: Consider another way of concatenating the string after prototyping.
532578
if let Some(h) = &self.message.storage_header {
533579
let tz = self.options.map(|o| o.tz);
534580
match tz {
535581
Some(Some(tz)) => {
536-
write_tz_string(f, &h.timestamp, &tz)?;
537-
write!(f, "{DLT_COLUMN_SENTINAL}{}", h.ecu_id)?;
582+
let _ = write_tz_string(&mut msg, &h.timestamp, &tz);
583+
let _ = write!(msg, "{DLT_COLUMN_SENTINAL}{}", h.ecu_id);
584+
}
585+
_ => {
586+
let _ = write!(msg, "{}", DltStorageHeader(h));
538587
}
539-
_ => write!(f, "{}", DltStorageHeader(h))?,
540588
};
541589
}
542590
let header = DltStandardHeader(&self.message.header);
543-
write!(f, "{DLT_COLUMN_SENTINAL}",)?;
544-
write!(f, "{header}")?;
545-
write!(f, "{DLT_COLUMN_SENTINAL}",)?;
591+
write!(msg, "{DLT_COLUMN_SENTINAL}",).unwrap();
592+
write!(msg, "{header}").unwrap();
593+
write!(msg, "{DLT_COLUMN_SENTINAL}",).unwrap();
546594

547595
match &self.message.payload {
548596
PayloadContent::Verbose(arguments) => {
549-
self.write_app_id_context_id_and_message_type(f)?;
550-
arguments
551-
.iter()
552-
.try_for_each(|arg| write!(f, "{}{}", DLT_ARGUMENT_SENTINAL, DltArgument(arg)))
597+
let _ = self.write_app_id_context_id_and_message_type(&mut msg);
598+
arguments.iter().for_each(|arg| {
599+
let _ = write!(msg, "{}{}", DLT_ARGUMENT_SENTINAL, DltArgument(arg));
600+
});
601+
}
602+
PayloadContent::NonVerbose(id, data) => {
603+
let _ = self.format_nonverbose_data(*id, data, &mut msg);
553604
}
554-
PayloadContent::NonVerbose(id, data) => self.format_nonverbose_data(*id, data, f),
555605
PayloadContent::ControlMsg(ctrl_id, _data) => {
556-
self.write_app_id_context_id_and_message_type(f)?;
606+
let _ = self.write_app_id_context_id_and_message_type(&mut msg);
557607
match service_id_lookup(ctrl_id.value()) {
558-
Some((name, _desc)) => write!(f, "[{name}]"),
559-
None => write!(f, "[Unknown CtrlCommand]"),
608+
Some((name, _desc)) => {
609+
let _ = write!(msg, "[{name}]");
610+
}
611+
None => {
612+
let _ = write!(msg, "[Unknown CtrlCommand]");
613+
}
560614
}
561615
}
616+
PayloadContent::NetworkTrace(slices) => {
617+
let _ = self.write_app_id_context_id_and_message_type(&mut msg);
618+
let is_someip = self
619+
.message
620+
.extended_header
621+
.as_ref()
622+
.is_some_and(|ext_header| {
623+
matches!(
624+
ext_header.message_type,
625+
MessageType::NetworkTrace(NetworkTraceType::Ipc)
626+
| MessageType::NetworkTrace(NetworkTraceType::Someip)
627+
)
628+
});
629+
630+
if is_someip {
631+
if let Some(resolver) = resolver {
632+
if let Some(slice) = slices.get(1) {
633+
match resolver.try_resolve(slice, ResolveParseHint::SomeIP) {
634+
Some(Ok(resolved)) => {
635+
let _ = write!(msg, "{resolved}");
636+
return Ok(msg);
637+
}
638+
Some(Err(_)) | None => {
639+
//TODO: Ignore nested Error while prototyping
640+
}
641+
}
642+
}
643+
}
644+
}
645+
646+
slices.iter().for_each(|slice| {
647+
let _ = write!(msg, "{}{:02X?}", DLT_ARGUMENT_SENTINAL, slice);
648+
});
649+
650+
return Err(GeneralParseLogError::new(
651+
msg,
652+
"Error while resolving Network trace payload".into(),
653+
ParseLogSeverity::Error,
654+
));
655+
}
562656
}
657+
658+
Ok(msg)
563659
}
564660
}
565661

566662
fn write_tz_string(
567-
f: &mut Formatter,
663+
f: &mut impl std::fmt::Write,
568664
time_stamp: &DltTimeStamp,
569665
tz: &Tz,
570666
) -> Result<(), fmt::Error> {

application/apps/indexer/parsers/src/dlt/mod.rs

+19-10
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,10 @@ use dlt_core::{
1313
parse::{dlt_consume_msg, dlt_message},
1414
};
1515
use serde::Serialize;
16-
use std::{io::Write, ops::Range};
16+
use std::{convert::Infallible, fmt::Display, io::Write, ops::Range};
1717

1818
use self::{attachment::FtScanner, fmt::FormatOptions};
1919

20-
impl LogMessage for FormattableMessage<'_> {
21-
fn to_writer<W: Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
22-
let bytes = self.message.as_bytes();
23-
let len = bytes.len();
24-
writer.write_all(&bytes)?;
25-
Ok(len)
26-
}
27-
}
28-
2920
#[derive(Debug, Serialize)]
3021
pub struct RawMessage {
3122
pub content: Vec<u8>,
@@ -48,20 +39,38 @@ impl std::fmt::Display for RawMessage {
4839
}
4940

5041
impl LogMessage for RangeMessage {
42+
type ParseError = Infallible;
43+
5144
/// A RangeMessage only has range information and cannot serialize to bytes
5245
fn to_writer<W: Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
5346
writer.write_u64::<BigEndian>(self.range.start as u64)?;
5447
writer.write_u64::<BigEndian>(self.range.end as u64)?;
5548
Ok(8 + 8)
5649
}
50+
51+
fn try_resolve(
52+
&self,
53+
_resolver: Option<&mut crate::nested_parser::ParseRestResolver>,
54+
) -> Result<impl Display, Self::ParseError> {
55+
Ok(self)
56+
}
5757
}
5858

5959
impl LogMessage for RawMessage {
60+
type ParseError = Infallible;
61+
6062
fn to_writer<W: Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
6163
let len = self.content.len();
6264
writer.write_all(&self.content)?;
6365
Ok(len)
6466
}
67+
68+
fn try_resolve(
69+
&self,
70+
_resolver: Option<&mut crate::nested_parser::ParseRestResolver>,
71+
) -> Result<impl Display, Self::ParseError> {
72+
Ok(self)
73+
}
6574
}
6675

6776
#[derive(Default)]

0 commit comments

Comments
 (0)