@@ -15,6 +15,12 @@ use crate::util::{deserialize_optional_string_to_i64, deserialize_string_to_i64}
15
15
use super :: bucket_priority:: BucketPriority ;
16
16
use super :: Checksum ;
17
17
18
+ /// While we would like to always borrow strings for efficiency, that's not consistently possible.
19
+ /// With the JSON decoder, borrowing from input data is only possible when the string contains no
20
+ /// escape sequences (otherwise, the string is not a direct view of input data and we need an
21
+ /// internal copy).
22
+ type SyncLineStr < ' a > = Cow < ' a , str > ;
23
+
18
24
#[ derive( Deserialize , Debug ) ]
19
25
20
26
pub enum SyncLine < ' a > {
@@ -53,7 +59,7 @@ pub struct CheckpointDiff<'a> {
53
59
#[ serde( borrow) ]
54
60
pub updated_buckets : Vec < BucketChecksum < ' a > > ,
55
61
#[ serde( borrow) ]
56
- pub removed_buckets : Vec < & ' a str > ,
62
+ pub removed_buckets : Vec < SyncLineStr < ' a > > ,
57
63
#[ serde( default ) ]
58
64
#[ serde( deserialize_with = "deserialize_optional_string_to_i64" ) ]
59
65
pub write_checkpoint : Option < i64 > ,
@@ -74,7 +80,8 @@ pub struct CheckpointPartiallyComplete {
74
80
75
81
#[ derive( Deserialize , Debug ) ]
76
82
pub struct BucketChecksum < ' a > {
77
- pub bucket : & ' a str ,
83
+ #[ serde( borrow) ]
84
+ pub bucket : SyncLineStr < ' a > ,
78
85
pub checksum : Checksum ,
79
86
#[ serde( default ) ]
80
87
pub priority : Option < BucketPriority > ,
@@ -87,14 +94,15 @@ pub struct BucketChecksum<'a> {
87
94
88
95
#[ derive( Deserialize , Debug ) ]
89
96
pub struct DataLine < ' a > {
90
- pub bucket : & ' a str ,
97
+ #[ serde( borrow) ]
98
+ pub bucket : SyncLineStr < ' a > ,
91
99
pub data : Vec < OplogEntry < ' a > > ,
92
100
// #[serde(default)]
93
101
// pub has_more: bool,
94
102
// #[serde(default, borrow)]
95
- // pub after: Option<&'a str >,
103
+ // pub after: Option<SyncLineStr<'a> >,
96
104
// #[serde(default, borrow)]
97
- // pub next_after: Option<&'a str >,
105
+ // pub next_after: Option<SyncLineStr<'a> >,
98
106
}
99
107
100
108
#[ derive( Deserialize , Debug ) ]
@@ -104,11 +112,11 @@ pub struct OplogEntry<'a> {
104
112
pub op_id : i64 ,
105
113
pub op : OpType ,
106
114
#[ serde( default , borrow) ]
107
- pub object_id : Option < & ' a str > ,
115
+ pub object_id : Option < SyncLineStr < ' a > > ,
108
116
#[ serde( default , borrow) ]
109
- pub object_type : Option < & ' a str > ,
117
+ pub object_type : Option < SyncLineStr < ' a > > ,
110
118
#[ serde( default , borrow) ]
111
- pub subkey : Option < & ' a str > ,
119
+ pub subkey : Option < SyncLineStr < ' a > > ,
112
120
#[ serde( default , borrow) ]
113
121
pub data : Option < OplogData < ' a > > ,
114
122
}
@@ -367,6 +375,17 @@ mod tests {
367
375
assert_eq ! ( diff. removed_buckets. len( ) , 0 ) ;
368
376
}
369
377
378
+ #[ test]
379
+ fn parse_checkpoint_diff_escape ( ) {
380
+ let SyncLine :: CheckpointDiff ( diff) = deserialize (
381
+ r#"{"checkpoint_diff": {"last_op_id": "10", "buckets": [], "updated_buckets": [], "removed_buckets": ["foo\""], "write_checkpoint": null}}"# ,
382
+ ) else {
383
+ panic ! ( "Expected checkpoint diff" )
384
+ } ;
385
+
386
+ assert_eq ! ( diff. removed_buckets[ 0 ] , "foo\" " ) ;
387
+ }
388
+
370
389
#[ test]
371
390
fn parse_checkpoint_diff_no_write_checkpoint ( ) {
372
391
let SyncLine :: CheckpointDiff ( diff) = deserialize (
0 commit comments