mpeg_audio_header/
reader.rs1use std::{
5 io::{self, prelude::*},
6 time::Duration,
7};
8
9use crate::{
10 error::{Error, PositionalError},
11 PositionalResult,
12};
13
14#[derive(Debug, Clone)]
16pub struct ReadPosition {
17 pub(crate) byte_offset: u64,
18 pub(crate) duration: Duration,
19}
20
21impl ReadPosition {
22 pub(crate) const fn new() -> Self {
23 Self {
24 byte_offset: 0,
25 duration: Duration::ZERO,
26 }
27 }
28
29 #[must_use]
31 pub const fn byte_offset(&self) -> u64 {
32 self.byte_offset
33 }
34
35 #[must_use]
37 pub const fn duration(&self) -> Duration {
38 self.duration
39 }
40}
41
42pub(crate) struct Reader<'r, T> {
43 reader: &'r mut T,
44 position: ReadPosition,
45}
46
47impl<'r, T: Read> Reader<'r, T> {
48 #[must_use]
49 pub(crate) fn new(reader: &'r mut T) -> Self {
50 Reader {
51 reader,
52 position: ReadPosition::new(),
53 }
54 }
55
56 fn read_exact(&mut self, buffer: &mut [u8]) -> PositionalResult<()> {
57 self.reader
58 .read_exact(buffer)
59 .map(|()| {
60 self.position.byte_offset += buffer.len() as u64;
61 })
62 .map_err(|e| self.positional_error(e.into()))
63 }
64
65 pub(crate) fn try_read_exact_until_eof(&mut self, buffer: &mut [u8]) -> PositionalResult<bool> {
66 self.read_exact(buffer).map(|()| true).or_else(|err| {
67 if err.is_unexpected_eof() {
68 Ok(false)
69 } else {
70 Err(err)
71 }
72 })
73 }
74
75 fn skip(&mut self, max_bytes: u64) -> PositionalResult<u64> {
76 match io::copy(&mut self.reader.take(max_bytes), &mut io::sink()) {
77 Err(e) => Err(self.positional_error(e.into())),
78 Ok(num_bytes_skipped) => {
79 debug_assert!(num_bytes_skipped <= max_bytes);
80 self.position.byte_offset += num_bytes_skipped;
81 Ok(num_bytes_skipped)
82 }
83 }
84 }
85
86 pub(crate) fn try_skip_exact_until_eof(&mut self, num_bytes: u64) -> PositionalResult<bool> {
87 match self.skip(num_bytes) {
88 Ok(skipped_bytes) => {
89 debug_assert!(skipped_bytes <= num_bytes);
90 Ok(skipped_bytes == num_bytes)
91 }
92 Err(err) => {
93 if err.is_unexpected_eof() {
94 Ok(false)
95 } else {
96 Err(err)
97 }
98 }
99 }
100 }
101
102 #[must_use]
103 pub(crate) fn position(&self) -> &ReadPosition {
104 &self.position
105 }
106
107 pub(crate) fn add_duration(&mut self, duration: Duration) {
108 self.position.duration += duration;
109 }
110
111 #[must_use]
112 pub(crate) fn positional_error(&self, source: Error) -> PositionalError {
113 let Self { position, .. } = self;
114 PositionalError {
115 source,
116 position: position.clone(),
117 }
118 }
119}