@@ -483,6 +483,14 @@ where
483
483
self . reader . next ( )
484
484
}
485
485
486
+ /// Returns the mark after which all events, skipped by [`Self::skip()`] call,
487
+ /// should be replayed after calling [`Self::start_replay()`].
488
+ #[ cfg( feature = "overlapped-lists" ) ]
489
+ #[ inline]
490
+ fn skip_checkpoint ( & self ) -> usize {
491
+ self . write . len ( )
492
+ }
493
+
486
494
/// Extracts XML tree of events from and stores them in the skipped events
487
495
/// buffer from which they can be retrieved later. You MUST call
488
496
/// [`Self::start_replay()`] after calling this to give access to the skipped
@@ -530,8 +538,8 @@ where
530
538
Ok ( ( ) )
531
539
}
532
540
533
- /// Moves all buffered events to the end of [`Self::write`] buffer and swaps
534
- /// read and write buffers .
541
+ /// Moves buffered events, skipped after given `checkpoint` from [`Self::write`]
542
+ /// skip buffer to [`Self::read`] buffer .
535
543
///
536
544
/// After calling this method, [`Self::peek()`] and [`Self::next()`] starts
537
545
/// return events that was skipped previously by calling [`Self::skip()`],
@@ -541,9 +549,15 @@ where
541
549
/// This method MUST be called if any number of [`Self::skip()`] was called
542
550
/// after [`Self::new()`] or `start_replay()` or you'll lost events.
543
551
#[ cfg( feature = "overlapped-lists" ) ]
544
- fn start_replay ( & mut self ) {
545
- self . write . append ( & mut self . read ) ;
546
- std:: mem:: swap ( & mut self . read , & mut self . write ) ;
552
+ fn start_replay ( & mut self , checkpoint : usize ) {
553
+ if checkpoint == 0 {
554
+ self . write . append ( & mut self . read ) ;
555
+ std:: mem:: swap ( & mut self . read , & mut self . write ) ;
556
+ } else {
557
+ let mut read = self . write . split_off ( checkpoint) ;
558
+ read. append ( & mut self . read ) ;
559
+ self . read = read;
560
+ }
547
561
}
548
562
549
563
fn next_start ( & mut self ) -> Result < Option < BytesStart < ' de > > , DeError > {
@@ -828,10 +842,7 @@ where
828
842
where
829
843
V : Visitor < ' de > ,
830
844
{
831
- let seq = visitor. visit_seq ( seq:: TopLevelSeqAccess :: new ( self ) ?) ;
832
- #[ cfg( feature = "overlapped-lists" ) ]
833
- self . start_replay ( ) ;
834
- seq
845
+ visitor. visit_seq ( seq:: TopLevelSeqAccess :: new ( self ) ?)
835
846
}
836
847
837
848
fn deserialize_map < V > ( self , visitor : V ) -> Result < V :: Value , DeError >
@@ -1024,6 +1035,10 @@ mod tests {
1024
1035
assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "root" ) ) ) ;
1025
1036
assert_eq ! ( de. peek( ) . unwrap( ) , & Start ( BytesStart :: new( "inner" ) ) ) ;
1026
1037
1038
+ // Mark that start_replay() should begin replay from this point
1039
+ let checkpoint = de. skip_checkpoint ( ) ;
1040
+ assert_eq ! ( checkpoint, 0 ) ;
1041
+
1027
1042
// Should skip first <inner> tree
1028
1043
de. skip ( ) . unwrap ( ) ;
1029
1044
assert_eq ! ( de. read, vec![ ] ) ;
@@ -1060,7 +1075,7 @@ mod tests {
1060
1075
//
1061
1076
// <target/>
1062
1077
// </root>
1063
- de. start_replay ( ) ;
1078
+ de. start_replay ( checkpoint ) ;
1064
1079
assert_eq ! (
1065
1080
de. read,
1066
1081
vec![
@@ -1074,6 +1089,10 @@ mod tests {
1074
1089
assert_eq ! ( de. write, vec![ ] ) ;
1075
1090
assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "inner" ) ) ) ;
1076
1091
1092
+ // Mark that start_replay() should begin replay from this point
1093
+ let checkpoint = de. skip_checkpoint ( ) ;
1094
+ assert_eq ! ( checkpoint, 0 ) ;
1095
+
1077
1096
// Skip `#text` node and consume <inner/> after it
1078
1097
de. skip ( ) . unwrap ( ) ;
1079
1098
assert_eq ! (
@@ -1105,7 +1124,7 @@ mod tests {
1105
1124
//
1106
1125
// <target/>
1107
1126
// </root>
1108
- de. start_replay ( ) ;
1127
+ de. start_replay ( checkpoint ) ;
1109
1128
assert_eq ! (
1110
1129
de. read,
1111
1130
vec![
@@ -1119,6 +1138,7 @@ mod tests {
1119
1138
assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "target" ) ) ) ;
1120
1139
assert_eq ! ( de. next( ) . unwrap( ) , End ( BytesEnd :: new( "target" ) ) ) ;
1121
1140
assert_eq ! ( de. next( ) . unwrap( ) , End ( BytesEnd :: new( "root" ) ) ) ;
1141
+ assert_eq ! ( de. next( ) . unwrap( ) , Eof ) ;
1122
1142
}
1123
1143
1124
1144
/// Checks that `read_to_end()` behaves correctly after `skip()`
@@ -1144,6 +1164,10 @@ mod tests {
1144
1164
1145
1165
assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "root" ) ) ) ;
1146
1166
1167
+ // Mark that start_replay() should begin replay from this point
1168
+ let checkpoint = de. skip_checkpoint ( ) ;
1169
+ assert_eq ! ( checkpoint, 0 ) ;
1170
+
1147
1171
// Skip the <skip> tree
1148
1172
de. skip ( ) . unwrap ( ) ;
1149
1173
assert_eq ! ( de. read, vec![ ] ) ;
@@ -1189,7 +1213,7 @@ mod tests {
1189
1213
// and after that stream that messages:
1190
1214
//
1191
1215
// </root>
1192
- de. start_replay ( ) ;
1216
+ de. start_replay ( checkpoint ) ;
1193
1217
assert_eq ! (
1194
1218
de. read,
1195
1219
vec![
@@ -1206,6 +1230,206 @@ mod tests {
1206
1230
de. read_to_end ( QName ( b"skip" ) ) . unwrap ( ) ;
1207
1231
1208
1232
assert_eq ! ( de. next( ) . unwrap( ) , End ( BytesEnd :: new( "root" ) ) ) ;
1233
+ assert_eq ! ( de. next( ) . unwrap( ) , Eof ) ;
1234
+ }
1235
+
1236
+ /// Checks that replay replayes only part of events
1237
+ /// Test for https://github.com/tafia/quick-xml/issues/435
1238
+ #[ test]
1239
+ fn partial_replay ( ) {
1240
+ let mut de = Deserializer :: from_str (
1241
+ r#"
1242
+ <root>
1243
+ <skipped-1/>
1244
+ <skipped-2/>
1245
+ <inner>
1246
+ <skipped-3/>
1247
+ <skipped-4/>
1248
+ <target-2/>
1249
+ </inner>
1250
+ <target-1/>
1251
+ </root>
1252
+ "# ,
1253
+ ) ;
1254
+
1255
+ // Initial conditions - both are empty
1256
+ assert_eq ! ( de. read, vec![ ] ) ;
1257
+ assert_eq ! ( de. write, vec![ ] ) ;
1258
+
1259
+ assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "root" ) ) ) ;
1260
+
1261
+ // start_replay() should start replay from this point
1262
+ let checkpoint1 = de. skip_checkpoint ( ) ;
1263
+ assert_eq ! ( checkpoint1, 0 ) ;
1264
+
1265
+ // Should skip first and second <skipped-N/> elements
1266
+ de. skip ( ) . unwrap ( ) ; // skipped-1
1267
+ de. skip ( ) . unwrap ( ) ; // skipped-2
1268
+ assert_eq ! ( de. read, vec![ ] ) ;
1269
+ assert_eq ! (
1270
+ de. write,
1271
+ vec![
1272
+ Start ( BytesStart :: new( "skipped-1" ) ) ,
1273
+ End ( BytesEnd :: new( "skipped-1" ) ) ,
1274
+ Start ( BytesStart :: new( "skipped-2" ) ) ,
1275
+ End ( BytesEnd :: new( "skipped-2" ) ) ,
1276
+ ]
1277
+ ) ;
1278
+
1279
+ ////////////////////////////////////////////////////////////////////////////////////////
1280
+
1281
+ assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "inner" ) ) ) ;
1282
+ assert_eq ! ( de. peek( ) . unwrap( ) , & Start ( BytesStart :: new( "skipped-3" ) ) ) ;
1283
+ assert_eq ! (
1284
+ de. read,
1285
+ vec![
1286
+ // This comment here to keep the same formatting of both arrays
1287
+ // otherwise rustfmt suggest one-line it
1288
+ Start ( BytesStart :: new( "skipped-3" ) ) ,
1289
+ ]
1290
+ ) ;
1291
+ assert_eq ! (
1292
+ de. write,
1293
+ vec![
1294
+ Start ( BytesStart :: new( "skipped-1" ) ) ,
1295
+ End ( BytesEnd :: new( "skipped-1" ) ) ,
1296
+ Start ( BytesStart :: new( "skipped-2" ) ) ,
1297
+ End ( BytesEnd :: new( "skipped-2" ) ) ,
1298
+ ]
1299
+ ) ;
1300
+
1301
+ // start_replay() should start replay from this point
1302
+ let checkpoint2 = de. skip_checkpoint ( ) ;
1303
+ assert_eq ! ( checkpoint2, 4 ) ;
1304
+
1305
+ // Should skip third and forth <skipped-N/> elements
1306
+ de. skip ( ) . unwrap ( ) ; // skipped-3
1307
+ de. skip ( ) . unwrap ( ) ; // skipped-4
1308
+ assert_eq ! ( de. read, vec![ ] ) ;
1309
+ assert_eq ! (
1310
+ de. write,
1311
+ vec![
1312
+ // checkpoint 1
1313
+ Start ( BytesStart :: new( "skipped-1" ) ) ,
1314
+ End ( BytesEnd :: new( "skipped-1" ) ) ,
1315
+ Start ( BytesStart :: new( "skipped-2" ) ) ,
1316
+ End ( BytesEnd :: new( "skipped-2" ) ) ,
1317
+ // checkpoint 2
1318
+ Start ( BytesStart :: new( "skipped-3" ) ) ,
1319
+ End ( BytesEnd :: new( "skipped-3" ) ) ,
1320
+ Start ( BytesStart :: new( "skipped-4" ) ) ,
1321
+ End ( BytesEnd :: new( "skipped-4" ) ) ,
1322
+ ]
1323
+ ) ;
1324
+ assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "target-2" ) ) ) ;
1325
+ assert_eq ! ( de. next( ) . unwrap( ) , End ( BytesEnd :: new( "target-2" ) ) ) ;
1326
+ assert_eq ! ( de. peek( ) . unwrap( ) , & End ( BytesEnd :: new( "inner" ) ) ) ;
1327
+ assert_eq ! (
1328
+ de. read,
1329
+ vec![
1330
+ // This comment here to keep the same formatting of both arrays
1331
+ // otherwise rustfmt suggest one-line it
1332
+ End ( BytesEnd :: new( "inner" ) ) ,
1333
+ ]
1334
+ ) ;
1335
+ assert_eq ! (
1336
+ de. write,
1337
+ vec![
1338
+ // checkpoint 1
1339
+ Start ( BytesStart :: new( "skipped-1" ) ) ,
1340
+ End ( BytesEnd :: new( "skipped-1" ) ) ,
1341
+ Start ( BytesStart :: new( "skipped-2" ) ) ,
1342
+ End ( BytesEnd :: new( "skipped-2" ) ) ,
1343
+ // checkpoint 2
1344
+ Start ( BytesStart :: new( "skipped-3" ) ) ,
1345
+ End ( BytesEnd :: new( "skipped-3" ) ) ,
1346
+ Start ( BytesStart :: new( "skipped-4" ) ) ,
1347
+ End ( BytesEnd :: new( "skipped-4" ) ) ,
1348
+ ]
1349
+ ) ;
1350
+
1351
+ // Start replay events from checkpoint 2
1352
+ de. start_replay ( checkpoint2) ;
1353
+ assert_eq ! (
1354
+ de. read,
1355
+ vec![
1356
+ Start ( BytesStart :: new( "skipped-3" ) ) ,
1357
+ End ( BytesEnd :: new( "skipped-3" ) ) ,
1358
+ Start ( BytesStart :: new( "skipped-4" ) ) ,
1359
+ End ( BytesEnd :: new( "skipped-4" ) ) ,
1360
+ End ( BytesEnd :: new( "inner" ) ) ,
1361
+ ]
1362
+ ) ;
1363
+ assert_eq ! (
1364
+ de. write,
1365
+ vec![
1366
+ Start ( BytesStart :: new( "skipped-1" ) ) ,
1367
+ End ( BytesEnd :: new( "skipped-1" ) ) ,
1368
+ Start ( BytesStart :: new( "skipped-2" ) ) ,
1369
+ End ( BytesEnd :: new( "skipped-2" ) ) ,
1370
+ ]
1371
+ ) ;
1372
+
1373
+ // Replayed events
1374
+ assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "skipped-3" ) ) ) ;
1375
+ assert_eq ! ( de. next( ) . unwrap( ) , End ( BytesEnd :: new( "skipped-3" ) ) ) ;
1376
+ assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "skipped-4" ) ) ) ;
1377
+ assert_eq ! ( de. next( ) . unwrap( ) , End ( BytesEnd :: new( "skipped-4" ) ) ) ;
1378
+
1379
+ assert_eq ! ( de. next( ) . unwrap( ) , End ( BytesEnd :: new( "inner" ) ) ) ;
1380
+ assert_eq ! ( de. read, vec![ ] ) ;
1381
+ assert_eq ! (
1382
+ de. write,
1383
+ vec![
1384
+ Start ( BytesStart :: new( "skipped-1" ) ) ,
1385
+ End ( BytesEnd :: new( "skipped-1" ) ) ,
1386
+ Start ( BytesStart :: new( "skipped-2" ) ) ,
1387
+ End ( BytesEnd :: new( "skipped-2" ) ) ,
1388
+ ]
1389
+ ) ;
1390
+
1391
+ ////////////////////////////////////////////////////////////////////////////////////////
1392
+
1393
+ // New events
1394
+ assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "target-1" ) ) ) ;
1395
+ assert_eq ! ( de. next( ) . unwrap( ) , End ( BytesEnd :: new( "target-1" ) ) ) ;
1396
+
1397
+ assert_eq ! ( de. read, vec![ ] ) ;
1398
+ assert_eq ! (
1399
+ de. write,
1400
+ vec![
1401
+ Start ( BytesStart :: new( "skipped-1" ) ) ,
1402
+ End ( BytesEnd :: new( "skipped-1" ) ) ,
1403
+ Start ( BytesStart :: new( "skipped-2" ) ) ,
1404
+ End ( BytesEnd :: new( "skipped-2" ) ) ,
1405
+ ]
1406
+ ) ;
1407
+
1408
+ // Start replay events from checkpoint 1
1409
+ de. start_replay ( checkpoint1) ;
1410
+ assert_eq ! (
1411
+ de. read,
1412
+ vec![
1413
+ Start ( BytesStart :: new( "skipped-1" ) ) ,
1414
+ End ( BytesEnd :: new( "skipped-1" ) ) ,
1415
+ Start ( BytesStart :: new( "skipped-2" ) ) ,
1416
+ End ( BytesEnd :: new( "skipped-2" ) ) ,
1417
+ ]
1418
+ ) ;
1419
+ assert_eq ! ( de. write, vec![ ] ) ;
1420
+
1421
+ // Replayed events
1422
+ assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "skipped-1" ) ) ) ;
1423
+ assert_eq ! ( de. next( ) . unwrap( ) , End ( BytesEnd :: new( "skipped-1" ) ) ) ;
1424
+ assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "skipped-2" ) ) ) ;
1425
+ assert_eq ! ( de. next( ) . unwrap( ) , End ( BytesEnd :: new( "skipped-2" ) ) ) ;
1426
+
1427
+ assert_eq ! ( de. read, vec![ ] ) ;
1428
+ assert_eq ! ( de. write, vec![ ] ) ;
1429
+
1430
+ // New events
1431
+ assert_eq ! ( de. next( ) . unwrap( ) , End ( BytesEnd :: new( "root" ) ) ) ;
1432
+ assert_eq ! ( de. next( ) . unwrap( ) , Eof ) ;
1209
1433
}
1210
1434
1211
1435
/// Checks that limiting buffer size works correctly
0 commit comments