Skip to main content

mp4_edit/
reader.rs

1use futures_io::{AsyncRead, AsyncSeek};
2use futures_util::io::{AsyncReadExt, AsyncSeekExt};
3use std::io::SeekFrom;
4use std::marker::PhantomData;
5
6use crate::parser::ParseErrorKind;
7use crate::ParseError;
8
9mod sealed {
10    pub trait Sealed {}
11}
12
13pub struct Seekable;
14pub struct NonSeekable;
15
16impl sealed::Sealed for Seekable {}
17impl sealed::Sealed for NonSeekable {}
18
19pub trait ReadCapability: sealed::Sealed {}
20
21impl ReadCapability for NonSeekable {}
22
23impl ReadCapability for Seekable {}
24
25pub struct Mp4Reader<R, C: ReadCapability> {
26    reader: R,
27    pub(crate) current_offset: usize,
28    peek_buffer: Vec<u8>,
29    _capability: PhantomData<C>,
30}
31
32impl<R: AsyncRead + Unpin + Send> Mp4Reader<R, NonSeekable> {
33    pub fn new(reader: R) -> Self {
34        Self {
35            reader,
36            current_offset: 0,
37            peek_buffer: Vec::new(),
38            _capability: PhantomData,
39        }
40    }
41}
42
43impl<R: AsyncRead + Unpin + Send, C: ReadCapability> Mp4Reader<R, C> {
44    pub(crate) async fn peek_exact(&mut self, buf: &mut [u8]) -> Result<(), ParseError> {
45        let size = buf.len();
46        if self.peek_buffer.len() < size {
47            let mut temp_buf = vec![0u8; size - self.peek_buffer.len()];
48            self.reader.read_exact(&mut temp_buf).await.map_err(|e| {
49                if e.kind() == std::io::ErrorKind::UnexpectedEof {
50                    return ParseError {
51                        kind: ParseErrorKind::Eof,
52                        location: Some((self.current_offset, size)),
53                        source: Some(Box::new(e)),
54                    };
55                }
56                ParseError {
57                    kind: ParseErrorKind::Io,
58                    location: Some((self.current_offset, size)),
59                    source: Some(Box::new(e)),
60                }
61            })?;
62            self.peek_buffer.extend_from_slice(&temp_buf[..]);
63        }
64        buf.copy_from_slice(&self.peek_buffer[..size]);
65        Ok(())
66    }
67
68    pub(crate) async fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), ParseError> {
69        self.peek_exact(buf).await?;
70        self.peek_buffer.drain(..buf.len());
71        self.current_offset += buf.len();
72        Ok(())
73    }
74
75    pub(crate) async fn read_data(&mut self, size: usize) -> Result<Vec<u8>, ParseError> {
76        let mut data = vec![0u8; size];
77        self.read_exact(&mut data).await?;
78        Ok(data)
79    }
80}
81
82impl<R: AsyncRead + AsyncSeek + Unpin + Send> Mp4Reader<R, Seekable> {
83    pub fn new(reader: R) -> Self {
84        Self {
85            reader,
86            current_offset: 0,
87            peek_buffer: Vec::new(),
88            _capability: PhantomData,
89        }
90    }
91
92    pub(crate) async fn seek(&mut self, pos: SeekFrom) -> Result<(), ParseError> {
93        match self.reader.seek(pos).await {
94            Ok(offset) => {
95                self.current_offset = offset as usize;
96                self.peek_buffer = Vec::new();
97                Ok(())
98            }
99            Err(err) => Err(ParseError {
100                kind: ParseErrorKind::Io,
101                location: None,
102                source: Some(Box::new(err)),
103            }),
104        }
105    }
106}