@@ -4,65 +4,79 @@ use JsonValue;
4
4
5
5
extern crate itoa;
6
6
7
+ const QU : u8 = b'"' ;
8
+ const BS : u8 = b'\\' ;
9
+ const B : u8 = b'b' ;
10
+ const T : u8 = b't' ;
11
+ const N : u8 = b'n' ;
12
+ const F : u8 = b'f' ;
13
+ const R : u8 = b'r' ;
14
+ const U : u8 = b'u' ;
15
+
7
16
static ESCAPED : [ u8 ; 256 ] = [
8
17
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
9
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , b'b' , b't' , b'n' , 0 , b'f' , b'r' , 0 , 0 , // 0
10
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 1
11
- 0 , 0 , b'"' , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 2
12
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 3
13
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 4
14
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , b'\\' , 0 , 0 , 0 , // 5
15
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 6
16
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 7
17
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 8
18
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 9
19
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // A
20
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // B
21
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // C
22
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // D
23
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // E
24
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // F
18
+ U , U , U , U , U , U , U , U , B , T , N , U , F , R , U , U , // 0
19
+ U , U , U , U , U , U , U , U , U , U , U , U , U , U , U , U , // 1
20
+ 0 , 0 , QU , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 2
21
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 3
22
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 4
23
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , BS , 0 , 0 , 0 , // 5
24
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 6
25
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , U , // 7
26
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 8
27
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 9
28
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // A
29
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // B
30
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // C
31
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // D
32
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // E
33
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // F
25
34
] ;
26
35
27
36
pub trait Generator {
28
- fn get_buffer ( & mut self ) -> & mut Vec < u8 > ;
37
+ type T : Write ;
29
38
30
- fn current_index ( & mut self ) -> usize {
31
- self . get_buffer ( ) . len ( )
32
- }
39
+ fn get_writer ( & mut self ) -> & mut Self :: T ;
33
40
34
41
#[ inline( always) ]
35
42
fn write ( & mut self , slice : & [ u8 ] ) {
36
- self . get_buffer ( ) . extend_from_slice ( slice)
43
+ self . get_writer ( ) . write_all ( slice) . unwrap ( ) ;
37
44
}
38
45
39
46
#[ inline( always) ]
40
47
fn write_char ( & mut self , ch : u8 ) {
41
- self . get_buffer ( ) . push ( ch )
48
+ self . get_writer ( ) . write_all ( & [ ch ] ) . unwrap ( ) ;
42
49
}
43
50
44
- fn write_min ( & mut self , slice : & [ u8 ] , minslice : & [ u8 ] ) ;
51
+ fn write_min ( & mut self , slice : & [ u8 ] , min : u8 ) ;
45
52
46
53
fn new_line ( & mut self ) { }
47
54
48
55
fn indent ( & mut self ) { }
49
56
50
57
fn dedent ( & mut self ) { }
51
58
59
+ #[ inline( never) ]
52
60
fn write_string_complex ( & mut self , string : & str , mut start : usize ) {
61
+ self . write ( string[ .. start] . as_bytes ( ) ) ;
62
+
53
63
for ( index, ch) in string. bytes ( ) . enumerate ( ) . skip ( start) {
54
64
let escape = ESCAPED [ ch as usize ] ;
55
65
if escape > 0 {
56
66
self . write ( string[ start .. index] . as_bytes ( ) ) ;
57
67
self . write ( & [ b'\\' , escape] ) ;
58
68
start = index + 1 ;
59
69
}
70
+ if escape == b'u' {
71
+ write ! ( self . get_writer( ) , "{:04x}" , ch) . unwrap ( ) ;
72
+ }
60
73
}
61
74
self . write ( string[ start ..] . as_bytes ( ) ) ;
62
75
63
76
self . write_char ( b'"' ) ;
64
77
}
65
78
79
+ #[ inline( always) ]
66
80
fn write_string ( & mut self , string : & str ) {
67
81
self . write_char ( b'"' ) ;
68
82
@@ -76,42 +90,33 @@ pub trait Generator {
76
90
self . write_char ( b'"' ) ;
77
91
}
78
92
79
- fn write_number ( & mut self , mut num : f64 ) {
93
+ fn write_number ( & mut self , num : f64 ) {
80
94
match num. classify ( ) {
81
- FpCategory :: Nan |
82
- FpCategory :: Infinite => {
83
- self . write ( b"null" ) ;
84
- return ;
95
+ FpCategory :: Normal |
96
+ FpCategory :: Subnormal => {
97
+ if num. fract ( ) == 0.0 && num. abs ( ) < 1e19 {
98
+ itoa:: write ( self . get_writer ( ) , num as i64 ) . unwrap ( ) ;
99
+ } else {
100
+ let abs = num. abs ( ) ;
101
+ if abs < 1e-15 || abs > 1e19 {
102
+ write ! ( self . get_writer( ) , "{:e}" , num) . unwrap ( ) ;
103
+ } else {
104
+ write ! ( self . get_writer( ) , "{}" , num) . unwrap ( ) ;
105
+ }
106
+ }
85
107
} ,
86
108
FpCategory :: Zero => {
87
- self . write ( if num. is_sign_negative ( ) { b"-0" } else { b"0" } ) ;
88
- return ;
109
+ if num. is_sign_negative ( ) {
110
+ self . write ( b"-0" ) ;
111
+ } else {
112
+ self . write_char ( b'0' ) ;
113
+ }
89
114
} ,
90
- _ => { } ,
91
- }
92
-
93
- if num. is_sign_negative ( ) {
94
- num = num. abs ( ) ;
95
- self . write_char ( b'-' ) ;
96
- }
97
-
98
- let fract = num. fract ( ) ;
99
-
100
- if fract > 0.0 {
101
- if num < 1e-15 {
102
- write ! ( self . get_buffer( ) , "{:e}" , num) . unwrap ( ) ;
103
- } else {
104
- write ! ( self . get_buffer( ) , "{}" , num) . unwrap ( ) ;
115
+ FpCategory :: Nan |
116
+ FpCategory :: Infinite => {
117
+ self . write ( b"null" ) ;
105
118
}
106
- return ;
107
- }
108
-
109
- if num > 1e19 {
110
- write ! ( self . get_buffer( ) , "{:e}" , num) . unwrap ( ) ;
111
- return ;
112
119
}
113
-
114
- itoa:: write ( self . get_buffer ( ) , num as u64 ) . unwrap ( ) ;
115
120
}
116
121
117
122
fn write_json ( & mut self , json : & JsonValue ) {
@@ -130,7 +135,7 @@ pub trait Generator {
130
135
first = false ;
131
136
self . new_line ( ) ;
132
137
} else {
133
- self . write ( b"," ) ;
138
+ self . write_char ( b',' ) ;
134
139
self . new_line ( ) ;
135
140
}
136
141
self . write_json ( item) ;
@@ -148,11 +153,11 @@ pub trait Generator {
148
153
first = false ;
149
154
self . new_line ( ) ;
150
155
} else {
151
- self . write ( b"," ) ;
156
+ self . write_char ( b',' ) ;
152
157
self . new_line ( ) ;
153
158
}
154
159
self . write_string ( key) ;
155
- self . write_min ( b": " , b":" ) ;
160
+ self . write_min ( b": " , b':' ) ;
156
161
self . write_json ( value) ;
157
162
}
158
163
self . dedent ( ) ;
@@ -161,8 +166,6 @@ pub trait Generator {
161
166
}
162
167
}
163
168
}
164
-
165
- fn consume ( self ) -> String ;
166
169
}
167
170
168
171
pub struct DumpGenerator {
@@ -175,21 +178,35 @@ impl DumpGenerator {
175
178
code : Vec :: with_capacity ( 1024 ) ,
176
179
}
177
180
}
181
+
182
+ pub fn consume ( self ) -> String {
183
+ // Original strings were unicode, numbers are all ASCII,
184
+ // therefore this is safe.
185
+ unsafe { String :: from_utf8_unchecked ( self . code ) }
186
+ }
178
187
}
179
188
180
189
impl Generator for DumpGenerator {
190
+ type T = Vec < u8 > ;
191
+
181
192
#[ inline( always) ]
182
- fn get_buffer ( & mut self ) -> & mut Vec < u8 > {
183
- & mut self . code
193
+ fn write ( & mut self , slice : & [ u8 ] ) {
194
+ self . code . extend_from_slice ( slice )
184
195
}
185
196
186
197
#[ inline( always) ]
187
- fn write_min ( & mut self , _: & [ u8 ] , minslice : & [ u8 ] ) {
188
- self . code . extend_from_slice ( minslice) ;
198
+ fn write_char ( & mut self , ch : u8 ) {
199
+ self . code . push ( ch)
200
+ }
201
+
202
+ #[ inline( always) ]
203
+ fn get_writer ( & mut self ) -> & mut Vec < u8 > {
204
+ & mut self . code
189
205
}
190
206
191
- fn consume ( self ) -> String {
192
- String :: from_utf8 ( self . code ) . unwrap ( )
207
+ #[ inline( always) ]
208
+ fn write_min ( & mut self , _: & [ u8 ] , min : u8 ) {
209
+ self . code . push ( min) ;
193
210
}
194
211
}
195
212
@@ -207,16 +224,32 @@ impl PrettyGenerator {
207
224
spaces_per_indent : spaces
208
225
}
209
226
}
227
+
228
+ pub fn consume ( self ) -> String {
229
+ unsafe { String :: from_utf8_unchecked ( self . code ) }
230
+ }
210
231
}
211
232
212
233
impl Generator for PrettyGenerator {
234
+ type T = Vec < u8 > ;
235
+
213
236
#[ inline( always) ]
214
- fn get_buffer ( & mut self ) -> & mut Vec < u8 > {
237
+ fn write ( & mut self , slice : & [ u8 ] ) {
238
+ self . code . extend_from_slice ( slice)
239
+ }
240
+
241
+ #[ inline( always) ]
242
+ fn write_char ( & mut self , ch : u8 ) {
243
+ self . code . push ( ch)
244
+ }
245
+
246
+ #[ inline( always) ]
247
+ fn get_writer ( & mut self ) -> & mut Vec < u8 > {
215
248
& mut self . code
216
249
}
217
250
218
251
#[ inline( always) ]
219
- fn write_min ( & mut self , slice : & [ u8 ] , _: & [ u8 ] ) {
252
+ fn write_min ( & mut self , slice : & [ u8 ] , _: u8 ) {
220
253
self . code . extend_from_slice ( slice) ;
221
254
}
222
255
@@ -234,8 +267,30 @@ impl Generator for PrettyGenerator {
234
267
fn dedent ( & mut self ) {
235
268
self . dent -= 1 ;
236
269
}
270
+ }
271
+
272
+ pub struct WriterGenerator < ' a , W : ' a + Write > {
273
+ writer : & ' a mut W
274
+ }
275
+
276
+ impl < ' a , W > WriterGenerator < ' a , W > where W : ' a + Write {
277
+ pub fn new ( writer : & ' a mut W ) -> Self {
278
+ WriterGenerator {
279
+ writer : writer
280
+ }
281
+ }
282
+ }
237
283
238
- fn consume ( self ) -> String {
239
- String :: from_utf8 ( self . code ) . unwrap ( )
284
+ impl < ' a , W > Generator for WriterGenerator < ' a , W > where W : Write {
285
+ type T = W ;
286
+
287
+ #[ inline( always) ]
288
+ fn get_writer ( & mut self ) -> & mut W {
289
+ & mut self . writer
290
+ }
291
+
292
+ #[ inline( always) ]
293
+ fn write_min ( & mut self , _: & [ u8 ] , min : u8 ) {
294
+ self . writer . write_all ( & [ min] ) . unwrap ( ) ;
240
295
}
241
296
}
0 commit comments