add line mode and fix an error message

This commit is contained in:
Mark 2025-05-04 20:30:24 +02:00
parent ed81d27adb
commit be0e032b06

View File

@ -42,6 +42,7 @@ a number n, optionally followed by one of K, M, G, or T, representing n bytes,
As a client, logbufpipe has multiple modes:
- raw/bytes: output the newest bytes and live data. may output half of a char.
- utf8: same as raw, but skip bytes until a valid utf8 char is encountered.
- line: same as raw, but skip bytes until a newline (\n, 0x0A) is encountered.
The size limit does not have to match that of the server. The smaller of the
two limits decides how much old data can be shown. If the path is a normal file
instead of a unix socket, acts as if the server had sent the data in the file.
@ -54,6 +55,7 @@ instead of a unix socket, acts as if the server had sent the data in the file.
Server,
Raw,
Utf8,
Line,
}
impl Mode {
fn arg1(&self) -> usize {
@ -66,13 +68,6 @@ instead of a unix socket, acts as if the server had sent the data in the file.
fn arg2(&self) -> usize {
self.arg1() + 1
}
fn arg1s(&self) -> &'static str {
if matches!(self, Self::Server) {
"first"
} else {
"second"
}
}
fn arg2s(&self) -> &'static str {
if matches!(self, Self::Server) {
"second"
@ -89,6 +84,7 @@ instead of a unix socket, acts as if the server had sent the data in the file.
{
Some("raw" | "bytes") => mode = Mode::Raw,
Some("utf8" | "utf-8" | "utf_8") => mode = Mode::Utf8,
Some("line" | "lines" | "newline" | "linefeed") => mode = Mode::Line,
Some(_) => {}
None => {
eprintln!("[logbufpipe] run logbufpipe --help for help");
@ -136,10 +132,7 @@ instead of a unix socket, acts as if the server had sent the data in the file.
let bytes = if let Some(bytes) = bytes {
bytes
} else {
eprintln!(
"[logbufpipe] {} argument must be the buffer's size in bytes or as <num>[KMGT], prefixed with u or b for client mode",
mode.arg1s(),
);
eprintln!("[logbufpipe] expected arguments to be [raw/utf8/line] <num>[K/M/G/T] <path>, see --help");
return ExitCode::FAILURE;
};
@ -148,7 +141,7 @@ instead of a unix socket, acts as if the server had sent the data in the file.
if let Some(path) = args_os().nth(mode.arg2()) {
let path = PathBuf::from(path);
match mode {
Mode::Raw | Mode::Utf8 => {
Mode::Raw | Mode::Utf8 | Mode::Line => {
async fn buf_raw(buf: &[u8], stdout: &mut Stdout) {
stdout.write_all(buf).await.unwrap();
stdout.flush().await.unwrap();
@ -193,6 +186,21 @@ instead of a unix socket, acts as if the server had sent the data in the file.
stdout.flush().await.unwrap();
}
}
async fn buf_line(buf: &[u8], stdout: &mut Stdout, skipping: &mut bool) {
if *skipping {
if let Some(i) = buf.iter().position(|v| *v == b'\n') {
// found a newline
*skipping = false;
if i + 1 < buf.len() {
stdout.write_all(&buf[i + 1..]).await.unwrap();
stdout.flush().await.unwrap();
}
}
} else {
stdout.write_all(buf).await.unwrap();
stdout.flush().await.unwrap();
}
}
match UnixStream::connect(&path).await {
Ok(mut con) => {
con.write_all(format!("{bytes}\n").as_bytes())
@ -223,6 +231,18 @@ instead of a unix socket, acts as if the server had sent the data in the file.
con.consume(len);
}
}
Mode::Line => {
let mut skipping = true;
loop {
let buf = con.fill_buf().await.unwrap();
if buf.is_empty() {
break;
}
let len = buf.len();
buf_line(buf, &mut stdout, &mut skipping).await;
con.consume(len);
}
}
}
}
Err(e) => {
@ -240,6 +260,9 @@ instead of a unix socket, acts as if the server had sent the data in the file.
Mode::Utf8 => {
buf_utf8(buf, &mut stdout, &mut buf_utf8_waiting_buf()).await;
}
Mode::Line => {
buf_line(buf, &mut stdout, &mut true).await;
}
}
} else {
eprintln!(