From b0c32097aac459296bbdfc09c71c08826bb30d66 Mon Sep 17 00:00:00 2001 From: Pavel Ivanov Date: Sun, 5 May 2024 18:21:14 +0200 Subject: [PATCH] fix: fixed sorting when some lines are empty --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- src/app.rs | 28 +++++++++++++++++++++++++++- src/index.rs | 2 ++ src/input.rs | 21 +++++++++++++++++++-- 5 files changed, 51 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e913395f..1a8c0742 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -611,7 +611,7 @@ checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" [[package]] name = "encstr" -version = "0.29.2-alpha.3" +version = "0.29.2-alpha.4" [[package]] name = "enum-map" @@ -768,7 +768,7 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hl" -version = "0.29.2-alpha.3" +version = "0.29.2-alpha.4" dependencies = [ "atoi", "bincode", diff --git a/Cargo.toml b/Cargo.toml index 88f6638b..2c613031 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ members = [".", "crate/encstr"] [workspace.package] repository = "https://github.com/pamburus/hl" authors = ["Pavel Ivanov "] -version = "0.29.2-alpha.3" +version = "0.29.2-alpha.4" edition = "2021" license = "MIT" diff --git a/src/app.rs b/src/app.rs index 8a59914f..fdf8a735 100644 --- a/src/app.rs +++ b/src/app.rs @@ -107,6 +107,11 @@ impl Options { Self { raw, ..self } } + #[cfg(test)] + fn with_sort(self, sort: bool) -> Self { + Self { sort, ..self } + } + #[cfg(test)] fn with_input_info(self, input_info: Option) -> Self { Self { input_info, ..self } @@ -1178,8 +1183,29 @@ mod tests { assert_eq!(std::str::from_utf8(&output).unwrap(), format!("{}\n\n{}\n", L1, L2),); } + #[test] + fn test_sort_with_blank_lines() { + let input = input(concat!( + r#"{"level":"debug","ts":"2024-01-25T19:10:20.435369+01:00","msg":"m2"}"#, + "\n\r\n", + r#"{"level":"debug","ts":"2024-01-25T19:09:16.860711+01:00","msg":"m1"}"#, + "\n", + )); + + let mut output = Vec::new(); + let app = App::new(options().with_sort(true)); + app.run(vec![input], &mut output).unwrap(); + assert_eq!( + std::str::from_utf8(&output).unwrap(), + concat!( + "2024-01-25 18:09:16.860 |DBG| m1\n", + "2024-01-25 18:10:20.435 |DBG| m2\n", + ), + ); + } + fn input>(s: S) -> InputHolder { - InputHolder::new(InputReference::File("-".into()), Some(Box::new(Cursor::new(s.into())))) + InputHolder::new(InputReference::Stdin, Some(Box::new(Cursor::new(s.into())))) } fn options() -> Options { diff --git a/src/index.rs b/src/index.rs index 39bff9e7..b0176fb5 100644 --- a/src/index.rs +++ b/src/index.rs @@ -442,6 +442,8 @@ impl Indexer { } } } + } else { + stat.add_invalid(); } lines.push((ts.or(prev_ts), i as u32, offset)); offset += data_len as u32 + 1; diff --git a/src/input.rs b/src/input.rs index 10cb7706..10f229be 100644 --- a/src/input.rs +++ b/src/input.rs @@ -141,7 +141,7 @@ impl InputHolder { pub fn open(self) -> io::Result { match self.reference { - InputReference::Stdin => Ok(Input::new(self.reference, Box::new(stdin()))), + InputReference::Stdin => Ok(Input::new(self.reference.clone(), self.stdin())), InputReference::File(path) => match self.stream { Some(stream) => Input::open_stream(&path, stream), None => Input::open(&path), @@ -151,13 +151,19 @@ impl InputHolder { pub fn index(self, indexer: &Indexer) -> Result { match self.reference { - InputReference::Stdin => IndexedInput::open_sequential(self.reference.clone(), Box::new(stdin()), indexer), + InputReference::Stdin => IndexedInput::open_sequential(self.reference.clone(), self.stdin(), indexer), InputReference::File(path) => match self.stream { Some(stream) => IndexedInput::open_stream(&path, stream, indexer), None => IndexedInput::open(&path, indexer), }, } } + + fn stdin(self) -> InputStream { + self.stream + .map(|s| Box::new(ReadSeekToRead(s)) as InputStream) + .unwrap_or_else(|| Box::new(stdin())) + } } pub struct Input { @@ -515,6 +521,17 @@ pub trait ReadSeek: Read + Seek {} impl ReadSeek for T {} +pub struct ReadSeekToRead(T); + +impl Read for ReadSeekToRead +where + T: ReadSeek, +{ + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } +} + trait AsInputStream { fn as_input_stream(self) -> InputStream; }