@@ -71,9 +71,6 @@ pub enum Error {
71
71
/// Invalid String Escape Sequence
72
72
InvalidEscapeSequence ,
73
73
74
- /// Unescaping and Escaped String requires a buffer
75
- EscapedStringRequiresBuffer ,
76
-
77
74
/// Escaped String length exceeds buffer size
78
75
EscapedStringIsTooLong ,
79
76
@@ -102,12 +99,16 @@ impl serde::de::StdError for Error {}
102
99
pub struct Deserializer < ' b , ' s > {
103
100
slice : & ' b [ u8 ] ,
104
101
index : usize ,
105
- string_unescape_buffer : & ' s mut [ u8 ] ,
102
+ string_unescape_buffer : Option < & ' s mut [ u8 ] > ,
106
103
}
107
104
108
105
impl < ' a , ' s > Deserializer < ' a , ' s > {
109
- /// Create a new `Deserializer`
110
- pub fn new ( slice : & ' a [ u8 ] , string_unescape_buffer : & ' s mut [ u8 ] ) -> Deserializer < ' a , ' s > {
106
+ /// Create a new `Deserializer`, optionally with a buffer to use to unescape strings.
107
+ /// If not present, strings are not unescaped.
108
+ pub fn new (
109
+ slice : & ' a [ u8 ] ,
110
+ string_unescape_buffer : Option < & ' s mut [ u8 ] > ,
111
+ ) -> Deserializer < ' a , ' s > {
111
112
Deserializer {
112
113
slice,
113
114
index : 0 ,
@@ -193,6 +194,12 @@ impl<'a, 's> Deserializer<'a, 's> {
193
194
}
194
195
195
196
fn parse_str ( & mut self ) -> Result < & ' a str > {
197
+ if self . parse_whitespace ( ) . ok_or ( Error :: EofWhileParsingValue ) ? == b'"' {
198
+ self . eat_char ( ) ;
199
+ } else {
200
+ return Err ( Error :: InvalidType ) ;
201
+ }
202
+
196
203
let start = self . index ;
197
204
loop {
198
205
match self . peek ( ) {
@@ -478,97 +485,89 @@ impl<'a, 'de, 's> de::Deserializer<'de> for &'a mut Deserializer<'de, 's> {
478
485
where
479
486
V : Visitor < ' de > ,
480
487
{
481
- let peek = self . parse_whitespace ( ) . ok_or ( Error :: EofWhileParsingValue ) ?;
488
+ let s = self . parse_str ( ) ?;
482
489
483
- match peek {
484
- b'"' => {
485
- self . eat_char ( ) ;
490
+ if let Some ( string_unescape_buffer ) = self . string_unescape_buffer . as_deref_mut ( ) {
491
+ if s . as_bytes ( ) . contains ( & b'\\' ) {
492
+ let mut string_unescape_buffer_slots = string_unescape_buffer . iter_mut ( ) ;
486
493
487
- let s = self . parse_str ( ) ?;
488
-
489
- if s. as_bytes ( ) . contains ( & b'\\' ) {
490
- let mut string_unescape_buffer_slots = self . string_unescape_buffer . iter_mut ( ) ;
491
-
492
- // We've already checked that the string is valid UTF-8, so the only b'\\' is the start of escape sequence
493
- let mut escaped_string_bytes = s. as_bytes ( ) . iter ( ) ;
494
-
495
- loop {
496
- match escaped_string_bytes. next ( ) . copied ( ) {
497
- None => break ,
498
- Some ( b'\\' ) => {
499
- let unescaped_byte = match escaped_string_bytes. next ( ) {
500
- Some ( b'"' ) => b'"' ,
501
- Some ( b'\\' ) => b'\\' ,
502
- Some ( b'/' ) => b'/' ,
503
- Some ( b'b' ) => 0x8 ,
504
- Some ( b'f' ) => 0xC ,
505
- Some ( b'n' ) => b'\n' ,
506
- Some ( b'r' ) => b'\r' ,
507
- Some ( b't' ) => b'\t' ,
508
- Some ( b'u' ) => {
509
- // TODO - Replace with `<[u8]>::split_first_chunk::<4>` once MSRV >= 1.77
510
- fn split_first_slice (
511
- bytes : & [ u8 ] ,
512
- len : usize ,
513
- ) -> Option < ( & [ u8 ] , & [ u8 ] ) >
514
- {
515
- Some ( ( bytes. get ( ..len) ?, bytes. get ( len..) ?) )
516
- }
517
-
518
- let ( escape_sequence, remaining_escaped_string_bytes) =
519
- split_first_slice ( escaped_string_bytes. as_slice ( ) , 4 )
520
- . ok_or ( Error :: InvalidEscapeSequence ) ?;
521
-
522
- escaped_string_bytes =
523
- remaining_escaped_string_bytes. iter ( ) ;
524
-
525
- let unescaped_char = core:: str:: from_utf8 ( escape_sequence)
526
- . ok ( )
527
- . and_then ( |escape_sequence| {
528
- u32:: from_str_radix ( escape_sequence, 16 ) . ok ( )
529
- } )
530
- . and_then ( char:: from_u32)
531
- . ok_or ( Error :: InvalidEscapeSequence ) ?;
494
+ // We've already checked that the string is valid UTF-8, so the only b'\\' is the start of escape sequence
495
+ let mut escaped_string_bytes = s. as_bytes ( ) . iter ( ) ;
496
+
497
+ loop {
498
+ match escaped_string_bytes. next ( ) . copied ( ) {
499
+ None => break ,
500
+ Some ( b'\\' ) => {
501
+ let unescaped_byte = match escaped_string_bytes. next ( ) {
502
+ Some ( b'"' ) => b'"' ,
503
+ Some ( b'\\' ) => b'\\' ,
504
+ Some ( b'/' ) => b'/' ,
505
+ Some ( b'b' ) => 0x8 ,
506
+ Some ( b'f' ) => 0xC ,
507
+ Some ( b'n' ) => b'\n' ,
508
+ Some ( b'r' ) => b'\r' ,
509
+ Some ( b't' ) => b'\t' ,
510
+ Some ( b'u' ) => {
511
+ // TODO - Replace with `<[u8]>::split_first_chunk::<4>` once MSRV >= 1.77
512
+ fn split_first_slice (
513
+ bytes : & [ u8 ] ,
514
+ len : usize ,
515
+ ) -> Option < ( & [ u8 ] , & [ u8 ] ) >
516
+ {
517
+ Some ( ( bytes. get ( ..len) ?, bytes. get ( len..) ?) )
518
+ }
532
519
533
- for & unescaped_byte in
534
- unescaped_char. encode_utf8 ( & mut [ 0 ; 4 ] ) . as_bytes ( )
535
- {
536
- * string_unescape_buffer_slots
537
- . next ( )
538
- . ok_or ( Error :: EscapedStringIsTooLong ) ? =
539
- unescaped_byte;
540
- }
520
+ let ( escape_sequence, remaining_escaped_string_bytes) =
521
+ split_first_slice ( escaped_string_bytes. as_slice ( ) , 4 )
522
+ . ok_or ( Error :: InvalidEscapeSequence ) ?;
541
523
542
- continue ;
524
+ escaped_string_bytes = remaining_escaped_string_bytes. iter ( ) ;
525
+
526
+ let unescaped_char = core:: str:: from_utf8 ( escape_sequence)
527
+ . ok ( )
528
+ . and_then ( |escape_sequence| {
529
+ u32:: from_str_radix ( escape_sequence, 16 ) . ok ( )
530
+ } )
531
+ . and_then ( char:: from_u32)
532
+ . ok_or ( Error :: InvalidEscapeSequence ) ?;
533
+
534
+ for & unescaped_byte in
535
+ unescaped_char. encode_utf8 ( & mut [ 0 ; 4 ] ) . as_bytes ( )
536
+ {
537
+ * string_unescape_buffer_slots
538
+ . next ( )
539
+ . ok_or ( Error :: EscapedStringIsTooLong ) ? = unescaped_byte;
543
540
}
544
- _ => return Err ( Error :: InvalidEscapeSequence ) ,
545
- } ;
546
541
547
- * string_unescape_buffer_slots
548
- . next ( )
549
- . ok_or ( Error :: EscapedStringIsTooLong ) ? = unescaped_byte;
550
- }
551
- Some ( c) => {
552
- * string_unescape_buffer_slots
553
- . next ( )
554
- . ok_or ( Error :: EscapedStringIsTooLong ) ? = c;
555
- }
542
+ continue ;
543
+ }
544
+ _ => return Err ( Error :: InvalidEscapeSequence ) ,
545
+ } ;
546
+
547
+ * string_unescape_buffer_slots
548
+ . next ( )
549
+ . ok_or ( Error :: EscapedStringIsTooLong ) ? = unescaped_byte;
550
+ }
551
+ Some ( c) => {
552
+ * string_unescape_buffer_slots
553
+ . next ( )
554
+ . ok_or ( Error :: EscapedStringIsTooLong ) ? = c;
556
555
}
557
556
}
557
+ }
558
558
559
- let remaining_length = string_unescape_buffer_slots. len ( ) ;
560
- let unescaped_string_length =
561
- self . string_unescape_buffer . len ( ) - remaining_length;
559
+ let remaining_length = string_unescape_buffer_slots. len ( ) ;
560
+ let unescaped_string_length = string_unescape_buffer. len ( ) - remaining_length;
562
561
563
- visitor. visit_str (
564
- str:: from_utf8 ( & self . string_unescape_buffer [ ..unescaped_string_length] )
565
- . map_err ( |_| Error :: InvalidUnicodeCodePoint ) ?,
566
- )
567
- } else {
568
- visitor. visit_borrowed_str ( s)
569
- }
562
+ visitor. visit_str (
563
+ str:: from_utf8 ( & string_unescape_buffer[ ..unescaped_string_length] )
564
+ . map_err ( |_| Error :: InvalidUnicodeCodePoint ) ?,
565
+ )
566
+ } else {
567
+ visitor. visit_borrowed_str ( s)
570
568
}
571
- _ => Err ( Error :: InvalidType ) ,
569
+ } else {
570
+ visitor. visit_borrowed_str ( s)
572
571
}
573
572
}
574
573
@@ -839,11 +838,9 @@ impl fmt::Display for Error {
839
838
}
840
839
}
841
840
842
- /// Deserializes an instance of type `T` from bytes of JSON text, using the provided buffer to unescape strings
843
- /// Returns the value and the number of bytes consumed in the process
844
- pub fn from_slice_escaped < ' a , T > (
841
+ fn from_slice_maybe_escaped < ' a , T > (
845
842
v : & ' a [ u8 ] ,
846
- string_unescape_buffer : & mut [ u8 ] ,
843
+ string_unescape_buffer : Option < & mut [ u8 ] > ,
847
844
) -> Result < ( T , usize ) >
848
845
where
849
846
T : de:: Deserialize < ' a > ,
@@ -855,19 +852,25 @@ where
855
852
Ok ( ( value, length) )
856
853
}
857
854
855
+ /// Deserializes an instance of type `T` from bytes of JSON text, using the provided buffer to unescape strings
856
+ /// Returns the value and the number of bytes consumed in the process
857
+ pub fn from_slice_escaped < ' a , T > (
858
+ v : & ' a [ u8 ] ,
859
+ string_unescape_buffer : & mut [ u8 ] ,
860
+ ) -> Result < ( T , usize ) >
861
+ where
862
+ T : de:: Deserialize < ' a > ,
863
+ {
864
+ from_slice_maybe_escaped ( v, Some ( string_unescape_buffer) )
865
+ }
866
+
858
867
/// Deserializes an instance of type `T` from bytes of JSON text
859
868
/// Returns the value and the number of bytes consumed in the process
860
869
pub fn from_slice < ' a , T > ( v : & ' a [ u8 ] ) -> Result < ( T , usize ) >
861
870
where
862
871
T : de:: Deserialize < ' a > ,
863
872
{
864
- from_slice_escaped ( v, & mut [ ] ) . map_err ( |error| {
865
- if let Error :: EscapedStringIsTooLong = error {
866
- Error :: EscapedStringRequiresBuffer
867
- } else {
868
- error
869
- }
870
- } )
873
+ from_slice_maybe_escaped ( v, None )
871
874
}
872
875
873
876
/// Deserializes an instance of type T from a string of JSON text, using the provided buffer to unescape strings
0 commit comments