@@ -483,6 +483,14 @@ where
483483 self . reader . next ( )
484484 }
485485
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+
486494 /// Extracts XML tree of events from and stores them in the skipped events
487495 /// buffer from which they can be retrieved later. You MUST call
488496 /// [`Self::start_replay()`] after calling this to give access to the skipped
@@ -530,8 +538,8 @@ where
530538 Ok ( ( ) )
531539 }
532540
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 .
535543 ///
536544 /// After calling this method, [`Self::peek()`] and [`Self::next()`] starts
537545 /// return events that was skipped previously by calling [`Self::skip()`],
@@ -541,9 +549,15 @@ where
541549 /// This method MUST be called if any number of [`Self::skip()`] was called
542550 /// after [`Self::new()`] or `start_replay()` or you'll lost events.
543551 #[ 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+ }
547561 }
548562
549563 fn next_start ( & mut self ) -> Result < Option < BytesStart < ' de > > , DeError > {
@@ -828,10 +842,7 @@ where
828842 where
829843 V : Visitor < ' de > ,
830844 {
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 ) ?)
835846 }
836847
837848 fn deserialize_map < V > ( self , visitor : V ) -> Result < V :: Value , DeError >
@@ -1024,6 +1035,10 @@ mod tests {
10241035 assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "root" ) ) ) ;
10251036 assert_eq ! ( de. peek( ) . unwrap( ) , & Start ( BytesStart :: new( "inner" ) ) ) ;
10261037
1038+ // Mark that start_replay() should begin replay from this point
1039+ let checkpoint = de. skip_checkpoint ( ) ;
1040+ assert_eq ! ( checkpoint, 0 ) ;
1041+
10271042 // Should skip first <inner> tree
10281043 de. skip ( ) . unwrap ( ) ;
10291044 assert_eq ! ( de. read, vec![ ] ) ;
@@ -1060,7 +1075,7 @@ mod tests {
10601075 //
10611076 // <target/>
10621077 // </root>
1063- de. start_replay ( ) ;
1078+ de. start_replay ( checkpoint ) ;
10641079 assert_eq ! (
10651080 de. read,
10661081 vec![
@@ -1074,6 +1089,10 @@ mod tests {
10741089 assert_eq ! ( de. write, vec![ ] ) ;
10751090 assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "inner" ) ) ) ;
10761091
1092+ // Mark that start_replay() should begin replay from this point
1093+ let checkpoint = de. skip_checkpoint ( ) ;
1094+ assert_eq ! ( checkpoint, 0 ) ;
1095+
10771096 // Skip `#text` node and consume <inner/> after it
10781097 de. skip ( ) . unwrap ( ) ;
10791098 assert_eq ! (
@@ -1105,7 +1124,7 @@ mod tests {
11051124 //
11061125 // <target/>
11071126 // </root>
1108- de. start_replay ( ) ;
1127+ de. start_replay ( checkpoint ) ;
11091128 assert_eq ! (
11101129 de. read,
11111130 vec![
@@ -1119,6 +1138,7 @@ mod tests {
11191138 assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "target" ) ) ) ;
11201139 assert_eq ! ( de. next( ) . unwrap( ) , End ( BytesEnd :: new( "target" ) ) ) ;
11211140 assert_eq ! ( de. next( ) . unwrap( ) , End ( BytesEnd :: new( "root" ) ) ) ;
1141+ assert_eq ! ( de. next( ) . unwrap( ) , Eof ) ;
11221142 }
11231143
11241144 /// Checks that `read_to_end()` behaves correctly after `skip()`
@@ -1144,6 +1164,10 @@ mod tests {
11441164
11451165 assert_eq ! ( de. next( ) . unwrap( ) , Start ( BytesStart :: new( "root" ) ) ) ;
11461166
1167+ // Mark that start_replay() should begin replay from this point
1168+ let checkpoint = de. skip_checkpoint ( ) ;
1169+ assert_eq ! ( checkpoint, 0 ) ;
1170+
11471171 // Skip the <skip> tree
11481172 de. skip ( ) . unwrap ( ) ;
11491173 assert_eq ! ( de. read, vec![ ] ) ;
@@ -1189,7 +1213,7 @@ mod tests {
11891213 // and after that stream that messages:
11901214 //
11911215 // </root>
1192- de. start_replay ( ) ;
1216+ de. start_replay ( checkpoint ) ;
11931217 assert_eq ! (
11941218 de. read,
11951219 vec![
@@ -1206,6 +1230,206 @@ mod tests {
12061230 de. read_to_end ( QName ( b"skip" ) ) . unwrap ( ) ;
12071231
12081232 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 ) ;
12091433 }
12101434
12111435 /// Checks that limiting buffer size works correctly
0 commit comments