xref: /Held/src/utils/file.rs (revision 5dacf00fa267a9ac7a4794894f9162d71b69c2b8)
1 use std::{
2     fs::{self, File},
3     io::{self, Read, Seek, Write},
4 };
5 
6 use super::buffer::EditBuffer;
7 
8 pub const BAK_SUFFIX: &'static str = ".heldbak";
9 
10 pub struct FileManager {
11     name: String,
12     file: File,
13     bak: Option<File>,
14 }
15 
16 impl FileManager {
17     pub fn new(file_path: String) -> io::Result<Self> {
18         let file = File::options()
19             .write(true)
20             .read(true)
21             .create(true)
22             .open(file_path.clone())?;
23 
24         Ok(Self {
25             file,
26             name: file_path,
27             bak: None,
28         })
29     }
30 
31     pub fn init(&mut self, bak: bool) -> io::Result<EditBuffer> {
32         let mut buf = Vec::new();
33         // 是否备份
34         if bak {
35             self.do_bak(&mut buf)?;
36         } else {
37             self.file.read_to_end(&mut buf)?;
38         }
39 
40         Ok(EditBuffer::new(buf))
41     }
42 
43     // 备份
44     fn do_bak(&mut self, buf: &mut Vec<u8>) -> io::Result<()> {
45         let mut bak = File::options()
46             .write(true)
47             .read(true)
48             .create(true)
49             .open(format!("{}{}", self.name, BAK_SUFFIX))?;
50 
51         bak.set_len(0)?;
52 
53         self.file.read_to_end(buf)?;
54         bak.write_all(&buf)?;
55 
56         self.file.seek(io::SeekFrom::Start(0))?;
57 
58         if self.bak.is_some() {
59             error!("The backup already exists. The operation may cause data loss.");
60         }
61 
62         self.bak = Some(bak);
63 
64         Ok(())
65     }
66 
67     pub fn store(&mut self, buf: &EditBuffer) -> io::Result<()> {
68         let data = buf.all_buffer();
69 
70         self.file.set_len(0)?;
71 
72         for (idx, line) in data.iter().enumerate() {
73             if idx == data.len() - 1 {
74                 self.file.write(&line[..line.len()])?;
75             } else {
76                 self.file.write(&line)?;
77             }
78         }
79 
80         if self.bak.is_some() {
81             fs::remove_file(format!("{}{}", self.name, BAK_SUFFIX))?;
82         }
83 
84         Ok(())
85     }
86 }
87