diff --git a/Cargo.toml b/Cargo.toml index 89f9484..d405aab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,11 +2,17 @@ name = "mapped-file" description = "Construct a memory mapping over any file object" keywords = ["unix", "mmap", "generic", "file", "fd"] -version = "0.1.0" +version = "0.0.1" edition = "2021" +license="MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +# Add support for file-descriptor operations other than simply mapping +# TODO: XXX: Incomplete, will be enabled by default when complete +file=[] + [dependencies] lazy_static = "1.4.0" libc = "0.2.132" diff --git a/README.md b/README.md new file mode 100644 index 0000000..e4bb26b --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +# `MemoryFile`: Map over any file object + +A safe and ergonomic `mmap()` wrapper for arbitrary file-descriptor handles. + +__NOTE__: Working release, but still in development. + +## Usage + +`MemoryFile` can be used to consume any type `T` that implements `AsRawFd`, form a mapping over that file-descriptor, and then unmap the memory before the `T` itself is dropped (which can be a reference or value.) +The `MemoryFile` can also be consumed back into the `T`, unmapping (and optionally syncing) the memory in the process. + +### Examples + +A function mapping file memory working on arbitrary file-descriptor holding objects. + +```rust +pub fn files_equal(file1: &T, file2: &U, size: usize) -> io::Result + where T: AsRawFd, + U: AsRawFd +{ + let file1 = MappedFile::try_new(file1, size, Perm::Readonly, Flags::Private)?.with_advice(Advice::Sequential)?; + let file2 = MappedFile::try_new(file2, size, Perm::Readonly, Flags::Private)?.with_advice(Advice::Sequential)?; + Ok(&file1[..] == &file2[..]) +} +``` + +Although, it is probably a better pattern to allow the caller to handle the mapping, and the callee to take any kind of mapping like so: + +``` rust +pub fn files_equal(file1: &MappedFile, file2: &MappedFile) -> bool + where T: AsRawFd, + U: AsRawFd +{ + &file1[..] == &file2[..] +} + +``` + +However, `MappedFile` also implements `Borrow<[u8]>`, so any `&MappedFile` can be passed to any function as `AsRef<[u8]>` too. + +# License +MIT diff --git a/src/file/unmanaged.rs b/src/file/unmanaged.rs index a68e93f..ffa3a3f 100644 --- a/src/file/unmanaged.rs +++ b/src/file/unmanaged.rs @@ -6,4 +6,38 @@ use super::*; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct UnmanagedFD(RawFd); +impl UnmanagedFD { + #[inline] + pub fn new(alias: &(impl AsRawFd + ?Sized)) -> Self + { + Self(alias.as_raw_fd()) + } +} + +impl From for UnmanagedFD +{ + #[inline] + fn from(from: RawFd) -> Self + { + debug_assert!(from >= 0, "Invalid file descriptor"); + Self(from) + } +} + +impl FromRawFd for UnmanagedFD +{ + unsafe fn from_raw_fd(fd: RawFd) -> Self { + Self(fd) + } +} + + +impl AsRawFd for UnmanagedFD +{ + #[inline(always)] + fn as_raw_fd(&self) -> RawFd { + self.0 + } +} + //TODO: implement a full version of the temporary struct `UnmanagedFD` from `utf8encode` diff --git a/src/lib.rs b/src/lib.rs index 6b656d1..9d89ae3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,7 @@ mod ffi; use ffi::c_try; pub mod hugetlb; +#[cfg(feature="file")] pub mod file; use hugetlb::{