better truncation handling

This commit is contained in:
Robin Appelman 2023-03-16 23:23:09 +01:00
commit 9a11408237
2 changed files with 14 additions and 10 deletions

View file

@ -29,6 +29,8 @@ pub enum Error {
Malformed, Malformed,
#[error("Incomplete logfile")] #[error("Incomplete logfile")]
Incomplete, Incomplete,
#[error("Incomplete logfile")]
Truncated, // like incomplete, but when we're certain the log is at fault, and not the parser
#[error("Malformed subject: {0}")] #[error("Malformed subject: {0}")]
Subject(#[from] SubjectError), Subject(#[from] SubjectError),
#[error("{0}")] #[error("{0}")]
@ -71,28 +73,27 @@ pub fn parse_with_handler<Handler: EventHandler>(
), ),
Error, Error,
> { > {
let events = raw_events(log); let mut events = raw_events(log);
let mut handler = Handler::default(); let mut handler = Handler::default();
let mut start_time: Option<NaiveDateTime> = None; let mut start_time: Option<NaiveDateTime> = None;
let mut subjects = SubjectMap::<Handler::PerSubjectData>::with_capacity(32); let mut subjects = SubjectMap::<Handler::PerSubjectData>::with_capacity(32);
let mut game_over = false; while let Some(event_res) = events.next() {
let raw_event = match event_res {
for event_res in events { Ok(raw_event) => raw_event,
let raw_event = event_res?; Err(Error::Truncated) => break,
if raw_event.ty == RawEventType::GameOver { Err(e) => return Err(e),
game_over = true; };
}
let should_handle = Handler::does_handle(raw_event.ty); let should_handle = Handler::does_handle(raw_event.ty);
if should_handle || start_time.is_none() { if should_handle || start_time.is_none() {
if should_handle { if should_handle {
let event = match GameEvent::parse(&raw_event) { let event = match GameEvent::parse(&raw_event) {
Ok(event) => event, Ok(event) => event,
Err(e) => { Err(e) => {
// handle truncated logs after game over // handle truncated logs
if game_over { if events.next().is_none() {
break; break;
} else { } else {
return Err(e.into()); return Err(e.into());

View file

@ -24,6 +24,9 @@ impl<'a> RawEvent<'a> {
} }
fn event_parser(input: &str) -> Result<RawEvent> { fn event_parser(input: &str) -> Result<RawEvent> {
if input.len() < 30 {
return Err(Error::Truncated);
}
let date = RawDate(&input[0..21]); let date = RawDate(&input[0..21]);
let (input, subject) = subject_parser(&input[23..])?; let (input, subject) = subject_parser(&input[23..])?;