|
1 | 1 | use JsonValue;
|
2 | 2 |
|
3 |
| -pub struct Generator { |
4 |
| - pub minify: bool, |
5 |
| - code: String, |
6 |
| - dent: u16, |
7 |
| - spaces_per_indent: u16, |
8 |
| -} |
| 3 | +pub trait Generator { |
| 4 | + fn new_line(&mut self) {} |
9 | 5 |
|
10 |
| -impl Generator { |
11 |
| - pub fn new(minify: bool, spaces: u16) -> Self { |
12 |
| - Generator { |
13 |
| - minify: minify, |
14 |
| - code: String::new(), |
15 |
| - dent: 0, |
16 |
| - spaces_per_indent: spaces |
| 6 | + fn write(&mut self, slice: &[u8]); |
| 7 | + |
| 8 | + fn write_min(&mut self, slice: &[u8], minslice: &[u8]); |
| 9 | + |
| 10 | + fn write_char(&mut self, ch: u8); |
| 11 | + |
| 12 | + fn indent(&mut self) {} |
| 13 | + |
| 14 | + fn dedent(&mut self) {} |
| 15 | + |
| 16 | + fn write_string(&mut self, string: &str) { |
| 17 | + self.write_char(b'"'); |
| 18 | + |
| 19 | + for ch in string.bytes() { |
| 20 | + match ch { |
| 21 | + b'\\' | b'"' => { |
| 22 | + self.write_char(b'\\'); |
| 23 | + self.write_char(ch); |
| 24 | + }, |
| 25 | + b'\n' => self.write(b"\\n"), |
| 26 | + b'\r' => self.write(b"\\r"), |
| 27 | + b'\t' => self.write(b"\\t"), |
| 28 | + 0xC => self.write(b"\\f"), |
| 29 | + 0x8 => self.write(b"\\b"), |
| 30 | + _ => self.write_char(ch) |
| 31 | + } |
17 | 32 | }
|
| 33 | + |
| 34 | + self.write_char(b'"'); |
18 | 35 | }
|
19 | 36 |
|
20 |
| - pub fn new_line(&mut self) { |
21 |
| - if !self.minify { |
22 |
| - self.code.push('\n'); |
23 |
| - for _ in 0..(self.dent * self.spaces_per_indent) { |
24 |
| - self.code.push(' '); |
25 |
| - } |
| 37 | + fn write_digits_from_u64(&mut self, mut num: u64, length: &mut u8) { |
| 38 | + let digit = (num % 10) as u8; |
| 39 | + num /= 10; |
| 40 | + if num > 0 { |
| 41 | + self.write_digits_from_u64(num, length); |
26 | 42 | }
|
| 43 | + *length += 1; |
| 44 | + self.write_char(digit + b'0'); |
27 | 45 | }
|
28 | 46 |
|
29 |
| - pub fn write_json(&mut self, json: &JsonValue) { |
30 |
| - match *json { |
31 |
| - JsonValue::String(ref string) => { |
32 |
| - self.write_char('"'); |
33 |
| - |
34 |
| - for ch in string.chars() { |
35 |
| - match ch { |
36 |
| - '\\' | '"' => { |
37 |
| - self.write_char('\\'); |
38 |
| - self.write_char(ch); |
39 |
| - }, |
40 |
| - '\n' => self.write("\\n"), |
41 |
| - '\r' => self.write("\\r"), |
42 |
| - '\t' => self.write("\\t"), |
43 |
| - '\u{000C}' => self.write("\\f"), |
44 |
| - '\u{0008}' => self.write("\\b"), |
45 |
| - _ => self.write_char(ch) |
46 |
| - } |
47 |
| - } |
| 47 | + fn write_number(&mut self, mut num: f64) { |
| 48 | + let mut length = 0; |
| 49 | + if num < 0.0 { |
| 50 | + num = -num; |
| 51 | + self.write_char(b'-'); |
| 52 | + } |
48 | 53 |
|
49 |
| - self.write_char('"'); |
50 |
| - }, |
51 |
| - JsonValue::Number(ref number) => self.write(&number.to_string()), |
52 |
| - JsonValue::Boolean(ref value) => self.write(if *value { "true" } else { "false" }), |
53 |
| - JsonValue::Null => self.write("null"), |
| 54 | + self.write_digits_from_u64(num as u64, &mut length); |
| 55 | + |
| 56 | + let mut fract = num.fract(); |
| 57 | + if fract < 1e-10 { |
| 58 | + return; |
| 59 | + } |
| 60 | + |
| 61 | + fract *= 10.0; |
| 62 | + self.write_char(b'.'); |
| 63 | + self.write_char((fract as u8) + b'0'); |
| 64 | + fract = fract.fract(); |
| 65 | + length += 2; |
| 66 | + |
| 67 | + while length < 17 && fract > 0.01 { |
| 68 | + fract *= 10.0; |
| 69 | + self.write_char((fract as u8) + b'0'); |
| 70 | + fract = fract.fract(); |
| 71 | + length += 1; |
| 72 | + } |
| 73 | + } |
| 74 | + |
| 75 | + fn write_json(&mut self, json: &JsonValue) { |
| 76 | + match *json { |
| 77 | + JsonValue::String(ref string) => self.write_string(string), |
| 78 | + JsonValue::Number(ref number) => self.write_number(*number), |
| 79 | + JsonValue::Boolean(ref value) => self.write(if *value { b"true" } else { b"false" }), |
| 80 | + JsonValue::Null => self.write(b"null"), |
54 | 81 | JsonValue::Array(ref array) => {
|
55 |
| - self.write_char('['); |
| 82 | + self.write_char(b'['); |
56 | 83 | self.indent();
|
57 | 84 | let mut first = true;
|
58 | 85 | for item in array {
|
59 | 86 | if first {
|
60 | 87 | first = false;
|
61 | 88 | self.new_line();
|
62 | 89 | } else {
|
63 |
| - self.write(","); |
| 90 | + self.write(b","); |
64 | 91 | self.new_line();
|
65 | 92 | }
|
66 | 93 | self.write_json(item);
|
67 | 94 | }
|
68 | 95 | self.dedent();
|
69 | 96 | self.new_line();
|
70 |
| - self.write_char(']'); |
| 97 | + self.write_char(b']'); |
71 | 98 | },
|
72 | 99 | JsonValue::Object(ref object) => {
|
73 |
| - self.write_char('{'); |
| 100 | + self.write_char(b'{'); |
74 | 101 | self.indent();
|
75 | 102 | let mut first = true;
|
76 | 103 | for (key, value) in object.iter() {
|
77 | 104 | if first {
|
78 | 105 | first = false;
|
79 | 106 | self.new_line();
|
80 | 107 | } else {
|
81 |
| - self.write(","); |
| 108 | + self.write(b","); |
82 | 109 | self.new_line();
|
83 | 110 | }
|
84 |
| - self.write(&format!("{:?}", key)); |
85 |
| - self.write_min(": ", ":"); |
| 111 | + self.write_string(key); |
| 112 | + self.write_min(b": ", b":"); |
86 | 113 | self.write_json(value);
|
87 | 114 | }
|
88 | 115 | self.dedent();
|
89 | 116 | self.new_line();
|
90 |
| - self.write_char('}'); |
| 117 | + self.write_char(b'}'); |
91 | 118 | }
|
92 | 119 | }
|
93 | 120 | }
|
94 | 121 |
|
95 |
| - pub fn write(&mut self, slice: &str) { |
96 |
| - self.code.push_str(slice); |
| 122 | + fn consume(self) -> String; |
| 123 | +} |
| 124 | + |
| 125 | +pub struct DumpGenerator { |
| 126 | + code: Vec<u8>, |
| 127 | +} |
| 128 | + |
| 129 | +impl DumpGenerator { |
| 130 | + pub fn new() -> Self { |
| 131 | + DumpGenerator { |
| 132 | + code: Vec::with_capacity(1024), |
| 133 | + } |
| 134 | + } |
| 135 | +} |
| 136 | + |
| 137 | +impl Generator for DumpGenerator { |
| 138 | + fn write(&mut self, slice: &[u8]) { |
| 139 | + self.code.extend_from_slice(slice); |
| 140 | + } |
| 141 | + |
| 142 | + fn write_min(&mut self, _: &[u8], minslice: &[u8]) { |
| 143 | + self.code.extend_from_slice(minslice); |
| 144 | + } |
| 145 | + |
| 146 | + fn write_char(&mut self, ch: u8) { |
| 147 | + self.code.push(ch); |
| 148 | + } |
| 149 | + |
| 150 | + fn consume(self) -> String { |
| 151 | + String::from_utf8(self.code).unwrap() |
| 152 | + } |
| 153 | +} |
| 154 | + |
| 155 | +pub struct PrettyGenerator { |
| 156 | + code: Vec<u8>, |
| 157 | + dent: u16, |
| 158 | + spaces_per_indent: u16, |
| 159 | +} |
| 160 | + |
| 161 | +impl PrettyGenerator { |
| 162 | + pub fn new(spaces: u16) -> Self { |
| 163 | + PrettyGenerator { |
| 164 | + code: Vec::with_capacity(1024), |
| 165 | + dent: 0, |
| 166 | + spaces_per_indent: spaces |
| 167 | + } |
97 | 168 | }
|
| 169 | +} |
98 | 170 |
|
99 |
| - pub fn write_min(&mut self, slice: &str, minslice: &str) { |
100 |
| - if self.minify { |
101 |
| - self.write(minslice); |
102 |
| - } else { |
103 |
| - self.write(slice); |
| 171 | +impl Generator for PrettyGenerator { |
| 172 | + fn new_line(&mut self) { |
| 173 | + self.code.push(b'\n'); |
| 174 | + for _ in 0..(self.dent * self.spaces_per_indent) { |
| 175 | + self.code.push(b' '); |
104 | 176 | }
|
105 | 177 | }
|
106 | 178 |
|
107 |
| - pub fn write_char(&mut self, ch: char) { |
| 179 | + fn write(&mut self, slice: &[u8]) { |
| 180 | + self.code.extend_from_slice(slice); |
| 181 | + } |
| 182 | + |
| 183 | + fn write_min(&mut self, slice: &[u8], _: &[u8]) { |
| 184 | + self.code.extend_from_slice(slice); |
| 185 | + } |
| 186 | + |
| 187 | + fn write_char(&mut self, ch: u8) { |
108 | 188 | self.code.push(ch);
|
109 | 189 | }
|
110 | 190 |
|
111 |
| - pub fn indent(&mut self) { |
| 191 | + fn indent(&mut self) { |
112 | 192 | self.dent += 1;
|
113 | 193 | }
|
114 | 194 |
|
115 |
| - pub fn dedent(&mut self) { |
| 195 | + fn dedent(&mut self) { |
116 | 196 | self.dent -= 1;
|
117 | 197 | }
|
118 | 198 |
|
119 |
| - pub fn consume(self) -> String { |
120 |
| - self.code |
| 199 | + fn consume(self) -> String { |
| 200 | + String::from_utf8(self.code).unwrap() |
121 | 201 | }
|
122 | 202 | }
|
0 commit comments