diff --git a/src/uu/dmesg/src/dmesg.rs b/src/uu/dmesg/src/dmesg.rs index 75bfe8f..fc60d94 100644 --- a/src/uu/dmesg/src/dmesg.rs +++ b/src/uu/dmesg/src/dmesg.rs @@ -5,7 +5,10 @@ use clap::{crate_version, Arg, ArgAction, Command}; use regex::Regex; -use std::fs; +use std::{ + fs::{self, File}, + io::{BufRead, BufReader}, +}; use uucore::{ error::{FromIo, UResult, USimpleError}, format_usage, help_about, help_usage, @@ -194,6 +197,56 @@ enum TimeFormat { Raw, } +struct RecordIterator { + file_reader: BufReader, +} + +impl Iterator for RecordIterator { + type Item = UResult; + + fn next(&mut self) -> Option { + match self.read_record_line() { + Err(e) => Some(Err(e)), + Ok(None) => None, + Ok(Some(line)) => match self.parse_record(&line) { + None => self.next(), + Some(record) => Some(Ok(record)), + }, + } + } +} + +impl RecordIterator { + fn read_record_line(&mut self) -> UResult> { + let mut buf = vec![]; + let num_bytes = self.file_reader.read_until(0, &mut buf)?; + match num_bytes { + 0 => Ok(None), + _ => Ok(Some(String::from_utf8_lossy(&buf).to_string())), + } + } + + fn parse_record(&self, record_line: &str) -> Option { + Self::record_regex() + .captures_iter(record_line) + .map(|c| c.extract()) + .filter_map(|(_, [pri_fac, seq, time, msg])| { + Record::from_str_fields(pri_fac, seq, time, msg.to_string()).ok() + }) + .next() + } + + fn record_regex() -> Regex { + let valid_number_pattern = "0|[1-9][0-9]*"; + let additional_fields_pattern = ",^[,;]*"; + let record_pattern = format!( + "(?m)^({0}),({0}),({0}),.(?:{1})*;(.*)$", + valid_number_pattern, additional_fields_pattern + ); + Regex::new(&record_pattern).expect("invalid regex.") + } +} + struct Record { priority_facility: u32, _sequence: u64,