simple_fs/span/
read_span.rs1use crate::{Error, Result, SPath, open_file};
2use std::fs::File;
3use std::io::{self, ErrorKind};
4
5#[cfg(unix)]
6use std::os::unix::fs::FileExt as _;
7#[cfg(windows)]
8use std::os::windows::fs::FileExt as _;
9
10pub fn read_span(path: impl AsRef<SPath>, start: usize, end: usize) -> Result<String> {
12 let len = end.checked_sub(start).ok_or(Error::SpanInvalidStartAfterEnd)?;
13
14 let path = path.as_ref();
15 let file = open_file(path)?;
16
17 let res = read_exact_at(&file, start as u64, len).map_err(|err| Error::FileCantRead((path, err).into()))?;
18
19 let txt = String::from_utf8(res).map_err(|_| Error::SpanInvalidUtf8)?;
20
21 Ok(txt)
22}
23
24fn read_exact_at(file: &File, offset: u64, len: usize) -> io::Result<Vec<u8>> {
28 let mut buf = vec![0u8; len];
29 let mut filled = 0usize;
30
31 while filled < len {
32 #[cfg(unix)]
33 let n = file.read_at(&mut buf[filled..], offset + filled as u64)?;
34 #[cfg(windows)]
35 let n = file.seek_read(&mut buf[filled..], offset + filled as u64)?;
36
37 if n == 0 {
38 return Err(io::Error::new(
39 ErrorKind::UnexpectedEof,
40 "span exceeds file size (hit EOF)",
41 ));
42 }
43 filled += n;
44 }
45 Ok(buf)
46}
47
48