docs: Add Rustdoc examples to server common types and compression engine

Co-authored-by: aider (openai/andrew/openrouter/sonoma-sky-alpha) <aider@aider.chat>
This commit is contained in:
Andrew Phillips
2025-09-10 14:05:24 -03:00
parent 46a245a59a
commit 6cff3bd165
2 changed files with 144 additions and 103 deletions

View File

@@ -1,8 +1,18 @@
```rust
/// GZip compression engine module. /// GZip compression engine module.
/// ///
/// This module provides the implementation for GZip compression and decompression /// This module provides the implementation for GZip compression and decompression
/// using the `flate2` crate. It includes the main `CompressionEngineGZip` struct /// using the `flate2` crate. It includes the main `CompressionEngineGZip` struct
/// and supporting types for handling GZip streams. /// and supporting types for handling GZip streams.
///
/// # Usage
///
/// ```rust
/// use keep::compression_engine::get_compression_engine;
/// let engine = get_compression_engine(keep::compression_engine::CompressionType::GZip)
/// .expect("GZip engine creation failed");
/// let reader = engine.open("/path/to/file.gz".into()).expect("Open failed");
/// ```
use anyhow::Result; use anyhow::Result;
use log::*; use log::*;
use std::fs::File; use std::fs::File;
@@ -16,11 +26,20 @@ use flate2::write::GzEncoder;
use crate::compression_engine::CompressionEngine; use crate::compression_engine::CompressionEngine;
```rust
/// GZip compression engine implementation. /// GZip compression engine implementation.
/// ///
/// This struct provides the functionality to compress and decompress data using /// This struct provides the functionality to compress and decompress data using
/// the GZip algorithm. It implements the `CompressionEngine` trait for integration /// the GZip algorithm. It implements the `CompressionEngine` trait for integration
/// with the compression service. /// with the compression service.
///
/// # Examples
///
/// ```rust
/// let engine = keep::compression_engine::get_compression_engine(keep::compression_engine::CompressionType::GZip)
/// .expect("Failed to get GZip engine");
/// assert!(engine.is_supported());
/// ```
#[derive(Debug, Eq, PartialEq, Clone, Default)] #[derive(Debug, Eq, PartialEq, Clone, Default)]
pub struct CompressionEngineGZip {} pub struct CompressionEngineGZip {}
@@ -30,6 +49,12 @@ impl CompressionEngineGZip {
/// # Returns /// # Returns
/// ///
/// A new `CompressionEngineGZip` instance. /// A new `CompressionEngineGZip` instance.
///
/// # Examples
///
/// ```
/// let engine = CompressionEngineGZip::new();
/// ```
pub fn new() -> CompressionEngineGZip { pub fn new() -> CompressionEngineGZip {
CompressionEngineGZip {} CompressionEngineGZip {}
} }
@@ -44,6 +69,13 @@ impl CompressionEngine for CompressionEngineGZip {
/// # Returns /// # Returns
/// ///
/// Always returns `true` since GZip is built-in. /// Always returns `true` since GZip is built-in.
///
/// # Examples
///
/// ```
/// let engine = CompressionEngineGZip::new();
/// assert!(engine.is_supported());
/// ```
fn is_supported(&self) -> bool { fn is_supported(&self) -> bool {
true true
} }
@@ -60,6 +92,16 @@ impl CompressionEngine for CompressionEngineGZip {
/// # Returns /// # Returns
/// ///
/// * `Result<Box<dyn Read>>` - A boxed reader that decompresses the GZip file on read. /// * `Result<Box<dyn Read>>` - A boxed reader that decompresses the GZip file on read.
///
/// # Errors
///
/// * `anyhow::Error` - If the file cannot be opened or decoded.
///
/// # Examples
///
/// ```
/// let reader = engine.open("/path/to/file.gz".into()).expect("Open failed");
/// ```
fn open(&self, file_path: PathBuf) -> Result<Box<dyn Read>> { fn open(&self, file_path: PathBuf) -> Result<Box<dyn Read>> {
debug!("COMPRESSION: Opening {:?} using {:?}", file_path, *self); debug!("COMPRESSION: Opening {:?} using {:?}", file_path, *self);
@@ -80,6 +122,16 @@ impl CompressionEngine for CompressionEngineGZip {
/// # Returns /// # Returns
/// ///
/// * `Result<Box<dyn Write>>` - A boxed writer that compresses data using GZip on write. /// * `Result<Box<dyn Write>>` - A boxed writer that compresses data using GZip on write.
///
/// # Errors
///
/// * `anyhow::Error` - If the file cannot be created or encoder fails.
///
/// # Examples
///
/// ```
/// let writer = engine.create("/path/to/file.gz".into()).expect("Create failed");
/// ```
fn create(&self, file_path: PathBuf) -> Result<Box<dyn Write>> { fn create(&self, file_path: PathBuf) -> Result<Box<dyn Write>> {
debug!("COMPRESSION: Writting to {:?} using {:?}", file_path, *self); debug!("COMPRESSION: Writting to {:?} using {:?}", file_path, *self);
@@ -90,10 +142,20 @@ impl CompressionEngine for CompressionEngineGZip {
} }
} }
```rust
/// Auto-finishing GZip encoder that automatically calls finish on drop. /// Auto-finishing GZip encoder that automatically calls finish on drop.
/// ///
/// This wrapper ensures that the GZip stream is properly closed even if the /// This wrapper ensures that the GZip stream is properly closed even if the
/// writer is dropped unexpectedly, preventing incomplete compression files. /// writer is dropped unexpectedly, preventing incomplete compression files.
///
/// # Examples
///
/// ```rust
/// let file = File::create("test.gz").unwrap();
/// let encoder = GzEncoder::new(file, Compression::default());
/// let auto_encoder = AutoFinishGzEncoder::new(encoder);
/// // Encoder will finish on drop
/// ```
pub struct AutoFinishGzEncoder<W: Write> { pub struct AutoFinishGzEncoder<W: Write> {
encoder: Option<GzEncoder<W>>, encoder: Option<GzEncoder<W>>,
} }
@@ -108,6 +170,14 @@ impl<W: Write> AutoFinishGzEncoder<W> {
/// # Returns /// # Returns
/// ///
/// A new `AutoFinishGzEncoder` instance. /// A new `AutoFinishGzEncoder` instance.
///
/// # Examples
///
/// ```
/// let file = File::create("test.gz").unwrap();
/// let encoder = GzEncoder::new(file, Compression::default());
/// let auto_encoder = AutoFinishGzEncoder::new(encoder);
/// ```
fn new(gz_encoder: GzEncoder<W>) -> AutoFinishGzEncoder<W> { fn new(gz_encoder: GzEncoder<W>) -> AutoFinishGzEncoder<W> {
AutoFinishGzEncoder { AutoFinishGzEncoder {
encoder: Some(gz_encoder), encoder: Some(gz_encoder),
@@ -120,6 +190,10 @@ impl<W: Write> Drop for AutoFinishGzEncoder<W> {
/// ///
/// This method ensures the GZip stream is properly closed by calling `finish()` /// This method ensures the GZip stream is properly closed by calling `finish()`
/// on the underlying encoder. /// on the underlying encoder.
///
/// # Errors
///
/// Errors during finish are logged but ignored.
fn drop(&mut self) { fn drop(&mut self) {
if let Some(encoder) = self.encoder.take() { if let Some(encoder) = self.encoder.take() {
debug!("COMPRESSION: Finishing"); debug!("COMPRESSION: Finishing");
@@ -138,6 +212,10 @@ impl<W: Write> Write for AutoFinishGzEncoder<W> {
/// # Returns /// # Returns
/// ///
/// * `io::Result<usize>` - The number of bytes written or an I/O error. /// * `io::Result<usize>` - The number of bytes written or an I/O error.
///
/// # Errors
///
/// Propagates errors from the underlying encoder.
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.encoder.as_mut().unwrap().write(buf) self.encoder.as_mut().unwrap().write(buf)
} }
@@ -147,6 +225,10 @@ impl<W: Write> Write for AutoFinishGzEncoder<W> {
/// # Returns /// # Returns
/// ///
/// * `io::Result<()>` - Success or an I/O error. /// * `io::Result<()>` - Success or an I/O error.
///
/// # Errors
///
/// Propagates errors from the underlying encoder.
fn flush(&mut self) -> io::Result<()> { fn flush(&mut self) -> io::Result<()> {
self.encoder.as_mut().unwrap().flush() self.encoder.as_mut().unwrap().flush()
} }

View File

@@ -3,6 +3,14 @@
/// This module provides shared structures, functions, and middleware used across /// This module provides shared structures, functions, and middleware used across
/// different parts of the server implementation, including configuration, state /// different parts of the server implementation, including configuration, state
/// management, API responses, authentication, and logging. /// management, API responses, authentication, and logging.
///
/// # Usage
///
/// ```rust
/// use keep::modes::server::common::{ServerConfig, AppState};
/// let config = ServerConfig { address: "127.0.0.1".to_string(), ..Default::default() };
/// let state = AppState { /* ... */ };
/// ```
use anyhow::Result; use anyhow::Result;
use axum::{ use axum::{
extract::{Request, ConnectInfo}, extract::{Request, ConnectInfo},
@@ -26,6 +34,17 @@ use crate::services::item_service::ItemService;
/// ///
/// This struct holds the configuration parameters for the HTTP server, including /// This struct holds the configuration parameters for the HTTP server, including
/// binding address, port, and authentication settings. /// binding address, port, and authentication settings.
///
/// # Examples
///
/// ```
/// let config = ServerConfig {
/// address: "127.0.0.1".to_string(),
/// port: Some(8080),
/// password: None,
/// password_hash: None,
/// };
/// ```
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ServerConfig { pub struct ServerConfig {
/// Server bind address. /// Server bind address.
@@ -50,11 +69,6 @@ pub struct ServerConfig {
pub password_hash: Option<String>, pub password_hash: Option<String>,
} }
/// Application state shared across all routes.
///
/// This struct encapsulates the shared state that is accessible to all request handlers,
/// including database connections, file paths, services, and configuration.
#[derive(Clone)]
/// Application state shared across all routes. /// Application state shared across all routes.
/// ///
/// This struct encapsulates the shared state that is accessible to all request handlers, /// This struct encapsulates the shared state that is accessible to all request handlers,
@@ -62,7 +76,10 @@ pub struct ServerConfig {
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```rust
/// use keep::modes::server::common::AppState;
/// use std::sync::Arc;
/// use tokio::sync::Mutex;
/// let state = AppState { /// let state = AppState {
/// db: Arc::new(Mutex::new(conn)), /// db: Arc::new(Mutex::new(conn)),
/// data_dir: PathBuf::from("/data"), /// data_dir: PathBuf::from("/data"),
@@ -71,6 +88,7 @@ pub struct ServerConfig {
/// settings: Arc::new(settings), /// settings: Arc::new(settings),
/// }; /// };
/// ``` /// ```
#[derive(Clone)]
pub struct AppState { pub struct AppState {
/// Database connection wrapped in Arc<Mutex>. /// Database connection wrapped in Arc<Mutex>.
/// ///
@@ -95,11 +113,6 @@ pub struct AppState {
pub settings: Arc<crate::config::Settings>, pub settings: Arc<crate::config::Settings>,
} }
/// Standard API response wrapper containing success status, data payload, and error information.
///
/// This generic type is used for all API responses to provide a consistent structure across
/// different endpoints.
#[derive(Debug, Serialize, Deserialize, ToSchema)]
/// Standard API response wrapper containing success status, data payload, and error information. /// Standard API response wrapper containing success status, data payload, and error information.
/// ///
/// This generic type is used for all API responses to provide a consistent structure across /// This generic type is used for all API responses to provide a consistent structure across
@@ -111,13 +124,15 @@ pub struct AppState {
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```rust
/// use keep::modes::server::common::ApiResponse;
/// let response: ApiResponse<Vec<ItemInfo>> = ApiResponse { /// let response: ApiResponse<Vec<ItemInfo>> = ApiResponse {
/// success: true, /// success: true,
/// data: Some(items), /// data: Some(items),
/// error: None, /// error: None,
/// }; /// };
/// ``` /// ```
#[derive(Debug, Serialize, Deserialize, ToSchema)]
#[schema(description = "Standard API response wrapper containing success status, data payload, and error information")] #[schema(description = "Standard API response wrapper containing success status, data payload, and error information")]
pub struct ApiResponse<T> { pub struct ApiResponse<T> {
/// Success indicator. /// Success indicator.
@@ -134,23 +149,21 @@ pub struct ApiResponse<T> {
pub error: Option<String>, pub error: Option<String>,
} }
/// Response type for list of item information.
///
/// Specialized response for endpoints that return multiple items.
#[derive(Serialize, Deserialize, ToSchema)]
/// Response type for list of item information. /// Response type for list of item information.
/// ///
/// Specialized response for endpoints that return multiple items. /// Specialized response for endpoints that return multiple items.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```rust
/// use keep::modes::server::common::ItemInfoListResponse;
/// let response = ItemInfoListResponse { /// let response = ItemInfoListResponse {
/// success: true, /// success: true,
/// data: Some(vec![item_info]), /// data: Some(vec![item_info]),
/// error: None, /// error: None,
/// }; /// };
/// ``` /// ```
#[derive(Serialize, Deserialize, ToSchema)]
pub struct ItemInfoListResponse { pub struct ItemInfoListResponse {
/// Success indicator. /// Success indicator.
/// ///
@@ -166,23 +179,21 @@ pub struct ItemInfoListResponse {
pub error: Option<String>, pub error: Option<String>,
} }
/// Response type for single item information.
///
/// Specialized response for endpoints that return a single item's details.
#[derive(Serialize, Deserialize, ToSchema)]
/// Response type for single item information. /// Response type for single item information.
/// ///
/// Specialized response for endpoints that return a single item's details. /// Specialized response for endpoints that return a single item's details.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```rust
/// use keep::modes::server::common::ItemInfoResponse;
/// let response = ItemInfoResponse { /// let response = ItemInfoResponse {
/// success: true, /// success: true,
/// data: Some(item_info), /// data: Some(item_info),
/// error: None, /// error: None,
/// }; /// };
/// ``` /// ```
#[derive(Serialize, Deserialize, ToSchema)]
pub struct ItemInfoResponse { pub struct ItemInfoResponse {
/// Success indicator. /// Success indicator.
/// ///
@@ -198,23 +209,21 @@ pub struct ItemInfoResponse {
pub error: Option<String>, pub error: Option<String>,
} }
/// Response type for item content information.
///
/// Specialized response for endpoints that return item content and related metadata.
#[derive(Serialize, Deserialize, ToSchema)]
/// Response type for item content information. /// Response type for item content information.
/// ///
/// Specialized response for endpoints that return item content and related metadata. /// Specialized response for endpoints that return item content and related metadata.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```rust
/// use keep::modes::server::common::ItemContentInfoResponse;
/// let response = ItemContentInfoResponse { /// let response = ItemContentInfoResponse {
/// success: true, /// success: true,
/// data: Some(content_info), /// data: Some(content_info),
/// error: None, /// error: None,
/// }; /// };
/// ``` /// ```
#[derive(Serialize, Deserialize, ToSchema)]
pub struct ItemContentInfoResponse { pub struct ItemContentInfoResponse {
/// Success indicator. /// Success indicator.
/// ///
@@ -230,23 +239,21 @@ pub struct ItemContentInfoResponse {
pub error: Option<String>, pub error: Option<String>,
} }
/// Response type for metadata.
///
/// Specialized response for metadata-only endpoints.
#[derive(Serialize, Deserialize, ToSchema)]
/// Response type for metadata. /// Response type for metadata.
/// ///
/// Specialized response for metadata-only endpoints. /// Specialized response for metadata-only endpoints.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```rust
/// use keep::modes::server::common::MetadataResponse;
/// let response = MetadataResponse { /// let response = MetadataResponse {
/// success: true, /// success: true,
/// data: Some(meta_map), /// data: Some(meta_map),
/// error: None, /// error: None,
/// }; /// };
/// ``` /// ```
#[derive(Serialize, Deserialize, ToSchema)]
pub struct MetadataResponse { pub struct MetadataResponse {
/// Success indicator. /// Success indicator.
/// ///
@@ -262,23 +269,21 @@ pub struct MetadataResponse {
pub error: Option<String>, pub error: Option<String>,
} }
/// Response type for status information.
///
/// Specialized response for system status endpoints.
#[derive(Serialize, Deserialize, ToSchema)]
/// Response type for status information. /// Response type for status information.
/// ///
/// Specialized response for system status endpoints. /// Specialized response for system status endpoints.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```rust
/// use keep::modes::server::common::StatusInfoResponse;
/// let response = StatusInfoResponse { /// let response = StatusInfoResponse {
/// success: true, /// success: true,
/// data: Some(status_info), /// data: Some(status_info),
/// error: None, /// error: None,
/// }; /// };
/// ``` /// ```
#[derive(Serialize, Deserialize, ToSchema)]
pub struct StatusInfoResponse { pub struct StatusInfoResponse {
/// Success indicator. /// Success indicator.
/// ///
@@ -294,11 +299,6 @@ pub struct StatusInfoResponse {
pub error: Option<String>, pub error: Option<String>,
} }
/// Complete information about a stored item including metadata and tags.
///
/// This structure represents the full details of an item, combining basic item
/// properties with associated tags and metadata.
#[derive(Serialize, Deserialize, ToSchema)]
/// Complete information about a stored item including metadata and tags. /// Complete information about a stored item including metadata and tags.
/// ///
/// This structure represents the full details of an item, combining basic item /// This structure represents the full details of an item, combining basic item
@@ -306,7 +306,9 @@ pub struct StatusInfoResponse {
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```rust
/// use keep::modes::server::common::ItemInfo;
/// use std::collections::HashMap;
/// let item_info = ItemInfo { /// let item_info = ItemInfo {
/// id: 42, /// id: 42,
/// ts: "2023-12-01T15:30:45Z".to_string(), /// ts: "2023-12-01T15:30:45Z".to_string(),
@@ -316,6 +318,7 @@ pub struct StatusInfoResponse {
/// metadata: HashMap::from([("mime_type".to_string(), "text/plain".to_string())]), /// metadata: HashMap::from([("mime_type".to_string(), "text/plain".to_string())]),
/// }; /// };
/// ``` /// ```
#[derive(Serialize, Deserialize, ToSchema)]
#[schema(description = "Complete information about a stored item including metadata and tags")] #[schema(description = "Complete information about a stored item including metadata and tags")]
pub struct ItemInfo { pub struct ItemInfo {
/// Item ID. /// Item ID.
@@ -350,17 +353,6 @@ pub struct ItemInfo {
pub metadata: HashMap<String, String>, pub metadata: HashMap<String, String>,
} }
/// Item information including content and metadata, with binary detection.
///
/// This structure provides item details along with its content, handling binary
/// content detection and safe string representation.
///
/// # Fields
///
/// * `metadata` - Flattened metadata HashMap.
/// * `content` - Optional string content (text only).
/// * `binary` - True if binary content.
#[derive(Serialize, Deserialize, ToSchema)]
/// Item information including content and metadata, with binary detection. /// Item information including content and metadata, with binary detection.
/// ///
/// This structure provides item details along with its content, handling binary /// This structure provides item details along with its content, handling binary
@@ -368,13 +360,16 @@ pub struct ItemInfo {
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```rust
/// use keep::modes::server::common::ItemContentInfo;
/// use std::collections::HashMap;
/// let content_info = ItemContentInfo { /// let content_info = ItemContentInfo {
/// metadata: HashMap::from([("mime_type".to_string(), "text/plain".to_string())]), /// metadata: HashMap::from([("mime_type".to_string(), "text/plain".to_string())]),
/// content: Some("Hello, world!".to_string()), /// content: Some("Hello, world!".to_string()),
/// binary: false, /// binary: false,
/// }; /// };
/// ``` /// ```
#[derive(Serialize, Deserialize, ToSchema)]
#[schema(description = "Item information including content and metadata, with binary detection")] #[schema(description = "Item information including content and metadata, with binary detection")]
pub struct ItemContentInfo { pub struct ItemContentInfo {
/// Metadata hashmap. /// Metadata hashmap.
@@ -395,23 +390,17 @@ pub struct ItemContentInfo {
pub binary: bool, pub binary: bool,
} }
/// Query parameters for tags.
///
/// Structure for handling tag-based query parameters in API requests.
///
/// # Fields
///
/// * `tags` - Optional comma-separated tags for filtering.
#[derive(Debug, Deserialize)]
/// Query parameters for tags. /// Query parameters for tags.
/// ///
/// Structure for handling tag-based query parameters in API requests. /// Structure for handling tag-based query parameters in API requests.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```rust
/// use keep::modes::server::common::TagsQuery;
/// let query = TagsQuery { tags: Some("tag1,tag2".to_string()) }; /// let query = TagsQuery { tags: Some("tag1,tag2".to_string()) };
/// ``` /// ```
#[derive(Debug, Deserialize)]
pub struct TagsQuery { pub struct TagsQuery {
/// Optional comma-separated tags. /// Optional comma-separated tags.
/// ///
@@ -419,24 +408,14 @@ pub struct TagsQuery {
pub tags: Option<String>, pub tags: Option<String>,
} }
/// Query parameters for listing items.
///
/// Structure for pagination and sorting parameters in item listing endpoints.
///
/// # Fields
///
/// * `tags` - Optional tags for filtering.
/// * `order` - Optional sort: "newest" or "oldest".
/// * `start` - Optional start index.
/// * `count` - Optional item limit.
#[derive(Debug, Deserialize)]
/// Query parameters for listing items. /// Query parameters for listing items.
/// ///
/// Structure for pagination and sorting parameters in item listing endpoints. /// Structure for pagination and sorting parameters in item listing endpoints.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```rust
/// use keep::modes::server::common::ListItemsQuery;
/// let query = ListItemsQuery { /// let query = ListItemsQuery {
/// tags: Some("important".to_string()), /// tags: Some("important".to_string()),
/// order: Some("newest".to_string()), /// order: Some("newest".to_string()),
@@ -444,6 +423,7 @@ pub struct TagsQuery {
/// count: Some(10), /// count: Some(10),
/// }; /// };
/// ``` /// ```
#[derive(Debug, Deserialize)]
pub struct ListItemsQuery { pub struct ListItemsQuery {
/// Optional comma-separated tags for filtering. /// Optional comma-separated tags for filtering.
/// ///
@@ -463,25 +443,14 @@ pub struct ListItemsQuery {
pub count: Option<u32>, pub count: Option<u32>,
} }
/// Query parameters for item retrieval.
///
/// Structure for content retrieval parameters, including binary handling and streaming options.
///
/// # Fields
///
/// * `allow_binary` - Allow binary (default true).
/// * `offset` - Byte offset (default 0).
/// * `length` - Byte length (default 0 = all).
/// * `stream` - Enable streaming (default false).
/// * `as_meta` - Return as JSON metadata (default false).
#[derive(Debug, Deserialize, utoipa::ToSchema)]
/// Query parameters for item retrieval. /// Query parameters for item retrieval.
/// ///
/// Structure for content retrieval parameters, including binary handling and streaming options. /// Structure for content retrieval parameters, including binary handling and streaming options.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```rust
/// use keep::modes::server::common::ItemQuery;
/// let query = ItemQuery { /// let query = ItemQuery {
/// allow_binary: true, /// allow_binary: true,
/// offset: 0, /// offset: 0,
@@ -490,6 +459,7 @@ pub struct ListItemsQuery {
/// as_meta: false, /// as_meta: false,
/// }; /// };
/// ``` /// ```
#[derive(Debug, Deserialize, utoipa::ToSchema)]
pub struct ItemQuery { pub struct ItemQuery {
/// Allow binary content (default: true). /// Allow binary content (default: true).
/// ///
@@ -518,26 +488,14 @@ pub struct ItemQuery {
pub as_meta: bool, pub as_meta: bool,
} }
/// Query parameters for item content retrieval.
///
/// Extended query parameters for content-specific operations, including tag filtering.
///
/// # Fields
///
/// * `tags` - Optional tags for filtering.
/// * `allow_binary` - Allow binary (default true).
/// * `offset` - Byte offset (default 0).
/// * `length` - Byte length (default 0 = all).
/// * `stream` - Enable streaming (default false).
/// * `as_meta` - Return as JSON metadata (default false).
#[derive(Debug, Deserialize, utoipa::ToSchema)]
/// Query parameters for item content retrieval. /// Query parameters for item content retrieval.
/// ///
/// Extended query parameters for content-specific operations, including tag filtering. /// Extended query parameters for content-specific operations, including tag filtering.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```rust
/// use keep::modes::server::common::ItemContentQuery;
/// let query = ItemContentQuery { /// let query = ItemContentQuery {
/// tags: Some("important".to_string()), /// tags: Some("important".to_string()),
/// allow_binary: true, /// allow_binary: true,
@@ -547,6 +505,7 @@ pub struct ItemQuery {
/// as_meta: false, /// as_meta: false,
/// }; /// };
/// ``` /// ```
#[derive(Debug, Deserialize, utoipa::ToSchema)]
pub struct ItemContentQuery { pub struct ItemContentQuery {
/// Optional comma-separated tags for filtering. /// Optional comma-separated tags for filtering.
/// ///