1use std::io::Read;
2
3use ciborium::Value;
4
5use crate::error::MoqTraceError;
6use crate::event::TraceEvent;
7use crate::header::TraceHeader;
8use crate::writer::{MOQTRACE_MAGIC, MOQTRACE_VERSION};
9
10#[derive(Debug)]
16pub struct MoqTraceReader<R: Read> {
17 inner: R,
18 header: TraceHeader,
19}
20
21impl<R: Read> MoqTraceReader<R> {
22 pub fn new(mut reader: R) -> Result<Self, MoqTraceError> {
24 let mut magic = [0u8; 8];
26 reader.read_exact(&mut magic)?;
27 if &magic != MOQTRACE_MAGIC {
28 return Err(MoqTraceError::InvalidMagic);
29 }
30
31 let mut version_bytes = [0u8; 4];
33 reader.read_exact(&mut version_bytes)?;
34 let version = u32::from_le_bytes(version_bytes);
35 if version != MOQTRACE_VERSION {
36 return Err(MoqTraceError::UnsupportedVersion(version));
37 }
38
39 let mut len_bytes = [0u8; 4];
41 reader.read_exact(&mut len_bytes)?;
42 let header_len = u32::from_le_bytes(len_bytes) as usize;
43
44 let mut header_bytes = vec![0u8; header_len];
46 reader.read_exact(&mut header_bytes)?;
47
48 let header_value: Value = ciborium::from_reader(&header_bytes[..])?;
49 let header = TraceHeader::try_from(header_value)?;
50
51 Ok(Self { inner: reader, header })
52 }
53
54 pub fn header(&self) -> &TraceHeader {
56 &self.header
57 }
58
59 pub fn read_event(&mut self) -> Result<Option<TraceEvent>, MoqTraceError> {
63 match ciborium::from_reader::<Value, _>(&mut self.inner) {
64 Ok(value) => {
65 let event = TraceEvent::try_from(value)?;
66 Ok(Some(event))
67 }
68 Err(ciborium::de::Error::Io(e)) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
69 Ok(None)
70 }
71 Err(e) => Err(MoqTraceError::CborDecode(e.to_string())),
72 }
73 }
74}
75
76impl<R: Read> IntoIterator for MoqTraceReader<R> {
77 type Item = Result<TraceEvent, MoqTraceError>;
78 type IntoIter = MoqTraceIterator<R>;
79
80 fn into_iter(self) -> Self::IntoIter {
81 MoqTraceIterator { reader: self }
82 }
83}
84
85pub struct MoqTraceIterator<R: Read> {
87 reader: MoqTraceReader<R>,
88}
89
90impl<R: Read> Iterator for MoqTraceIterator<R> {
91 type Item = Result<TraceEvent, MoqTraceError>;
92
93 fn next(&mut self) -> Option<Self::Item> {
94 match self.reader.read_event() {
95 Ok(Some(event)) => Some(Ok(event)),
96 Ok(None) => None,
97 Err(e) => Some(Err(e)),
98 }
99 }
100}