Skip to content

Commit f86262a

Browse files
committed
DLT SomeIP: Make solution more broad supporting templating
* Resolving log messages provides an enum with text or template which need to be resolved. * Sessions can try to resolve all the chunks from the templates * Faulty messages are removed for now to keep the focus here on multiple parsers. * Renaming modules, types and methods
1 parent c6a7b8f commit f86262a

File tree

10 files changed

+188
-170
lines changed

10 files changed

+188
-170
lines changed

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use parsers::{dlt::DltParser, MessageStreamItem, ParseYield};
44
use processor::grabber::LineRange;
55
use rustyline::{error::ReadlineError, DefaultEditor};
66
use session::{
7-
parse_err::{get_log_text, ParseErrorReslover},
7+
parse_rest_resolver::{resolve_log_msg, ParseRestReslover},
88
session::Session,
99
};
1010
use sources::{
@@ -49,7 +49,7 @@ pub(crate) async fn handle_interactive_session(input: Option<PathBuf>) {
4949
let udp_source = UdpSource::new(RECEIVER, vec![]).await.unwrap();
5050
let dlt_parser = DltParser::new(None, None, None, false);
5151
let mut dlt_msg_producer = MessageProducer::new(dlt_parser, udp_source, None);
52-
let mut parse_reslover = ParseErrorReslover::new();
52+
let mut parse_reslover = ParseRestReslover::new();
5353
let msg_stream = dlt_msg_producer.as_stream();
5454
pin_mut!(msg_stream);
5555
loop {
@@ -61,11 +61,11 @@ pub(crate) async fn handle_interactive_session(input: Option<PathBuf>) {
6161
item = msg_stream.next() => {
6262
match item {
6363
Some((_, MessageStreamItem::Item(ParseYield::Message(item)))) => {
64-
let msg = get_log_text(item, &mut parse_reslover);
64+
let msg = resolve_log_msg(item, &mut parse_reslover);
6565
println!("msg: {msg}");
6666
}
6767
Some((_, MessageStreamItem::Item(ParseYield::MessageAndAttachment((item, attachment))))) => {
68-
let msg = get_log_text(item, &mut parse_reslover);
68+
let msg = resolve_log_msg(item, &mut parse_reslover);
6969
println!("msg: {msg}, attachment: {attachment:?}");
7070
}
7171
Some((_, MessageStreamItem::Item(ParseYield::Attachment(attachment)))) => {

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

+11-9
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ use std::{
3232
str,
3333
};
3434

35-
use crate::{LogMessage, ParseLogError, ResolveErrorHint, ToTextResult};
35+
use crate::{
36+
LogMessage, LogMsgResolveResult, ResolveParseHint, TemplateLogMsg, TemplateLogMsgChunk,
37+
};
3638

3739
const DLT_COLUMN_SENTINAL: char = '\u{0004}';
3840
const DLT_ARGUMENT_SENTINAL: char = '\u{0005}';
@@ -538,8 +540,6 @@ impl<'a> FormattableMessage<'a> {
538540
}
539541

540542
impl LogMessage for FormattableMessage<'_> {
541-
const CAN_ERROR: bool = true;
542-
543543
fn to_writer<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
544544
let bytes = self.message.as_bytes();
545545
let len = bytes.len();
@@ -563,7 +563,7 @@ impl LogMessage for FormattableMessage<'_> {
563563
/// context-id
564564
///
565565
/// payload
566-
fn to_text(&self) -> ToTextResult {
566+
fn try_resolve(&self) -> LogMsgResolveResult {
567567
let mut msg = String::new();
568568
// Taken from Documentation: string formatting is considered an infallible operation.
569569
// Thus we can ignore `fmt::Error` errors.
@@ -623,12 +623,14 @@ impl LogMessage for FormattableMessage<'_> {
623623

624624
if is_someip {
625625
if let Some(slice) = slices.get(1) {
626-
let err = ParseLogError::new(
627-
slice.to_owned(),
628-
crate::ParseErrorType::Other("Need Some IP".into()),
629-
Some(ResolveErrorHint::SomeIP),
626+
let template = TemplateLogMsg::new(
627+
vec![
628+
TemplateLogMsgChunk::Text(msg),
629+
TemplateLogMsgChunk::Bytes(slice.to_owned()),
630+
],
631+
vec![ResolveParseHint::SomeIP],
630632
);
631-
return ToTextResult::new(msg, Some(err));
633+
return LogMsgResolveResult::Template(template);
632634
}
633635
}
634636

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

+2-6
Original file line numberDiff line numberDiff line change
@@ -39,30 +39,26 @@ impl std::fmt::Display for RawMessage {
3939
}
4040

4141
impl LogMessage for RangeMessage {
42-
const CAN_ERROR: bool = false;
43-
4442
/// A RangeMessage only has range information and cannot serialize to bytes
4543
fn to_writer<W: Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
4644
writer.write_u64::<BigEndian>(self.range.start as u64)?;
4745
writer.write_u64::<BigEndian>(self.range.end as u64)?;
4846
Ok(8 + 8)
4947
}
5048

51-
fn to_text(&self) -> crate::ToTextResult {
49+
fn try_resolve(&self) -> crate::LogMsgResolveResult {
5250
self.into()
5351
}
5452
}
5553

5654
impl LogMessage for RawMessage {
57-
const CAN_ERROR: bool = false;
58-
5955
fn to_writer<W: Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
6056
let len = self.content.len();
6157
writer.write_all(&self.content)?;
6258
Ok(len)
6359
}
6460

65-
fn to_text(&self) -> crate::ToTextResult {
61+
fn try_resolve(&self) -> crate::LogMsgResolveResult {
6662
self.into()
6763
}
6864
}

application/apps/indexer/parsers/src/lib.rs

+97-71
Original file line numberDiff line numberDiff line change
@@ -78,99 +78,125 @@ pub enum ByteRepresentation {
7878
Range((usize, usize)),
7979
}
8080

81-
#[derive(Debug, Clone)]
82-
pub enum ParseErrorType {
83-
Fmt(String),
84-
Other(String),
81+
#[derive(Debug)]
82+
pub enum MessageStreamItem<T: LogMessage> {
83+
Item(ParseYield<T>),
84+
Skipped,
85+
Incomplete,
86+
Empty,
87+
Done,
8588
}
8689

87-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
88-
/// Gives Hint about how this error can be resolved by processor
89-
pub enum ResolveErrorHint {
90-
/// The message needs to be parsed with SomeIP Parser.
91-
SomeIP,
90+
pub trait LogMessage: Serialize {
91+
/// Serializes a message directly into a Writer
92+
/// returns the size of the serialized message
93+
fn to_writer<W: Write>(&self, writer: &mut W) -> Result<usize, std::io::Error>;
94+
95+
/// Tries to resolve the message to get its text representation.
96+
///
97+
/// TODO: This function should return another optional field, containing information
98+
/// about errors, warning ...
99+
fn try_resolve(&self) -> LogMessageContent;
92100
}
93101

94102
#[derive(Debug, Clone)]
95-
pub struct ParseLogError {
96-
pub remain_bytes: Vec<u8>,
97-
pub error_type: ParseErrorType,
98-
pub resolve_hint: Option<ResolveErrorHint>,
99-
}
100-
101-
impl ParseLogError {
102-
pub fn new(
103-
remain_bytes: Vec<u8>,
104-
error_type: ParseErrorType,
105-
resolve_hint: Option<ResolveErrorHint>,
106-
) -> Self {
107-
Self {
108-
remain_bytes,
109-
error_type,
110-
resolve_hint,
111-
}
112-
}
103+
/// Represents The content of a log message after trying to resolve it.
104+
pub enum LogMessageContent {
105+
Text(String),
106+
Template(TemplateLogMsg),
113107
}
114108

115-
impl Display for ParseLogError {
116-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117-
match &self.error_type {
118-
ParseErrorType::Other(msg) | ParseErrorType::Fmt(msg) => write!(f, "{msg}"),
119-
}
120-
}
109+
#[derive(Debug, Clone)]
110+
/// Represents an unresolved log messages that contains chunks that needs to be resolved.
111+
pub struct TemplateLogMsg {
112+
chunks: Vec<TemplateLogMsgChunk>,
113+
resolve_hints: Vec<ResolveParseHint>,
121114
}
122115

123-
impl From<std::fmt::Error> for ParseLogError {
124-
fn from(value: std::fmt::Error) -> Self {
125-
Self {
126-
remain_bytes: Vec::new(),
127-
error_type: ParseErrorType::Fmt(value.to_string()),
128-
resolve_hint: None,
129-
}
130-
}
116+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
117+
/// Gives Hint about how the payload rest can be resolved
118+
pub enum ResolveParseHint {
119+
/// The message needs to be parsed with SomeIP Parser.
120+
SomeIP,
131121
}
132122

133-
impl std::error::Error for ParseLogError {}
134-
135123
#[derive(Debug, Clone)]
136-
pub struct ToTextResult {
137-
pub msg: String,
138-
pub error: Option<ParseLogError>,
139-
}
140-
141-
impl ToTextResult {
142-
pub fn new(msg: String, error: Option<ParseLogError>) -> Self {
143-
Self { msg, error }
144-
}
124+
/// Represents a chunk in [`TemplateLogMsg`]
125+
pub enum TemplateLogMsgChunk {
126+
/// Resolved Chunk
127+
Text(String),
128+
/// Unresolved Chunk
129+
Bytes(Vec<u8>),
145130
}
146131

147-
impl<T> From<T> for ToTextResult
132+
impl<T> From<T> for LogMessageContent
148133
where
149134
T: Display,
150135
{
151136
fn from(value: T) -> Self {
152-
Self::new(value.to_string(), None)
137+
Self::Text(value.to_string())
153138
}
154139
}
155140

156-
pub trait LogMessage: Serialize {
157-
//TODO AAZ: Measure this an remove if rust already optimize the code without it.
158-
/// Indicates that parsing this struct to text can error.
159-
const CAN_ERROR: bool;
141+
impl TemplateLogMsg {
142+
pub fn new(chunks: Vec<TemplateLogMsgChunk>, resolve_hints: Vec<ResolveParseHint>) -> Self {
143+
Self {
144+
chunks,
145+
resolve_hints,
146+
}
147+
}
160148

161-
/// Serializes a message directly into a Writer
162-
/// returns the size of the serialized message
163-
fn to_writer<W: Write>(&self, writer: &mut W) -> Result<usize, std::io::Error>;
149+
pub fn get_resolve_hints(&self) -> Vec<ResolveParseHint> {
150+
self.resolve_hints.to_vec()
151+
}
164152

165-
/// Get the text representation of this message.
166-
fn to_text(&self) -> ToTextResult;
167-
}
153+
/// Applies the given [`FnMut`] on the unresolved chunks, replacing them with texts if succeed.
154+
/// This function will return a String once chunks get resolved.
155+
///
156+
/// * `parse_fn`: Function to apply on the unresolved chunks.
157+
pub fn try_resolve<F>(&mut self, mut parse_fn: F) -> Option<String>
158+
where
159+
F: FnMut(&[u8]) -> Option<String>,
160+
{
161+
let mut all_resolved = true;
162+
for ch in self.chunks.iter_mut() {
163+
match ch {
164+
TemplateLogMsgChunk::Text(_) => continue,
165+
TemplateLogMsgChunk::Bytes(bytes) => match parse_fn(&bytes) {
166+
Some(resolved) => *ch = TemplateLogMsgChunk::Text(resolved),
167+
None => all_resolved = false,
168+
},
169+
}
170+
}
168171

169-
#[derive(Debug)]
170-
pub enum MessageStreamItem<T: LogMessage> {
171-
Item(ParseYield<T>),
172-
Skipped,
173-
Incomplete,
174-
Empty,
175-
Done,
172+
if all_resolved {
173+
self.chunks
174+
.iter()
175+
.map(|ch| match ch {
176+
TemplateLogMsgChunk::Text(msg) => msg,
177+
TemplateLogMsgChunk::Bytes(_) => panic!("All must be resolved"),
178+
})
179+
.cloned()
180+
.reduce(|mut acc, msg| {
181+
acc.push_str(&msg);
182+
acc
183+
})
184+
} else {
185+
None
186+
}
187+
}
188+
189+
/// Concatenates the chunks to a string, replacing the unresolved chunks with their bytes
190+
/// representation.
191+
pub fn resolve_lossy(self) -> String {
192+
self.chunks
193+
.into_iter()
194+
.fold(String::new(), |mut acc, ch| match ch {
195+
TemplateLogMsgChunk::Text(msg) => {
196+
acc.push_str(&msg);
197+
acc
198+
}
199+
TemplateLogMsgChunk::Bytes(bytes) => format!("{acc} {bytes:?}"),
200+
})
201+
}
176202
}

application/apps/indexer/parsers/src/someip.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{Error, LogMessage, ParseYield, Parser, ToTextResult};
1+
use crate::{Error, LogMessage, LogMsgResolveResult, ParseYield, Parser};
22
use std::{borrow::Cow, fmt, fmt::Display, io::Write, path::PathBuf};
33

44
use someip_messages::*;
@@ -325,14 +325,12 @@ impl SomeipLogMessage {
325325
}
326326

327327
impl LogMessage for SomeipLogMessage {
328-
const CAN_ERROR: bool = false;
329-
330328
fn to_writer<W: Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
331329
writer.write_all(&self.bytes)?;
332330
Ok(self.bytes.len())
333331
}
334332

335-
fn to_text(&self) -> ToTextResult {
333+
fn try_resolve(&self) -> LogMsgResolveResult {
336334
self.into()
337335
}
338336
}

application/apps/indexer/parsers/src/text.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{Error, LogMessage, ParseYield, Parser, ToTextResult};
1+
use crate::{Error, LogMessage, LogMsgResolveResult, ParseYield, Parser};
22
use serde::Serialize;
33
use std::{fmt, io::Write};
44

@@ -16,15 +16,13 @@ impl fmt::Display for StringMessage {
1616
}
1717

1818
impl LogMessage for StringMessage {
19-
const CAN_ERROR: bool = false;
20-
2119
fn to_writer<W: Write>(&self, writer: &mut W) -> Result<usize, std::io::Error> {
2220
let len = self.content.len();
2321
writer.write_all(self.content.as_bytes())?;
2422
Ok(len)
2523
}
2624

27-
fn to_text(&self) -> ToTextResult {
25+
fn try_resolve(&self) -> LogMsgResolveResult {
2826
self.into()
2927
}
3028
}

0 commit comments

Comments
 (0)