refactor: simplify filter plugin signatures by removing boxed parameters
This commit is contained in:
committed by
Andrew Phillips (aider)
parent
9c354d5ef4
commit
059bde09e4
@@ -53,8 +53,8 @@ impl GrepFilter {
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `reader` - A boxed mutable reference to the input reader providing the data stream.
|
||||
/// * `writer` - A boxed mutable reference to the output writer where matching lines are sent.
|
||||
/// * `reader` - Mutable reference to the input data stream.
|
||||
/// * `writer` - Mutable reference to the output writer where matching lines are sent.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
@@ -67,33 +67,33 @@ impl GrepFilter {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// filter.filter(Box::new(&mut input), Box::new(&mut output))?;
|
||||
/// filter.filter(&mut input, &mut output)?;
|
||||
/// ```
|
||||
impl FilterPlugin for GrepFilter {
|
||||
fn filter(&mut self, mut reader: Box<&mut dyn Read>, mut writer: Box<&mut dyn Write>) -> Result<()> {
|
||||
let mut buf_reader = std::io::BufReader::new(&mut *reader);
|
||||
fn filter(&mut self, reader: &mut dyn Read, writer: &mut dyn Write) -> Result<()> {
|
||||
let mut buf_reader = std::io::BufReader::new(reader);
|
||||
for line in buf_reader.by_ref().lines() {
|
||||
let line = line?;
|
||||
if self.regex.is_match(&line) {
|
||||
writeln!(&mut *writer, "{}", line)?;
|
||||
writeln!(writer, "{}", line)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Clones this filter into a new boxed instance.
|
||||
///
|
||||
/// Creates a new GrepFilter with the same regex pattern.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A new `Box<dyn FilterPlugin>` representing a clone of this filter.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let cloned = filter.clone_box();
|
||||
/// ```
|
||||
///
|
||||
/// Creates a new GrepFilter with the same regex pattern.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A new `Box<dyn FilterPlugin>` representing a clone of this filter.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let cloned = filter.clone_box();
|
||||
/// ```
|
||||
fn clone_box(&self) -> Box<dyn FilterPlugin> {
|
||||
Box::new(Self {
|
||||
regex: self.regex.clone(),
|
||||
@@ -101,20 +101,20 @@ impl FilterPlugin for GrepFilter {
|
||||
}
|
||||
|
||||
/// Returns the configuration options for this filter.
|
||||
///
|
||||
/// The only option is the required "pattern" for the regex.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A vector containing one `FilterOption` for "pattern" (required, no default).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let opts = filter.options();
|
||||
/// assert_eq!(opts.len(), 1);
|
||||
/// assert!(opts[0].required);
|
||||
/// ```
|
||||
///
|
||||
/// The only option is the required "pattern" for the regex.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A vector containing one `FilterOption` for "pattern" (required, no default).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let opts = filter.options();
|
||||
/// assert_eq!(opts.len(), 1);
|
||||
/// assert!(opts[0].required);
|
||||
/// ```
|
||||
fn options(&self) -> Vec<FilterOption> {
|
||||
vec![
|
||||
FilterOption {
|
||||
@@ -124,4 +124,4 @@ impl FilterPlugin for GrepFilter {
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ use std::io::{Result, Read, Write, BufRead};
|
||||
use crate::common::PIPESIZE;
|
||||
use crate::services::filter_service::register_filter_plugin;
|
||||
|
||||
/// A filter that reads the first N bytes from the input stream.
|
||||
/// A filter that reads the first N bytes from the input stream.
|
||||
///
|
||||
/// Limits the output to the initial bytes specified in the configuration.
|
||||
@@ -55,8 +54,8 @@ impl HeadBytesFilter {
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `reader` - Boxed mutable reference to the input data stream.
|
||||
/// * `writer` - Boxed mutable reference to the output stream.
|
||||
/// * `reader` - Mutable reference to the input data stream.
|
||||
/// * `writer` - Mutable reference to the output stream.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
@@ -73,7 +72,7 @@ impl HeadBytesFilter {
|
||||
/// // Input "Hello World" becomes "Hello"
|
||||
/// ```
|
||||
impl FilterPlugin for HeadBytesFilter {
|
||||
fn filter(&mut self, mut reader: Box<&mut dyn Read>, mut writer: Box<&mut dyn Write>) -> Result<()> {
|
||||
fn filter(&mut self, reader: &mut dyn Read, writer: &mut dyn Write) -> Result<()> {
|
||||
if self.remaining == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
@@ -81,11 +80,11 @@ impl FilterPlugin for HeadBytesFilter {
|
||||
let mut buffer = vec![0; PIPESIZE];
|
||||
while self.remaining > 0 {
|
||||
let to_read = std::cmp::min(self.remaining, PIPESIZE);
|
||||
let bytes_read = (&mut *reader).read(&mut buffer[..to_read])?;
|
||||
let bytes_read = reader.read(&mut buffer[..to_read])?;
|
||||
if bytes_read == 0 {
|
||||
break;
|
||||
}
|
||||
(&mut *writer).write_all(&buffer[..bytes_read])?;
|
||||
writer.write_all(&buffer[..bytes_read])?;
|
||||
self.remaining -= bytes_read;
|
||||
}
|
||||
Ok(())
|
||||
@@ -123,14 +122,6 @@ impl FilterPlugin for HeadBytesFilter {
|
||||
}
|
||||
|
||||
/// A filter that reads the first N lines from the input stream.
|
||||
/// A filter that reads the first N lines from the input stream.
|
||||
///
|
||||
/// Limits output to the initial lines specified, writing each full line to output.
|
||||
/// Handles line endings properly using buffered reading.
|
||||
///
|
||||
/// # Fields
|
||||
///
|
||||
/// * `remaining` - Number of lines left to read before stopping.
|
||||
pub struct HeadLinesFilter {
|
||||
remaining: usize,
|
||||
}
|
||||
@@ -173,8 +164,8 @@ impl HeadLinesFilter {
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `reader` - Boxed mutable reference to the input data stream.
|
||||
/// * `writer` - Boxed mutable reference to the output stream.
|
||||
/// * `reader` - Mutable reference to the input data stream.
|
||||
/// * `writer` - Mutable reference to the output stream.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
@@ -191,15 +182,15 @@ impl HeadLinesFilter {
|
||||
/// // Input "Line1\nLine2\nLine3" becomes "Line1\nLine2\n"
|
||||
/// ```
|
||||
impl FilterPlugin for HeadLinesFilter {
|
||||
fn filter(&mut self, mut reader: Box<&mut dyn Read>, mut writer: Box<&mut dyn Write>) -> Result<()> {
|
||||
fn filter(&mut self, reader: &mut dyn Read, writer: &mut dyn Write) -> Result<()> {
|
||||
if self.remaining == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut buf_reader = std::io::BufReader::new(&mut *reader);
|
||||
let mut buf_reader = std::io::BufReader::new(reader);
|
||||
for line in buf_reader.by_ref().lines() {
|
||||
let line = line?;
|
||||
writeln!(&mut *writer, "{}", line)?;
|
||||
writeln!(writer, "{}", line)?;
|
||||
self.remaining -= 1;
|
||||
if self.remaining == 0 {
|
||||
break;
|
||||
|
||||
@@ -19,36 +19,6 @@ impl SkipBytesFilter {
|
||||
remaining: count,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new instance from options.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `options` - An optional JSON value containing configuration options for the filter.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A `Result` containing a boxed `FilterPlugin` on success, or an `io::Error` if options are invalid.
|
||||
pub fn create(options: Option<serde_json::Value>) -> Result<Box<dyn FilterPlugin>> {
|
||||
let options = options.ok_or_else(|| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
"skip_bytes filter requires options"
|
||||
)
|
||||
})?;
|
||||
|
||||
let count = options.get("n")
|
||||
.and_then(|v| v.as_u64())
|
||||
.map(|n| n as usize)
|
||||
.ok_or_else(|| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
"skip_bytes filter requires 'n' parameter"
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(Box::new(Self::new(count)))
|
||||
}
|
||||
}
|
||||
|
||||
impl FilterPlugin for SkipBytesFilter {
|
||||
@@ -56,19 +26,19 @@ impl FilterPlugin for SkipBytesFilter {
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `reader` - A boxed mutable reference to the input reader providing the data stream.
|
||||
/// * `writer` - A boxed mutable reference to the output writer where filtered data is sent.
|
||||
/// * `reader` - Mutable reference to the input reader providing the data stream.
|
||||
/// * `writer` - Mutable reference to the output writer where filtered data is sent.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `Ok(())` on success, or an `io::Error` if reading or writing fails.
|
||||
fn filter(&mut self, mut reader: Box<&mut dyn Read>, mut writer: Box<&mut dyn Write>) -> Result<()> {
|
||||
fn filter(&mut self, reader: &mut dyn Read, writer: &mut dyn Write) -> Result<()> {
|
||||
// Skip bytes in chunks
|
||||
if self.remaining > 0 {
|
||||
let mut buffer = vec![0; PIPESIZE];
|
||||
while self.remaining > 0 {
|
||||
let to_read = std::cmp::min(self.remaining, PIPESIZE);
|
||||
let bytes_read = (&mut *reader).read(&mut buffer[..to_read])?;
|
||||
let bytes_read = reader.read(&mut buffer[..to_read])?;
|
||||
if bytes_read == 0 {
|
||||
break;
|
||||
}
|
||||
@@ -77,7 +47,7 @@ impl FilterPlugin for SkipBytesFilter {
|
||||
}
|
||||
|
||||
// Copy the remaining data using io::copy for efficiency
|
||||
std::io::copy(&mut *reader, &mut *writer)?;
|
||||
std::io::copy(reader, writer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -124,36 +94,6 @@ impl SkipLinesFilter {
|
||||
remaining: count,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new instance from options.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `options` - An optional JSON value containing configuration options for the filter.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A `Result` containing a boxed `FilterPlugin` on success, or an `io::Error` if options are invalid.
|
||||
pub fn create(options: Option<serde_json::Value>) -> Result<Box<dyn FilterPlugin>> {
|
||||
let options = options.ok_or_else(|| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
"skip_lines filter requires options"
|
||||
)
|
||||
})?;
|
||||
|
||||
let count = options.get("n")
|
||||
.and_then(|v| v.as_u64())
|
||||
.map(|n| n as usize)
|
||||
.ok_or_else(|| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
"skip_lines filter requires 'n' parameter"
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(Box::new(Self::new(count)))
|
||||
}
|
||||
}
|
||||
|
||||
impl FilterPlugin for SkipLinesFilter {
|
||||
@@ -161,20 +101,20 @@ impl FilterPlugin for SkipLinesFilter {
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `reader` - A boxed mutable reference to the input reader providing the data stream.
|
||||
/// * `writer` - A boxed mutable reference to the output writer where filtered data is sent.
|
||||
/// * `reader` - Mutable reference to the input reader providing the data stream.
|
||||
/// * `writer` - Mutable reference to the output writer where filtered data is sent.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `Ok(())` on success, or an `io::Error` if reading or writing fails.
|
||||
fn filter(&mut self, mut reader: Box<&mut dyn Read>, mut writer: Box<&mut dyn Write>) -> Result<()> {
|
||||
let mut buf_reader = std::io::BufReader::new(&mut *reader);
|
||||
fn filter(&mut self, reader: &mut dyn Read, writer: &mut dyn Write) -> Result<()> {
|
||||
let mut buf_reader = std::io::BufReader::new(reader);
|
||||
for line in buf_reader.by_ref().lines() {
|
||||
let line = line?;
|
||||
if self.remaining > 0 {
|
||||
self.remaining -= 1;
|
||||
} else {
|
||||
writeln!(&mut *writer, "{}", line)?;
|
||||
writeln!(writer, "{}", line)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -212,4 +152,4 @@ impl FilterPlugin for SkipLinesFilter {
|
||||
fn register_skip_filters() {
|
||||
register_filter_plugin("skip_bytes", || Box::new(SkipBytesFilter::new(0)));
|
||||
register_filter_plugin("skip_lines", || Box::new(SkipLinesFilter::new(0)));
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,11 @@ use strip_ansi_escapes::Writer;
|
||||
use super::{FilterPlugin, FilterOption};
|
||||
|
||||
/// A filter that removes ANSI escape sequences from the input.
|
||||
///
|
||||
/// # Fields
|
||||
///
|
||||
/// None, stateless filter.
|
||||
#[derive(Default)]
|
||||
pub struct StripAnsiFilter;
|
||||
|
||||
impl StripAnsiFilter {
|
||||
@@ -21,16 +26,17 @@ impl FilterPlugin for StripAnsiFilter {
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `reader` - A boxed mutable reference to the input reader providing the data stream with potential ANSI codes.
|
||||
/// * `writer` - A boxed mutable reference to the output writer where plain text is sent.
|
||||
/// * `reader` - Mutable reference to the input reader providing the data stream with potential ANSI codes.
|
||||
/// * `writer` - Mutable reference to the output writer where plain text is sent.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `Ok(())` on success, or an `io::Error` if reading or writing fails.
|
||||
fn filter(&mut self, mut reader: Box<&mut dyn Read>, mut writer: Box<&mut dyn Write>) -> Result<()> {
|
||||
let mut ansi_writer = Writer::new(&mut *writer);
|
||||
std::io::copy(&mut *reader, &mut ansi_writer)?;
|
||||
ansi_writer.flush()
|
||||
fn filter(&mut self, reader: &mut dyn Read, writer: &mut dyn Write) -> Result<()> {
|
||||
let mut ansi_writer = Writer::new(writer);
|
||||
std::io::copy(reader, &mut ansi_writer)?;
|
||||
ansi_writer.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Clones this filter into a new boxed instance.
|
||||
|
||||
@@ -22,36 +22,6 @@ impl TailBytesFilter {
|
||||
count,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new instance from options.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `options` - An optional JSON value containing configuration options for the filter.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A `Result` containing a boxed `FilterPlugin` on success, or an `io::Error` if options are invalid.
|
||||
pub fn create(options: Option<serde_json::Value>) -> Result<Box<dyn FilterPlugin>> {
|
||||
let options = options.ok_or_else(|| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
"tail_bytes filter requires options"
|
||||
)
|
||||
})?;
|
||||
|
||||
let count = options.get("n")
|
||||
.and_then(|v| v.as_u64())
|
||||
.map(|n| n as usize)
|
||||
.ok_or_else(|| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
"tail_bytes filter requires 'n' parameter"
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(Box::new(Self::new(count)))
|
||||
}
|
||||
}
|
||||
|
||||
impl FilterPlugin for TailBytesFilter {
|
||||
@@ -59,16 +29,16 @@ impl FilterPlugin for TailBytesFilter {
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `reader` - A boxed mutable reference to the input reader providing the data stream.
|
||||
/// * `writer` - A boxed mutable reference to the output writer where filtered data is sent.
|
||||
/// * `reader` - Mutable reference to the input reader providing the data stream.
|
||||
/// * `writer` - Mutable reference to the output writer where filtered data is sent.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `Ok(())` on success, or an `io::Error` if reading or writing fails.
|
||||
fn filter(&mut self, mut reader: Box<&mut dyn Read>, mut writer: Box<&mut dyn Write>) -> Result<()> {
|
||||
fn filter(&mut self, reader: &mut dyn Read, writer: &mut dyn Write) -> Result<()> {
|
||||
let mut temp_buffer = vec![0; PIPESIZE];
|
||||
loop {
|
||||
let bytes_read = (&mut *reader).read(&mut temp_buffer)?;
|
||||
let bytes_read = reader.read(&mut temp_buffer)?;
|
||||
if bytes_read == 0 {
|
||||
break;
|
||||
}
|
||||
@@ -84,7 +54,7 @@ impl FilterPlugin for TailBytesFilter {
|
||||
|
||||
// Write the buffered data at the end
|
||||
let result: Vec<u8> = self.buffer.iter().cloned().collect();
|
||||
(&mut *writer).write_all(&result)?;
|
||||
writer.write_all(&result)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -134,36 +104,6 @@ impl TailLinesFilter {
|
||||
count,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new instance from options.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `options` - An optional JSON value containing configuration options for the filter.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A `Result` containing a boxed `FilterPlugin` on success, or an `io::Error` if options are invalid.
|
||||
pub fn create(options: Option<serde_json::Value>) -> Result<Box<dyn FilterPlugin>> {
|
||||
let options = options.ok_or_else(|| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
"tail_lines filter requires options"
|
||||
)
|
||||
})?;
|
||||
|
||||
let count = options.get("n")
|
||||
.and_then(|v| v.as_u64())
|
||||
.map(|n| n as usize)
|
||||
.ok_or_else(|| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
"tail_lines filter requires 'n' parameter"
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(Box::new(Self::new(count)))
|
||||
}
|
||||
}
|
||||
|
||||
impl FilterPlugin for TailLinesFilter {
|
||||
@@ -171,14 +111,14 @@ impl FilterPlugin for TailLinesFilter {
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `reader` - A boxed mutable reference to the input reader providing the data stream.
|
||||
/// * `writer` - A boxed mutable reference to the output writer where filtered data is sent.
|
||||
/// * `reader` - Mutable reference to the input reader providing the data stream.
|
||||
/// * `writer` - Mutable reference to the output writer where filtered data is sent.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `Ok(())` on success, or an `io::Error` if reading or writing fails.
|
||||
fn filter(&mut self, mut reader: Box<&mut dyn Read>, mut writer: Box<&mut dyn Write>) -> Result<()> {
|
||||
let mut buf_reader = std::io::BufReader::new(&mut *reader);
|
||||
fn filter(&mut self, reader: &mut dyn Read, writer: &mut dyn Write) -> Result<()> {
|
||||
let mut buf_reader = std::io::BufReader::new(reader);
|
||||
for line in buf_reader.by_ref().lines() {
|
||||
let line = line?;
|
||||
if self.lines.len() == self.count {
|
||||
@@ -189,7 +129,7 @@ impl FilterPlugin for TailLinesFilter {
|
||||
|
||||
// Write the buffered lines
|
||||
for line in &self.lines {
|
||||
writeln!(&mut *writer, "{}", line)?;
|
||||
writeln!(writer, "{}", line)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user