Skip to content

Commit 849ffcf

Browse files
committed
demo: Add next_chunk_type to high level reader
1 parent b6030b8 commit 849ffcf

4 files changed

Lines changed: 54 additions & 0 deletions

File tree

demo/src/ddnet/reader.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,16 @@ impl<'a, P: for<'p> Protocol<'p>> DemoReader<'a, P> {
169169
}
170170
}
171171
}
172+
/// Peeks into the next chunk header to determine the next chunk type.
173+
/// It returns `None` in one of three cases:
174+
/// - the demo ends
175+
/// - the stream position couldn't be determined
176+
/// - a read or parsing error happened
177+
/// If `Ok` is returned, the reader's position is unchanged.
178+
/// If `Err` is returned, the reader's position is unspecified.
179+
pub fn next_chunk_type(&mut self) -> Result<Option<reader::ChunkType>, io::Error> {
180+
self.raw.next_chunk_type()
181+
}
172182
/// Gets the position of the underlying reader.
173183
pub fn stream_position(&mut self) -> Result<u64, io::Error> {
174184
self.raw.stream_position()

demo/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub use self::format::DemoKind;
77
pub use self::format::RawChunk;
88
pub use self::format::Version;
99
pub use self::format::Warning;
10+
pub use self::reader::ChunkType;
1011
pub use self::reader::ReadError;
1112
pub use self::reader::Reader;
1213
pub use self::writer::WriteError;

demo/src/reader.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use libtw2_warn::Warn;
99
use std::io;
1010
use thiserror::Error;
1111

12+
use crate::format::ChunkHeader;
1213
use crate::format::TickMarker;
1314
use crate::format::Warning;
1415
use crate::format::MAX_SNAPSHOT_SIZE;
@@ -53,6 +54,13 @@ pub struct Reader<'a> {
5354
huffman: ArrayVec<[u8; MAX_SNAPSHOT_SIZE]>,
5455
}
5556

57+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58+
pub enum ChunkType {
59+
Tick,
60+
Snapshot,
61+
Message,
62+
}
63+
5664
impl<'a> Reader<'a> {
5765
pub fn new<W, R>(mut data: R, warn: &mut W) -> Result<Reader<'a>, ReadError>
5866
where
@@ -163,6 +171,31 @@ impl<'a> Reader<'a> {
163171
}
164172
}
165173
}
174+
/// Peeks into the next chunk header to determine the next chunk type.
175+
/// It returns `None` in one of three cases:
176+
/// - the demo ends
177+
/// - the stream position couldn't be determined
178+
/// - a read or parsing error happened
179+
/// If `Ok` is returned, the reader's position is unchanged.
180+
/// If `Err` is returned, the reader's position is unspecified.
181+
pub(crate) fn next_chunk_type(&mut self) -> Result<Option<ChunkType>, io::Error> {
182+
let position = self.stream_position()?;
183+
let chunk_type =
184+
match ChunkHeader::read(&mut self.data, self.start.version, &mut libtw2_warn::Ignore) {
185+
Ok(Some(ChunkHeader::Tick { .. })) => Some(ChunkType::Tick),
186+
Ok(Some(ChunkHeader::Data {
187+
kind: format::DataKind::Snapshot | format::DataKind::SnapshotDelta,
188+
..
189+
})) => Some(ChunkType::Snapshot),
190+
Ok(Some(ChunkHeader::Data {
191+
kind: format::DataKind::Message,
192+
..
193+
})) => Some(ChunkType::Message),
194+
_ => None,
195+
};
196+
self.data.seek(io::SeekFrom::Start(position))?;
197+
Ok(chunk_type)
198+
}
166199
/// Gets the position of the underlying reader.
167200
pub fn stream_position(&mut self) -> Result<u64, io::Error> {
168201
self.data.stream_position()

tools/src/bin/demo_check_seeking.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use clap::App;
22
use clap::Arg;
33
use libtw2_demo::ddnet;
44
use libtw2_demo::ddnet::DemoReader;
5+
use libtw2_demo::ChunkType;
56
use libtw2_gamenet_ddnet::Protocol as DDNet;
67
use libtw2_warn as warn;
78
use std::error::Error;
@@ -28,9 +29,18 @@ impl SeekableDemo for DemoReader<'static, DDNet> {
2829
fn next_keyframe(&mut self) -> Result<Option<(i32, u64)>, Box<dyn Error>> {
2930
loop {
3031
let position = self.stream_position()?;
32+
let chunk_type = self.next_chunk_type()?;
3133
let Some(chunk) = self.next_chunk(&mut warn::Ignore)? else {
34+
assert!(chunk_type.is_none());
3235
return Ok(None);
3336
};
37+
assert!(matches!(
38+
(chunk_type, &chunk),
39+
(Some(ChunkType::Message), ddnet::Chunk::Message(_))
40+
| (Some(ChunkType::Snapshot), ddnet::Chunk::Snapshot(_))
41+
| (Some(ChunkType::Tick), ddnet::Chunk::Tick { .. })
42+
| (None, ddnet::Chunk::Invalid)
43+
));
3444
if let ddnet::Chunk::Tick {
3545
keyframe: true,
3646
tick,

0 commit comments

Comments
 (0)