1use crate::{get_file_len, FileHandle, FileHandle::*, LengthSpec};
2use std::{
3 fs::File,
4 io::{self, Read, Seek},
5};
6
7fn open_as_mmap(fh: &File, offset: u64, len: usize) -> io::Result<memmap2::Mmap> {
10 unsafe {
11 memmap2::MmapOptions::new()
12 .offset(offset)
13 .len(len)
14 .map_copy_read_only(fh)
15 }
16}
17
18pub(crate) fn read_part_from_file_intern(
24 fh: &mut File,
25 offset: u64,
26 lenspec: LengthSpec,
27 flen_hint: Option<u64>,
28) -> io::Result<FileHandle> {
29 let evl: Option<usize> = {
31 let maxlen_i = std::isize::MAX as usize;
32
33 if lenspec.is_exact && lenspec.bound.map(|len| len > maxlen_i) == Some(true) {
34 return Err(io::Error::new(
35 io::ErrorKind::InvalidInput,
36 "length is too big",
37 ));
38 }
39
40 [
41 lenspec.bound,
42 flen_hint
43 .or_else(|| get_file_len(fh))
44 .map(|lx| (lx - offset) as usize),
45 ]
46 .iter()
47 .flatten()
48 .min()
49 .and_then(|&mxl| if mxl < maxlen_i { Some(mxl) } else { None })
50 };
51
52 match evl {
54 Some(0) => {
55 return Ok(Buffered(Vec::new().into()));
56 }
57 Some(lx) => {
58 if let Ok(ret) = open_as_mmap(fh, offset, lx) {
60 return Ok(Mapped(ret));
61 }
62 }
63 None => {}
64 }
65
66 fh.seek(io::SeekFrom::Start(offset))?;
68 let contents = match evl {
69 Some(0) => Vec::new(),
70 Some(lx) => {
71 let mut contents = core::iter::repeat(0u8).take(lx).collect::<Vec<_>>();
72 if lenspec.is_exact {
73 fh.read_exact(&mut contents)?;
74 } else {
75 let bcnt = fh.read(&mut contents)?;
76 contents.truncate(bcnt);
77 }
78 contents
79 }
80 None => {
81 let mut contents = Vec::new();
82 if let Err(x) = fh.read_to_end(&mut contents) {
83 if lenspec.is_exact || contents.is_empty() {
84 return Err(x);
85 }
86 }
87 contents
88 }
89 };
90 Ok(Buffered(contents.into_boxed_slice()))
91}
92
93#[inline]
94pub(crate) fn do_offset_add(offset: u64, x: i64) -> Option<u64> {
95 if x < 0 {
96 let xn = (-x) as u64;
97 if xn <= offset {
98 Some(offset - xn)
99 } else {
100 None
101 }
102 } else {
103 Some(offset + (x as u64))
104 }
105}