symphonia_core/io/
monitor_stream.rs

1// Symphonia
2// Copyright (c) 2019-2022 The Project Symphonia Developers.
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
8use std::io;
9
10use super::ReadBytes;
11
12/// A `Monitor` provides a common interface to examine the operations observed be
13/// a [`MonitorStream`].
14pub trait Monitor {
15    fn process_byte(&mut self, byte: u8);
16
17    #[inline(always)]
18    fn process_double_bytes(&mut self, buf: [u8; 2]) {
19        self.process_byte(buf[0]);
20        self.process_byte(buf[1]);
21    }
22
23    #[inline(always)]
24    fn process_triple_bytes(&mut self, buf: [u8; 3]) {
25        self.process_byte(buf[0]);
26        self.process_byte(buf[1]);
27        self.process_byte(buf[2]);
28    }
29
30    #[inline(always)]
31    fn process_quad_bytes(&mut self, buf: [u8; 4]) {
32        self.process_byte(buf[0]);
33        self.process_byte(buf[1]);
34        self.process_byte(buf[2]);
35        self.process_byte(buf[3]);
36    }
37
38    fn process_buf_bytes(&mut self, buf: &[u8]);
39}
40
41/// A `MonitorStream` is a passive stream that observes all operations performed on the inner
42/// stream and forwards an immutable reference of the result to a [`Monitor`].
43pub struct MonitorStream<B: ReadBytes, M: Monitor> {
44    inner: B,
45    monitor: M,
46}
47
48impl<B: ReadBytes, M: Monitor> MonitorStream<B, M> {
49    pub fn new(inner: B, monitor: M) -> MonitorStream<B, M> {
50        MonitorStream { inner, monitor }
51    }
52
53    pub fn inner(&self) -> &B {
54        &self.inner
55    }
56
57    pub fn inner_mut(&mut self) -> &mut B {
58        &mut self.inner
59    }
60
61    pub fn into_inner(self) -> B {
62        self.inner
63    }
64
65    pub fn monitor(&self) -> &M {
66        &self.monitor
67    }
68
69    pub fn monitor_mut(&mut self) -> &mut M {
70        &mut self.monitor
71    }
72}
73
74impl<B: ReadBytes, M: Monitor> ReadBytes for MonitorStream<B, M> {
75    #[inline(always)]
76    fn read_byte(&mut self) -> io::Result<u8> {
77        let byte = self.inner.read_byte()?;
78        self.monitor.process_byte(byte);
79        Ok(byte)
80    }
81
82    #[inline(always)]
83    fn read_double_bytes(&mut self) -> io::Result<[u8; 2]> {
84        let bytes = self.inner.read_double_bytes()?;
85        self.monitor.process_double_bytes(bytes);
86        Ok(bytes)
87    }
88
89    #[inline(always)]
90    fn read_triple_bytes(&mut self) -> io::Result<[u8; 3]> {
91        let bytes = self.inner.read_triple_bytes()?;
92        self.monitor.process_triple_bytes(bytes);
93        Ok(bytes)
94    }
95
96    #[inline(always)]
97    fn read_quad_bytes(&mut self) -> io::Result<[u8; 4]> {
98        let bytes = self.inner.read_quad_bytes()?;
99        self.monitor.process_quad_bytes(bytes);
100        Ok(bytes)
101    }
102
103    fn read_buf(&mut self, buf: &mut [u8]) -> io::Result<usize> {
104        let len = self.inner.read_buf(buf)?;
105        self.monitor.process_buf_bytes(&buf[0..len]);
106        Ok(len)
107    }
108
109    fn read_buf_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
110        self.inner.read_buf_exact(buf)?;
111        self.monitor.process_buf_bytes(buf);
112        Ok(())
113    }
114
115    fn scan_bytes_aligned<'a>(
116        &mut self,
117        pattern: &[u8],
118        align: usize,
119        buf: &'a mut [u8],
120    ) -> io::Result<&'a mut [u8]> {
121        let result = self.inner.scan_bytes_aligned(pattern, align, buf)?;
122        self.monitor.process_buf_bytes(result);
123        Ok(result)
124    }
125
126    fn ignore_bytes(&mut self, count: u64) -> io::Result<()> {
127        self.inner.ignore_bytes(count)
128    }
129
130    #[inline(always)]
131    fn pos(&self) -> u64 {
132        self.inner.pos()
133    }
134}