Skip to main content

pito_codecs/mp4/
source.rs

1use std::io;
2use std::sync::Arc;
3
4pub trait ByteSource {
5    fn len(&self) -> u64;
6    fn read_at(&self, offset: u64, buf: &mut [u8]) -> io::Result<()>;
7    fn is_empty(&self) -> bool {
8        self.len() == 0
9    }
10}
11
12fn eof() -> io::Error {
13    io::Error::new(io::ErrorKind::UnexpectedEof, "read past end of byte source")
14}
15
16impl ByteSource for [u8] {
17    fn len(&self) -> u64 {
18        <[u8]>::len(self) as u64
19    }
20    fn read_at(&self, offset: u64, buf: &mut [u8]) -> io::Result<()> {
21        let start = usize::try_from(offset).map_err(|_| eof())?;
22        let end = start.checked_add(buf.len()).ok_or_else(eof)?;
23        let src = self.get(start..end).ok_or_else(eof)?;
24        buf.copy_from_slice(src);
25        Ok(())
26    }
27}
28
29impl ByteSource for Vec<u8> {
30    fn len(&self) -> u64 {
31        self.as_slice().len() as u64
32    }
33    fn read_at(&self, offset: u64, buf: &mut [u8]) -> io::Result<()> {
34        self.as_slice().read_at(offset, buf)
35    }
36}
37
38impl<T: ByteSource + ?Sized> ByteSource for &T {
39    fn len(&self) -> u64 {
40        (**self).len()
41    }
42    fn read_at(&self, offset: u64, buf: &mut [u8]) -> io::Result<()> {
43        (**self).read_at(offset, buf)
44    }
45}
46
47impl<T: ByteSource + ?Sized> ByteSource for Arc<T> {
48    fn len(&self) -> u64 {
49        (**self).len()
50    }
51    fn read_at(&self, offset: u64, buf: &mut [u8]) -> io::Result<()> {
52        (**self).read_at(offset, buf)
53    }
54}
55
56impl<T: ByteSource + ?Sized> ByteSource for Box<T> {
57    fn len(&self) -> u64 {
58        (**self).len()
59    }
60    fn read_at(&self, offset: u64, buf: &mut [u8]) -> io::Result<()> {
61        (**self).read_at(offset, buf)
62    }
63}
64
65#[cfg(not(target_arch = "wasm32"))]
66impl ByteSource for std::fs::File {
67    fn len(&self) -> u64 {
68        self.metadata().map(|m| m.len()).unwrap_or(0)
69    }
70    #[cfg(unix)]
71    fn read_at(&self, offset: u64, buf: &mut [u8]) -> io::Result<()> {
72        std::os::unix::fs::FileExt::read_exact_at(self, buf, offset)
73    }
74    #[cfg(windows)]
75    fn read_at(&self, mut offset: u64, mut buf: &mut [u8]) -> io::Result<()> {
76        use std::os::windows::fs::FileExt;
77        while !buf.is_empty() {
78            let n = self.seek_read(buf, offset)?;
79            if n == 0 {
80                return Err(eof());
81            }
82            offset += n as u64;
83            buf = &mut buf[n..];
84        }
85        Ok(())
86    }
87    #[cfg(not(any(unix, windows)))]
88    fn read_at(&self, offset: u64, buf: &mut [u8]) -> io::Result<()> {
89        use std::io::{Read, Seek, SeekFrom};
90        let mut f = self;
91        f.seek(SeekFrom::Start(offset))?;
92        f.read_exact(buf)
93    }
94}