omf/file/
read_at.rs

1/// Read from a file-like object at an offset.
2pub trait ReadAt: Send + Sync + 'static {
3    /// Seeks to `offset` and performs reads into `buf`.
4    ///
5    /// Returns the number of bytes read.
6    ///
7    /// Note that similar to File::read, it is not an error to return with a short read.
8    /// May or may not move any underlying file pointer, even if the read fails or is short.
9    fn read_at(&self, buf: &mut [u8], offset: u64) -> std::io::Result<usize>;
10
11    /// Returns the length of the data.
12    fn size(&self) -> std::io::Result<u64>;
13}
14
15#[cfg(windows)]
16impl ReadAt for std::fs::File {
17    fn read_at(&self, buf: &mut [u8], offset: u64) -> std::io::Result<usize> {
18        use std::os::windows::fs::FileExt;
19        self.seek_read(buf, offset)
20    }
21
22    fn size(&self) -> std::io::Result<u64> {
23        self.metadata().map(|m| m.len())
24    }
25}
26
27#[cfg(unix)]
28impl ReadAt for std::fs::File {
29    fn read_at(&self, buf: &mut [u8], offset: u64) -> std::io::Result<usize> {
30        use std::os::unix::fs::FileExt;
31        FileExt::read_at(self, buf, offset)
32    }
33
34    fn size(&self) -> std::io::Result<u64> {
35        self.metadata().map(|m| m.len())
36    }
37}
38
39impl ReadAt for Vec<u8> {
40    fn read_at(&self, buf: &mut [u8], offset: u64) -> std::io::Result<usize> {
41        let start = usize::try_from(offset).expect("offset must fit in usize");
42        let end = start.saturating_add(buf.len()).min(self.len());
43        let slice = &self[start..end];
44        buf[..slice.len()].copy_from_slice(slice);
45        Ok(slice.len())
46    }
47
48    fn size(&self) -> std::io::Result<u64> {
49        Ok(self.len().try_into().expect("length must fit in u64"))
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn read_at_vec_middle() {
59        let data = vec![1, 2, 3, 4, 5];
60        let mut buf = [0; 3];
61        assert_eq!(data.read_at(&mut buf, 1).unwrap(), 3);
62        assert_eq!(&buf, &[2, 3, 4]);
63    }
64
65    #[test]
66    fn read_at_vec_end() {
67        let data = vec![1, 2, 3, 4, 5];
68        let mut buf = [0; 3];
69        assert_eq!(data.read_at(&mut buf, 3).unwrap(), 2);
70        assert_eq!(&buf, &[4, 5, 0]);
71    }
72}