@@ -4,65 +4,79 @@ use JsonValue;
44
55extern crate itoa;
66
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+
716static ESCAPED : [ u8 ; 256 ] = [
817// 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
2534] ;
2635
2736pub trait Generator {
28- fn get_buffer ( & mut self ) -> & mut Vec < u8 > ;
37+ type T : Write ;
2938
30- fn current_index ( & mut self ) -> usize {
31- self . get_buffer ( ) . len ( )
32- }
39+ fn get_writer ( & mut self ) -> & mut Self :: T ;
3340
3441 #[ inline( always) ]
3542 fn write ( & mut self , slice : & [ u8 ] ) {
36- self . get_buffer ( ) . extend_from_slice ( slice)
43+ self . get_writer ( ) . write_all ( slice) . unwrap ( ) ;
3744 }
3845
3946 #[ inline( always) ]
4047 fn write_char ( & mut self , ch : u8 ) {
41- self . get_buffer ( ) . push ( ch )
48+ self . get_writer ( ) . write_all ( & [ ch ] ) . unwrap ( ) ;
4249 }
4350
44- fn write_min ( & mut self , slice : & [ u8 ] , minslice : & [ u8 ] ) ;
51+ fn write_min ( & mut self , slice : & [ u8 ] , min : u8 ) ;
4552
4653 fn new_line ( & mut self ) { }
4754
4855 fn indent ( & mut self ) { }
4956
5057 fn dedent ( & mut self ) { }
5158
59+ #[ inline( never) ]
5260 fn write_string_complex ( & mut self , string : & str , mut start : usize ) {
61+ self . write ( string[ .. start] . as_bytes ( ) ) ;
62+
5363 for ( index, ch) in string. bytes ( ) . enumerate ( ) . skip ( start) {
5464 let escape = ESCAPED [ ch as usize ] ;
5565 if escape > 0 {
5666 self . write ( string[ start .. index] . as_bytes ( ) ) ;
5767 self . write ( & [ b'\\' , escape] ) ;
5868 start = index + 1 ;
5969 }
70+ if escape == b'u' {
71+ write ! ( self . get_writer( ) , "{:04x}" , ch) . unwrap ( ) ;
72+ }
6073 }
6174 self . write ( string[ start ..] . as_bytes ( ) ) ;
6275
6376 self . write_char ( b'"' ) ;
6477 }
6578
79+ #[ inline( always) ]
6680 fn write_string ( & mut self , string : & str ) {
6781 self . write_char ( b'"' ) ;
6882
@@ -76,42 +90,33 @@ pub trait Generator {
7690 self . write_char ( b'"' ) ;
7791 }
7892
79- fn write_number ( & mut self , mut num : f64 ) {
93+ fn write_number ( & mut self , num : f64 ) {
8094 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+ }
85107 } ,
86108 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+ }
89114 } ,
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" ) ;
105118 }
106- return ;
107- }
108-
109- if num > 1e19 {
110- write ! ( self . get_buffer( ) , "{:e}" , num) . unwrap ( ) ;
111- return ;
112119 }
113-
114- itoa:: write ( self . get_buffer ( ) , num as u64 ) . unwrap ( ) ;
115120 }
116121
117122 fn write_json ( & mut self , json : & JsonValue ) {
@@ -130,7 +135,7 @@ pub trait Generator {
130135 first = false ;
131136 self . new_line ( ) ;
132137 } else {
133- self . write ( b"," ) ;
138+ self . write_char ( b',' ) ;
134139 self . new_line ( ) ;
135140 }
136141 self . write_json ( item) ;
@@ -148,11 +153,11 @@ pub trait Generator {
148153 first = false ;
149154 self . new_line ( ) ;
150155 } else {
151- self . write ( b"," ) ;
156+ self . write_char ( b',' ) ;
152157 self . new_line ( ) ;
153158 }
154159 self . write_string ( key) ;
155- self . write_min ( b": " , b":" ) ;
160+ self . write_min ( b": " , b':' ) ;
156161 self . write_json ( value) ;
157162 }
158163 self . dedent ( ) ;
@@ -161,8 +166,6 @@ pub trait Generator {
161166 }
162167 }
163168 }
164-
165- fn consume ( self ) -> String ;
166169}
167170
168171pub struct DumpGenerator {
@@ -175,21 +178,35 @@ impl DumpGenerator {
175178 code : Vec :: with_capacity ( 1024 ) ,
176179 }
177180 }
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+ }
178187}
179188
180189impl Generator for DumpGenerator {
190+ type T = Vec < u8 > ;
191+
181192 #[ 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 )
184195 }
185196
186197 #[ 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
189205 }
190206
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) ;
193210 }
194211}
195212
@@ -207,16 +224,32 @@ impl PrettyGenerator {
207224 spaces_per_indent : spaces
208225 }
209226 }
227+
228+ pub fn consume ( self ) -> String {
229+ unsafe { String :: from_utf8_unchecked ( self . code ) }
230+ }
210231}
211232
212233impl Generator for PrettyGenerator {
234+ type T = Vec < u8 > ;
235+
213236 #[ 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 > {
215248 & mut self . code
216249 }
217250
218251 #[ inline( always) ]
219- fn write_min ( & mut self , slice : & [ u8 ] , _: & [ u8 ] ) {
252+ fn write_min ( & mut self , slice : & [ u8 ] , _: u8 ) {
220253 self . code . extend_from_slice ( slice) ;
221254 }
222255
@@ -234,8 +267,30 @@ impl Generator for PrettyGenerator {
234267 fn dedent ( & mut self ) {
235268 self . dent -= 1 ;
236269 }
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+ }
237283
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 ( ) ;
240295 }
241296}
0 commit comments