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, C: ReadCapability> Mp4Reader<R, C> {
33    pub fn into_inner(self) -> (Vec<u8>, R) {
34        (self.peek_buffer, self.reader)
35    }
36}
37
38impl<R: AsyncRead + Unpin + Send> Mp4Reader<R, NonSeekable> {
39    pub fn new(reader: R) -> Self {
40        Self {
41            reader,
42            current_offset: 0,
43            peek_buffer: Vec::new(),
44            _capability: PhantomData,
45        }
46    }
47}
48
49impl<R: AsyncRead + Unpin + Send, C: ReadCapability> Mp4Reader<R, C> {
50    pub(crate) async fn peek_exact(&mut self, buf: &mut [u8]) -> Result<(), ParseError> {
51        let size = buf.len();
52        if self.peek_buffer.len() < size {
53            let mut temp_buf = vec![0u8; size - self.peek_buffer.len()];
54            self.reader.read_exact(&mut temp_buf).await.map_err(|e| {
55                if e.kind() == std::io::ErrorKind::UnexpectedEof {
56                    return ParseError {
57                        kind: ParseErrorKind::Eof,
58                        location: Some((self.current_offset, size)),
59                        source: Some(Box::new(e)),
60                    };
61                }
62                ParseError {
63                    kind: ParseErrorKind::Io,
64                    location: Some((self.current_offset, size)),
65                    source: Some(Box::new(e)),
66                }
67            })?;
68            self.peek_buffer.extend_from_slice(&temp_buf[..]);
69        }
70        buf.copy_from_slice(&self.peek_buffer[..size]);
71        Ok(())
72    }
73
74    pub(crate) async fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), ParseError> {
75        self.peek_exact(buf).await?;
76        self.peek_buffer.drain(..buf.len());
77        self.current_offset += buf.len();
78        Ok(())
79    }
80
81    pub(crate) async fn read_data(&mut self, size: usize) -> Result<Vec<u8>, ParseError> {
82        let mut data = vec![0u8; size];
83        self.read_exact(&mut data).await?;
84        Ok(data)
85    }
86}
87
88impl<R: AsyncRead + AsyncSeek + Unpin + Send> Mp4Reader<R, Seekable> {
89    pub fn new(reader: R) -> Self {
90        Self {
91            reader,
92            current_offset: 0,
93            peek_buffer: Vec::new(),
94            _capability: PhantomData,
95        }
96    }
97
98    pub(crate) async fn seek(&mut self, pos: SeekFrom) -> Result<(), ParseError> {
99        match self.reader.seek(pos).await {
100            Ok(offset) => {
101                self.current_offset = offset as usize;
102                self.peek_buffer = Vec::new();
103                Ok(())
104            }
105            Err(err) => Err(ParseError {
106                kind: ParseErrorKind::Io,
107                location: None,
108                source: Some(Box::new(err)),
109            }),
110        }
111    }
112}