#[derive(Copy, Clone)]
enum MmapFileMutType {
Cow,
Normal,
}
macro_rules! remmap {
($path: ty) => {
#[inline]
fn remmap<T: MmapAsRawDesc>(
path: &$path,
file: T,
opts: Option<&MmapOptions>,
typ: MmapFileMutType,
) -> Result<MmapMut, Error> {
unsafe {
match opts {
None => match typ {
MmapFileMutType::Cow => MmapOptions::new().map_copy(file),
MmapFileMutType::Normal => MmapMut::map_mut(file),
},
Some(opts) => {
let opts = opts.clone();
match typ {
MmapFileMutType::Cow => opts.map_copy(file),
MmapFileMutType::Normal => opts.map_mut(file),
}
}
}
.map_err(|e| {
Error::new_source_msg(ErrorKind::RemmapFailed, path.to_string_lossy(), e)
})
}
}
};
}
macro_rules! impl_flush {
() => {
fn flush(&self) -> crate::error::Result<()> {
self.mmap
.flush()
.map_err(|e| Error::new_source_msg(ErrorKind::FlushFailed, self.path_string(), e))
}
fn flush_async(&self) -> crate::error::Result<()> {
self.mmap
.flush_async()
.map_err(|e| Error::new_source_msg(ErrorKind::FlushFailed, self.path_string(), e))
}
fn flush_range(&self, offset: usize, len: usize) -> crate::error::Result<()> {
self.mmap
.flush_range(offset, len)
.map_err(|e| Error::new_source_msg(ErrorKind::FlushFailed, self.path_string(), e))
}
fn flush_async_range(&self, offset: usize, len: usize) -> crate::error::Result<()> {
self.mmap
.flush_async_range(offset, len)
.map_err(|e| Error::new_source_msg(ErrorKind::FlushFailed, self.path_string(), e))
}
};
}
macro_rules! impl_file_lock {
() => {
#[inline]
fn lock_exclusive(&self) -> crate::error::Result<()> {
self.file
.lock_exclusive()
.map_err(|e| Error::new(ErrorKind::IO, e))
}
#[inline]
fn lock_shared(&self) -> crate::error::Result<()> {
self.file
.lock_shared()
.map_err(|e| Error::new(ErrorKind::IO, e))
}
#[inline]
fn try_lock_exclusive(&self) -> crate::error::Result<()> {
self.file
.try_lock_exclusive()
.map_err(|e| Error::new(ErrorKind::IO, e))
}
#[inline]
fn try_lock_shared(&self) -> crate::error::Result<()> {
self.file
.try_lock_shared()
.map_err(|e| Error::new(ErrorKind::IO, e))
}
#[inline]
fn unlock(&self) -> crate::error::Result<()> {
self.file.unlock().map_err(|e| Error::new(ErrorKind::IO, e))
}
};
}
cfg_sync! {
macro_rules! impl_mmap_file_ext_base {
() => {
fn len(&self) -> usize {
self.mmap.len()
}
fn as_slice(&self) -> &[u8] {
self.mmap.as_ref()
}
fn path(&self) -> &Path {
self.path.as_path()
}
fn metadata(&self) -> crate::error::Result<MetaData> {
self.file.metadata().map(MetaData::disk).map_err(|e| Error::new(ErrorKind::IO, e))
}
impl_file_lock!();
};
}
macro_rules! impl_mmap_file_ext {
($name: ident) => {
impl MmapFileExt for $name {
impl_mmap_file_ext_base!();
#[inline]
fn is_exec(&self) -> bool {
self.exec
}
}
};
}
macro_rules! impl_mmap_file_ext_for_mut {
($name: ident) => {
impl MmapFileExt for $name {
impl_mmap_file_ext_base!();
#[inline]
fn is_exec(&self) -> bool {
false
}
}
};
}
mod sync_impl;
pub use sync_impl::{DiskMmapFile, DiskMmapFileMut};
}
cfg_async! {
macro_rules! impl_async_mmap_file_ext {
($name: ident) => {
#[async_trait]
impl AsyncMmapFileExt for $name {
fn len(&self) -> usize {
self.mmap.len()
}
fn as_slice(&self) -> &[u8] {
self.mmap.as_ref()
}
fn path(&self) -> &Path {
self.path.as_path()
}
#[inline]
async fn metadata(&self) -> crate::error::Result<MetaData> {
self.file
.metadata()
.await
.map(MetaData::disk)
.map_err(|e| Error::new(ErrorKind::IO, e))
}
#[inline]
fn is_exec(&self) -> bool {
self.exec
}
impl_file_lock!();
}
};
}
macro_rules! impl_async_mmap_file_ext_for_mut {
($name: ident) => {
#[async_trait]
impl AsyncMmapFileExt for $name {
fn len(&self) -> usize {
self.mmap.len()
}
fn as_slice(&self) -> &[u8] {
self.mmap.as_ref()
}
fn path(&self) -> &Path {
self.path.as_path()
}
#[inline]
async fn metadata(&self) -> crate::error::Result<MetaData> {
self.file
.metadata()
.await
.map(MetaData::disk)
.map_err(|e| Error::new(ErrorKind::IO, e))
}
#[inline]
fn is_exec(&self) -> bool {
false
}
impl_file_lock!();
}
};
}
macro_rules! declare_and_impl_async_fmmap_file {
($filename_prefix: literal, $doc_test_runtime: literal, $path_str: literal, $base_file: ty) => {
pub struct AsyncDiskMmapFile {
pub(crate) mmap: Mmap,
pub(crate) file: $base_file,
pub(crate) path: PathBuf,
exec: bool,
}
impl_async_mmap_file_ext!(AsyncDiskMmapFile);
impl AsyncDiskMmapFile {
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::AsyncMmapFileExt;")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFile;")]
#[doc = concat!("# use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileMutExt};")]
#[doc = " # use scopeguard::defer;"]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = concat!("# let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_disk_open_test.txt\").await.unwrap();")]
#[doc = concat!(" # defer!(std::fs::remove_file(\"", $filename_prefix, "_disk_open_test.txt\").unwrap());")]
#[doc = concat!("# file.truncate(100).await.unwrap();")]
#[doc = concat!("# file.write_all(\"some data...\".as_bytes(), 0).unwrap();")]
#[doc = concat!("# file.flush().unwrap();")]
#[doc = "# drop(file);"]
#[doc = "// mmap the file"]
#[doc = concat!("let mut file = AsyncDiskMmapFile::open(\"", $filename_prefix, "_disk_open_test.txt\").await.unwrap();")]
#[doc = "let mut buf = vec![0; \"some data...\".len()];"]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some data...\".as_bytes());"]
#[doc = "# })"]
#[doc = "```"]
pub async fn open<P: AsRef<Path>>(path: P,) -> Result<Self, Error> {
Self::open_in(path, None).await
}
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::{AsyncOptions, AsyncMmapFileExt};")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFile;")]
#[doc = concat!("# use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileMutExt};")]
#[doc = " # use scopeguard::defer;"]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = concat!("# let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_disk_open_with_options_test.txt\").await.unwrap();")]
#[doc = concat!(" # defer!(std::fs::remove_file(\"", $filename_prefix, "_disk_open_with_options_test.txt\").unwrap());")]
#[doc = concat!("# file.truncate(23).await.unwrap();")]
#[doc = concat!("# file.write_all(\"sanity text\".as_bytes(), 0).unwrap();")]
#[doc = concat!("# file.write_all(\"some data...\".as_bytes(), \"sanity text\".as_bytes().len()).unwrap();")]
#[doc = concat!("# file.flush().unwrap();")]
#[doc = "# drop(file);"]
#[doc = "// mmap the file"]
#[doc = "let opts = AsyncOptions::new()"]
#[doc = " // mmap content after the sanity text"]
#[doc = " .offset(\"sanity text\".as_bytes().len() as u64);"]
#[doc = "// mmap the file"]
#[doc = concat!("let mut file = AsyncDiskMmapFile::open_with_options(\"", $filename_prefix, "_disk_open_with_options_test.txt\", opts).await.unwrap();")]
#[doc = "let mut buf = vec![0; \"some data...\".len()];"]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some data...\".as_bytes());"]
#[doc = "# })"]
#[doc = "```"]
pub async fn open_with_options<P: AsRef<Path>>(path: P, opts: AsyncOptions) -> Result<Self, Error> {
Self::open_in(path, Some(opts)).await
}
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::AsyncMmapFileExt;")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFile;")]
#[doc = concat!("# use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileMutExt};")]
#[doc = " # use scopeguard::defer;"]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = concat!("# let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_disk_open_exec_test.txt\").await.unwrap();")]
#[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_disk_open_exec_test.txt\").unwrap());")]
#[doc = concat!("# file.truncate(100).await.unwrap();")]
#[doc = concat!("# file.write_all(\"some data...\".as_bytes(), 0).unwrap();")]
#[doc = concat!("# file.flush().unwrap();")]
#[doc = "# drop(file);"]
#[doc = "// mmap the file"]
#[doc = concat!("let mut file = AsyncDiskMmapFile::open_exec(\"", $filename_prefix, "_disk_open_exec_test.txt\").await.unwrap();")]
#[doc = "let mut buf = vec![0; \"some data...\".len()];"]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some data...\".as_bytes());"]
#[doc = "# })"]
#[doc = "```"]
pub async fn open_exec<P: AsRef<Path>>(path: P,) -> Result<Self, Error> {
Self::open_exec_in(path, None).await
}
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::{AsyncOptions, AsyncMmapFileExt};")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFile;")]
#[doc = concat!("# use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileMutExt};")]
#[doc = " # use scopeguard::defer;"]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = concat!("# let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_disk_open_exec_with_options_test.txt\").await.unwrap();")]
#[doc = concat!(" # defer!(std::fs::remove_file(\"", $filename_prefix, "_disk_open_exec_with_options_test.txt\").unwrap());")]
#[doc = concat!("# file.truncate(23).await.unwrap();")]
#[doc = concat!("# file.write_all(\"sanity text\".as_bytes(), 0).unwrap();")]
#[doc = concat!("# file.write_all(\"some data...\".as_bytes(), \"sanity text\".as_bytes().len()).unwrap();")]
#[doc = concat!("# file.flush().unwrap();")]
#[doc = "# drop(file);"]
#[doc = "// mmap the file"]
#[doc = "let opts = AsyncOptions::new()"]
#[doc = " // mmap content after the sanity text"]
#[doc = " .offset(\"sanity text\".as_bytes().len() as u64);"]
#[doc = "// mmap the file"]
#[doc = concat!("let mut file = AsyncDiskMmapFile::open_exec_with_options(\"", $filename_prefix, "_disk_open_exec_with_options_test.txt\", opts).await.unwrap();")]
#[doc = "let mut buf = vec![0; \"some data...\".len()];"]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some data...\".as_bytes());"]
#[doc = "# })"]
#[doc = "```"]
pub async fn open_exec_with_options<P: AsRef<Path>>(path: P, opts: AsyncOptions) -> Result<Self, Error> {
Self::open_exec_in(path, Some(opts)).await
}
async fn open_in<P: AsRef<Path>>(path: P, opts: Option<AsyncOptions>) -> Result<Self, Error> {
let file = open_read_only_file_async(&path).await.map_err(|e| Error::new_source_msg(ErrorKind::OpenFailed, path.as_ref().to_string_lossy(), e))?;
match opts {
None => {
let mmap = unsafe {
Mmap::map(&file).map_err(|e| Error::new(ErrorKind::MmapFailed, e))?
};
Ok(Self {
mmap,
file,
path: path.as_ref().to_path_buf(),
exec: false
})
}
Some(opts) => {
let mmap = unsafe {
opts.mmap_opts.map(&file).map_err(|e| Error::new(ErrorKind::MmapFailed, e))?
};
Ok(Self {
mmap,
file,
path: path.as_ref().to_path_buf(),
exec: false,
})
}
}
}
async fn open_exec_in<P: AsRef<Path>>(path: P, opts: Option<AsyncOptions>) -> Result<Self, Error> {
let file = open_read_only_file_async(&path)
.await
.map_err(|e| Error::new_source_msg(ErrorKind::OpenFailed, path.as_ref().to_string_lossy(), e))?;
match opts {
None => {
let mmap = unsafe {
MmapOptions::new().map_exec(&file).map_err(|e| Error::new(ErrorKind::MmapFailed, e))?
};
Ok(Self {
mmap,
file,
path: path.as_ref().to_path_buf(),
exec: true,
})
}
Some(opts) => {
let mmap = unsafe {
opts.mmap_opts.map_exec(&file).map_err(|e| Error::new(ErrorKind::MmapFailed, e))?
};
Ok(Self {
mmap,
file,
path: path.as_ref().to_path_buf(),
exec: true
})
}
}
}
}
};
}
macro_rules! impl_async_mmap_file_mut_ext_for_mut {
($filename_prefix: literal, $doc_test_runtime: literal, $path_str: literal) => {
#[async_trait]
impl AsyncMmapFileMutExt for AsyncDiskMmapFileMut {
fn as_mut_slice(&mut self) -> &mut [u8] {
self.mmap.as_mut()
}
fn is_cow(&self) -> bool {
matches!(self.typ, MmapFileMutType::Cow)
}
impl_flush!();
#[cfg(not(target_os = "linux"))]
async fn truncate(&mut self, max_sz: u64) -> Result<(), Error> {
if self.is_cow() {
return Err(Error::new_with_message(ErrorKind::TruncationFailed, "cannot truncate a copy-on-write mmap file"));
}
let meta = self.file.metadata().await.map_err(|e| Error::new(ErrorKind::IO, e))?;
if meta.len() > 0 {
self.flush()?;
}
unsafe {
drop_in_place(&mut self.mmap);
self.file.set_len(max_sz).await.map_err(|e| Error::new_source_msg(ErrorKind::TruncationFailed, self.path_lossy(), e))?;
let mmap = remmap(self.path(), &self.file, self.opts.as_ref(), self.typ)?;
write(&mut self.mmap, mmap);
}
Ok(())
}
#[cfg(target_os = "linux")]
async fn truncate(&mut self, max_sz: u64) -> Result<(), Error> {
if self.is_cow() {
return Err(Error::new_with_message(ErrorKind::TruncationFailed, "cannot truncate a copy-on-write mmap file"));
}
self.flush()?;
self.file.set_len(max_sz).await.map_err(|e| Error::new_source_msg(ErrorKind::TruncationFailed, self.path_lossy(), e))?;
self.mmap = remmap(self.path(), &self.file, self.opts.as_ref(), self.typ)?;
Ok(())
}
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::AsyncMmapFileMutExt;")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFileMut;")]
#[doc = ""]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::create(\"", $filename_prefix, "_disk_remove_test.txt\").await.unwrap();")]
#[doc = ""]
#[doc = "file.truncate(100).await;"]
#[doc = "file.write_all(\"some data...\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = ""]
#[doc = "file.drop_remove().await.unwrap();"]
#[doc = ""]
#[doc = concat!("let err = ", $path_str, "::fs::File::open(\"", $filename_prefix, "_disk_remove_test.txt\").await;")]
#[doc = "assert_eq!(err.unwrap_err().kind(), std::io::ErrorKind::NotFound);"]
#[doc = "# })"]
#[doc = "```"]
async fn drop_remove(mut self) -> crate::error::Result<()> {
let path = self.path;
drop(self.mmap);
self.file.set_len(0).await.map_err(|e| Error::new(ErrorKind::IO, e))?;
drop(self.file);
remove_file(path).await.map_err(|e| Error::new(ErrorKind::IO, e))?;
Ok(())
}
#[doc = "```ignore"]
#[doc = "use fmmap::MetaDataExt;"]
#[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileExt, AsyncMmapFileMutExt};")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFileMut;")]
#[doc = "# use scopeguard::defer;"]
#[doc = ""]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::create(\"", $filename_prefix, "_disk_close_with_truncate_test.txt\").await.unwrap();")]
#[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_disk_close_with_truncate_test.txt\").unwrap());")]
#[doc = "file.truncate(100).await;"]
#[doc = "file.write_all(\"some data...\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = "file.close_with_truncate(50).await.unwrap();"]
#[doc = ""]
#[doc = concat!("let file = AsyncDiskMmapFileMut::open(\"", $filename_prefix, "_disk_close_with_truncate_test.txt\").await.unwrap();")]
#[doc = "let meta = file.metadata().await.unwrap();"]
#[doc = "assert_eq!(meta.len(), 50);"]
#[doc = "# })"]
#[doc = "```"]
async fn close_with_truncate(self, max_sz: i64) -> crate::error::Result<()> {
#[cfg(not(target_os = "linux"))]
{
let meta = self.file.metadata().await.map_err(|e| Error::new(ErrorKind::IO, e))?;
if meta.len() > 0 {
self.flush()?;
}
}
#[cfg(target_os = "linux")]
{
self.flush()?;
}
drop(self.mmap);
if max_sz >= 0 {
self.file.set_len(max_sz as u64).await.map_err(|e| Error::new(ErrorKind::IO, e))?;
sync_parent_async(&self.path).await?;
}
Ok(())
}
}
};
}
macro_rules! declare_and_impl_async_fmmap_file_mut {
($filename_prefix: literal, $doc_test_runtime: literal, $path_str: literal, $base_file: ty, $immutable_file: ident) => {
pub struct AsyncDiskMmapFileMut {
pub(crate) mmap: MmapMut,
pub(crate) file: $base_file,
pub(crate) path: PathBuf,
opts: Option<MmapOptions>,
typ: MmapFileMutType,
}
impl_async_mmap_file_ext_for_mut!(AsyncDiskMmapFileMut);
impl_async_mmap_file_mut_ext_for_mut!($filename_prefix, $doc_test_runtime, $path_str);
impl AsyncDiskMmapFileMut {
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::AsyncMmapFileMutExt;")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFileMut;")]
#[doc = " # use scopeguard::defer;"]
#[doc = ""]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::create(\"", $filename_prefix, "_disk_create_test.txt\").await.unwrap();")]
#[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_disk_create_test.txt\").unwrap());")]
#[doc = "file.truncate(100).await;"]
#[doc = "file.write_all(\"some data...\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = "# })"]
#[doc = "```"]
#[doc = ""]
#[doc = concat!("[`create_with_options`]: raw/", $path_str, "/struct.AsyncDiskMmapFileMut.html#method.create_with_options")]
#[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
pub async fn create<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
Self::create_in(path, None).await
}
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::{AsyncOptions, AsyncMmapFileMutExt};")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFileMut;")]
#[doc = " # use scopeguard::defer;"]
#[doc = ""]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = "let opts = AsyncOptions::new()"]
#[doc = " // truncate to 100"]
#[doc = " .max_size(100);"]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::create_with_options(\"", $filename_prefix, "_disk_create_with_options_test.txt\", opts).await.unwrap();")]
#[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_disk_create_with_options_test.txt\").unwrap());")]
#[doc = "file.write_all(\"some data...\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = "# })"]
#[doc = "```"]
#[doc = ""]
#[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
pub async fn create_with_options<P: AsRef<Path>>(path: P, opts: AsyncOptions) -> Result<Self, Error> {
Self::create_in(path, Some(opts)).await
}
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileExt, AsyncMmapFileMutExt};")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFileMut;")]
#[doc = " # use scopeguard::defer;"]
#[doc = ""]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = concat!("# let mut file = AsyncDiskMmapFileMut::create(\"", $filename_prefix, "_disk_open_test.txt\").await.unwrap();")]
#[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_disk_open_test.txt\").unwrap());")]
#[doc = concat!("# file.truncate(100).await.unwrap();")]
#[doc = concat!("# file.write_all(\"some data...\".as_bytes(), 0).unwrap();")]
#[doc = concat!("# file.flush().unwrap();")]
#[doc = "# drop(file);"]
#[doc = ""]
#[doc = "// mmap the file"]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::open(\"", $filename_prefix, "_disk_open_test.txt\").await.unwrap();")]
#[doc = "let mut buf = vec![0; \"some data...\".len()];"]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some data...\".as_bytes());"]
#[doc = ""]
#[doc = "// modify the file data"]
#[doc = "file.truncate(\"some modified data...\".len() as u64).await.unwrap();"]
#[doc = "file.write_all(\"some modified data...\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = "drop(file);"]
#[doc = ""]
#[doc = "// reopen to check content"]
#[doc = "let mut buf = vec![0; \"some modified data...\".len()];"]
#[doc = concat!("let file = AsyncDiskMmapFileMut::open(\"", $filename_prefix, "_disk_open_test.txt\").await.unwrap();")]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some modified data...\".as_bytes());"]
#[doc = "# })"]
#[doc = "```"]
#[doc = ""]
#[doc = "File does not exists"]
#[doc = ""]
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileExt, AsyncMmapFileMutExt};")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFileMut;")]
#[doc = " # use scopeguard::defer;"]
#[doc = ""]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = "// mmap the file"]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::open(\"", $filename_prefix, "_disk_open_test.txt\").await.unwrap();")]
#[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_disk_open_test.txt\").unwrap());")]
#[doc = "file.truncate(100).await.unwrap();"]
#[doc = "file.write_all(\"some data...\".as_bytes(), 0).unwrap();"]
#[doc = ""]
#[doc = "let mut buf = vec![0; \"some data...\".len()];"]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some data...\".as_bytes());"]
#[doc = ""]
#[doc = "// modify the file data"]
#[doc = "file.truncate(\"some modified data...\".len() as u64).await.unwrap();"]
#[doc = "file.write_all(\"some modified data...\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = "drop(file);"]
#[doc = ""]
#[doc = "// reopen to check content"]
#[doc = "let mut buf = vec![0; \"some modified data...\".len()];"]
#[doc = concat!("let file = AsyncDiskMmapFileMut::open(\"", $filename_prefix, "_disk_open_test.txt\").await.unwrap();")]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some modified data...\".as_bytes());"]
#[doc = "# })"]
#[doc = "```"]
#[doc = ""]
#[doc = concat!("[`open_with_options`]: raw/", $path_str, "/struct.AsyncDiskMmapFileMut.html#method.open_with_options")]
#[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
pub async fn open<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
Self::open_in(path, None).await
}
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileExt, AsyncMmapFileMutExt, AsyncOptions};")]
#[doc = "# use scopeguard::defer;"]
#[doc = ""]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = concat!("# let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_open_with_options_test.txt\").await.unwrap();")]
#[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_open_with_options_test.txt\").unwrap());")]
#[doc = "# file.truncate(23).await.unwrap();"]
#[doc = "# file.write_all(\"sanity text\".as_bytes(), 0).unwrap();"]
#[doc = "# file.write_all(\"some data...\".as_bytes(), \"sanity text\".as_bytes().len()).unwrap();"]
#[doc = "# file.flush().unwrap();"]
#[doc = "# drop(file);"]
#[doc = ""]
#[doc = "let opts = AsyncOptions::new()"]
#[doc = " // allow read"]
#[doc = " .read(true)"]
#[doc = " // allow write"]
#[doc = " .write(true)"]
#[doc = " // allow append"]
#[doc = " .append(true)"]
#[doc = " // truncate to 100"]
#[doc = " .max_size(100)"]
#[doc = " // mmap content after the sanity text"]
#[doc = " .offset(\"sanity text\".as_bytes().len() as u64);"]
#[doc = concat!("let mut file = AsyncMmapFileMut::open_with_options(\"", $filename_prefix, "_open_with_options_test.txt\", opts).await.unwrap();")]
#[doc = "let mut buf = vec![0; \"some data...\".len()];"]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some data...\".as_bytes());"]
#[doc = ""]
#[doc = "// modify the file data"]
#[doc = "file.truncate((\"some modified data...\".len() + \"sanity text\".len()) as u64).await.unwrap();"]
#[doc = "file.write_all(\"some modified data...\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = "drop(file);"]
#[doc = ""]
#[doc = "// reopen to check content"]
#[doc = "let mut buf = vec![0; \"some modified data...\".len()];"]
#[doc = concat!("let mut file = AsyncMmapFileMut::open(\"", $filename_prefix, "_open_with_options_test.txt\").await.unwrap();")]
#[doc = "// skip the sanity text"]
#[doc = "file.read_exact(buf.as_mut_slice(), \"sanity text\".as_bytes().len()).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some modified data...\".as_bytes());"]
#[doc = "# })"]
#[doc = "```"]
#[doc = ""]
#[doc = "File does not exists"]
#[doc = ""]
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileExt, AsyncMmapFileMutExt, AsyncOptions};")]
#[doc = "# use scopeguard::defer;"]
#[doc = ""]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = "// mmap the file with options"]
#[doc = "let opts = AsyncOptions::new()"]
#[doc = " // allow read"]
#[doc = " .read(true)"]
#[doc = " // allow write"]
#[doc = " .write(true)"]
#[doc = " // allow append"]
#[doc = " .append(true)"]
#[doc = " // truncate to 100"]
#[doc = " .max_size(100);"]
#[doc = concat!("let mut file = AsyncMmapFileMut::open_with_options(\"", $filename_prefix, "_open_with_options_test.txt\", opts).await.unwrap();")]
#[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_open_with_options_test.txt\").unwrap());")]
#[doc = "file.write_all(\"some data...\".as_bytes(), 0).unwrap();"]
#[doc = ""]
#[doc = "let mut buf = vec![0; \"some data...\".len()];"]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some data...\".as_bytes());"]
#[doc = ""]
#[doc = "// modify the file data"]
#[doc = "file.truncate(\"some modified data...\".len() as u64).await.unwrap();"]
#[doc = "file.write_all(\"some modified data...\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = "drop(file);"]
#[doc = ""]
#[doc = "// reopen to check content"]
#[doc = "let mut buf = vec![0; \"some modified data...\".len()];"]
#[doc = concat!("let mut file = AsyncMmapFileMut::open(\"", $filename_prefix, "_open_with_options_test.txt\").await.unwrap();")]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some modified data...\".as_bytes());"]
#[doc = "# })"]
#[doc = "```"]
#[doc = ""]
#[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
pub async fn open_with_options<P: AsRef<Path>>(path: P, opts: AsyncOptions) -> Result<Self, Error> {
Self::open_in(path, Some(opts)).await
}
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileExt, AsyncMmapFileMutExt};")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFileMut;")]
#[doc = " # use scopeguard::defer;"]
#[doc = ""]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = "// create a temp file"]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::create(\"", $filename_prefix, "_disk_open_existing_test.txt\").await.unwrap();")]
#[doc = "file.truncate(100).await.unwrap();"]
#[doc = "file.write_all(\"some data...\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_disk_open_existing_test.txt\").unwrap());")]
#[doc = "drop(file);"]
#[doc = ""]
#[doc = "// mmap the file"]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::open_exist(\"", $filename_prefix, "_disk_open_existing_test.txt\").await.unwrap();")]
#[doc = "let mut buf = vec![0; \"some data...\".len()];"]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some data...\".as_bytes());"]
#[doc = ""]
#[doc = "// modify the file data"]
#[doc = "file.truncate(\"some modified data...\".len() as u64).await.unwrap();"]
#[doc = "file.write_all(\"some modified data...\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = "drop(file);"]
#[doc = ""]
#[doc = ""]
#[doc = "// reopen to check content"]
#[doc = "let mut buf = vec![0; \"some modified data...\".len()];"]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::open_exist(\"", $filename_prefix, "_disk_open_existing_test.txt\").await.unwrap();")]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some modified data...\".as_bytes());"]
#[doc = "# })"]
#[doc = "```"]
#[doc = ""]
#[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
pub async fn open_exist<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
Self::open_exist_in(path, None).await
}
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileExt, AsyncMmapFileMutExt, AsyncOptions};")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFileMut;")]
#[doc = " # use scopeguard::defer;"]
#[doc = ""]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = "// create a temp file"]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::create(\"", $filename_prefix, "_disk_open_existing_test_with_options.txt\").await.unwrap();")]
#[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_disk_open_existing_test_with_options.txt\").unwrap());")]
#[doc = "file.truncate(23).await.unwrap();"]
#[doc = "file.write_all(\"sanity text\".as_bytes(), 0).unwrap();"]
#[doc = "file.write_all(\"some data...\".as_bytes(), \"sanity text\".as_bytes().len()).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = "drop(file);"]
#[doc = ""]
#[doc = "// mmap the file"]
#[doc = "let opts = AsyncOptions::new()"]
#[doc = " // truncate to 100"]
#[doc = " .max_size(100)"]
#[doc = " // mmap content after the sanity text"]
#[doc = " .offset(\"sanity text\".as_bytes().len() as u64);"]
#[doc = ""]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::open_exist_with_options(\"", $filename_prefix, "_disk_open_existing_test_with_options.txt\", opts).await.unwrap();")]
#[doc = "let mut buf = vec![0; \"some data...\".len()];"]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some data...\".as_bytes());"]
#[doc = ""]
#[doc = "// modify the file data"]
#[doc = "file.truncate((\"some modified data...\".len() + \"sanity text\".len()) as u64).await.unwrap();"]
#[doc = "file.write_all(\"some modified data...\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = ""]
#[doc = ""]
#[doc = "// reopen to check content, cow will not change the content."]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::open(\"", $filename_prefix, "_disk_open_existing_test_with_options.txt\").await.unwrap();")]
#[doc = "let mut buf = vec![0; \"some modified data...\".len()];"]
#[doc = "// skip the sanity text"]
#[doc = "file.read_exact(buf.as_mut_slice(), \"sanity text\".as_bytes().len()).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some modified data...\".as_bytes());"]
#[doc = "# })"]
#[doc = "```"]
#[doc = ""]
#[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
pub async fn open_exist_with_options<P: AsRef<Path>>(path: P, opts: AsyncOptions) -> Result<Self, Error> {
Self::open_exist_in(path, Some(opts)).await
}
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileExt, AsyncMmapFileMutExt};")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFileMut;")]
#[doc = "# use scopeguard::defer;"]
#[doc = ""]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = "// create a temp file"]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::create(\"", $filename_prefix, "_disk_open_cow_test.txt\").await.unwrap();")]
#[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_disk_open_cow_test.txt\").unwrap());")]
#[doc = "file.truncate(12).await.unwrap();"]
#[doc = "file.write_all(\"some data...\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = "drop(file);"]
#[doc = ""]
#[doc = "// mmap the file"]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::open_cow(\"", $filename_prefix, "_disk_open_cow_test.txt\").await.unwrap();")]
#[doc = "let mut buf = vec![0; \"some data...\".len()];"]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some data...\".as_bytes());"]
#[doc = ""]
#[doc = "// modify the file data"]
#[doc = "file.write_all(\"some data!!!\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = ""]
#[doc = "// cow, change will only be seen in current caller"]
#[doc = "assert_eq!(file.as_slice(), \"some data!!!\".as_bytes());"]
#[doc = "drop(file);"]
#[doc = ""]
#[doc = "// reopen to check content, cow will not change the content."]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::open(\"", $filename_prefix, "_disk_open_cow_test.txt\").await.unwrap();")]
#[doc = "let mut buf = vec![0; \"some data...\".len()];"]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some data...\".as_bytes());"]
#[doc = "# })"]
#[doc = "```"]
#[doc = ""]
#[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
pub async fn open_cow<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
Self::open_cow_in(path, None).await
}
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileExt, AsyncMmapFileMutExt, AsyncOptions};")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFileMut;")]
#[doc = concat!("use ", $path_str, "::fs::File;")]
#[doc = "# use scopeguard::defer;"]
#[doc = ""]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = "// create a temp file"]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::create(\"", $filename_prefix, "_disk_open_cow_with_options_test.txt\").await.unwrap();")]
#[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_disk_open_cow_with_options_test.txt\").unwrap());")]
#[doc = "file.truncate(23).await.unwrap();"]
#[doc = "file.write_all(\"sanity text\".as_bytes(), 0).unwrap();"]
#[doc = "file.write_all(\"some data...\".as_bytes(), \"sanity text\".as_bytes().len()).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = "drop(file);"]
#[doc = ""]
#[doc = "// mmap the file"]
#[doc = "let opts = AsyncOptions::new()"]
#[doc = " // mmap content after the sanity text"]
#[doc = " .offset(\"sanity text\".as_bytes().len() as u64);"]
#[doc = ""]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::open_cow_with_options(\"", $filename_prefix, "_disk_open_cow_with_options_test.txt\", opts).await.unwrap();")]
#[doc = "let mut buf = vec![0; \"some data...\".len()];"]
#[doc = "file.read_exact(buf.as_mut_slice(), 0).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some data...\".as_bytes());"]
#[doc = ""]
#[doc = "// modify the file data"]
#[doc = "file.write_all(\"some data!!!\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = ""]
#[doc = "// cow, change will only be seen in current caller"]
#[doc = "assert_eq!(file.as_slice(), \"some data!!!\".as_bytes());"]
#[doc = "drop(file);"]
#[doc = ""]
#[doc = "// reopen to check content, cow will not change the content."]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::open(\"", $filename_prefix, "_disk_open_cow_with_options_test.txt\").await.unwrap();")]
#[doc = "let mut buf = vec![0; \"some data...\".len()];"]
#[doc = "// skip the sanity text"]
#[doc = "file.read_exact(buf.as_mut_slice(), \"sanity text\".as_bytes().len()).unwrap();"]
#[doc = "assert_eq!(buf.as_slice(), \"some data...\".as_bytes());"]
#[doc = "# })"]
#[doc = "```"]
#[doc = ""]
#[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
pub async fn open_cow_with_options<P: AsRef<Path>>(path: P, opts: AsyncOptions) -> Result<Self, Error> {
Self::open_cow_in(path, Some(opts)).await
}
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::AsyncMmapFileMutExt;")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFileMut;")]
#[doc = "# use scopeguard::defer;"]
#[doc = ""]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::create(\"", $filename_prefix, "_disk_freeze_test.txt\").await.unwrap();")]
#[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_disk_freeze_test.txt\").unwrap());")]
#[doc = "file.truncate(100).await;"]
#[doc = "file.write_all(\"some data...\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = "// freeze"]
#[doc = "file.freeze().unwrap();"]
#[doc = "# })"]
#[doc = "```"]
pub fn freeze(self) -> Result<$immutable_file, Error> {
Ok($immutable_file {
mmap: self.mmap.make_read_only().map_err(|e| Error::new(ErrorKind::IO, e))?,
file: self.file,
path: self.path,
exec: false,
})
}
#[doc = "```ignore"]
#[doc = concat!("use fmmap::", $path_str, "::AsyncMmapFileMutExt;")]
#[doc = concat!("use fmmap::raw::", $path_str, "::AsyncDiskMmapFileMut;")]
#[doc = "# use scopeguard::defer;"]
#[doc = ""]
#[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
#[doc = concat!("let mut file = AsyncDiskMmapFileMut::create(\"", $filename_prefix, "_disk_freeze_exec_test.txt\").await.unwrap();")]
#[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_disk_freeze_exec_test.txt\").unwrap());")]
#[doc = "file.truncate(100).await;"]
#[doc = "file.write_all(\"some data...\".as_bytes(), 0).unwrap();"]
#[doc = "file.flush().unwrap();"]
#[doc = "// freeze_exec"]
#[doc = "file.freeze_exec().unwrap();"]
#[doc = "# })"]
#[doc = "```"]
pub fn freeze_exec(self) -> Result<$immutable_file, Error> {
Ok($immutable_file {
mmap: self.mmap.make_exec().map_err(|e| Error::new(ErrorKind::IO, e))?,
file: self.file,
path: self.path,
exec: true
})
}
}
};
}
macro_rules! impl_async_fmmap_file_mut_private {
($name: ident) => {
impl $name {
async fn create_in<P: AsRef<Path>>(path: P, opts: Option<AsyncOptions>) -> Result<Self, Error> {
let file = create_file_async(&path)
.await
.map_err(|e| Error::new_source_msg(ErrorKind::OpenFailed, path.as_ref().to_string_lossy(), e))?;
match opts {
None => {
let mmap = unsafe { MmapMut::map_mut(&file).map_err(|e| Error::new(ErrorKind::MmapFailed, e))? };
Ok(Self {
mmap,
file,
path: path.as_ref().to_path_buf(),
opts: None,
typ: MmapFileMutType::Normal,
})
}
Some(opts) => {
if opts.max_size > 0 {
file.set_len(opts.max_size).await.map_err(|e| Error::new_source_msg(ErrorKind::TruncationFailed, path.as_ref().to_string_lossy(), e))?;
sync_parent_async(&path).await?;
}
let opts_bk = opts.mmap_opts.clone();
let mmap = unsafe { opts.mmap_opts.map_mut(&file).map_err(|e| Error::new(ErrorKind::MmapFailed, e))? };
Ok(Self {
mmap,
file,
path: path.as_ref().to_path_buf(),
opts: Some(opts_bk),
typ: MmapFileMutType::Normal,
})
}
}
}
async fn open_in<P: AsRef<Path>>(path: P, opts: Option<AsyncOptions>) -> Result<Self, Error> {
match opts {
None => {
let file = open_or_create_file_async(&path)
.await
.map_err(|e| Error::new_source_msg(ErrorKind::OpenFailed, path.as_ref().to_string_lossy(), e))?;
let mmap = unsafe { MmapMut::map_mut(&file).map_err(|e| Error::new(ErrorKind::MmapFailed, e))? };
Ok(Self {
mmap,
file,
path: path.as_ref().to_path_buf(),
opts: None,
typ: MmapFileMutType::Normal,
})
}
Some(mut opts) => {
let file = opts.file_opts.create(true).open(&path)
.await
.map_err(|e| Error::new_source_msg(ErrorKind::OpenFailed, path.as_ref().to_string_lossy(), e))?;
let meta = file.metadata().await?;
let file_sz = meta.len();
if file_sz == 0 && opts.max_size > 0 {
file.set_len(opts.max_size).await.map_err(|e| Error::new_source_msg(ErrorKind::TruncationFailed, path.as_ref().to_string_lossy(), e))?;
sync_parent_async(&path).await?;
}
let opts_bk = opts.mmap_opts.clone();
let mmap = unsafe {
opts.mmap_opts.map_mut(&file).map_err(|e| Error::new(ErrorKind::MmapFailed, e))?
};
Ok(Self {
mmap,
file,
path: path.as_ref().to_path_buf(),
opts: Some(opts_bk),
typ: MmapFileMutType::Normal,
})
}
}
}
async fn open_exist_in<P: AsRef<Path>>(path: P, opts: Option<AsyncOptions>) -> Result<Self, Error> {
let file = open_exist_file_with_append_async(&path)
.await
.map_err(|e| Error::new_source_msg(ErrorKind::OpenFailed, path.as_ref().to_string_lossy(), e))?;
match opts {
None => {
let mmap = unsafe { MmapMut::map_mut(&file)? };
Ok(Self {
mmap,
file,
path: path.as_ref().to_path_buf(),
opts: None,
typ: MmapFileMutType::Normal,
})
}
Some(opts) => {
let meta = file.metadata().await?;
let file_sz = meta.len();
if file_sz == 0 && opts.max_size > 0 {
file.set_len(opts.max_size).await.map_err(|e| Error::new_source_msg(ErrorKind::TruncationFailed, path.as_ref().to_string_lossy(), e))?;
sync_parent_async(&path).await?;
}
let opts_bk = opts.mmap_opts.clone();
let mmap = unsafe {
opts.mmap_opts.map_mut(&file)? };
Ok(Self {
mmap,
file,
path: path.as_ref().to_path_buf(),
opts: Some(opts_bk),
typ: MmapFileMutType::Normal,
})
}
}
}
async fn open_cow_in<P: AsRef<Path>>(path: P, opts: Option<AsyncOptions>) -> Result<Self, Error> {
let file = open_exist_file_with_append_async(&path)
.await
.map_err(|e| Error::new_source_msg(ErrorKind::OpenFailed, path.as_ref().to_string_lossy(), e))?;
match opts {
None => {
let mmap = unsafe { MmapOptions::new().map_copy(&file)? };
Ok(Self {
mmap,
file,
path: path.as_ref().to_path_buf(),
opts: None,
typ: MmapFileMutType::Cow,
})
}
Some(opts) => {
let opts_bk = opts.mmap_opts.clone();
let mmap = unsafe {
opts.mmap_opts.map_copy(&file)? };
Ok(Self {
mmap,
file,
path: path.as_ref().to_path_buf(),
opts: Some(opts_bk),
typ: MmapFileMutType::Cow,
})
}
}
}
}
};
}
}
cfg_tokio! {
pub(crate) mod tokio_impl;
}
cfg_smol! {
pub(crate) mod smol_impl;
}
cfg_async_std! {
pub(crate) mod async_std_impl;
}