nectar_primitives/file/
sync_read_at.rs1use std::io;
4
5use bytes::Bytes;
6
7pub trait SyncReadAt {
11 fn read_at(&self, offset: u64, buf: &mut [u8]) -> io::Result<usize>;
13
14 fn len(&self) -> u64;
16
17 fn is_empty(&self) -> bool {
19 self.len() == 0
20 }
21}
22
23impl SyncReadAt for [u8] {
24 fn read_at(&self, offset: u64, buf: &mut [u8]) -> io::Result<usize> {
25 let offset = offset as usize;
26 if offset >= self.len() {
27 return Ok(0);
28 }
29 let available = self.len() - offset;
30 let to_read = buf.len().min(available);
31 buf[..to_read].copy_from_slice(&self[offset..offset + to_read]);
32 Ok(to_read)
33 }
34
35 fn len(&self) -> u64 {
36 <[u8]>::len(self) as u64
37 }
38}
39
40impl SyncReadAt for Vec<u8> {
41 fn read_at(&self, offset: u64, buf: &mut [u8]) -> io::Result<usize> {
42 self.as_slice().read_at(offset, buf)
43 }
44
45 fn len(&self) -> u64 {
46 Self::len(self) as u64
47 }
48}
49
50impl SyncReadAt for Bytes {
51 fn read_at(&self, offset: u64, buf: &mut [u8]) -> io::Result<usize> {
52 self.as_ref().read_at(offset, buf)
53 }
54
55 fn len(&self) -> u64 {
56 Self::len(self) as u64
57 }
58}
59
60impl<T: SyncReadAt + ?Sized> SyncReadAt for &T {
61 fn read_at(&self, offset: u64, buf: &mut [u8]) -> io::Result<usize> {
62 (**self).read_at(offset, buf)
63 }
64
65 fn len(&self) -> u64 {
66 (**self).len()
67 }
68}
69
70#[cfg(unix)]
71impl SyncReadAt for std::fs::File {
72 fn read_at(&self, offset: u64, buf: &mut [u8]) -> io::Result<usize> {
73 use std::os::unix::fs::FileExt;
74 FileExt::read_at(self, buf, offset)
75 }
76
77 fn len(&self) -> u64 {
78 self.metadata().map(|m| m.len()).unwrap_or(0)
79 }
80}
81
82#[cfg(windows)]
83impl SyncReadAt for std::fs::File {
84 fn read_at(&self, offset: u64, buf: &mut [u8]) -> io::Result<usize> {
85 use std::os::windows::fs::FileExt;
86 FileExt::seek_read(self, buf, offset)
87 }
88
89 fn len(&self) -> u64 {
90 self.metadata().map(|m| m.len()).unwrap_or(0)
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn test_read_at_slice() {
100 let data = b"hello world";
101 let mut buf = [0u8; 5];
102
103 let n = data.as_slice().read_at(0, &mut buf).unwrap();
104 assert_eq!(n, 5);
105 assert_eq!(&buf, b"hello");
106
107 let n = data.as_slice().read_at(6, &mut buf).unwrap();
108 assert_eq!(n, 5);
109 assert_eq!(&buf, b"world");
110
111 let n = data.as_slice().read_at(9, &mut buf).unwrap();
112 assert_eq!(n, 2);
113 assert_eq!(&buf[..2], b"ld");
114
115 let n = data.as_slice().read_at(100, &mut buf).unwrap();
116 assert_eq!(n, 0);
117 }
118
119 #[test]
120 fn test_read_at_vec() {
121 let data = vec![0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9];
122 let mut buf = [0u8; 3];
123
124 let n = data.read_at(5, &mut buf).unwrap();
125 assert_eq!(n, 3);
126 assert_eq!(buf, [5, 6, 7]);
127
128 assert_eq!(data.len(), 10);
129 }
130
131 #[test]
132 fn test_read_at_bytes() {
133 let data = Bytes::from_static(b"test data");
134 let mut buf = [0u8; 4];
135
136 let n = data.read_at(5, &mut buf).unwrap();
137 assert_eq!(n, 4);
138 assert_eq!(&buf, b"data");
139
140 assert_eq!(SyncReadAt::len(&data), 9);
141 }
142
143 #[test]
144 fn test_read_at_ref() {
145 let data = b"reference";
146 let r: &[u8] = data;
147 let mut buf = [0u8; 3];
148
149 let n = (&r).read_at(0, &mut buf).unwrap();
150 assert_eq!(n, 3);
151 assert_eq!(&buf, b"ref");
152 }
153}