wasm_bridge_jco/
source.rs1use std::fmt::{self, Write};
2use std::ops::Deref;
3
4pub use wit_parser;
5
6#[derive(Default)]
7pub struct Source {
8 s: String,
9 indent: usize,
10}
11
12impl Source {
13 pub fn push_str(&mut self, src: &str) {
14 let lines = src.lines().collect::<Vec<_>>();
15 for (i, line) in lines.iter().enumerate() {
16 let trimmed = line.trim();
17 if trimmed.starts_with('}') && self.s.ends_with(" ") {
18 self.s.pop();
19 self.s.pop();
20 }
21 self.s.push_str(if lines.len() == 1 {
22 line
23 } else {
24 line.trim_start()
25 });
26 if trimmed.ends_with('{') {
27 self.indent += 1;
28 }
29 if trimmed.starts_with('}') {
30 self.indent = self.indent.saturating_sub(1);
35 }
36 if i != lines.len() - 1 || src.ends_with('\n') {
37 self.newline();
38 }
39 }
40 }
41
42 pub fn indent(&mut self, amt: usize) {
43 self.indent += amt;
44 }
45
46 pub fn deindent(&mut self, amt: usize) {
47 self.indent -= amt;
48 }
49
50 fn newline(&mut self) {
51 self.s.push('\n');
52 for _ in 0..self.indent {
53 self.s.push_str(" ");
54 }
55 }
56
57 pub fn as_mut_string(&mut self) -> &mut String {
58 &mut self.s
59 }
60}
61
62impl Write for Source {
63 fn write_str(&mut self, s: &str) -> fmt::Result {
64 self.push_str(s);
65 Ok(())
66 }
67}
68
69impl Deref for Source {
70 type Target = str;
71 fn deref(&self) -> &str {
72 &self.s
73 }
74}
75
76impl From<Source> for String {
77 fn from(s: Source) -> String {
78 s.s
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::Source;
85
86 #[test]
87 fn simple_append() {
88 let mut s = Source::default();
89 s.push_str("x");
90 assert_eq!(s.s, "x");
91 s.push_str("y");
92 assert_eq!(s.s, "xy");
93 s.push_str("z ");
94 assert_eq!(s.s, "xyz ");
95 s.push_str(" a ");
96 assert_eq!(s.s, "xyz a ");
97 s.push_str("\na");
98 assert_eq!(s.s, "xyz a \na");
99 }
100
101 #[test]
102 fn newline_remap() {
103 let mut s = Source::default();
104 s.push_str("function() {\n");
105 s.push_str("y\n");
106 s.push_str("}\n");
107 assert_eq!(s.s, "function() {\n y\n}\n");
108 }
109
110 #[test]
111 fn if_else() {
112 let mut s = Source::default();
113 s.push_str("if() {\n");
114 s.push_str("y\n");
115 s.push_str("} else if () {\n");
116 s.push_str("z\n");
117 s.push_str("}\n");
118 assert_eq!(s.s, "if() {\n y\n} else if () {\n z\n}\n");
119 }
120
121 #[test]
122 fn trim_ws() {
123 let mut s = Source::default();
124 s.push_str(
125 "function() {
126 x
127 }",
128 );
129 assert_eq!(s.s, "function() {\n x\n}");
130 }
131}