ricecoder_storage/config/
documents.rs1use crate::error::{StorageError, StorageResult};
6use crate::types::DocumentFormat;
7use std::path::Path;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct Document {
12 pub content: String,
14 pub format: DocumentFormat,
16}
17
18pub struct DocumentLoader;
20
21impl DocumentLoader {
22 pub fn load_from_file<P: AsRef<Path>>(path: P) -> StorageResult<Document> {
27 let path = path.as_ref();
28 let content = std::fs::read_to_string(path).map_err(|e| {
29 StorageError::io_error(path.to_path_buf(), crate::error::IoOperation::Read, e)
30 })?;
31
32 let extension = path
33 .extension()
34 .and_then(|ext| ext.to_str())
35 .ok_or_else(|| {
36 StorageError::parse_error(path.to_path_buf(), "unknown", "File has no extension")
37 })?;
38
39 let format = DocumentFormat::from_extension(extension).ok_or_else(|| {
40 StorageError::parse_error(
41 path.to_path_buf(),
42 "unknown",
43 format!("Unsupported document format: {}", extension),
44 )
45 })?;
46
47 Ok(Document { content, format })
48 }
49
50 pub fn load_from_string(content: String, format: DocumentFormat) -> Document {
52 Document { content, format }
53 }
54
55 pub fn save_to_file<P: AsRef<Path>>(document: &Document, path: P) -> StorageResult<()> {
57 let path = path.as_ref();
58 std::fs::write(path, &document.content).map_err(|e| {
59 StorageError::io_error(path.to_path_buf(), crate::error::IoOperation::Write, e)
60 })
61 }
62
63 pub fn extension_for_format(format: DocumentFormat) -> &'static str {
65 format.extension()
66 }
67
68 pub fn detect_format<P: AsRef<Path>>(path: P) -> StorageResult<DocumentFormat> {
70 let path = path.as_ref();
71 let extension = path
72 .extension()
73 .and_then(|ext| ext.to_str())
74 .ok_or_else(|| {
75 StorageError::parse_error(path.to_path_buf(), "unknown", "File has no extension")
76 })?;
77
78 DocumentFormat::from_extension(extension).ok_or_else(|| {
79 StorageError::parse_error(
80 path.to_path_buf(),
81 "unknown",
82 format!("Unsupported document format: {}", extension),
83 )
84 })
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_load_yaml_document() {
94 let yaml_content = "# Steering Document\nkey: value\n";
95 let doc = DocumentLoader::load_from_string(yaml_content.to_string(), DocumentFormat::Yaml);
96 assert_eq!(doc.content, yaml_content);
97 assert_eq!(doc.format, DocumentFormat::Yaml);
98 }
99
100 #[test]
101 fn test_load_markdown_document() {
102 let md_content = "# Steering Document\n\nThis is a markdown document.\n";
103 let doc =
104 DocumentLoader::load_from_string(md_content.to_string(), DocumentFormat::Markdown);
105 assert_eq!(doc.content, md_content);
106 assert_eq!(doc.format, DocumentFormat::Markdown);
107 }
108
109 #[test]
110 fn test_save_and_load_yaml_document() {
111 let temp_dir = tempfile::TempDir::new().expect("Failed to create temp dir");
112 let file_path = temp_dir.path().join("steering.yaml");
113 let original = Document {
114 content: "# Steering\nkey: value\n".to_string(),
115 format: DocumentFormat::Yaml,
116 };
117
118 DocumentLoader::save_to_file(&original, &file_path).expect("Failed to save document");
119
120 let loaded = DocumentLoader::load_from_file(&file_path).expect("Failed to load document");
121
122 assert_eq!(original, loaded);
123 }
124
125 #[test]
126 fn test_save_and_load_markdown_document() {
127 let temp_dir = tempfile::TempDir::new().expect("Failed to create temp dir");
128 let file_path = temp_dir.path().join("steering.md");
129 let original = Document {
130 content: "# Steering\n\nThis is markdown.\n".to_string(),
131 format: DocumentFormat::Markdown,
132 };
133
134 DocumentLoader::save_to_file(&original, &file_path).expect("Failed to save document");
135
136 let loaded = DocumentLoader::load_from_file(&file_path).expect("Failed to load document");
137
138 assert_eq!(original, loaded);
139 }
140
141 #[test]
142 fn test_detect_yaml_format() {
143 let format = DocumentLoader::detect_format("test.yaml").expect("Failed to detect format");
144 assert_eq!(format, DocumentFormat::Yaml);
145
146 let format = DocumentLoader::detect_format("test.yml").expect("Failed to detect format");
147 assert_eq!(format, DocumentFormat::Yaml);
148 }
149
150 #[test]
151 fn test_detect_markdown_format() {
152 let format = DocumentLoader::detect_format("test.md").expect("Failed to detect format");
153 assert_eq!(format, DocumentFormat::Markdown);
154
155 let format =
156 DocumentLoader::detect_format("test.markdown").expect("Failed to detect format");
157 assert_eq!(format, DocumentFormat::Markdown);
158 }
159
160 #[test]
161 fn test_extension_for_format() {
162 assert_eq!(
163 DocumentLoader::extension_for_format(DocumentFormat::Yaml),
164 "yaml"
165 );
166 assert_eq!(
167 DocumentLoader::extension_for_format(DocumentFormat::Markdown),
168 "md"
169 );
170 }
171}