docs: Add rustdoc for filter_plugin, binary_detection, and lib.rs
Co-authored-by: aider (openai/andrew/openrouter/sonoma-sky-alpha) <aider@aider.chat>
This commit is contained in:
@@ -17,6 +17,39 @@ use std::collections::HashMap;
|
||||
/// * `Result<(), StatusCode>` -
|
||||
/// * `Ok(())` if binary content is allowed or content is not binary
|
||||
/// * `Err(StatusCode::BAD_REQUEST)` if binary content is not allowed and content is binary
|
||||
/// Check if content is binary when allow_binary is false
|
||||
///
|
||||
/// Validates whether binary content is permitted for the item. If not allowed and content
|
||||
/// is detected as binary, returns a bad request status. Uses metadata or streams content
|
||||
/// for detection if needed.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `item_service` - Reference to the async item service for content access.
|
||||
/// * `item_id` - The ID of the item to check.
|
||||
/// * `metadata` - Metadata associated with the item (checked for "text" key).
|
||||
/// * `allow_binary` - Whether binary content is allowed (bypasses check if true).
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<(), StatusCode>` -
|
||||
/// * `Ok(())` if binary content is allowed or content is not binary.
|
||||
/// * `Err(StatusCode::BAD_REQUEST)` if binary content is not allowed and content is binary.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Propagates `StatusCode` for validation failures.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// // If allow_binary = false and content is text
|
||||
/// check_binary_content_allowed(&service, 1, &metadata, false)?;
|
||||
/// // Succeeds
|
||||
///
|
||||
/// // If allow_binary = false and content is binary
|
||||
/// // Returns Err(StatusCode::BAD_REQUEST)
|
||||
/// ```
|
||||
pub async fn check_binary_content_allowed(
|
||||
item_service: &AsyncItemService,
|
||||
item_id: i64,
|
||||
@@ -46,6 +79,34 @@ pub async fn check_binary_content_allowed(
|
||||
/// * `Ok(true)` if content is binary
|
||||
/// * `Ok(false)` if content is text
|
||||
/// * `Err(StatusCode)` if an error occurs during checking
|
||||
/// Helper function to determine if content is binary
|
||||
///
|
||||
/// Checks existing "text" metadata first; if absent or unset, streams and analyzes
|
||||
/// the content to detect binary nature. Logs warnings on detection failures.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `item_service` - Reference to the async item service for content access.
|
||||
/// * `item_id` - The ID of the item to check.
|
||||
/// * `metadata` - Metadata associated with the item (checked for "text" key).
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<bool, StatusCode>` -
|
||||
/// * `Ok(true)` if content is binary.
|
||||
/// * `Ok(false)` if content is text.
|
||||
/// * `Err(StatusCode)` if an error occurs during checking (e.g., INTERNAL_SERVER_ERROR).
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// * `StatusCode::INTERNAL_SERVER_ERROR` if content access fails.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let is_bin = is_content_binary(&service, 1, &metadata).await?;
|
||||
/// assert!(is_bin == false); // For text content
|
||||
/// ```
|
||||
pub async fn is_content_binary(
|
||||
item_service: &AsyncItemService,
|
||||
item_id: i64,
|
||||
|
||||
@@ -4,20 +4,43 @@ 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.
|
||||
/// Useful for previewing file contents without reading everything.
|
||||
///
|
||||
/// # Fields
|
||||
///
|
||||
/// * `remaining` - Number of bytes left to read before stopping.
|
||||
pub struct HeadBytesFilter {
|
||||
remaining: usize,
|
||||
}
|
||||
|
||||
/// A filter that reads the first N bytes from the input stream.
|
||||
///
|
||||
/// Limits the output to the initial bytes specified in the configuration.
|
||||
/// Useful for previewing file contents without reading everything.
|
||||
///
|
||||
/// # Fields
|
||||
///
|
||||
/// * `remaining` - Number of bytes left to read before stopping.
|
||||
impl HeadBytesFilter {
|
||||
/// Creates a new `HeadBytesFilter` that will read up to the specified number of bytes.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `count` - The maximum number of bytes to read from the input
|
||||
/// * `count` - The maximum number of bytes to read from the input.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Self` - A new instance of `HeadBytesFilter`
|
||||
/// A new instance configured to read at most `count` bytes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let filter = HeadBytesFilter::new(1024);
|
||||
/// assert_eq!(filter.remaining, 1024);
|
||||
/// ```
|
||||
pub fn new(count: usize) -> Self {
|
||||
Self {
|
||||
remaining: count,
|
||||
@@ -25,19 +48,31 @@ impl HeadBytesFilter {
|
||||
}
|
||||
}
|
||||
|
||||
/// Filters input by reading only the first N bytes and writing them to the output.
|
||||
///
|
||||
/// Reads from the input in chunks until the byte limit is reached or EOF, then writes
|
||||
/// the collected bytes to the output. Stops early if the limit is zero.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `reader` - Boxed mutable reference to the input data stream.
|
||||
/// * `writer` - Boxed mutable reference to the output stream.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<()>` - Success if filtering completes, or I/O error.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// * `io::Error` from reading or writing operations.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// // Assuming a filter chain with head_bytes(5)
|
||||
/// // Input "Hello World" becomes "Hello"
|
||||
/// ```
|
||||
impl FilterPlugin for HeadBytesFilter {
|
||||
/// Filters the input by reading only the first N bytes and writing them to the output.
|
||||
///
|
||||
/// # 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
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<()>` -
|
||||
/// * `Ok(())` on success
|
||||
/// * `Err(io::Error)` if reading or writing fails
|
||||
fn filter(&mut self, mut reader: Box<&mut dyn Read>, mut writer: Box<&mut dyn Write>) -> Result<()> {
|
||||
if self.remaining == 0 {
|
||||
return Ok(());
|
||||
@@ -58,9 +93,11 @@ impl FilterPlugin for HeadBytesFilter {
|
||||
|
||||
/// Clones this filter into a new boxed instance.
|
||||
///
|
||||
/// Creates an independent copy with the same configuration.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Box<dyn FilterPlugin>` - A new boxed clone of this filter
|
||||
/// A new `Box<dyn FilterPlugin>` clone.
|
||||
fn clone_box(&self) -> Box<dyn FilterPlugin> {
|
||||
Box::new(Self {
|
||||
remaining: self.remaining,
|
||||
@@ -69,9 +106,11 @@ impl FilterPlugin for HeadBytesFilter {
|
||||
|
||||
/// Returns the configuration options for this filter.
|
||||
///
|
||||
/// Defines the "count" parameter as required with no default.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Vec<FilterOption>` - A vector describing the filter's configurable parameters
|
||||
/// Vector of `FilterOption` describing parameters.
|
||||
fn options(&self) -> Vec<FilterOption> {
|
||||
vec![
|
||||
FilterOption {
|
||||
@@ -84,20 +123,43 @@ 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,
|
||||
}
|
||||
|
||||
/// 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.
|
||||
impl HeadLinesFilter {
|
||||
/// Creates a new `HeadLinesFilter` that will read up to the specified number of lines.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `count` - The maximum number of lines to read from the input
|
||||
/// * `count` - The maximum number of lines to read from the input.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Self` - A new instance of `HeadLinesFilter`
|
||||
/// A new instance configured to read at most `count` lines.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let filter = HeadLinesFilter::new(3);
|
||||
/// assert_eq!(filter.remaining, 3);
|
||||
/// ```
|
||||
pub fn new(count: usize) -> Self {
|
||||
Self {
|
||||
remaining: count,
|
||||
@@ -105,19 +167,30 @@ impl HeadLinesFilter {
|
||||
}
|
||||
}
|
||||
|
||||
/// Filters input by reading only the first N lines and writing them to the output.
|
||||
///
|
||||
/// Uses buffered line reading to process input line-by-line until the limit or EOF.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `reader` - Boxed mutable reference to the input data stream.
|
||||
/// * `writer` - Boxed mutable reference to the output stream.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<()>` - Success if filtering completes, or I/O error.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// * `io::Error` from line reading or writing operations.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// // Assuming a filter chain with head_lines(2)
|
||||
/// // Input "Line1\nLine2\nLine3" becomes "Line1\nLine2\n"
|
||||
/// ```
|
||||
impl FilterPlugin for HeadLinesFilter {
|
||||
/// Filters the input by reading only the first N lines and writing them to the output.
|
||||
///
|
||||
/// # 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
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<()>` -
|
||||
/// * `Ok(())` on success
|
||||
/// * `Err(io::Error)` if reading or writing fails
|
||||
fn filter(&mut self, mut reader: Box<&mut dyn Read>, mut writer: Box<&mut dyn Write>) -> Result<()> {
|
||||
if self.remaining == 0 {
|
||||
return Ok(());
|
||||
@@ -137,9 +210,11 @@ impl FilterPlugin for HeadLinesFilter {
|
||||
|
||||
/// Clones this filter into a new boxed instance.
|
||||
///
|
||||
/// Creates an independent copy with the same configuration.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Box<dyn FilterPlugin>` - A new boxed clone of this filter
|
||||
/// A new `Box<dyn FilterPlugin>` clone.
|
||||
fn clone_box(&self) -> Box<dyn FilterPlugin> {
|
||||
Box::new(Self {
|
||||
remaining: self.remaining,
|
||||
@@ -148,9 +223,11 @@ impl FilterPlugin for HeadLinesFilter {
|
||||
|
||||
/// Returns the configuration options for this filter.
|
||||
///
|
||||
/// Defines the "count" parameter as required with no default.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Vec<FilterOption>` - A vector describing the filter's configurable parameters
|
||||
/// Vector of `FilterOption` describing parameters.
|
||||
fn options(&self) -> Vec<FilterOption> {
|
||||
vec![
|
||||
FilterOption {
|
||||
|
||||
37
src/lib.rs
37
src/lib.rs
@@ -2,6 +2,32 @@
|
||||
#![deny(unsafe_code)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
//! Keep library for managing temporary files with compression and metadata.
|
||||
//!
|
||||
//! This library provides core functionality for the Keep application, including
|
||||
//! database operations, compression engines, item services, and plugin systems
|
||||
//! for metadata and filtering. It supports CLI modes, server APIs, and plugin
|
||||
//! registration via ctors.
|
||||
//!
|
||||
//! # Usage
|
||||
//!
|
||||
//! Add to Cargo.toml and use re-exported types:
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! keep = "0.1"
|
||||
//! ```
|
||||
//!
|
||||
//! ```rust
|
||||
//! use keep::Args;
|
||||
//! let args = Args::parse();
|
||||
//! ```
|
||||
//!
|
||||
//! # Features
|
||||
//!
|
||||
//! - `server`: Enables Axum-based HTTP server.
|
||||
//! - `gzip`, `lz4`: Built-in compression support.
|
||||
//! - `magic`: File type detection via libmagic.
|
||||
|
||||
// Re-export modules for testing
|
||||
pub mod common;
|
||||
pub mod compression_engine;
|
||||
@@ -39,7 +65,16 @@ use meta_plugin::{
|
||||
#[allow(unused_imports)]
|
||||
use meta_plugin::magic_file;
|
||||
|
||||
// Initialize plugins at library load time
|
||||
/// Initializes plugins at library load time.
|
||||
///
|
||||
/// Ensures all filter and meta plugins are registered via their ctors.
|
||||
/// Call this early in application startup if needed (though ctors handle most cases).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// keep::init_plugins();
|
||||
/// ```
|
||||
pub fn init_plugins() {
|
||||
// This will be expanded in Step 3 implementation
|
||||
// For now, the ctors handle registration
|
||||
|
||||
Reference in New Issue
Block a user