1use std::{
2 fs::File,
3 io::{BufReader, Read, Write},
4 path::Path,
5};
6
7pub fn tfp(fp: impl AsRef<Path>) -> std::io::Result<String> {
8 let file = File::open(&fp)?;
9 let mut reader = BufReader::new(file);
10 let mut buffer = [0; 1]; let mut change = false;
13 let mut li = Vec::new();
14 let mut line = Vec::new();
15
16 loop {
17 let bytes_read = reader.read(&mut buffer)?;
18 if bytes_read == 0 {
19 break;
20 }
21
22 let c = buffer[0];
23 match c {
24 b'\n' => {
25 let t = String::from_utf8_lossy(&line);
26 let trimmed_line = t.trim_end();
27 if trimmed_line.len() != t.len() {
28 change = true;
29 }
30 li.push(trimmed_line.to_owned());
31 line.clear();
32 }
33 b'\r' => {
34 change = true;
35 let t = String::from_utf8_lossy(&line);
36 let trimmed_line = t.trim_end();
37 li.push(trimmed_line.to_owned());
38 line.clear();
39 let bytes_read = reader.read(&mut buffer)?;
40 if bytes_read > 0 {
41 let c = buffer[0];
42 if c != b'\n' {
43 if c == b'\r' {
45 li.push("".into());
46 } else {
47 line.push(c);
48 }
49 }
50 }
51 }
52 _ => {
53 line.push(c);
54 }
55 }
56 }
57
58 if !line.is_empty() {
59 let t = String::from_utf8_lossy(&line);
60 let trimmed_line = t.trim_end();
61 if trimmed_line.len() != t.len() {
62 change = true;
63 }
64 li.push(trimmed_line.to_owned());
65 }
66
67 while let Some(i) = li.last() {
68 if i.is_empty() {
69 change = true;
70 li.pop();
71 } else {
72 break;
73 }
74 }
75
76 let txt = li.join("\n");
77 if change {
78 let mut file = File::create(fp)?;
79 file.write_all(txt.as_bytes())?;
80 }
81
82 Ok(txt)
83}