1use std::path::{Path, PathBuf};
2
3use serde::{Deserialize, Serialize};
4
5use super::{CorpusKind, IndexError, IndexKind};
6
7const META_FILE: &str = "meta.json";
8const STORE_VERSION: u32 = 1;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct StoreMeta {
13 pub version: u32,
14 pub root: PathBuf,
15 pub corpus_kind: CorpusKind,
16 pub follow_links: bool,
17 #[serde(default)]
18 pub indexes: Vec<IndexKind>,
19}
20
21impl StoreMeta {
22 #[must_use]
24 pub const fn new(
25 root: PathBuf,
26 corpus_kind: CorpusKind,
27 follow_links: bool,
28 indexes: Vec<IndexKind>,
29 ) -> Self {
30 Self {
31 version: STORE_VERSION,
32 root,
33 corpus_kind,
34 follow_links,
35 indexes,
36 }
37 }
38
39 #[must_use]
41 pub fn path(dir: &Path) -> PathBuf {
42 dir.join(META_FILE)
43 }
44
45 pub fn read(dir: &Path) -> crate::Result<Self> {
51 let meta_path = Self::path(dir);
52 let raw = std::fs::read_to_string(&meta_path)?;
53 serde_json::from_str(&raw).map_err(|e| {
54 crate::Error::Index(IndexError::InvalidManifest {
55 path: meta_path,
56 source: e,
57 })
58 })
59 }
60
61 pub fn write(&self, dir: &Path) -> crate::Result<()> {
67 let meta_path = Self::path(dir);
68 let json = serde_json::to_vec_pretty(self).map_err(|e| {
69 crate::Error::Index(IndexError::InvalidManifest {
70 path: meta_path.clone(),
71 source: e,
72 })
73 })?;
74 std::fs::write(&meta_path, json)?;
75 Ok(())
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82 use tempfile::TempDir;
83
84 #[test]
85 fn read_write_roundtrip() {
86 let tmp = TempDir::new().expect("create temp dir");
87
88 let meta = StoreMeta::new(
89 PathBuf::from("/some/root"),
90 CorpusKind::Directory,
91 true,
92 vec![IndexKind::Trigram],
93 );
94 meta.write(tmp.path()).expect("write meta");
95
96 let loaded = StoreMeta::read(tmp.path()).expect("read meta");
97 assert_eq!(loaded.version, meta.version);
98 assert_eq!(loaded.root, meta.root);
99 assert_eq!(loaded.corpus_kind, meta.corpus_kind);
100 assert_eq!(loaded.follow_links, meta.follow_links);
101 assert_eq!(loaded.indexes, meta.indexes);
102 }
103
104 #[test]
105 fn path_returns_meta_json() {
106 let p = StoreMeta::path(Path::new("/foo/bar"));
107 assert_eq!(p, PathBuf::from("/foo/bar/meta.json"));
108 }
109}