rapidgzip_core/
read_at.rs1use std::fs::File;
2use std::io;
3use std::sync::Arc;
4
5pub trait ReadAt: Send + Sync {
14 fn len(&self) -> io::Result<u64>;
16
17 fn read_at(&self, offset: u64, buffer: &mut [u8]) -> io::Result<usize>;
22
23 fn is_empty(&self) -> io::Result<bool> {
25 self.len().map(|length| length == 0)
26 }
27}
28
29#[cfg(unix)]
30impl ReadAt for File {
31 fn len(&self) -> io::Result<u64> {
32 self.metadata().map(|metadata| metadata.len())
33 }
34
35 fn read_at(&self, offset: u64, buffer: &mut [u8]) -> io::Result<usize> {
36 std::os::unix::fs::FileExt::read_at(self, buffer, offset)
37 }
38}
39
40#[cfg(windows)]
41impl ReadAt for File {
42 fn len(&self) -> io::Result<u64> {
43 self.metadata().map(|metadata| metadata.len())
44 }
45
46 fn read_at(&self, offset: u64, buffer: &mut [u8]) -> io::Result<usize> {
47 std::os::windows::fs::FileExt::seek_read(self, buffer, offset)
48 }
49}
50
51impl ReadAt for [u8] {
52 fn len(&self) -> io::Result<u64> {
53 Ok(self.len() as u64)
54 }
55
56 fn read_at(&self, offset: u64, buffer: &mut [u8]) -> io::Result<usize> {
57 let start = usize::try_from(offset).unwrap_or(usize::MAX);
58 if start >= self.len() {
59 return Ok(0);
60 }
61 let count = buffer.len().min(self.len() - start);
62 buffer[..count].copy_from_slice(&self[start..start + count]);
63 Ok(count)
64 }
65}
66
67impl ReadAt for Vec<u8> {
68 fn len(&self) -> io::Result<u64> {
69 Ok(self.as_slice().len() as u64)
70 }
71
72 fn read_at(&self, offset: u64, buffer: &mut [u8]) -> io::Result<usize> {
73 self.as_slice().read_at(offset, buffer)
74 }
75}
76
77impl<T: ReadAt + ?Sized> ReadAt for Arc<T> {
78 fn len(&self) -> io::Result<u64> {
79 (**self).len()
80 }
81
82 fn read_at(&self, offset: u64, buffer: &mut [u8]) -> io::Result<usize> {
83 (**self).read_at(offset, buffer)
84 }
85}
86
87impl<T: ReadAt + ?Sized> ReadAt for Box<T> {
88 fn len(&self) -> io::Result<u64> {
89 (**self).len()
90 }
91
92 fn read_at(&self, offset: u64, buffer: &mut [u8]) -> io::Result<usize> {
93 (**self).read_at(offset, buffer)
94 }
95}