sakurs_cli/input/
file_reader.rs1use anyhow::{Context, Result};
4use std::fs;
5use std::path::Path;
6
7pub struct FileReader;
9
10impl FileReader {
11 pub fn read_text(path: &Path) -> Result<String> {
13 let content = fs::read_to_string(path)
14 .with_context(|| format!("Failed to read file: {}", path.display()))?;
15
16 Ok(content)
17 }
18
19 pub fn file_size(path: &Path) -> Result<u64> {
21 let metadata = fs::metadata(path)
22 .with_context(|| format!("Failed to get metadata for: {}", path.display()))?;
23
24 Ok(metadata.len())
25 }
26
27 pub fn should_stream(path: &Path, threshold_mb: u64) -> Result<bool> {
29 let size = Self::file_size(path)?;
30 Ok(size > threshold_mb * 1024 * 1024)
31 }
32}
33
34#[cfg(test)]
35mod tests {
36 use super::*;
37 use std::fs::{self, File};
38 use tempfile::TempDir;
39
40 #[test]
41 fn test_read_text_success() {
42 let temp_dir = TempDir::new().unwrap();
43 let file_path = temp_dir.path().join("test.txt");
44
45 let content = "Hello, world!\nThis is a test.";
46 fs::write(&file_path, content).unwrap();
47
48 let result = FileReader::read_text(&file_path).unwrap();
49 assert_eq!(result, content);
50 }
51
52 #[test]
53 fn test_read_text_nonexistent_file() {
54 let path = Path::new("/nonexistent/file.txt");
55 let result = FileReader::read_text(path);
56
57 assert!(result.is_err());
58 let err_msg = result.unwrap_err().to_string();
59 assert!(err_msg.contains("Failed to read file"));
60 }
61
62 #[test]
63 fn test_read_text_utf8_content() {
64 let temp_dir = TempDir::new().unwrap();
65 let file_path = temp_dir.path().join("utf8.txt");
66
67 let content = "Hello δΈη! π Emoji and UTF-8";
68 fs::write(&file_path, content).unwrap();
69
70 let result = FileReader::read_text(&file_path).unwrap();
71 assert_eq!(result, content);
72 }
73
74 #[test]
75 fn test_file_size() {
76 let temp_dir = TempDir::new().unwrap();
77 let file_path = temp_dir.path().join("sized.txt");
78
79 let content = "a".repeat(1024);
80 fs::write(&file_path, &content).unwrap();
81
82 let size = FileReader::file_size(&file_path).unwrap();
83 assert_eq!(size, 1024);
84 }
85
86 #[test]
87 fn test_file_size_nonexistent() {
88 let path = Path::new("/nonexistent/file.txt");
89 let result = FileReader::file_size(path);
90
91 assert!(result.is_err());
92 let err_msg = result.unwrap_err().to_string();
93 assert!(err_msg.contains("Failed to get metadata"));
94 }
95
96 #[test]
97 fn test_should_stream_small_file() {
98 let temp_dir = TempDir::new().unwrap();
99 let file_path = temp_dir.path().join("small.txt");
100
101 fs::write(&file_path, "small content").unwrap();
102
103 let should_stream = FileReader::should_stream(&file_path, 1).unwrap();
104 assert!(!should_stream);
105 }
106
107 #[test]
108 fn test_should_stream_large_file() {
109 let temp_dir = TempDir::new().unwrap();
110 let file_path = temp_dir.path().join("large.txt");
111
112 let content = "a".repeat(2048);
114 fs::write(&file_path, content).unwrap();
115
116 let should_stream = FileReader::should_stream(&file_path, 0).unwrap();
118 assert!(should_stream);
119 }
120
121 #[test]
122 fn test_empty_file() {
123 let temp_dir = TempDir::new().unwrap();
124 let file_path = temp_dir.path().join("empty.txt");
125
126 File::create(&file_path).unwrap();
127
128 let content = FileReader::read_text(&file_path).unwrap();
129 assert_eq!(content, "");
130
131 let size = FileReader::file_size(&file_path).unwrap();
132 assert_eq!(size, 0);
133 }
134
135 #[cfg(unix)]
136 #[test]
137 fn test_read_text_permission_denied() {
138 use std::os::unix::fs::PermissionsExt;
139
140 let temp_dir = TempDir::new().unwrap();
141 let file_path = temp_dir.path().join("no_read.txt");
142
143 fs::write(&file_path, "content").unwrap();
144
145 let metadata = fs::metadata(&file_path).unwrap();
147 let mut permissions = metadata.permissions();
148 permissions.set_mode(0o000);
149 fs::set_permissions(&file_path, permissions).unwrap();
150
151 let result = FileReader::read_text(&file_path);
152 assert!(result.is_err());
153
154 let mut permissions = fs::metadata(&file_path).unwrap().permissions();
156 permissions.set_mode(0o644);
157 fs::set_permissions(&file_path, permissions).unwrap();
158 }
159}