Skip to main content

redox_core/
io.rs

1//! Core IO helpers for loading/saving text buffers.
2//!
3//! This module is intentionally small and UI-agnostic. It just provides helpers
4//! that read and write UTF-8 text to/from the rope-backed `TextBuffer`.
5
6use std::path::Path;
7
8use anyhow::{Context as _, Result};
9
10use crate::buffer::TextBuffer;
11
12/// Read a UTF-8 file into a `TextBuffer`.
13///
14/// The file is parsed as UTF-8.
15pub fn load_buffer(path: impl AsRef<Path>) -> Result<TextBuffer> {
16    TextBuffer::from_file(path)
17}
18
19/// Write a `TextBuffer` to a UTF-8 file.
20///
21/// This writes the entire buffer to disk in one go.
22pub fn save_buffer(path: impl AsRef<Path>, buffer: &TextBuffer) -> Result<()> {
23    let path = path.as_ref();
24    std::fs::write(path, buffer.to_string())
25        .with_context(|| format!("failed to write file: {}", path.to_string_lossy()))?;
26    Ok(())
27}
28
29#[cfg(test)]
30mod tests {
31    use super::*;
32    use std::time::{SystemTime, UNIX_EPOCH};
33
34    fn temp_path(tag: &str) -> std::path::PathBuf {
35        let nanos = SystemTime::now()
36            .duration_since(UNIX_EPOCH)
37            .expect("clock went backwards")
38            .as_nanos();
39        std::env::temp_dir().join(format!("redox_io_test_{tag}_{nanos}.txt"))
40    }
41
42    #[test]
43    fn save_then_load_roundtrip() {
44        let path = temp_path("roundtrip");
45        let b = TextBuffer::from_str("hello\nworld\n");
46
47        save_buffer(&path, &b).expect("save failed");
48        let loaded = load_buffer(&path).expect("load failed");
49
50        assert_eq!(loaded.to_string(), "hello\nworld\n");
51        let _ = std::fs::remove_file(path);
52    }
53
54    #[test]
55    fn load_buffer_rejects_invalid_utf8() {
56        let path = temp_path("invalid_utf8");
57        std::fs::write(&path, [0xffu8, 0xfeu8]).expect("failed to write invalid utf8");
58
59        let err = load_buffer(&path).expect_err("expected invalid utf8 error");
60        let msg = err.to_string();
61        assert!(msg.contains("not valid UTF-8") || msg.contains("file is not valid UTF-8"));
62
63        let _ = std::fs::remove_file(path);
64    }
65}