diff --git a/slippi/parse.py b/slippi/parse.py index db1881d..c90eb79 100644 --- a/slippi/parse.py +++ b/slippi/parse.py @@ -121,14 +121,14 @@ def _parse_events(stream, payload_sizes, total_size, handlers, skip_frames): event = None # `total_size` will be zero for in-progress replays - while (total_size == 0 or bytes_read < total_size) and event != ParseEvent.END: + while (total_size == 0 or bytes_read < total_size) and not isinstance(event, End): (b, event) = _parse_event(stream, payload_sizes) bytes_read += b if isinstance(event, Start): handler = handlers.get(ParseEvent.START) if handler: handler(event) - if skip_frames: + if skip_frames and total_size != 0: skip = total_size - bytes_read - payload_sizes[EventType.GAME_END.value] - 1 stream.seek(skip, os.SEEK_CUR) bytes_read += skip @@ -137,7 +137,7 @@ def _parse_events(stream, payload_sizes, total_size, handlers, skip_frames): handler = handlers.get(ParseEvent.END) if handler: handler(event) - elif isinstance(event, Frame.Event): + elif isinstance(event, Frame.Event) and not skip_frames: # Accumulate all events for a single frame into a single `Frame` object. # We can't use Frame Bookend events to detect end-of-frame, @@ -193,7 +193,10 @@ def _parse(stream, handlers, skip_frames): (length,) = unpack('l', stream) (bytes_read, payload_sizes) = _parse_event_payloads(stream) - _parse_events(stream, payload_sizes, length - bytes_read, handlers, skip_frames) + if length != 0: + length -= bytes_read + + _parse_events(stream, payload_sizes, length, handlers, skip_frames) expect_bytes(b'U\x08metadata', stream) diff --git a/test/replays.py b/test/replays.py index 57c1194..e951b1c 100755 --- a/test/replays.py +++ b/test/replays.py @@ -112,6 +112,17 @@ def test_game(self): self.assertEqual(game.metadata.duration, len(game.frames)) + def test_streaming_game(self): + game = Game(path('game')) + streaming_game = Game(path('streaming_game')) + streaming_game_skip = Game(path('streaming_game'), skip_frames=True) + + self.assertEqual(game.start, streaming_game.start) + self.assertEqual(game.end, streaming_game.end) + self.assertEqual(game.metadata, streaming_game.metadata) + + self.assertFalse(streaming_game_skip.frames) + def test_game_skip_frames(self): game = Game(path('game'), skip_frames=True) diff --git a/test/replays/streaming_game.slp b/test/replays/streaming_game.slp new file mode 100644 index 0000000..8836296 Binary files /dev/null and b/test/replays/streaming_game.slp differ