reovim_driver_codec/metadata.rs
1//! Codec metadata for round-trip encoding.
2//!
3//! Stores information about how a file was decoded, so it can be
4//! re-encoded faithfully on save. Metadata is stored per-buffer
5//! in [`CodecSessionState`](crate::CodecSessionState).
6
7use std::collections::HashMap;
8
9use crate::ContentType;
10
11/// Metadata from a codec decode operation.
12///
13/// Captures everything needed for round-trip encoding: the content type,
14/// and a flexible key-value store for codec-specific data (e.g., BOM
15/// presence, original line ending style, encoding name).
16///
17/// # Examples
18///
19/// ```
20/// use reovim_driver_codec::{CodecMetadata, ContentType};
21///
22/// let mut metadata = CodecMetadata::new(ContentType::new("text/utf-8"));
23/// metadata.set("bom", "true");
24/// metadata.set("line_ending", "crlf");
25///
26/// assert_eq!(metadata.get("bom"), Some("true"));
27/// assert_eq!(metadata.content_type().as_str(), "text/utf-8");
28/// ```
29#[derive(Debug, Clone)]
30pub struct CodecMetadata {
31 /// The content type that produced this metadata.
32 content_type: ContentType,
33 /// Codec-specific key-value data.
34 data: HashMap<String, String>,
35}
36
37impl CodecMetadata {
38 /// Create new metadata for the given content type.
39 #[must_use]
40 pub fn new(content_type: ContentType) -> Self {
41 Self {
42 content_type,
43 data: HashMap::new(),
44 }
45 }
46
47 /// Get the content type.
48 #[must_use]
49 pub const fn content_type(&self) -> &ContentType {
50 &self.content_type
51 }
52
53 /// Get a metadata value by key.
54 #[must_use]
55 pub fn get(&self, key: &str) -> Option<&str> {
56 self.data.get(key).map(String::as_str)
57 }
58
59 /// Set a metadata value.
60 pub fn set(&mut self, key: impl Into<String>, value: impl Into<String>) {
61 self.data.insert(key.into(), value.into());
62 }
63
64 /// Remove a metadata value, returning it if present.
65 pub fn remove(&mut self, key: &str) -> Option<String> {
66 self.data.remove(key)
67 }
68
69 /// Check if a metadata key exists.
70 #[must_use]
71 pub fn contains_key(&self, key: &str) -> bool {
72 self.data.contains_key(key)
73 }
74
75 /// Get the underlying data map (for serialization).
76 #[must_use]
77 pub const fn data(&self) -> &HashMap<String, String> {
78 &self.data
79 }
80
81 /// Get the number of metadata entries.
82 #[must_use]
83 pub fn len(&self) -> usize {
84 self.data.len()
85 }
86
87 /// Check if there are no metadata entries.
88 #[must_use]
89 pub fn is_empty(&self) -> bool {
90 self.data.is_empty()
91 }
92}
93
94impl PartialEq for CodecMetadata {
95 fn eq(&self, other: &Self) -> bool {
96 self.content_type == other.content_type && self.data == other.data
97 }
98}
99
100impl Eq for CodecMetadata {}
101
102#[cfg(test)]
103#[path = "metadata_tests.rs"]
104mod tests;