copefmt/
lib.rs

1use std::io::{prelude::*, BufReader, BufWriter};
2
3pub struct Formatter<R: Read, W: Write> {
4    reader: BufReader<R>,
5    writer: BufWriter<W>,
6    current: u8,
7    previous: u8,
8    newline: String,
9    indent: String,
10    levels: Vec<Level>,
11}
12
13#[derive(Clone)]
14struct Level {
15    break_newline: bool,
16}
17
18impl<R: Read, W: Write> Formatter<R, W> {
19    pub fn new(reader: R, writer: W) -> Self {
20        Self {
21            reader: BufReader::new(reader),
22            writer: BufWriter::new(writer),
23            current: 0,
24            previous: 0,
25            newline: "\n".to_string(),
26            indent: "    ".to_string(),
27            levels: Vec::with_capacity(10),
28        }
29    }
30
31    pub fn format(mut self) -> std::io::Result<()> {
32        while self.read_next() {
33            self.update();
34            self.write()?;
35        }
36        Ok(())
37    }
38}
39
40// Private methods
41impl<R: Read, W: Write> Formatter<R, W> {
42    fn push_level(&mut self, level: Level) {
43        self.levels.push(level);
44    }
45
46    fn pop_level(&mut self) {
47        if !self.levels.is_empty() {
48            self.levels.pop();
49        }
50    }
51
52    fn current_level(&self) -> Level {
53        self.levels.last().cloned().unwrap_or(Level {
54            break_newline: false,
55        })
56    }
57
58    fn indent_level(&self) -> i32 {
59        self.levels.len() as _
60    }
61
62    fn read_next(&mut self) -> bool {
63        self.previous = self.current;
64        let buf = std::slice::from_mut(&mut self.current);
65        self.reader.read_exact(buf).is_ok()
66    }
67
68    fn update(&mut self) {
69        self.update_level();
70    }
71
72    fn update_level(&mut self) {
73        match self.previous {
74            b'}' | b')' if self.indent_level() > 0 => self.pop_level(),
75            _ => {}
76        };
77        match self.current {
78            b'{' => self.push_level(Level {
79                break_newline: true,
80            }),
81            b'(' => self.push_level(Level {
82                break_newline: false,
83            }),
84            _ => {}
85        };
86    }
87
88    fn write(&mut self) -> std::io::Result<()> {
89        match self.previous {
90            b'{' | b'(' | b',' => {
91                if self.current_level().break_newline {
92                    self.write_newline()?;
93                    self.write_indent(self.indent_level())?;
94                }
95            }
96            _ => {}
97        };
98
99        match self.current {
100            b'}' | b')' => {
101                if self.current_level().break_newline {
102                    self.write_newline()?;
103                    self.write_indent(self.indent_level() - 1)?;
104                }
105            }
106            _ => {}
107        };
108
109        let current = std::slice::from_ref(&self.current);
110        self.writer.write_all(current).unwrap();
111
112        Ok(())
113    }
114
115    fn write_newline(&mut self) -> std::io::Result<()> {
116        self.writer.write_all(self.newline.as_bytes())
117    }
118
119    fn write_indent(&mut self, n: i32) -> std::io::Result<()> {
120        let buf = self.indent.as_bytes();
121        for _ in 0..n {
122            self.writer.write_all(buf)?;
123        }
124        Ok(())
125    }
126}