Skip to content

Commit 5157093

Browse files
Merge pull request #41 from triblespace/codex/work-on-next-task-from-inventory
Add map_file_region helper
2 parents 2122aa9 + eface47 commit 5157093

File tree

5 files changed

+40
-1
lines changed

5 files changed

+40
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
- skip Python examples when the `pyo3` feature is disabled to fix `cargo test`
5151
- added `Bytes::map_file` helper for convenient file mapping
5252
(accepts any `memmap2::MmapAsRawDesc`, e.g. `&File` or `&NamedTempFile`)
53+
- added `Bytes::map_file_region` to map a specific region of a file
5354
- reverted automatic installation of Python development packages in the
5455
preflight script; rely on the system `python3-dev` package
5556
- set the preflight script to use Python 3.12 for building pyo3 code

INVENTORY.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
- None at the moment.
55

66
## Desired Functionality
7-
- Helper `map_file_region` to map only part of a file.
87
- Example demonstrating Python + winnow parsing.
98
- Additional Kani proofs covering `try_unwrap_owner` and weak references.
109

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ fn read_header(file: &std::fs::File) -> std::io::Result<anybytes::view::View<Hea
9898
}
9999
```
100100

101+
To map only a portion of a file use the unsafe helper
102+
`Bytes::map_file_region(file, offset, len)`.
103+
101104
## Features
102105

103106
By default the crate enables the `mmap` and `zerocopy` features.

src/bytes.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,31 @@ impl Bytes {
233233
Ok(Self::from_source(map))
234234
}
235235

236+
/// Memory-map a specific region of the given file descriptor and return the
237+
/// bytes.
238+
///
239+
/// # Safety
240+
///
241+
/// The caller must ensure that the mapped file is not modified for the
242+
/// lifetime of the returned [`Bytes`]. Changing the file contents while it
243+
/// is mapped can lead to undefined behavior. The file handle does not need
244+
/// to remain open after mapping. The `offset` must meet the underlying
245+
/// platform's alignment requirements (typically page size).
246+
///
247+
/// The argument may be any type that implements [`memmap2::MmapAsRawDesc`],
248+
/// such as [`&std::fs::File`] or [`&tempfile::NamedTempFile`].
249+
#[cfg(feature = "mmap")]
250+
pub unsafe fn map_file_region<F>(file: F, offset: u64, len: usize) -> std::io::Result<Self>
251+
where
252+
F: memmap2::MmapAsRawDesc,
253+
{
254+
let map = memmap2::MmapOptions::new()
255+
.offset(offset)
256+
.len(len)
257+
.map(file)?;
258+
Ok(Self::from_source(map))
259+
}
260+
236261
#[inline]
237262
pub(crate) fn as_slice<'a>(&'a self) -> &'a [u8] {
238263
self.data

src/tests.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,17 @@ fn test_map_file() {
247247
assert_eq!(bytes.as_ref(), b"testfile");
248248
}
249249

250+
#[cfg(feature = "mmap")]
251+
#[test]
252+
fn test_map_file_region() {
253+
use std::io::Write;
254+
let mut file = tempfile::NamedTempFile::new().expect("temp file");
255+
file.write_all(b"abcdef").expect("write");
256+
file.flush().unwrap();
257+
let bytes = unsafe { Bytes::map_file_region(&file, 1, 3) }.expect("map file region");
258+
assert_eq!(bytes.as_ref(), b"bcd");
259+
}
260+
250261
#[test]
251262
fn test_cow_u8_owned_source() {
252263
use std::borrow::Cow;

0 commit comments

Comments
 (0)