Schema changes: - Rename items.size to items.uncompressed_size for clarity - Add compressed_size (INTEGER NULL) - tracks compressed file size on disk - Add closed (BOOLEAN NOT NULL DEFAULT 1) - tracks whether item is fully written - Existing items default to closed=true via migration Lifecycle: - Items created with closed=false, set to true on successful save/import - Compressed size captured via fs::metadata() after compression writer closes - Truncated uploads (413) get compressed_size set, closed=true, uncompressed_size=None - Update command now backfills both uncompressed_size and compressed_size Also includes bug fixes and dedup from prior review: - Fix stream_raw_content_response using uncompressed_size for raw byte Content-Length - ApiResponse::ok()/empty() constructors, TryFrom<ItemWithMeta> for ItemInfo - tag_names() method on ItemWithMeta, meta_filter() on Settings - Fix .unwrap() panics in compression engine Read/Write impls - Fix TOCTOU race in stream_raw_content_response (now uses compressed_size) - Fix swallowed write errors in meta plugins (digest, magic_file, exec) - Fix term::stderr().unwrap() panic in item_service - Deduplicate ItemService::new() calls across 20 API handlers - ImportMeta supports #[serde(alias = "size")] for backward compat All 75 tests, 67 doc tests pass. Clippy clean.
65 lines
2.1 KiB
Rust
65 lines
2.1 KiB
Rust
use crate::db::{Item, Meta, Tag};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::collections::HashMap;
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
/// Structure representing an item with its associated tags and metadata.
|
|
///
|
|
/// This is a composite type used for querying and displaying items with their relational data.
|
|
/// It combines the core Item with lists of Tags and Meta for complete item representation.
|
|
pub struct ItemWithMeta {
|
|
/// The core item data.
|
|
pub item: Item,
|
|
/// Associated tags.
|
|
pub tags: Vec<Tag>,
|
|
/// Associated metadata.
|
|
pub meta: Vec<Meta>,
|
|
}
|
|
|
|
impl ItemWithMeta {
|
|
/// Converts metadata to a HashMap for easy lookup.
|
|
///
|
|
/// This method transforms the vec of Meta into a simple key-value map,
|
|
/// useful for quick access by metadata name.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// `HashMap<String, String>` - Metadata as key-value pairs, where keys are names and values are strings.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// let item_with_meta = ItemWithMeta { /* ... */ };
|
|
/// let meta_map = item_with_meta.meta_as_map();
|
|
/// assert_eq!(meta_map.get("hostname"), Some(&"example.com".to_string()));
|
|
/// ```
|
|
pub fn meta_as_map(&self) -> HashMap<String, String> {
|
|
self.meta
|
|
.iter()
|
|
.cloned()
|
|
.map(|m| (m.name, m.value))
|
|
.collect()
|
|
}
|
|
|
|
/// Returns a list of tag names for this item.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// `Vec<String>` - Tag names extracted from the tags list.
|
|
pub fn tag_names(&self) -> Vec<String> {
|
|
self.tags.iter().map(|t| t.name.clone()).collect()
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
/// Structure representing an item with its content, tags, and metadata.
|
|
///
|
|
/// This extends ItemWithMeta by including the actual content bytes, suitable for full item retrieval
|
|
/// including binary or text data. Note: For large content, consider streaming alternatives.
|
|
pub struct ItemWithContent {
|
|
/// Item with associated metadata and tags.
|
|
pub item_with_meta: ItemWithMeta,
|
|
/// The content bytes.
|
|
pub content: Vec<u8>,
|
|
}
|