1use crate::event::TraceEvent;
2use std::io::{BufRead, BufReader, Read, Write};
3
4pub const MOQTRACE_MAGIC: &[u8; 8] = b"MOQTRACE";
5pub const MOQTRACE_VERSION: u32 = 1;
6
7#[derive(Debug, thiserror::Error)]
8pub enum MoqTraceError {
9 #[error("io error: {0}")]
10 Io(#[from] std::io::Error),
11 #[error("json error: {0}")]
12 Json(#[from] serde_json::Error),
13 #[error("invalid magic bytes")]
14 InvalidMagic,
15 #[error("unsupported version: {0}")]
16 UnsupportedVersion(u32),
17}
18
19#[derive(Debug)]
21pub struct MoqTraceWriter<W: Write> {
22 inner: W,
23}
24
25#[derive(Debug)]
27pub struct MoqTraceReader<R: Read> {
28 inner: BufReader<R>,
29}
30
31impl<W: Write> MoqTraceWriter<W> {
32 pub fn new(mut writer: W) -> Result<Self, MoqTraceError> {
33 writer.write_all(MOQTRACE_MAGIC)?;
34 writer.write_all(&MOQTRACE_VERSION.to_le_bytes())?;
35 Ok(Self { inner: writer })
36 }
37
38 pub fn write_event(&mut self, event: &TraceEvent) -> Result<(), MoqTraceError> {
39 let json = serde_json::to_string(event)?;
40 self.inner.write_all(json.as_bytes())?;
41 self.inner.write_all(b"\n")?;
42 Ok(())
43 }
44
45 pub fn flush(&mut self) -> Result<(), MoqTraceError> {
46 self.inner.flush()?;
47 Ok(())
48 }
49}
50
51impl<R: Read> MoqTraceReader<R> {
52 pub fn new(mut reader: R) -> Result<Self, MoqTraceError> {
53 let mut magic = [0u8; 8];
54 reader.read_exact(&mut magic)?;
55 if &magic != MOQTRACE_MAGIC {
56 return Err(MoqTraceError::InvalidMagic);
57 }
58 let mut version_bytes = [0u8; 4];
59 reader.read_exact(&mut version_bytes)?;
60 let version = u32::from_le_bytes(version_bytes);
61 if version != MOQTRACE_VERSION {
62 return Err(MoqTraceError::UnsupportedVersion(version));
63 }
64 Ok(Self { inner: BufReader::new(reader) })
65 }
66
67 pub fn read_event(&mut self) -> Result<Option<TraceEvent>, MoqTraceError> {
68 let mut line = String::new();
69 let bytes_read = self.inner.read_line(&mut line)?;
70 if bytes_read == 0 || line.trim().is_empty() {
71 return Ok(None);
72 }
73 let event: TraceEvent = serde_json::from_str(line.trim())?;
74 Ok(Some(event))
75 }
76}
77
78impl<R: Read> IntoIterator for MoqTraceReader<R> {
79 type Item = Result<TraceEvent, MoqTraceError>;
80 type IntoIter = MoqTraceIterator<R>;
81
82 fn into_iter(self) -> Self::IntoIter {
83 MoqTraceIterator { reader: self }
84 }
85}
86
87pub struct MoqTraceIterator<R: Read> {
88 reader: MoqTraceReader<R>,
89}
90
91impl<R: Read> Iterator for MoqTraceIterator<R> {
92 type Item = Result<TraceEvent, MoqTraceError>;
93
94 fn next(&mut self) -> Option<Self::Item> {
95 match self.reader.read_event() {
96 Ok(Some(event)) => Some(Ok(event)),
97 Ok(None) => None,
98 Err(e) => Some(Err(e)),
99 }
100 }
101}