@@ -128,15 +128,13 @@ pub trait BaseGenerator {
128128 #[ inline]
129129 fn write_string_content ( & mut self , string : & str ) -> io:: Result < ( ) > {
130130 let mut string = string. as_bytes ( ) ;
131-
132131 unsafe {
133132 // Looking at the table above the lower 5 bits are entirely
134133 // quote characters that gives us a bitmask of 0x1f for that
135134 // region, only quote (`"`) and backslash (`\`) are not in
136135 // this range.
137136 stry ! ( self . write_str_simd( & mut string) ) ;
138137 }
139-
140138 write_string_rust ( self . get_writer ( ) , & mut string)
141139 }
142140
@@ -238,7 +236,9 @@ pub trait BaseGenerator {
238236 /// # Errors
239237 /// if the write fails
240238 unsafe fn write_str_simd ( & mut self , string : & mut & [ u8 ] ) -> io:: Result < ( ) > {
241- self . write_simple_string ( std:: str:: from_utf8_unchecked ( string) )
239+ write_string_rust ( self . get_writer ( ) , string) ?;
240+ * string = & string[ string. len ( ) ..] ;
241+ Ok ( ( ) )
242242 }
243243
244244 #[ cfg( target_arch = "aarch64" ) ]
@@ -257,57 +257,63 @@ pub trait BaseGenerator {
257257
258258 #[ inline]
259259 unsafe fn bit_mask ( ) -> uint8x16_t {
260- mem:: transmute ( [
261- 0x01_u8 , 0x02 , 0x4 , 0x8 , 0x10 , 0x20 , 0x40 , 0x80 , 0x01 , 0x02 , 0x4 , 0x8 , 0x10 , 0x20 ,
262- 0x40 , 0x80 ,
263- ] )
260+ unsafe {
261+ mem:: transmute ( [
262+ 0x01_u8 , 0x02 , 0x4 , 0x8 , 0x10 , 0x20 , 0x40 , 0x80 , 0x01 , 0x02 , 0x4 , 0x8 , 0x10 ,
263+ 0x20 , 0x40 , 0x80 ,
264+ ] )
265+ }
264266 }
265267
266268 #[ inline]
267269 unsafe fn neon_movemask ( input : uint8x16_t ) -> u16 {
268- let simd_input: uint8x16_t = vandq_u8 ( input, bit_mask ( ) ) ;
269- let tmp: uint8x16_t = vpaddq_u8 ( simd_input, simd_input) ;
270- let tmp = vpaddq_u8 ( tmp, tmp) ;
271- let tmp = vpaddq_u8 ( tmp, tmp) ;
270+ unsafe {
271+ let simd_input: uint8x16_t = vandq_u8 ( input, bit_mask ( ) ) ;
272+ let tmp: uint8x16_t = vpaddq_u8 ( simd_input, simd_input) ;
273+ let tmp = vpaddq_u8 ( tmp, tmp) ;
274+ let tmp = vpaddq_u8 ( tmp, tmp) ;
272275
273- vgetq_lane_u16 ( vreinterpretq_u16_u8 ( tmp) , 0 )
276+ vgetq_lane_u16 ( vreinterpretq_u16_u8 ( tmp) , 0 )
277+ }
274278 }
275279
276280 let writer = self . get_writer ( ) ;
277281 // The case where we have a 16+ byte block
278282 // we repeate the same logic as above but with
279283 // only 16 bytes
280284 let mut idx = 0 ;
281- let zero = vdupq_n_u8 ( 0 ) ;
282- let lower_quote_range = vdupq_n_u8 ( 0x1F ) ;
283- let quote = vdupq_n_u8 ( b'"' ) ;
284- let backslash = vdupq_n_u8 ( b'\\' ) ;
285- while string. len ( ) - idx > 16 {
286- // Load 16 bytes of data;
287- let data: uint8x16_t = vld1q_u8 ( string. as_ptr ( ) . add ( idx) ) ;
288- // Test the data against being backslash and quote.
289- let bs_or_quote = vorrq_u8 ( vceqq_u8 ( data, backslash) , vceqq_u8 ( data, quote) ) ;
290- // Now mask the data with the quote range (0x1F).
291- let in_quote_range = vandq_u8 ( data, lower_quote_range) ;
292- // then test of the data is unchanged. aka: xor it with the
293- // Any field that was inside the quote range it will be zero
294- // now.
295- let is_unchanged = veorq_u8 ( data, in_quote_range) ;
296- let in_range = vceqq_u8 ( is_unchanged, zero) ;
297- let quote_bits = neon_movemask ( vorrq_u8 ( bs_or_quote, in_range) ) ;
298- if quote_bits == 0 {
299- idx += 16 ;
300- } else {
301- let quote_dist = quote_bits. trailing_zeros ( ) as usize ;
302- stry ! ( writer. write_all( & string[ 0 ..idx + quote_dist] ) ) ;
303- let ch = string[ idx + quote_dist] ;
304- match ESCAPED [ ch as usize ] {
305- b'u' => stry ! ( u_encode( writer, ch) ) ,
306- escape => stry ! ( writer. write_all( & [ b'\\' , escape] ) ) ,
285+ unsafe {
286+ let zero = vdupq_n_u8 ( 0 ) ;
287+ let lower_quote_range = vdupq_n_u8 ( 0x1F ) ;
288+ let quote = vdupq_n_u8 ( b'"' ) ;
289+ let backslash = vdupq_n_u8 ( b'\\' ) ;
290+ while string. len ( ) - idx > 16 {
291+ // Load 16 bytes of data;
292+ let data: uint8x16_t = vld1q_u8 ( string. as_ptr ( ) . add ( idx) ) ;
293+ // Test the data against being backslash and quote.
294+ let bs_or_quote = vorrq_u8 ( vceqq_u8 ( data, backslash) , vceqq_u8 ( data, quote) ) ;
295+ // Now mask the data with the quote range (0x1F).
296+ let in_quote_range = vandq_u8 ( data, lower_quote_range) ;
297+ // then test of the data is unchanged. aka: xor it with the
298+ // Any field that was inside the quote range it will be zero
299+ // now.
300+ let is_unchanged = veorq_u8 ( data, in_quote_range) ;
301+ let in_range = vceqq_u8 ( is_unchanged, zero) ;
302+ let quote_bits = neon_movemask ( vorrq_u8 ( bs_or_quote, in_range) ) ;
303+ if quote_bits == 0 {
304+ idx += 16 ;
305+ } else {
306+ let quote_dist = quote_bits. trailing_zeros ( ) as usize ;
307+ stry ! ( writer. write_all( & string[ 0 ..idx + quote_dist] ) ) ;
308+ let ch = string[ idx + quote_dist] ;
309+ match ESCAPED [ ch as usize ] {
310+ b'u' => stry ! ( u_encode( writer, ch) ) ,
311+ escape => stry ! ( writer. write_all( & [ b'\\' , escape] ) ) ,
312+ }
313+
314+ * string = & string[ idx + quote_dist + 1 ..] ;
315+ idx = 0 ;
307316 }
308-
309- * string = & string[ idx + quote_dist + 1 ..] ;
310- idx = 0 ;
311317 }
312318 }
313319 stry ! ( writer. write_all( & string[ 0 ..idx] ) ) ;
@@ -414,11 +420,9 @@ where
414420 write_str_simd_sse42 ( writer, string)
415421 } else {
416422 #[ cfg( not( feature = "portable" ) ) ]
417- let r = write_string_rust ( writer, string) ;
423+ return write_string_rust ( writer, string) ;
418424 #[ cfg( feature = "portable" ) ]
419- let r = write_str_simd_portable ( writer, string) ;
420-
421- r
425+ return write_str_simd_portable ( writer, string) ;
422426 }
423427}
424428#[ inline]
@@ -468,7 +472,7 @@ unsafe fn write_str_simd_portable<W>(writer: &mut W, string: &mut &[u8]) -> io::
468472where
469473 W : Write ,
470474{
471- use std:: simd:: { u8x32 , SimdPartialEq , ToBitMask } ;
475+ use std:: simd:: { SimdPartialEq , ToBitMask , u8x32 } ;
472476
473477 let mut idx = 0 ;
474478 let zero = u8x32:: splat ( 0 ) ;
@@ -781,7 +785,7 @@ where
781785 }
782786}
783787
784- impl < ' w , W > BaseGenerator for WriterGenerator < ' w , W >
788+ impl < W > BaseGenerator for WriterGenerator < ' _ , W >
785789where
786790 W : Write ,
787791{
@@ -799,7 +803,6 @@ where
799803}
800804
801805/// Pretty Writer Generator
802-
803806pub struct PrettyWriterGenerator < ' w , W >
804807where
805808 W : ' w + Write ,
@@ -823,7 +826,7 @@ where
823826 }
824827}
825828
826- impl < ' w , W > BaseGenerator for PrettyWriterGenerator < ' w , W >
829+ impl < W > BaseGenerator for PrettyWriterGenerator < ' _ , W >
827830where
828831 W : Write ,
829832{
@@ -873,3 +876,22 @@ pub(crate) fn extend_from_slice(dst: &mut Vec<u8>, src: &[u8]) {
873876 dst. set_len ( dst_len + src_len) ;
874877 }
875878}
879+
880+ #[ cfg( test) ]
881+ mod tests {
882+
883+ #[ test]
884+ fn test_write_string_rust ( ) {
885+ let mut writer = Vec :: new ( ) ;
886+ let mut string = "Hello, World!" . as_bytes ( ) ;
887+ super :: write_string_rust ( & mut writer, & mut string) . expect ( "failed to write string" ) ;
888+ assert_eq ! ( writer, "Hello, World!" . as_bytes( ) ) ;
889+ }
890+ #[ test]
891+ fn test_write_string_rust2 ( ) {
892+ let mut writer = Vec :: new ( ) ;
893+ let mut string = "Hello, \" World!\" " . as_bytes ( ) ;
894+ super :: write_string_rust ( & mut writer, & mut string) . expect ( "failed to write string" ) ;
895+ assert_eq ! ( writer, "Hello, \\ \" World!\\ \" " . as_bytes( ) ) ;
896+ }
897+ }
0 commit comments