positioned_io_preview/
raf.rs1use std::fs::File;
2use std::io;
3use std::io::Write;
4#[cfg(windows)]
5use std::io::{Seek, SeekFrom};
6use std::path::Path;
7#[cfg(unix)]
8use std::os::unix::fs::FileExt;
9#[cfg(windows)]
10use std::os::windows::fs::FileExt;
11
12use super::{ReadAt, WriteAt};
13
14#[derive(Debug)]
47pub struct RandomAccessFile {
48 file: File,
49 #[cfg(not(unix))]
50 pos: u64,
51}
52
53impl RandomAccessFile {
54 pub fn open<P: AsRef<Path>>(path: P) -> io::Result<RandomAccessFile> {
57 RandomAccessFile::try_new(File::open(path)?)
58 }
59
60 pub fn try_new(file: File) -> io::Result<RandomAccessFile> {
62 RandomAccessFile::try_new_impl(file)
63 }
64
65 #[cfg(all(unix, target_os = "linux"))]
66 fn try_new_impl(file: File) -> io::Result<RandomAccessFile> {
67 unsafe {
68 use std::os::unix::io::AsRawFd;
69 libc::posix_fadvise(file.as_raw_fd(), 0, file.metadata()?.len() as i64, libc::POSIX_FADV_RANDOM);
70 }
71
72 Ok(RandomAccessFile { file })
73 }
74
75 #[cfg(all(unix, not(target_os = "linux")))]
76 fn try_new_impl(file: File) -> io::Result<RandomAccessFile> {
77 Ok(RandomAccessFile { file })
78 }
79
80 #[cfg(not(unix))]
81 fn try_new_impl(mut file: File) -> io::Result<RandomAccessFile> {
82 let pos = file.seek(SeekFrom::Current(0))?;
83 Ok(RandomAccessFile { file, pos })
84 }
85
86 pub fn try_into_inner(self) -> Result<File, (RandomAccessFile, io::Error)> {
88 RandomAccessFile::try_into_inner_impl(self)
89 }
90
91 #[cfg(unix)]
92 fn try_into_inner_impl(self) -> Result<File, (RandomAccessFile, io::Error)> {
93 Ok(self.file)
94 }
95
96 #[cfg(not(unix))]
97 fn try_into_inner_impl(mut self) -> Result<File, (RandomAccessFile, io::Error)> {
98 match self.file.seek(SeekFrom::Start(self.pos)) {
99 Ok(_) => Ok(self.file),
100 Err(err) => Err((self, err)),
101 }
102 }
103}
104
105
106#[cfg(unix)]
107impl ReadAt for RandomAccessFile {
108 #[inline]
109 fn read_at(&self, pos: u64, buf: &mut [u8]) -> io::Result<usize> {
110 FileExt::read_at(&self.file, buf, pos)
111 }
112}
113
114#[cfg(unix)]
115impl WriteAt for &RandomAccessFile {
116 fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize> {
117 FileExt::write_at(&self.file, buf, pos)
118 }
119
120 fn flush(&mut self) -> io::Result<()> {
121 Write::flush(&mut &self.file)
122 }
123}
124
125#[cfg(windows)]
126impl ReadAt for RandomAccessFile {
127 #[inline]
128 fn read_at(&self, pos: u64, buf: &mut [u8]) -> io::Result<usize> {
129 FileExt::seek_read(&self.file, buf, pos)
130 }
131}
132
133#[cfg(windows)]
134impl WriteAt for &RandomAccessFile {
135 fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize> {
136 FileExt::seek_write(&self.file, buf, pos)
137 }
138
139 fn flush(&mut self) -> io::Result<()> {
140 Write::flush(&mut &self.file)
141 }
142}
143
144impl WriteAt for RandomAccessFile {
145 fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize> {
146 WriteAt::write_at(&mut &*self, pos, buf)
147 }
148
149 fn flush(&mut self) -> io::Result<()> {
150 WriteAt::flush(&mut &*self)
151 }
152}