Skip to main content

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;