lindera_dictionary/loader/
metadata.rs

1use std::path::Path;
2
3use crate::LinderaResult;
4use crate::dictionary::metadata::Metadata;
5use crate::error::LinderaErrorKind;
6#[cfg(feature = "mmap")]
7use crate::util::mmap_file;
8use crate::util::read_file;
9
10/// MetadataLoader is a loader for reading persisted metadata files.
11///
12/// # Examples
13///
14/// ```no_run
15/// use lindera_dictionary::loader::metadata::MetadataLoader;
16/// use std::path::Path;
17///
18/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
19/// // Normal loading
20/// let metadata = MetadataLoader::load(Path::new("/path/to/dictionary"))?;
21///
22/// // Memory-mapped loading (when mmap feature is enabled)
23/// #[cfg(feature = "mmap")]
24/// let metadata = MetadataLoader::load_mmap(Path::new("/path/to/dictionary"))?;
25/// # Ok(())
26/// # }
27/// ```
28pub struct MetadataLoader {}
29
30impl MetadataLoader {
31    /// Loads metadata file (metadata.json) from the specified directory.
32    ///
33    /// # Arguments
34    ///
35    /// * `input_dir` - Path to the directory containing the metadata file
36    ///
37    /// # Returns
38    ///
39    /// The loaded Metadata object, or an error
40    ///
41    /// # Errors
42    ///
43    /// Returns an error if file reading fails or deserialization fails.
44    pub fn load(input_dir: &Path) -> LinderaResult<Metadata> {
45        let data = read_file(input_dir.join("metadata.json").as_path())?;
46
47        let metadata: Metadata = serde_json::from_slice(&data).map_err(|err| {
48            LinderaErrorKind::Deserialize
49                .with_error(anyhow::anyhow!(err))
50                .add_context("Failed to deserialize metadata.json file")
51        })?;
52
53        Ok(metadata)
54    }
55
56    /// Loads metadata file using memory mapping.
57    ///
58    /// This method is only available when the "mmap" feature is enabled.
59    /// It's useful for efficiently reading large files.
60    ///
61    /// # Arguments
62    ///
63    /// * `input_dir` - Path to the directory containing the metadata file
64    ///
65    /// # Returns
66    ///
67    /// The loaded Metadata object, or an error
68    #[cfg(feature = "mmap")]
69    pub fn load_mmap(input_dir: &Path) -> LinderaResult<Metadata> {
70        let data = mmap_file(input_dir.join("metadata.json").as_path())?;
71
72        let metadata: Metadata = serde_json::from_slice(&data).map_err(|err| {
73            LinderaErrorKind::Deserialize
74                .with_error(anyhow::anyhow!(err))
75                .add_context("Failed to deserialize metadata.json file (mmap)")
76        })?;
77
78        Ok(metadata)
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use crate::builder::metadata::MetadataBuilder;
85    use crate::dictionary::metadata::Metadata;
86
87    use super::*;
88
89    #[test]
90    fn test_metadata_load() {
91        // Note: This is an integration test that uses the actual file system
92        // In a real environment, we recommend using the tempfile crate
93
94        let temp_path = std::env::temp_dir().join("lindera_test_metadata");
95        std::fs::create_dir_all(&temp_path).unwrap();
96
97        // Create a sample metadata object
98        let metadata = Metadata::default();
99
100        // Create test metadata file
101        let metadata_builder = MetadataBuilder::new();
102        metadata_builder.build(&metadata, &temp_path).unwrap();
103
104        // Load from file
105        let loaded_metadata = MetadataLoader::load(&temp_path).unwrap();
106
107        assert_eq!(loaded_metadata.encoding, "UTF-8");
108        assert_eq!(loaded_metadata.default_word_cost, -10000);
109        assert_eq!(loaded_metadata.default_left_context_id, 1288);
110        // Cleanup
111        std::fs::remove_dir_all(&temp_path).ok();
112    }
113
114    #[test]
115    fn test_metadata_load_nonexistent_file() {
116        let temp_path = std::env::temp_dir().join("lindera_test_nonexistent");
117
118        // Try to load non-existent file (should return error)
119        let result = MetadataLoader::load(&temp_path);
120        assert!(result.is_err());
121    }
122}