docs: Add rustdoc for server, diff, and gzip components

Co-authored-by: aider (openai/andrew/openrouter/sonoma-sky-alpha) <aider@aider.chat>
This commit is contained in:
Andrew Phillips
2025-09-10 12:04:46 -03:00
parent a72352eb15
commit ddafeb3a28
3 changed files with 236 additions and 351 deletions

View File

@@ -17,138 +17,229 @@ use tokio::sync::Mutex;
use utoipa::ToSchema;
use crate::services::item_service::ItemService;
/// Server configuration structure
#[derive(Debug, Clone)]
pub struct ServerConfig {
/// Server bind address
pub address: String,
/// Optional server port
pub port: Option<u16>,
/// Optional authentication password
pub password: Option<String>,
/// Optional hashed authentication password
pub password_hash: Option<String>,
}
/// Application state shared across all routes
#[derive(Clone)]
pub struct AppState {
/// Database connection wrapped in Arc<Mutex>
pub db: Arc<Mutex<rusqlite::Connection>>,
/// Data directory path
pub data_dir: PathBuf,
/// Item service instance
pub item_service: Arc<ItemService>,
/// Command line argument parser
pub cmd: Arc<Mutex<clap::Command>>,
/// Application settings
pub settings: Arc<crate::config::Settings>,
}
/// Standard API response wrapper containing success status, data payload, and error information
#[derive(Debug, Serialize, Deserialize, ToSchema)]
#[schema(description = "Standard API response wrapper containing success status, data payload, and error information")]
pub struct ApiResponse<T> {
/// Success indicator
pub success: bool,
/// Optional data payload
pub data: Option<T>,
/// Optional error message
pub error: Option<String>,
}
// Specific response types for OpenAPI documentation
/// Response type for list of item information
#[derive(Serialize, Deserialize, ToSchema)]
pub struct ItemInfoListResponse {
/// Success indicator
pub success: bool,
/// Optional list of item information
pub data: Option<Vec<ItemInfo>>,
/// Optional error message
pub error: Option<String>,
}
/// Response type for single item information
#[derive(Serialize, Deserialize, ToSchema)]
pub struct ItemInfoResponse {
/// Success indicator
pub success: bool,
/// Optional item information
pub data: Option<ItemInfo>,
/// Optional error message
pub error: Option<String>,
}
/// Response type for item content information
#[derive(Serialize, Deserialize, ToSchema)]
pub struct ItemContentInfoResponse {
/// Success indicator
pub success: bool,
/// Optional item content information
pub data: Option<ItemContentInfo>,
/// Optional error message
pub error: Option<String>,
}
/// Response type for metadata
#[derive(Serialize, Deserialize, ToSchema)]
pub struct MetadataResponse {
/// Success indicator
pub success: bool,
/// Optional metadata hashmap
pub data: Option<HashMap<String, String>>,
/// Optional error message
pub error: Option<String>,
}
/// Response type for status information
#[derive(Serialize, Deserialize, ToSchema)]
pub struct StatusInfoResponse {
/// Success indicator
pub success: bool,
/// Optional status information
pub data: Option<crate::common::status::StatusInfo>,
/// Optional error message
pub error: Option<String>,
}
/// Complete information about a stored item including metadata and tags
#[derive(Serialize, Deserialize, ToSchema)]
#[schema(description = "Complete information about a stored item including metadata and tags")]
pub struct ItemInfo {
/// Item ID
#[schema(example = 42)]
pub id: i64,
/// Timestamp
#[schema(example = "2023-12-01T15:30:45Z")]
pub ts: String,
/// Size in bytes
#[schema(example = 1024)]
pub size: Option<i64>,
/// Compression type
#[schema(example = "gzip")]
pub compression: String,
/// List of tags
#[schema(example = json!(["important", "work", "document"]))]
pub tags: Vec<String>,
/// Metadata hashmap
#[schema(example = json!({"mime_type": "text/plain", "mime_encoding": "utf-8", "line_count": "42"}))]
pub metadata: HashMap<String, String>,
}
/// Item information including content and metadata, with binary detection
#[derive(Serialize, Deserialize, ToSchema)]
#[schema(description = "Item information including content and metadata, with binary detection")]
pub struct ItemContentInfo {
/// Metadata hashmap
#[serde(flatten)]
#[schema(example = json!({"mime_type": "text/plain", "mime_encoding": "utf-8", "line_count": "42"}))]
pub metadata: HashMap<String, String>,
/// Optional content as string
#[schema(example = "Hello, world!\nThis is the content of the file.")]
pub content: Option<String>,
/// Binary content indicator
#[schema(example = false)]
pub binary: bool,
}
/// Query parameters for tags
#[derive(Debug, Deserialize)]
pub struct TagsQuery {
/// Optional comma-separated tags
pub tags: Option<String>,
}
/// Query parameters for listing items
#[derive(Debug, Deserialize)]
pub struct ListItemsQuery {
/// Optional comma-separated tags for filtering
pub tags: Option<String>,
/// Optional sort order
pub order: Option<String>,
/// Optional pagination start index
pub start: Option<u32>,
/// Optional number of items to return
pub count: Option<u32>,
}
/// Query parameters for item retrieval
#[derive(Debug, Deserialize, utoipa::ToSchema)]
pub struct ItemQuery {
/// Allow binary content (default: true)
#[serde(default = "default_allow_binary")]
pub allow_binary: bool,
/// Byte offset (default: 0)
#[serde(default)]
pub offset: u64,
/// Byte length (default: 0, meaning all)
#[serde(default)]
pub length: u64,
/// Stream response (default: false)
#[serde(default = "default_stream")]
pub stream: bool,
/// Return as metadata JSON (default: false)
#[serde(default = "default_as_meta")]
pub as_meta: bool,
}
/// Query parameters for item content retrieval
#[derive(Debug, Deserialize, utoipa::ToSchema)]
pub struct ItemContentQuery {
/// Optional comma-separated tags for filtering
pub tags: Option<String>,
/// Allow binary content (default: true)
#[serde(default = "default_allow_binary")]
pub allow_binary: bool,
/// Byte offset (default: 0)
#[serde(default)]
pub offset: u64,
/// Byte length (default: 0, meaning all)
#[serde(default)]
pub length: u64,
/// Stream response (default: false)
#[serde(default = "default_stream")]
pub stream: bool,
/// Return as metadata JSON (default: false)
#[serde(default = "default_as_meta")]
pub as_meta: bool,
}
/// Default function for allow_binary parameter
fn default_allow_binary() -> bool {
true
}
/// Default function for stream parameter
fn default_stream() -> bool {
false
}
/// Default function for as_meta parameter
fn default_as_meta() -> bool {
false
}
/// Validates bearer authentication token
///
/// # Arguments
///
/// * `auth_str` - The authorization string from the header
/// * `expected_password` - The expected plain text password
/// * `expected_hash` - Optional expected password hash
///
/// # Returns
///
/// * `bool` - True if authentication succeeds, false otherwise
fn check_bearer_auth(auth_str: &str, expected_password: &str, expected_hash: &Option<String>) -> bool {
if !auth_str.starts_with("Bearer ") {
return false;
@@ -165,18 +256,17 @@ fn check_bearer_auth(auth_str: &str, expected_password: &str, expected_hash: &Op
provided_password == expected_password
}
fn default_allow_binary() -> bool {
true
}
fn default_stream() -> bool {
false
}
fn default_as_meta() -> bool {
false
}
/// Validates basic authentication credentials
///
/// # Arguments
///
/// * `auth_str` - The authorization string from the header
/// * `expected_password` - The expected plain text password
/// * `expected_hash` - Optional expected password hash
///
/// # Returns
///
/// * `bool` - True if authentication succeeds, false otherwise
fn check_basic_auth(auth_str: &str, expected_password: &str, expected_hash: &Option<String>) -> bool {
if !auth_str.starts_with("Basic ") {
return false;
@@ -202,6 +292,17 @@ fn check_basic_auth(auth_str: &str, expected_password: &str, expected_hash: &Opt
false
}
/// Checks authorization header for valid credentials
///
/// # Arguments
///
/// * `headers` - HTTP headers from the request
/// * `password` - Optional expected password
/// * `password_hash` - Optional expected password hash
///
/// # Returns
///
/// * `bool` - True if authorization is valid, false otherwise
pub fn check_auth(headers: &HeaderMap, password: &Option<String>, password_hash: &Option<String>) -> bool {
// If neither password nor hash is set, no authentication required
if password.is_none() && password_hash.is_none() {
@@ -217,6 +318,17 @@ pub fn check_auth(headers: &HeaderMap, password: &Option<String>, password_hash:
false
}
/// Middleware for logging requests and responses
///
/// # Arguments
///
/// * `ConnectInfo(addr)` - Connection information including client address
/// * `request` - The incoming HTTP request
/// * `next` - The next middleware in the chain
///
/// # Returns
///
/// The response with logging applied
pub async fn logging_middleware(
ConnectInfo(addr): ConnectInfo<SocketAddr>,
request: Request,
@@ -249,10 +361,20 @@ pub async fn logging_middleware(
response
}
/// Creates authentication middleware for the application
///
/// # Arguments
///
/// * `password` - Optional plain text password for authentication
/// * `password_hash` - Optional hashed password for authentication
///
/// # Returns
///
/// An authentication middleware function that can be used with axum
pub fn create_auth_middleware(
password: Option<String>,
password_hash: Option<String>,
) -> impl Fn(ConnectInfo<SocketAddr>, Request, Next) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Response, StatusCode>> + Send>> + Clone {
) -> impl Fn(ConnectInfo<SocketAddr>, Request, Next) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Response, StatusCode>> + Send>> + Clone + Send {
move |ConnectInfo(addr): ConnectInfo<SocketAddr>, request: Request, next: Next| {
let password = password.clone();
let password_hash = password_hash.clone();