fmmap/mmap_file.rs
1macro_rules! read_impl {
2 ($this:ident, $offset: tt, $typ:tt::$conv:tt) => {{
3 const SIZE: usize = mem::size_of::<$typ>();
4 // try to convert directly from the bytes
5 // this Option<ret> trick is to avoid keeping a borrow on self
6 // when advance() is called (mut borrow) and to call bytes() only once
7 let mut buf = [0; SIZE];
8 $this
9 .read_exact(&mut buf, $offset)
10 .map(|_| unsafe { $typ::$conv(*(&buf as *const _ as *const [_; SIZE])) })
11 }};
12}
13
14macro_rules! impl_from {
15 ($outer: ident, $enum_inner: ident, [$($inner: ident), +$(,)?]) => {
16 $(
17 impl From<$inner> for $outer {
18 fn from(file: $inner) -> Self {
19 $outer{ inner: <$enum_inner>::from(file) }
20 }
21 }
22 )*
23 };
24}
25
26macro_rules! impl_from_mut {
27 ($outer: ident, $enum_inner: ident, [$($inner: ident), +$(,)?]) => {
28 $(
29 impl From<$inner> for $outer {
30 fn from(file: $inner) -> Self {
31 $outer{
32 inner: <$enum_inner>::from(file),
33 remove_on_drop: false,
34 deleted: false,
35 }
36 }
37 }
38 )*
39 };
40}
41
42macro_rules! impl_drop {
43 ($name: ident, $inner: ident, $empty: ident) => {
44 impl Drop for $name {
45 fn drop(&mut self) {
46 if self.remove_on_drop && !self.deleted {
47 let empty = <$inner>::Empty(<$empty>::default());
48 // swap the inner to empty
49 let inner = mem::replace(&mut self.inner, empty);
50 // do remove and ignore the result
51 let path = inner.path_buf();
52 drop(inner);
53 let _ = std::fs::remove_file(path);
54 }
55 }
56 }
57 };
58}
59
60macro_rules! impl_flush {
61 () => {
62 fn flush(&self) -> Result<()> {
63 self.inner.flush()
64 }
65
66 fn flush_async(&self) -> Result<()> {
67 self.inner.flush_async()
68 }
69
70 fn flush_range(&self, offset: usize, len: usize) -> Result<()> {
71 self.inner.flush_range(offset, len)
72 }
73
74 fn flush_async_range(&self, offset: usize, len: usize) -> Result<()> {
75 self.inner.flush_async_range(offset, len)
76 }
77 };
78}
79
80macro_rules! impl_file_lock {
81 () => {
82 #[inline]
83 fn lock_exclusive(&self) -> crate::error::Result<()> {
84 self.inner.lock_exclusive()
85 }
86
87 #[inline]
88 fn lock_shared(&self) -> crate::error::Result<()> {
89 self.inner.lock_shared()
90 }
91
92 #[inline]
93 fn try_lock_exclusive(&self) -> crate::error::Result<()> {
94 self.inner.try_lock_exclusive()
95 }
96
97 #[inline]
98 fn try_lock_shared(&self) -> crate::error::Result<()> {
99 self.inner.try_lock_shared()
100 }
101
102 #[inline]
103 fn unlock(&self) -> crate::error::Result<()> {
104 self.inner.unlock()
105 }
106 };
107}
108
109macro_rules! impl_constructor_for_memory_mmap_file {
110 ($memory_base: ident, $name: ident, $name_str: literal, $path_str: literal) => {
111 use bytes::Bytes;
112
113 impl $name {
114 #[doc = concat!("Create a in-memory ", $name_str)]
115 #[doc = "# Examples"]
116 #[doc = "```ignore"]
117 #[doc = "use bytes::{BufMut, BytesMut};"]
118 #[doc = concat!("use fmmap::", $path_str, "::", $name_str, ";")]
119 #[doc = ""]
120 #[doc = "let mut data = BytesMut::with_capacity(100);"]
121 #[doc = "data.put_slice(\"some data...\".as_bytes());"]
122 #[doc = concat!($name_str, "::memory(\"foo.mem\", data.freeze());")]
123 #[doc = "```"]
124 pub fn memory<P: AsRef<Path>>(path: P, data: Bytes) -> Self {
125 Self::from(<$memory_base>::new(path, data))
126 }
127
128 #[doc = concat!("Create a in-memory ", $name_str, " from Vec")]
129 #[doc = "# Examples"]
130 #[doc = "```ignore"]
131 #[doc = concat!("use fmmap::", $path_str, "::", $name_str, ";")]
132 #[doc = ""]
133 #[doc = "let data = (0..=255u8).collect::<Vec<_>>();"]
134 #[doc = concat!($name_str, "::memory_from_vec(\"foo.mem\", data);")]
135 #[doc = "```"]
136 pub fn memory_from_vec<P: AsRef<Path>>(path: P, src: Vec<u8>) -> Self {
137 Self::from(<$memory_base>::from_vec(path, src))
138 }
139
140 #[doc = concat!("Create a in-memory ", $name_str, " from String")]
141 #[doc = "# Examples"]
142 #[doc = "```ignore"]
143 #[doc = concat!("use fmmap::", $path_str, "::", $name_str, ";")]
144 #[doc = ""]
145 #[doc = "let data: &'static str = \"some data...\";"]
146 #[doc = concat!($name_str, "::memory_from_string(\"foo.mem\", data.to_string());")]
147 #[doc = "```"]
148 pub fn memory_from_string<P: AsRef<Path>>(path: P, src: String) -> Self {
149 Self::from(<$memory_base>::from_string(path, src))
150 }
151
152 #[doc = concat!("Create a in-memory ", $name_str, " from static slice")]
153 #[doc = "# Examples"]
154 #[doc = "```ignore"]
155 #[doc = "use bytes::Bytes;"]
156 #[doc = concat!("use fmmap::", $path_str, "::", $name_str, ";")]
157 #[doc = ""]
158 #[doc = "let data: &'static [u8] = \"some data...\".as_bytes();"]
159 #[doc = concat!($name_str, "::memory_from_slice(\"foo.mem\", data);")]
160 #[doc = "```"]
161 pub fn memory_from_slice<P: AsRef<Path>>(path: P, src: &'static [u8]) -> Self {
162 Self::from(<$memory_base>::from_slice(path, src))
163 }
164
165 #[doc = concat!("Create a in-memory ", $name_str, " from static str")]
166 #[doc = "# Examples"]
167 #[doc = "```ignore"]
168 #[doc = "use bytes::Bytes;"]
169 #[doc = concat!("use fmmap::", $path_str, "::", $name_str, ";")]
170 #[doc = ""]
171 #[doc = "let data: &'static str = \"some data...\";"]
172 #[doc = concat!($name_str, "::memory_from_str(\"foo.mem\", data);")]
173 #[doc = "```"]
174 pub fn memory_from_str<P: AsRef<Path>>(path: P, src: &'static str) -> Self {
175 Self::from(<$memory_base>::from_str(path, src))
176 }
177
178 #[doc = concat!("Create a in-memory ", $name_str, " by copy from slice")]
179 #[doc = "# Examples"]
180 #[doc = "```ignore"]
181 #[doc = concat!("use fmmap::", $path_str, "::", $name_str, ";")]
182 #[doc = ""]
183 #[doc = concat!($name_str, "::memory_copy_from_slice(\"foo.mem\", \"some data...\".as_bytes());")]
184 #[doc = "```"]
185 pub fn memory_copy_from_slice<P: AsRef<Path>>(path: P, src: &[u8]) -> Self {
186 Self::from(<$memory_base>::copy_from_slice(path, src))
187 }
188 }
189 };
190}
191
192macro_rules! impl_constructor_for_memory_mmap_file_mut {
193 ($memory_base: ident, $name: ident, $name_str: literal, $path_str: literal) => {
194 impl $name {
195 #[doc = concat!("Create a in-memory ", $name_str)]
196 #[doc = "# Examples"]
197 #[doc = "```ignore"]
198 #[doc = concat!("use fmmap::", $path_str, "::", $name_str, ";")]
199 #[doc = ""]
200 #[doc = concat!($name_str, "::memory(\"foo.mem\");")]
201 #[doc = "```"]
202 pub fn memory<P: AsRef<Path>>(path: P) -> Self {
203 Self::from(<$memory_base>::new(path))
204 }
205
206 #[doc = concat!("Create a in-memory ", $name_str, "with capacity")]
207 #[doc = "# Examples"]
208 #[doc = "```ignore"]
209 #[doc = concat!("use fmmap::", $path_str, "::", $name_str, ";")]
210 #[doc = ""]
211 #[doc = concat!($name_str, "::memory_with_capacity(\"foo.mem\", 1000);")]
212 #[doc = "```"]
213 pub fn memory_with_capacity<P: AsRef<Path>>(path: P, cap: usize) -> Self {
214 Self::from(<$memory_base>::with_capacity(path, cap))
215 }
216
217 #[doc = concat!("Create a in-memory ", $name_str, " from Vec")]
218 #[doc = "# Examples"]
219 #[doc = "```ignore"]
220 #[doc = concat!("use fmmap::", $path_str, "::", $name_str, ";")]
221 #[doc = ""]
222 #[doc = "let data = (0..=255u8).collect::<Vec<_>>();"]
223 #[doc = concat!($name_str, "::memory_from_vec(\"foo.mem\", data);")]
224 #[doc = "```"]
225 pub fn memory_from_vec<P: AsRef<Path>>(path: P, src: Vec<u8>) -> Self {
226 Self::from(<$memory_base>::from_vec(path, src))
227 }
228
229 #[doc = concat!("Create a in-memory ", $name_str, " from String")]
230 #[doc = "# Examples"]
231 #[doc = "```ignore"]
232 #[doc = concat!("use fmmap::", $path_str, "::", $name_str, ";")]
233 #[doc = ""]
234 #[doc = "let data: &'static str = \"some data...\";"]
235 #[doc = concat!($name_str, "::memory_from_string(\"foo.mem\", data.to_string());")]
236 #[doc = "```"]
237 pub fn memory_from_string<P: AsRef<Path>>(path: P, src: String) -> Self {
238 Self::from(<$memory_base>::from_string(path, src))
239 }
240
241 #[doc = concat!("Create a in-memory ", $name_str, " from static str")]
242 #[doc = "# Examples"]
243 #[doc = "```ignore"]
244 #[doc = "use bytes::Bytes;"]
245 #[doc = concat!("use fmmap::", $path_str, "::", $name_str, ";")]
246 #[doc = ""]
247 #[doc = "let data: &'static str = \"some data...\";"]
248 #[doc = concat!($name_str, "::memory_from_str(\"foo.mem\", data);")]
249 #[doc = "```"]
250 pub fn memory_from_str<P: AsRef<Path>>(path: P, src: &'static str) -> Self {
251 Self::from(<$memory_base>::from_str(path, src))
252 }
253
254 #[doc = concat!("Create a in-memory ", $name_str, " by from slice")]
255 #[doc = "# Examples"]
256 #[doc = "```ignore"]
257 #[doc = concat!("use fmmap::", $path_str, "::", $name_str, ";")]
258 #[doc = ""]
259 #[doc = concat!($name_str, "::memory_from_slice(\"foo.mem\", \"some data...\".as_bytes());")]
260 #[doc = "```"]
261 pub fn memory_from_slice<P: AsRef<Path>>(path: P, src: &[u8]) -> Self {
262 Self::from(<$memory_base>::from_slice(path, src))
263 }
264 }
265 };
266}
267
268cfg_sync! {
269 macro_rules! impl_mmap_file_ext {
270 ($name: ident) => {
271 impl MmapFileExt for $name {
272 #[inline]
273 fn len(&self) -> usize {
274 self.inner.len()
275 }
276
277 #[inline]
278 fn as_slice(&self) -> &[u8] {
279 self.inner.as_slice()
280 }
281
282 #[inline]
283 fn path(&self) -> &Path {
284 self.inner.path()
285 }
286
287 #[inline]
288 fn is_exec(&self) -> bool {
289 self.inner.is_exec()
290 }
291
292 #[inline]
293 fn metadata(&self) -> Result<MetaData> {
294 self.inner.metadata()
295 }
296
297 impl_file_lock!();
298 }
299 };
300 }
301
302 mod sync_impl;
303 pub use sync_impl::{MmapFileExt, MmapFileMutExt, MmapFile, MmapFileMut};
304}
305
306cfg_async! {
307 macro_rules! impl_async_mmap_file_ext {
308 ($name: ident) => {
309
310 impl AsyncMmapFileExt for $name {
311 #[inline]
312 fn len(&self) -> usize {
313 self.inner.len()
314 }
315
316 #[inline]
317 fn as_slice(&self) -> &[u8] {
318 self.inner.as_slice()
319 }
320
321 #[inline]
322 fn path(&self) -> &Path {
323 self.inner.path()
324 }
325
326 #[inline]
327 fn is_exec(&self) -> bool {
328 self.inner.is_exec()
329 }
330
331 #[inline]
332 async fn metadata(&self) -> Result<MetaData> {
333 self.inner.metadata().await
334 }
335
336 impl_file_lock!();
337 }
338 };
339 }
340
341 macro_rules! impl_async_mmap_file_mut_ext {
342 ($filename_prefix: literal, $doc_test_runtime: literal, $path_str: literal) => {
343
344 impl AsyncMmapFileMutExt for AsyncMmapFileMut {
345 #[inline]
346 fn as_mut_slice(&mut self) -> &mut [u8] {
347 self.inner.as_mut_slice()
348 }
349
350 #[inline]
351 fn is_cow(&self) -> bool {
352 self.inner.is_cow()
353 }
354
355 impl_flush!();
356
357 #[inline]
358 async fn truncate(&mut self, max_sz: u64) -> Result<()> {
359 self.inner.truncate(max_sz).await
360 }
361
362 /// Remove the underlying file
363 ///
364 /// # Example
365 ///
366 /// ```ignore
367 #[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileMutExt};")]
368 #[doc = concat!("use ", $path_str, "::fs::File;")]
369 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
370 #[doc = concat!("let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_remove_test.txt\").await.unwrap();")]
371 ///
372 /// file.truncate(12).await;
373 /// file.write_all("some data...".as_bytes(), 0).unwrap();
374 /// file.flush().unwrap();
375 ///
376 /// file.drop_remove().await.unwrap();
377 ///
378 #[doc = concat!("let err = File::open(\"", $filename_prefix, "_remove_test.txt\").await;")]
379 /// assert_eq!(err.unwrap_err().kind(), std::io::ErrorKind::NotFound);
380 /// # })
381 /// ```
382 async fn drop_remove(mut self) -> Result<()> {
383 let empty = AsyncMmapFileMutInner::Empty(AsyncEmptyMmapFile::default());
384 // swap the inner to empty
385 let inner = mem::replace(&mut self.inner, empty);
386 if !self.remove_on_drop {
387 // do remove
388 inner.drop_remove().await?;
389 self.deleted = true;
390 }
391 Ok(())
392 }
393
394 /// Close and truncate the underlying file
395 ///
396 /// # Examples
397 ///
398 /// ```ignore
399 #[doc = concat!("use fmmap::{MetaDataExt,", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileExt, AsyncMmapFileMutExt}};")]
400 /// # use scopeguard::defer;
401 ///
402 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
403 #[doc = concat!("let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_close_with_truncate_test.txt\").await.unwrap();")]
404 #[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_close_with_truncate_test.txt\").unwrap());")]
405 /// file.truncate(100).await;
406 /// file.write_all("some data...".as_bytes(), 0).unwrap();
407 /// file.flush().unwrap();
408 ///
409 /// file.close_with_truncate(50).await.unwrap();
410 ///
411 #[doc = concat!("let file = AsyncMmapFileMut::open(\"", $filename_prefix, "_close_with_truncate_test.txt\").await.unwrap();")]
412 /// let meta = file.metadata().await.unwrap();
413 /// assert_eq!(meta.len(), 50);
414 /// # })
415 /// ```
416 async fn close_with_truncate(mut self, max_sz: i64) -> Result<()> {
417 let empty = AsyncMmapFileMutInner::Empty(AsyncEmptyMmapFile::default());
418 // swap the inner to empty
419 let inner = mem::replace(&mut self.inner, empty);
420 inner.close_with_truncate(max_sz).await
421 }
422 }
423 };
424 }
425
426 macro_rules! declare_async_mmap_file_ext {
427 ($disk_file_mut: ty, $opts: ty, $reader: ty) => {
428 /// Utility methods to [`AsyncMmapFile`]
429 ///
430 /// [`AsyncMmapFile`]: structs.AsyncMmapFile.html
431
432 #[enum_dispatch]
433 pub trait AsyncMmapFileExt: Sync {
434 /// Returns the current mmap length
435 fn len(&self) -> usize;
436
437 /// Returns the mmap is empty of not.
438 fn is_empty(&self) -> bool {
439 self.len() == 0
440 }
441
442 /// Returns the underlying slice of the mmap
443 fn as_slice(&self) -> &[u8];
444
445 /// slice returns data starting from offset off of size sz.
446 ///
447 /// # Panics
448 /// If there's not enough data, it would
449 /// panic.
450 fn slice(&self, offset: usize, sz: usize) -> &[u8] {
451 &self.as_slice()[offset..offset+sz]
452 }
453
454 /// bytes returns data starting from offset off of size sz.
455 ///
456 /// # Errors
457 /// If there's not enough data, it would return
458 /// `Err(Error::from(ErrorKind::EOF))`.
459 fn bytes(&self, offset: usize, sz: usize) -> Result<&[u8]> {
460 let buf = self.as_slice();
461 if buf.len() < offset + sz {
462 Err(Error::from(ErrorKind::EOF))
463 } else {
464 Ok(&buf[offset..offset+sz])
465 }
466 }
467
468 /// Returns the path of the inner file.
469 fn path(&self) -> &Path;
470
471 /// Returns the path buf of the inner file.
472 fn path_buf(&self) -> PathBuf {
473 self.path().to_path_buf()
474 }
475
476 /// Returns the path lossy string of the inner file.
477 fn path_lossy(&self) -> Cow<'_, str> {
478 self.path().to_string_lossy()
479 }
480
481 /// Returns the path string of the inner file.
482 fn path_string(&self) -> String {
483 self.path_lossy().to_string()
484 }
485
486 /// Whether the mmap is executable
487 fn is_exec(&self) -> bool;
488
489 /// Returns the metadata of file metadata
490 ///
491 /// Metadata information about a file.
492 /// This structure is returned from the metadata or
493 /// symlink_metadata function or method and represents
494 /// known metadata about a file such as its permissions, size, modification times, etc
495 fn metadata(&self) -> impl core::future::Future<Output = Result<MetaData>> + Send;
496
497 /// Copy the content of the mmap file to Vec
498 #[inline]
499 fn copy_all_to_vec(&self) -> Vec<u8> {
500 self.as_slice().to_vec()
501 }
502
503 /// Copy a range of content of the mmap file to Vec
504 #[inline]
505 fn copy_range_to_vec(&self, offset: usize, len: usize) -> Vec<u8> {
506 self.slice(offset, len).to_vec()
507 }
508
509 /// Write the content of the mmap file to a new file.
510 #[inline]
511 fn write_all_to_new_file<P: AsRef<Path> + Send + Sync>(&self, new_file_path: P) -> impl core::future::Future<Output = Result<()>> + Send {
512 async move {
513 let buf = self.as_slice();
514 let opts = <$opts>::new().max_size(buf.len() as u64);
515
516 let mut mmap = <$disk_file_mut>::create_with_options(new_file_path, opts).await?;
517 mmap.writer(0)?.write_all(buf).await?;
518 mmap.flush()
519 }
520 }
521
522 /// Write a range of content of the mmap file to new file.
523 #[inline]
524 fn write_range_to_new_file<P: AsRef<Path> + Send + Sync>(&self, new_file_path: P, offset: usize, len: usize) -> impl core::future::Future<Output = Result<()>> + Send {
525 async move {
526 let buf = self.as_slice();
527 if buf.len() < offset + len {
528 return Err(Error::from(ErrorKind::EOF));
529 }
530 let opts = <$opts>::new().max_size(len as u64);
531
532 let mut mmap = <$disk_file_mut>::create_with_options(new_file_path, opts).await?;
533 mmap.writer(0)?.write_all(&buf[offset..offset + len]).await?;
534 mmap.flush()
535 }
536 }
537
538 /// Returns a [`AsyncMmapFileReader`] which helps read data from mmap like a normal File.
539 ///
540 /// # Errors
541 /// If there's not enough data, it would return
542 /// `Err(Error::from(ErrorKind::EOF))`.
543 ///
544 /// [`AsyncMmapFileReader`]: structs.AsyncMmapFileReader.html
545 fn reader(&self, offset: usize) -> Result<$reader> {
546 let buf = self.as_slice();
547 if buf.len() < offset {
548 Err(Error::from(ErrorKind::EOF))
549 } else {
550 Ok(<$reader>::new(Cursor::new(&buf[offset..]), offset, buf.len() - offset))
551 }
552 }
553
554 /// Returns a [`AsyncMmapFileReader`] base on the given `offset` and `len`, which helps read data from mmap like a normal File.
555 ///
556 /// # Errors
557 /// If there's not enough data, it would return
558 /// `Err(Error::from(ErrorKind::EOF))`.
559 ///
560 /// [`AsyncMmapFileReader`]: structs.AsyncMmapFileReader.html
561 fn range_reader(&self, offset: usize, len: usize) -> Result<$reader> {
562 let buf = self.as_slice();
563 if buf.len() < offset + len {
564 Err(Error::from(ErrorKind::EOF))
565 } else {
566 Ok(<$reader>::new(Cursor::new(&buf[offset.. offset + len]), offset, len))
567 }
568 }
569
570 /// Locks the file for exclusive usage, blocking if the file is currently locked.
571 ///
572 /// # Notes
573 /// This function will do nothing if the underlying is not a real file, e.g. in-memory.
574 fn lock_exclusive(&self) -> Result<()>;
575
576 /// Locks the file for shared usage, blocking if the file is currently locked exclusively.
577 ///
578 /// # Notes
579 /// This function will do nothing if the underlying is not a real file, e.g. in-memory.
580 fn lock_shared(&self) -> Result<()>;
581
582 /// Locks the file for exclusive usage, or returns a an error if the file is currently locked (see lock_contended_error).
583 ///
584 /// # Notes
585 /// This function will do nothing if the underlying is not a real file, e.g. in-memory.
586 fn try_lock_exclusive(&self) -> Result<()>;
587
588 /// Locks the file for shared usage, or returns a an error if the file is currently locked exclusively (see lock_contended_error).
589 ///
590 /// # Notes
591 /// This function will do nothing if the underlying is not a real file, e.g. in-memory.
592 fn try_lock_shared(&self) -> Result<()>;
593
594 /// Unlocks the file.
595 ///
596 /// # Notes
597 /// This function will do nothing if the underlying is not a real file, e.g. in-memory.
598 fn unlock(&self) -> Result<()>;
599
600 /// Read bytes to the dst buf from the offset, returns how many bytes read.
601 fn read(&self, dst: &mut [u8], offset: usize) -> usize {
602 let buf = self.as_slice();
603
604 if buf.len() < offset {
605 0
606 } else {
607 let remaining = buf.len() - offset;
608 let dst_len = dst.len();
609 if remaining > dst_len {
610 dst.copy_from_slice(&buf[offset..offset + dst_len]);
611 dst_len
612 } else {
613 dst.copy_from_slice(&buf[offset..offset + remaining]);
614 remaining
615 }
616 }
617 }
618
619 /// Read the exact number of bytes required to fill buf.
620 fn read_exact(&self, dst: &mut [u8], offset: usize) -> Result<()> {
621 let buf = self.as_slice();
622 let remaining = buf.len().checked_sub(offset);
623 match remaining {
624 None => Err(Error::from(ErrorKind::EOF)),
625 Some(remaining) => {
626 let dst_len = dst.len();
627 if remaining < dst_len {
628 Err(Error::from(ErrorKind::EOF))
629 } else {
630 dst.copy_from_slice(&buf[offset..offset + dst_len]);
631 Ok(())
632 }
633 }
634 }
635 }
636
637 /// Read a signed 8 bit integer from offset.
638 fn read_i8(&self, offset: usize) -> Result<i8> {
639 let buf = self.as_slice();
640
641 let remaining = buf.len().checked_sub(offset);
642 match remaining {
643 None => Err(Error::from(ErrorKind::EOF)),
644 Some(remaining) => {
645 if remaining < 1 {
646 Err(Error::from(ErrorKind::EOF))
647 } else {
648 Ok(buf[offset] as i8)
649 }
650 }
651 }
652 }
653
654 /// Read a signed 16 bit integer from offset in big-endian byte order.
655 fn read_i16(&self, offset: usize) -> Result<i16> {
656 read_impl!(self, offset, i16::from_be_bytes)
657 }
658
659 /// Read a signed 16 bit integer from offset in little-endian byte order.
660 fn read_i16_le(&self, offset: usize) -> Result<i16> {
661 read_impl!(self, offset, i16::from_le_bytes)
662 }
663
664 /// Read a signed integer from offset in big-endian byte order.
665 fn read_isize(&self, offset: usize) -> Result<isize> {
666 read_impl!(self, offset, isize::from_be_bytes)
667 }
668
669 /// Read a signed integer from offset in little-endian byte order.
670 fn read_isize_le(&self, offset: usize) -> Result<isize> {
671 read_impl!(self, offset, isize::from_le_bytes)
672 }
673
674 /// Read a signed 32 bit integer from offset in big-endian byte order.
675 fn read_i32(&self, offset: usize) -> Result<i32> {
676 read_impl!(self, offset, i32::from_be_bytes)
677 }
678
679 /// Read a signed 32 bit integer from offset in little-endian byte order.
680 fn read_i32_le(&self, offset: usize) -> Result<i32> {
681 read_impl!(self, offset, i32::from_le_bytes)
682 }
683
684 /// Read a signed 64 bit integer from offset in big-endian byte order.
685 fn read_i64(&self, offset: usize) -> Result<i64> {
686 read_impl!(self, offset, i64::from_be_bytes)
687 }
688
689 /// Read a signed 64 bit integer from offset in little-endian byte order.
690 fn read_i64_le(&self, offset: usize) -> Result<i64> {
691 read_impl!(self, offset, i64::from_le_bytes)
692 }
693
694 /// Read a signed 128 bit integer from offset in big-endian byte order.
695 fn read_i128(&self, offset: usize) -> Result<i128> {
696 read_impl!(self, offset, i128::from_be_bytes)
697 }
698
699 /// Read a signed 128 bit integer from offset in little-endian byte order.
700 fn read_i128_le(&self, offset: usize) -> Result<i128> {
701 read_impl!(self, offset, i128::from_le_bytes)
702 }
703
704 /// Read an unsigned 8 bit integer from offset.
705 fn read_u8(&self, offset: usize) -> Result<u8> {
706 let buf = self.as_slice();
707
708 let remaining = buf.len().checked_sub(offset);
709 match remaining {
710 None => Err(Error::from(ErrorKind::EOF)),
711 Some(remaining) => {
712 if remaining < 1 {
713 Err(Error::from(ErrorKind::EOF))
714 } else {
715 Ok(buf[offset])
716 }
717 }
718 }
719 }
720
721 /// Read an unsigned 16 bit integer from offset in big-endian.
722 fn read_u16(&self, offset: usize) -> Result<u16> {
723 read_impl!(self, offset, u16::from_be_bytes)
724 }
725
726 /// Read an unsigned 16 bit integer from offset in little-endian.
727 fn read_u16_le(&self, offset: usize) -> Result<u16> {
728 read_impl!(self, offset, u16::from_le_bytes)
729 }
730
731 /// Read an unsigned integer from offset in big-endian byte order.
732 fn read_usize(&self, offset: usize) -> Result<usize> {
733 read_impl!(self, offset, usize::from_be_bytes)
734 }
735
736 /// Read an unsigned integer from offset in little-endian byte order.
737 fn read_usize_le(&self, offset: usize) -> Result<usize> {
738 read_impl!(self, offset, usize::from_le_bytes)
739 }
740
741 /// Read an unsigned 32 bit integer from offset in big-endian.
742 fn read_u32(&self, offset: usize) -> Result<u32> {
743 read_impl!(self, offset, u32::from_be_bytes)
744 }
745
746 /// Read an unsigned 32 bit integer from offset in little-endian.
747 fn read_u32_le(&self, offset: usize) -> Result<u32> {
748 read_impl!(self, offset, u32::from_le_bytes)
749 }
750
751 /// Read an unsigned 64 bit integer from offset in big-endian.
752 fn read_u64(&self, offset: usize) -> Result<u64> {
753 read_impl!(self, offset, u64::from_be_bytes)
754 }
755
756 /// Read an unsigned 64 bit integer from offset in little-endian.
757 fn read_u64_le(&self, offset: usize) -> Result<u64> {
758 read_impl!(self, offset, u64::from_le_bytes)
759 }
760
761 /// Read an unsigned 128 bit integer from offset in big-endian.
762 fn read_u128(&self, offset: usize) -> Result<u128> {
763 read_impl!(self, offset, u128::from_be_bytes)
764 }
765
766 /// Read an unsigned 128 bit integer from offset in little-endian.
767 fn read_u128_le(&self, offset: usize) -> Result<u128> {
768 read_impl!(self, offset, u128::from_le_bytes)
769 }
770
771 /// Read an IEEE754 single-precision (4 bytes) floating point number from
772 /// offset in big-endian byte order.
773 fn read_f32(&self, offset: usize) -> Result<f32> {
774 read_impl!(self, offset, f32::from_be_bytes)
775 }
776
777 /// Read an IEEE754 single-precision (4 bytes) floating point number from
778 /// offset in little-endian byte order.
779 fn read_f32_le(&self, offset: usize) -> Result<f32> {
780 read_impl!(self, offset, f32::from_le_bytes)
781 }
782
783 /// Read an IEEE754 single-precision (8 bytes) floating point number from
784 /// offset in big-endian byte order.
785 fn read_f64(&self, offset: usize) -> Result<f64> {
786 read_impl!(self, offset, f64::from_be_bytes)
787 }
788
789 /// Read an IEEE754 single-precision (8 bytes) floating point number from
790 /// offset in little-endian byte order.
791 fn read_f64_le(&self, offset: usize) -> Result<f64> {
792 read_impl!(self, offset, f64::from_le_bytes)
793 }
794 }
795 };
796 }
797
798 macro_rules! declare_async_mmap_file_mut_ext {
799 ($writer: ty) => {
800 /// Utility methods to [`AsyncMmapFileMut`]
801 ///
802 /// [`AsyncMmapFileMut`]: structs.AsyncMmapFileMut.html
803
804 #[enum_dispatch]
805 pub trait AsyncMmapFileMutExt {
806 /// Returns the mutable underlying slice of the mmap
807 fn as_mut_slice(&mut self) -> &mut [u8];
808
809 /// slice_mut returns mutable data starting from offset off of size sz.
810 ///
811 /// # Panics
812 /// If there's not enough data, it would
813 /// panic.
814 fn slice_mut(&mut self, offset: usize, sz: usize) -> &mut [u8] {
815 &mut self.as_mut_slice()[offset..offset+sz]
816 }
817
818 /// Whether mmap is copy on write
819 fn is_cow(&self) -> bool;
820
821 /// bytes_mut returns mutable data starting from offset off of size sz.
822 ///
823 /// # Errors
824 /// If there's not enough data, it would return
825 /// `Err(Error::from(ErrorKind::EOF))`.
826 fn bytes_mut(&mut self, offset: usize, sz: usize) -> Result<&mut [u8]> {
827 let buf = self.as_mut_slice();
828 if buf.len() < offset + sz {
829 Err(Error::from(ErrorKind::EOF))
830 } else {
831 Ok(&mut buf[offset..offset+sz])
832 }
833 }
834
835 /// Fill 0 to the specific range
836 fn zero_range(&mut self, start: usize, end: usize) {
837 let buf = self.as_mut_slice();
838 let end = end.min(buf.len());
839 buf[start..end].fill(0);
840 }
841
842 /// Flushes outstanding memory map modifications to disk (if the inner is a real file).
843 ///
844 /// When this method returns with a non-error result,
845 /// all outstanding changes to a file-backed memory map are guaranteed to be durably stored.
846 /// The file’s metadata (including last modification timestamp) may not be updated.
847 fn flush(&self) -> Result<()>;
848
849 /// Asynchronously flushes outstanding memory map modifications to disk(if the inner is a real file).
850 ///
851 /// This method initiates flushing modified pages to durable storage,
852 /// but it will not wait for the operation to complete before returning.
853 /// The file’s metadata (including last modification timestamp) may not be updated.
854 fn flush_async(&self) -> Result<()>;
855
856 /// Flushes outstanding memory map modifications in the range to disk(if the inner is a real file).
857 ///
858 /// The offset and length must be in the bounds of the memory map.
859 ///
860 /// When this method returns with a non-error result,
861 /// all outstanding changes to a file-backed memory
862 /// in the range are guaranteed to be durable stored.
863 /// The file’s metadata (including last modification timestamp) may not be updated.
864 /// It is not guaranteed the only the changes in the specified range are flushed;
865 /// other outstanding changes to the memory map may be flushed as well.
866 fn flush_range(&self, offset: usize, len: usize) -> Result<()>;
867
868 /// Asynchronously flushes outstanding memory map modifications in the range to disk(if the inner is a real file).
869 ///
870 /// The offset and length must be in the bounds of the memory map.
871 ///
872 /// This method initiates flushing modified pages to durable storage,
873 /// but it will not wait for the operation to complete before returning.
874 /// The file’s metadata (including last modification timestamp) may not be updated.
875 /// It is not guaranteed that the only changes flushed are those in the specified range;
876 /// other outstanding changes to the memory map may be flushed as well.
877 fn flush_async_range(&self, offset: usize, len: usize) -> Result<()>;
878
879 /// Truncates the file to the `max_size`, which will lead to
880 /// do re-mmap and sync_dir if the inner is a real file.
881 fn truncate(&mut self, max_sz: u64) -> impl core::future::Future<Output = Result<()>> + Send;
882
883 /// Remove the underlying file
884 fn drop_remove(self) -> impl core::future::Future<Output = Result<()>> + Send;
885
886 /// Close and truncate the underlying file
887 fn close_with_truncate(self, max_sz: i64) -> impl core::future::Future<Output = Result<()>> + Send;
888
889 /// Returns a [`AsyncMmapFileWriter`] base on the given `offset`, which helps read or write data from mmap like a normal File.
890 ///
891 /// # Notes
892 /// If you use a writer to write data to mmap, there is no guarantee all
893 /// data will be durably stored. So you need to call [`flush`]/[`flush_range`]/[`flush_async`]/[`flush_async_range`] in [`AsyncMmapFileMutExt`]
894 /// to guarantee all data will be durably stored.
895 ///
896 /// # Errors
897 /// If there's not enough data, it would return
898 /// `Err(Error::from(ErrorKind::EOF))`.
899 ///
900 /// [`flush`]: traits.MmapFileMutExt.html#methods.flush
901 /// [`flush_range`]: traits.MmapFileMutExt.html#methods.flush_range
902 /// [`flush_async`]: traits.MmapFileMutExt.html#methods.flush_async
903 /// [`flush_async_range`]: traits.MmapFileMutExt.html#methods.flush_async_range
904 /// [`MmapFileWriter`]: structs.MmapFileWriter.html
905 fn writer(&mut self, offset: usize) -> Result<$writer> {
906 let buf = self.as_mut_slice();
907 let buf_len = buf.len();
908 if buf_len < offset {
909 Err(Error::from(ErrorKind::EOF))
910 } else {
911 Ok(<$writer>::new(Cursor::new(&mut buf[offset..]), offset, buf_len - offset))
912 }
913 }
914
915 /// Returns a [`AsyncMmapFileWriter`] base on the given `offset` and `len`, which helps read or write data from mmap like a normal File.
916 ///
917 /// # Notes
918 /// If you use a writer to write data to mmap, there is no guarantee all
919 /// data will be durably stored. So you need to call [`flush`]/[`flush_range`]/[`flush_async`]/[`flush_async_range`] in [`MmapFileMutExt`]
920 /// to guarantee all data will be durably stored.
921 ///
922 /// # Errors
923 /// If there's not enough data, it would return
924 /// `Err(Error::from(ErrorKind::EOF))`.
925 ///
926 /// [`flush`]: traits.AsyncMmapFileMutExt.html#methods.flush
927 /// [`flush_range`]: traits.AsyncMmapFileMutExt.html#methods.flush_range
928 /// [`flush_async`]: traits.AsyncMmapFileMutExt.html#methods.flush_async
929 /// [`flush_async_range`]: traits.AsyncMmapFileMutExt.html#methods.flush_async_range
930 /// [`AsyncMmapFileWriter`]: structs.AsyncMmapFileWriter.html
931 fn range_writer(&mut self, offset: usize, len: usize) -> Result<$writer> {
932 let buf = self.as_mut_slice();
933 if buf.len() < offset + len {
934 Err(Error::from(ErrorKind::EOF))
935 } else {
936 Ok(<$writer>::new(
937 Cursor::new(&mut buf[offset..offset + len]), offset, len))
938 }
939 }
940
941 /// Write bytes to the mmap from the offset.
942 fn write(&mut self, src: &[u8], offset: usize) -> usize {
943 let buf = self.as_mut_slice();
944 if buf.len() <= offset {
945 0
946 } else {
947 let remaining = buf.len() - offset;
948 let src_len = src.len();
949 if remaining > src_len {
950 buf[offset..offset + src_len].copy_from_slice(src);
951 src_len
952 } else {
953 buf[offset..offset + remaining].copy_from_slice(&src[..remaining]);
954 remaining
955 }
956 }
957 }
958
959 /// Write the all of bytes in `src` to the mmap from the offset.
960 fn write_all(&mut self, src: &[u8], offset: usize) -> Result<()> {
961 let buf = self.as_mut_slice();
962 let remaining = buf.len().checked_sub(offset);
963 match remaining {
964 None => Err(Error::from(ErrorKind::EOF)),
965 Some(remaining) => {
966 let src_len = src.len();
967 if remaining < src_len {
968 Err(Error::from(ErrorKind::EOF))
969 } else {
970 buf[offset..offset + src_len].copy_from_slice(src);
971 Ok(())
972 }
973 }
974 }
975 }
976
977 /// Writes a signed 8 bit integer to mmap from the offset.
978 fn write_i8(&mut self, val: i8, offset: usize) -> Result<()> {
979 self.write_all(&[val as u8], offset)
980 }
981
982 /// Writes a signed 16 bit integer to mmap from the offset in the big-endian byte order.
983 fn write_i16(&mut self, val: i16, offset: usize) -> Result<()> {
984 self.write_all(&val.to_be_bytes(), offset)
985 }
986
987 /// Writes a signed 16 bit integer to mmap from the offset in the little-endian byte order.
988 fn write_i16_le(&mut self, val: i16, offset: usize) -> Result<()> {
989 self.write_all(&val.to_le_bytes(), offset)
990 }
991
992 /// Writes a signed integer to mmap from the offset in the big-endian byte order.
993 fn write_isize(&mut self, val: isize, offset: usize) -> Result<()> {
994 self.write_all(&val.to_be_bytes(), offset)
995 }
996
997 /// Writes a signed integer to mmap from the offset in the little-endian byte order.
998 fn write_isize_le(&mut self, val: isize, offset: usize) -> Result<()> {
999 self.write_all(&val.to_le_bytes(), offset)
1000 }
1001
1002 /// Writes a signed 32 bit integer to mmap from the offset in the big-endian byte order.
1003 fn write_i32(&mut self, val: i32, offset: usize) -> Result<()> {
1004 self.write_all(&val.to_be_bytes(), offset)
1005 }
1006
1007 /// Writes a signed 32 bit integer to mmap from the offset in the little-endian byte order.
1008 fn write_i32_le(&mut self, val: i32, offset: usize) -> Result<()> {
1009 self.write_all(&val.to_le_bytes(), offset)
1010 }
1011
1012 /// Writes a signed 64 bit integer to mmap from the offset in the big-endian byte order.
1013 fn write_i64(&mut self, val: i64, offset: usize) -> Result<()> {
1014 self.write_all(&val.to_be_bytes(), offset)
1015 }
1016
1017 /// Writes a signed 64 bit integer to mmap from the offset in the little-endian byte order.
1018 fn write_i64_le(&mut self, val: i64, offset: usize) -> Result<()> {
1019 self.write_all(&val.to_le_bytes(), offset)
1020 }
1021
1022 /// Writes a signed 128 bit integer to mmap from the offset in the big-endian byte order.
1023 fn write_i128(&mut self, val: i128, offset: usize) -> Result<()> {
1024 self.write_all(&val.to_be_bytes(), offset)
1025 }
1026
1027 /// Writes a signed 128 bit integer to mmap from the offset in the little-endian byte order.
1028 fn write_i128_le(&mut self, val: i128, offset: usize) -> Result<()> {
1029 self.write_all(&val.to_le_bytes(), offset)
1030 }
1031
1032 /// Writes an unsigned 8 bit integer to mmap from the offset.
1033 fn write_u8(&mut self, val: u8, offset: usize) -> Result<()> {
1034 self.write_all(&[val], offset)
1035 }
1036
1037 /// Writes an unsigned 16 bit integer to mmap from the offset in the big-endian byte order.
1038 fn write_u16(&mut self, val: u16, offset: usize) -> Result<()> {
1039 self.write_all(&val.to_be_bytes(), offset)
1040 }
1041
1042 /// Writes an unsigned 16 bit integer to mmap from the offset in the little-endian byte order.
1043 fn write_u16_le(&mut self, val: u16, offset: usize) -> Result<()> {
1044 self.write_all(&val.to_le_bytes(), offset)
1045 }
1046
1047 /// Writes an unsigned integer to mmap from the offset in the big-endian byte order.
1048 fn write_usize(&mut self, val: usize, offset: usize) -> Result<()> {
1049 self.write_all(&val.to_be_bytes(), offset)
1050 }
1051
1052 /// Writes an unsigned integer to mmap from the offset in the little-endian byte order.
1053 fn write_usize_le(&mut self, val: usize, offset: usize) -> Result<()> {
1054 self.write_all(&val.to_le_bytes(), offset)
1055 }
1056
1057 /// Writes an unsigned 32 bit integer to mmap from the offset in the big-endian byte order.
1058 fn write_u32(&mut self, val: u32, offset: usize) -> Result<()> {
1059 self.write_all(&val.to_be_bytes(), offset)
1060 }
1061
1062 /// Writes an unsigned 32 bit integer to mmap from the offset in the little-endian byte order.
1063 fn write_u32_le(&mut self, val: u32, offset: usize) -> Result<()> {
1064 self.write_all(&val.to_le_bytes(), offset)
1065 }
1066
1067 /// Writes an unsigned 64 bit integer to mmap from the offset in the big-endian byte order.
1068 fn write_u64(&mut self, val: u64, offset: usize) -> Result<()> {
1069 self.write_all(&val.to_be_bytes(), offset)
1070 }
1071
1072 /// Writes an unsigned 64 bit integer to mmap from the offset in the little-endian byte order.
1073 fn write_u64_le(&mut self, val: u64, offset: usize) -> Result<()> {
1074 self.write_all(&val.to_le_bytes(), offset)
1075 }
1076
1077 /// Writes an unsigned 128 bit integer to mmap from the offset in the big-endian byte order.
1078 fn write_u128(&mut self, val: u128, offset: usize) -> Result<()> {
1079 self.write_all(&val.to_be_bytes(), offset)
1080 }
1081
1082 /// Writes an unsigned 128 bit integer to mmap from the offset in the little-endian byte order.
1083 fn write_u128_le(&mut self, val: u128, offset: usize) -> Result<()> {
1084 self.write_all(&val.to_le_bytes(), offset)
1085 }
1086
1087 /// Writes an IEEE754 single-precision (4 bytes) floating point number to mmap from the offset in big-endian byte order.
1088 fn write_f32(&mut self, val: f32, offset: usize) -> Result<()> {
1089 self.write_all(&val.to_be_bytes(), offset)
1090 }
1091
1092 /// Writes an IEEE754 single-precision (4 bytes) floating point number to mmap from the offset in little-endian byte order.
1093 fn write_f32_le(&mut self, val: f32, offset: usize) -> Result<()> {
1094 self.write_all(&val.to_le_bytes(), offset)
1095 }
1096
1097 /// Writes an IEEE754 single-precision (8 bytes) floating point number to mmap from the offset in big-endian byte order.
1098 fn write_f64(&mut self, val: f64, offset: usize) -> Result<()> {
1099 self.write_all(&val.to_be_bytes(), offset)
1100 }
1101
1102 /// Writes an IEEE754 single-precision (8 bytes) floating point number to mmap from the offset in little-endian byte order.
1103 fn write_f64_le(&mut self, val: f64, offset: usize) -> Result<()> {
1104 self.write_all(&val.to_le_bytes(), offset)
1105 }
1106 }
1107 };
1108 }
1109
1110 macro_rules! declare_and_impl_inners {
1111 () => {
1112 enum AsyncMmapFileInner {
1113 Empty(AsyncEmptyMmapFile),
1114 Memory(AsyncMemoryMmapFile),
1115 Disk(AsyncDiskMmapFile)
1116 }
1117
1118 impl From<AsyncEmptyMmapFile> for AsyncMmapFileInner {
1119 fn from(v: AsyncEmptyMmapFile) -> AsyncMmapFileInner {
1120 AsyncMmapFileInner::Empty(v)
1121 }
1122 }
1123 impl From<AsyncMemoryMmapFile> for AsyncMmapFileInner {
1124 fn from(v: AsyncMemoryMmapFile) -> AsyncMmapFileInner {
1125 AsyncMmapFileInner::Memory(v)
1126 }
1127 }
1128 impl From<AsyncDiskMmapFile> for AsyncMmapFileInner {
1129 fn from(v: AsyncDiskMmapFile) -> AsyncMmapFileInner {
1130 AsyncMmapFileInner::Disk(v)
1131 }
1132 }
1133
1134
1135 impl AsyncMmapFileExt for AsyncMmapFileInner {
1136 #[inline]
1137 fn len(&self) -> usize {
1138 match self {
1139 AsyncMmapFileInner::Empty(inner) => AsyncMmapFileExt::len(inner),
1140 AsyncMmapFileInner::Memory(inner) => AsyncMmapFileExt::len(inner),
1141 AsyncMmapFileInner::Disk(inner) => AsyncMmapFileExt::len(inner),
1142 }
1143 }
1144
1145 #[inline]
1146 fn as_slice(&self) -> &[u8] {
1147 match self {
1148 AsyncMmapFileInner::Empty(inner) => AsyncMmapFileExt::as_slice(inner),
1149 AsyncMmapFileInner::Memory(inner) => AsyncMmapFileExt::as_slice(inner),
1150 AsyncMmapFileInner::Disk(inner) => AsyncMmapFileExt::as_slice(inner),
1151 }
1152 }
1153
1154 #[inline]
1155 fn path(&self) -> &Path {
1156 match self {
1157 AsyncMmapFileInner::Empty(inner) => AsyncMmapFileExt::path(inner),
1158 AsyncMmapFileInner::Memory(inner) => AsyncMmapFileExt::path(inner),
1159 AsyncMmapFileInner::Disk(inner) => AsyncMmapFileExt::path(inner),
1160 }
1161 }
1162
1163 #[inline]
1164 fn is_exec(&self) -> bool {
1165 match self {
1166 AsyncMmapFileInner::Empty(inner) => AsyncMmapFileExt::is_exec(inner),
1167 AsyncMmapFileInner::Memory(inner) => AsyncMmapFileExt::is_exec(inner),
1168 AsyncMmapFileInner::Disk(inner) => AsyncMmapFileExt::is_exec(inner),
1169 }
1170 }
1171
1172 #[inline]
1173 async fn metadata(&self) -> Result<MetaData> {
1174 match self {
1175 AsyncMmapFileInner::Empty(inner) => AsyncMmapFileExt::metadata(inner).await,
1176 AsyncMmapFileInner::Memory(inner) => AsyncMmapFileExt::metadata(inner).await,
1177 AsyncMmapFileInner::Disk(inner) => AsyncMmapFileExt::metadata(inner).await,
1178 }
1179 }
1180
1181 #[inline]
1182 fn lock_exclusive(&self) -> Result<()> {
1183 match self {
1184 AsyncMmapFileInner::Empty(inner) => AsyncMmapFileExt::lock_exclusive(inner),
1185 AsyncMmapFileInner::Memory(inner) => AsyncMmapFileExt::lock_exclusive(inner),
1186 AsyncMmapFileInner::Disk(inner) => AsyncMmapFileExt::lock_exclusive(inner),
1187 }
1188 }
1189
1190 #[inline]
1191 fn lock_shared(&self) -> Result<()> {
1192 match self {
1193 AsyncMmapFileInner::Empty(inner) => AsyncMmapFileExt::lock_shared(inner),
1194 AsyncMmapFileInner::Memory(inner) => AsyncMmapFileExt::lock_shared(inner),
1195 AsyncMmapFileInner::Disk(inner) => AsyncMmapFileExt::lock_shared(inner),
1196 }
1197 }
1198
1199 #[inline]
1200 fn try_lock_exclusive(&self) -> Result<()> {
1201 match self {
1202 AsyncMmapFileInner::Empty(inner) => AsyncMmapFileExt::try_lock_exclusive(inner),
1203 AsyncMmapFileInner::Memory(inner) => {
1204 AsyncMmapFileExt::try_lock_exclusive(inner)
1205 }
1206 AsyncMmapFileInner::Disk(inner) => AsyncMmapFileExt::try_lock_exclusive(inner),
1207 }
1208 }
1209
1210 #[inline]
1211 fn try_lock_shared(&self) -> Result<()> {
1212 match self {
1213 AsyncMmapFileInner::Empty(inner) => AsyncMmapFileExt::try_lock_shared(inner),
1214 AsyncMmapFileInner::Memory(inner) => AsyncMmapFileExt::try_lock_shared(inner),
1215 AsyncMmapFileInner::Disk(inner) => AsyncMmapFileExt::try_lock_shared(inner),
1216 }
1217 }
1218
1219 #[inline]
1220 fn unlock(&self) -> Result<()> {
1221 match self {
1222 AsyncMmapFileInner::Empty(inner) => AsyncMmapFileExt::unlock(inner),
1223 AsyncMmapFileInner::Memory(inner) => AsyncMmapFileExt::unlock(inner),
1224 AsyncMmapFileInner::Disk(inner) => AsyncMmapFileExt::unlock(inner),
1225 }
1226 }
1227 }
1228
1229 enum AsyncMmapFileMutInner {
1230 Empty(AsyncEmptyMmapFile),
1231 Memory(AsyncMemoryMmapFileMut),
1232 Disk(AsyncDiskMmapFileMut)
1233 }
1234
1235 impl From<AsyncEmptyMmapFile> for AsyncMmapFileMutInner {
1236 fn from(v: AsyncEmptyMmapFile) -> AsyncMmapFileMutInner {
1237 AsyncMmapFileMutInner::Empty(v)
1238 }
1239 }
1240 impl From<AsyncMemoryMmapFileMut> for AsyncMmapFileMutInner {
1241 fn from(v: AsyncMemoryMmapFileMut) -> AsyncMmapFileMutInner {
1242 AsyncMmapFileMutInner::Memory(v)
1243 }
1244 }
1245 impl From<AsyncDiskMmapFileMut> for AsyncMmapFileMutInner {
1246 fn from(v: AsyncDiskMmapFileMut) -> AsyncMmapFileMutInner {
1247 AsyncMmapFileMutInner::Disk(v)
1248 }
1249 }
1250
1251
1252 impl AsyncMmapFileExt for AsyncMmapFileMutInner {
1253 #[inline]
1254 fn len(&self) -> usize {
1255 match self {
1256 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileExt::len(inner),
1257 AsyncMmapFileMutInner::Memory(inner) => AsyncMmapFileExt::len(inner),
1258 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileExt::len(inner),
1259 }
1260 }
1261
1262 #[inline]
1263 fn as_slice(&self) -> &[u8] {
1264 match self {
1265 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileExt::as_slice(inner),
1266 AsyncMmapFileMutInner::Memory(inner) => AsyncMmapFileExt::as_slice(inner),
1267 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileExt::as_slice(inner),
1268 }
1269 }
1270
1271 #[inline]
1272 fn path(&self) -> &Path {
1273 match self {
1274 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileExt::path(inner),
1275 AsyncMmapFileMutInner::Memory(inner) => AsyncMmapFileExt::path(inner),
1276 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileExt::path(inner),
1277 }
1278 }
1279
1280 #[inline]
1281 fn is_exec(&self) -> bool {
1282 match self {
1283 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileExt::is_exec(inner),
1284 AsyncMmapFileMutInner::Memory(inner) => AsyncMmapFileExt::is_exec(inner),
1285 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileExt::is_exec(inner),
1286 }
1287 }
1288
1289 #[inline]
1290 async fn metadata(&self) -> Result<MetaData> {
1291 match self {
1292 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileExt::metadata(inner).await,
1293 AsyncMmapFileMutInner::Memory(inner) => AsyncMmapFileExt::metadata(inner).await,
1294 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileExt::metadata(inner).await,
1295 }
1296 }
1297
1298 #[inline]
1299 fn lock_exclusive(&self) -> Result<()> {
1300 match self {
1301 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileExt::lock_exclusive(inner),
1302 AsyncMmapFileMutInner::Memory(inner) => AsyncMmapFileExt::lock_exclusive(inner),
1303 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileExt::lock_exclusive(inner),
1304 }
1305 }
1306
1307 #[inline]
1308 fn lock_shared(&self) -> Result<()> {
1309 match self {
1310 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileExt::lock_shared(inner),
1311 AsyncMmapFileMutInner::Memory(inner) => AsyncMmapFileExt::lock_shared(inner),
1312 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileExt::lock_shared(inner),
1313 }
1314 }
1315
1316 #[inline]
1317 fn try_lock_exclusive(&self) -> Result<()> {
1318 match self {
1319 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileExt::try_lock_exclusive(inner),
1320 AsyncMmapFileMutInner::Memory(inner) => {
1321 AsyncMmapFileExt::try_lock_exclusive(inner)
1322 }
1323 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileExt::try_lock_exclusive(inner),
1324 }
1325 }
1326
1327 #[inline]
1328 fn try_lock_shared(&self) -> Result<()> {
1329 match self {
1330 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileExt::try_lock_shared(inner),
1331 AsyncMmapFileMutInner::Memory(inner) => AsyncMmapFileExt::try_lock_shared(inner),
1332 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileExt::try_lock_shared(inner),
1333 }
1334 }
1335
1336 #[inline]
1337 fn unlock(&self) -> Result<()> {
1338 match self {
1339 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileExt::unlock(inner),
1340 AsyncMmapFileMutInner::Memory(inner) => AsyncMmapFileExt::unlock(inner),
1341 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileExt::unlock(inner),
1342 }
1343 }
1344 }
1345
1346
1347 impl AsyncMmapFileMutExt for AsyncMmapFileMutInner {
1348 #[inline]
1349 fn as_mut_slice(&mut self) -> &mut [u8] {
1350 match self {
1351 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileMutExt::as_mut_slice(inner),
1352 AsyncMmapFileMutInner::Memory(inner) => {
1353 AsyncMmapFileMutExt::as_mut_slice(inner)
1354 }
1355 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileMutExt::as_mut_slice(inner),
1356 }
1357 }
1358
1359 #[inline]
1360 fn is_cow(&self) -> bool {
1361 match self {
1362 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileMutExt::is_cow(inner),
1363 AsyncMmapFileMutInner::Memory(inner) => AsyncMmapFileMutExt::is_cow(inner),
1364 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileMutExt::is_cow(inner),
1365 }
1366 }
1367
1368 #[inline]
1369 fn flush(&self) -> Result<()> {
1370 match self {
1371 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileMutExt::flush(inner),
1372 AsyncMmapFileMutInner::Memory(inner) => AsyncMmapFileMutExt::flush(inner),
1373 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileMutExt::flush(inner),
1374 }
1375 }
1376
1377 #[inline]
1378 fn flush_async(&self) -> Result<()> {
1379 match self {
1380 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileMutExt::flush_async(inner),
1381 AsyncMmapFileMutInner::Memory(inner) => AsyncMmapFileMutExt::flush_async(inner),
1382 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileMutExt::flush_async(inner),
1383 }
1384 }
1385
1386 #[inline]
1387 fn flush_range(&self, offset: usize, len: usize) -> Result<()> {
1388 match self {
1389 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileMutExt::flush_range(
1390 inner,
1391 offset,
1392 len,
1393 ),
1394 AsyncMmapFileMutInner::Memory(inner) => AsyncMmapFileMutExt::flush_range(
1395 inner,
1396 offset,
1397 len,
1398 ),
1399 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileMutExt::flush_range(
1400 inner,
1401 offset,
1402 len,
1403 ),
1404 }
1405 }
1406
1407 #[inline]
1408 fn flush_async_range(&self, offset: usize, len: usize) -> Result<()> {
1409 match self {
1410 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileMutExt::flush_async_range(
1411 inner,
1412 offset,
1413 len,
1414 ),
1415 AsyncMmapFileMutInner::Memory(inner) => AsyncMmapFileMutExt::flush_async_range(
1416 inner,
1417 offset,
1418 len,
1419 ),
1420 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileMutExt::flush_async_range(
1421 inner,
1422 offset,
1423 len,
1424 ),
1425 }
1426 }
1427
1428 async fn truncate(&mut self, max_sz: u64) -> Result<()> {
1429 match self {
1430 AsyncMmapFileMutInner::Empty(inner) => {
1431 AsyncMmapFileMutExt::truncate(inner, max_sz).await
1432 }
1433 AsyncMmapFileMutInner::Memory(inner) => {
1434 AsyncMmapFileMutExt::truncate(inner, max_sz).await
1435 }
1436 AsyncMmapFileMutInner::Disk(inner) => {
1437 AsyncMmapFileMutExt::truncate(inner, max_sz).await
1438 }
1439 }
1440 }
1441
1442 async fn drop_remove(self) -> Result<()> {
1443 match self {
1444 AsyncMmapFileMutInner::Empty(inner) => AsyncMmapFileMutExt::drop_remove(inner).await,
1445 AsyncMmapFileMutInner::Memory(inner) => AsyncMmapFileMutExt::drop_remove(inner).await,
1446 AsyncMmapFileMutInner::Disk(inner) => AsyncMmapFileMutExt::drop_remove(inner).await,
1447 }
1448 }
1449
1450 async fn close_with_truncate(self, max_sz: i64) -> Result<()> {
1451 match self {
1452 AsyncMmapFileMutInner::Empty(inner) => {
1453 AsyncMmapFileMutExt::close_with_truncate(inner, max_sz).await
1454 }
1455 AsyncMmapFileMutInner::Memory(inner) => {
1456 AsyncMmapFileMutExt::close_with_truncate(inner, max_sz).await
1457 }
1458 AsyncMmapFileMutInner::Disk(inner) => {
1459 AsyncMmapFileMutExt::close_with_truncate(inner, max_sz).await
1460 }
1461 }
1462 }
1463 }
1464
1465 };
1466 }
1467
1468
1469 macro_rules! declare_and_impl_async_mmap_file {
1470 ($filename_prefix: literal, $doc_test_runtime: literal, $path_str: literal) => {
1471 /// A read-only memory map file.
1472 ///
1473 /// There is 3 status of this struct:
1474 /// - __Disk__: mmap to a real file
1475 /// - __Memory__: use [`Bytes`] to mock a mmap, which is useful for test and in-memory storage engine
1476 /// - __Empty__: a state represents null mmap, which is helpful for drop, close the `AsyncMmapFile`. This state cannot be constructed directly.
1477 ///
1478 /// [`Bytes`]: https://docs.rs/bytes/1.1.0/bytes/struct.Bytes.html
1479 #[repr(transparent)]
1480 pub struct AsyncMmapFile {
1481 inner: AsyncMmapFileInner
1482 }
1483
1484 impl_from!(AsyncMmapFile, AsyncMmapFileInner, [AsyncEmptyMmapFile, AsyncMemoryMmapFile, AsyncDiskMmapFile]);
1485
1486 impl_async_mmap_file_ext!(AsyncMmapFile);
1487
1488 impl AsyncMmapFile {
1489 /// Open a readable memory map backed by a file
1490 ///
1491 /// # Examples
1492 ///
1493 #[doc = "```ignore"]
1494 #[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFile, AsyncMmapFileExt};")]
1495 #[doc = concat!("# use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileMutExt};")]
1496 /// # use scopeguard::defer;
1497 ///
1498 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
1499 #[doc = concat!("# let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_open_test.txt\").await.unwrap();")]
1500 #[doc = concat!(" # defer!(std::fs::remove_file(\"", $filename_prefix, "_open_test.txt\").unwrap());")]
1501 /// # file.truncate(12).await.unwrap();
1502 /// # file.write_all("some data...".as_bytes(), 0).unwrap();
1503 /// # file.flush().unwrap();
1504 /// # drop(file);
1505 /// // mmap the file
1506 #[doc = concat!("let mut file = AsyncMmapFile::open(\"", $filename_prefix, "_open_test.txt\").await.unwrap();")]
1507 /// let mut buf = vec![0; "some data...".len()];
1508 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1509 /// assert_eq!(buf.as_slice(), "some data...".as_bytes());
1510 /// # })
1511 #[doc = "```"]
1512 pub async fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
1513 Ok(Self::from(AsyncDiskMmapFile::open(path).await?))
1514 }
1515
1516 /// Open a readable memory map backed by a file with [`Options`]
1517 ///
1518 /// # Examples
1519 ///
1520 #[doc = "```ignore"]
1521 #[doc = concat!("use fmmap::", $path_str, "::{AsyncOptions, AsyncMmapFile, AsyncMmapFileExt};")]
1522 #[doc = concat!("# use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileMutExt};")]
1523 /// # use scopeguard::defer;
1524 ///
1525 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
1526 #[doc = concat!("# let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_open_with_options_test.txt\").await.unwrap();")]
1527 #[doc = concat!(" # defer!(std::fs::remove_file(\"", $filename_prefix, "_open_with_options_test.txt\").unwrap());")]
1528 /// # file.truncate(23).await.unwrap();
1529 /// # file.write_all("sanity text".as_bytes(), 0).unwrap();
1530 /// # file.write_all("some data...".as_bytes(), "sanity text".as_bytes().len()).unwrap();
1531 /// # file.flush().unwrap();
1532 /// # drop(file);
1533 ///
1534 /// // mmap the file
1535 /// let opts = AsyncOptions::new()
1536 /// // mmap content after the sanity text
1537 /// .offset("sanity text".as_bytes().len() as u64);
1538 /// // mmap the file
1539 #[doc = concat!("let mut file = AsyncMmapFile::open_with_options(\"", $filename_prefix, "_open_with_options_test.txt\", opts).await.unwrap();")]
1540 /// let mut buf = vec![0; "some data...".len()];
1541 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1542 /// assert_eq!(buf.as_slice(), "some data...".as_bytes());
1543 /// # })
1544 #[doc = "```"]
1545 ///
1546 #[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
1547 pub async fn open_with_options<P: AsRef<Path>>(path: P, opts: AsyncOptions) -> Result<Self> {
1548 Ok(Self::from(AsyncDiskMmapFile::open_with_options(path, opts).await?))
1549 }
1550
1551 /// Open a readable and executable memory map backed by a file
1552 ///
1553 /// # Examples
1554 ///
1555 #[doc = "```ignore"]
1556 #[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFile, AsyncMmapFileExt};")]
1557 #[doc = concat!("# use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileMutExt};")]
1558 /// # use scopeguard::defer;
1559 ///
1560 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
1561 #[doc = concat!("# let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_open_exec_test.txt\").await.unwrap();")]
1562 #[doc = concat!(" # defer!(std::fs::remove_file(\"", $filename_prefix, "_open_exec_test.txt\").unwrap());")]
1563 /// # file.truncate(12).await.unwrap();
1564 /// # file.write_all("some data...".as_bytes(), 0).unwrap();
1565 /// # file.flush().unwrap();
1566 /// # drop(file);
1567 /// // mmap the file
1568 #[doc = concat!("let mut file = AsyncMmapFile::open_exec(\"", $filename_prefix, "_open_exec_test.txt\").await.unwrap();")]
1569 /// let mut buf = vec![0; "some data...".len()];
1570 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1571 /// assert_eq!(buf.as_slice(), "some data...".as_bytes());
1572 /// # })
1573 #[doc = "```"]
1574 pub async fn open_exec<P: AsRef<Path>>(path: P) -> Result<Self> {
1575 Ok(Self::from(AsyncDiskMmapFile::open_exec(path).await?))
1576 }
1577
1578 /// Open a readable and executable memory map backed by a file with [`Options`].
1579 ///
1580 /// # Examples
1581 ///
1582 #[doc = "```ignore"]
1583 #[doc = concat!("use fmmap::", $path_str, "::{AsyncOptions, AsyncMmapFile, AsyncMmapFileExt};")]
1584 #[doc = concat!("# use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileMutExt};")]
1585 /// # use scopeguard::defer;
1586 ///
1587 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
1588 #[doc = concat!("# let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_open_exec_with_options_test.txt\").await.unwrap();")]
1589 #[doc = concat!(" # defer!(std::fs::remove_file(\"", $filename_prefix, "_open_exec_with_options_test.txt\").unwrap());")]
1590 /// # file.truncate(23).await.unwrap();
1591 /// # file.write_all("sanity text".as_bytes(), 0).unwrap();
1592 /// # file.write_all("some data...".as_bytes(), "sanity text".as_bytes().len()).unwrap();
1593 /// # file.flush().unwrap();
1594 /// # drop(file);
1595 ///
1596 /// // mmap the file
1597 /// let opts = AsyncOptions::new()
1598 /// // mmap content after the sanity text
1599 /// .offset("sanity text".as_bytes().len() as u64);
1600 /// // mmap the file
1601 #[doc = concat!("let mut file = AsyncMmapFile::open_exec_with_options(\"", $filename_prefix, "_open_exec_with_options_test.txt\", opts).await.unwrap();")]
1602 /// let mut buf = vec![0; "some data...".len()];
1603 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1604 /// assert_eq!(buf.as_slice(), "some data...".as_bytes());
1605 /// # })
1606 #[doc = "```"]
1607 ///
1608 #[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
1609 pub async fn open_exec_with_options<P: AsRef<Path>>(path: P, opts: AsyncOptions) -> Result<Self> {
1610 Ok(Self::from(AsyncDiskMmapFile::open_exec_with_options(path, opts).await?))
1611 }
1612 }
1613
1614 impl_constructor_for_memory_mmap_file!(AsyncMemoryMmapFile, AsyncMmapFile, "AsyncMmapFile", $path_str);
1615 };
1616 }
1617
1618 macro_rules! delcare_and_impl_async_mmap_file_mut {
1619 ($filename_prefix: literal, $doc_test_runtime: literal, $path_str: literal) => {
1620 /// A writable memory map file.
1621 ///
1622 /// There is 3 status of this struct:
1623 /// - __Disk__: mmap to a real file
1624 /// - __Memory__: use [`BytesMut`] to mock a mmap, which is useful for test and in-memory storage engine
1625 /// - __Empty__: a state represents null mmap, which is helpful for drop, remove, close the `AsyncMmapFileMut`. This state cannot be constructed directly.
1626 ///
1627 /// [`BytesMut`]: https://docs.rs/bytes/1.1.0/bytes/struct.BytesMut.html
1628 pub struct AsyncMmapFileMut {
1629 inner: AsyncMmapFileMutInner,
1630 remove_on_drop: bool,
1631 deleted: bool,
1632 }
1633
1634 impl_from_mut!(AsyncMmapFileMut, AsyncMmapFileMutInner, [AsyncEmptyMmapFile, AsyncMemoryMmapFileMut, AsyncDiskMmapFileMut]);
1635
1636 impl_async_mmap_file_ext!(AsyncMmapFileMut);
1637
1638 impl_async_mmap_file_mut_ext!($filename_prefix, $doc_test_runtime, $path_str);
1639
1640 impl AsyncMmapFileMut {
1641 /// Create a new file and mmap this file
1642 ///
1643 /// # Notes
1644 /// The new file is zero size, so, before write, you should truncate first.
1645 /// Or you can use [`create_with_options`] and set `max_size` field for [`AsyncOptions`] to enable directly write
1646 /// without truncating.
1647 /// # Examples
1648 ///
1649 #[doc = "```ignore"]
1650 #[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileMutExt};")]
1651 /// # use scopeguard::defer;
1652 ///
1653 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
1654 #[doc = concat!("let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_create_test.txt\").await.unwrap();")]
1655 #[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_create_test.txt\").unwrap());")]
1656 /// file.truncate(12).await;
1657 /// file.write_all("some data...".as_bytes(), 0).unwrap();
1658 /// file.flush().unwrap();
1659 /// # })
1660 #[doc = "```"]
1661 ///
1662 #[doc = concat!("[`create_with_options`]: ", $path_str, "/struct.AsyncMmapFileMut.html#method.create_with_options")]
1663 #[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
1664 pub async fn create<P: AsRef<Path>>(path: P) -> Result<Self> {
1665 Ok(Self::from(AsyncDiskMmapFileMut::create(path).await?))
1666 }
1667
1668 /// Create a new file and mmap this file with [`AsyncOptions`]
1669 ///
1670 /// # Example
1671 ///
1672 #[doc = "```ignore"]
1673 #[doc = concat!("use fmmap::", $path_str, "::{AsyncOptions, AsyncMmapFileMut, AsyncMmapFileMutExt};")]
1674 /// # use scopeguard::defer;
1675 ///
1676 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
1677 /// let opts = AsyncOptions::new()
1678 /// // truncate to 100
1679 /// .max_size(100);
1680 #[doc = concat!("let mut file = AsyncMmapFileMut::create_with_options(\"", $filename_prefix, "_create_with_options_test.txt\", opts).await.unwrap();")]
1681 #[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_create_with_options_test.txt\").unwrap());")]
1682 /// file.write_all("some data...".as_bytes(), 0).unwrap();
1683 /// file.flush().unwrap();
1684 /// # })
1685 #[doc = "```"]
1686 ///
1687 #[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
1688 pub async fn create_with_options<P: AsRef<Path>>(path: P, opts: AsyncOptions) -> Result<Self> {
1689 Ok(Self::from(AsyncDiskMmapFileMut::create_with_options(path, opts).await?))
1690 }
1691
1692 /// Open or Create(if not exists) a file and mmap this file.
1693 ///
1694 /// # Notes
1695 /// If the file does not exist, then the new file will be open in zero size, so before do write, you should truncate first.
1696 /// Or you can use [`open_with_options`] and set `max_size` field for [`AsyncOptions`] to enable directly write
1697 /// without truncating.
1698 ///
1699 /// # Examples
1700 ///
1701 /// File already exists
1702 ///
1703 #[doc = "```ignore"]
1704 #[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileExt, AsyncMmapFileMutExt};")]
1705 /// # use scopeguard::defer;
1706 ///
1707 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
1708 #[doc = concat!("# let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_open_test.txt\").await.unwrap();")]
1709 #[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_open_test.txt\").unwrap());")]
1710 /// # file.truncate(12).await.unwrap();
1711 /// # file.write_all("some data...".as_bytes(), 0).unwrap();
1712 /// # file.flush().unwrap();
1713 /// # drop(file);
1714 ///
1715 /// // mmap the file
1716 #[doc = concat!("let mut file = AsyncMmapFileMut::open(\"", $filename_prefix, "_open_test.txt\").await.unwrap();")]
1717 /// let mut buf = vec![0; "some data...".len()];
1718 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1719 /// assert_eq!(buf.as_slice(), "some data...".as_bytes());
1720 ///
1721 /// // modify the file data
1722 /// file.truncate("some modified data...".len() as u64).await.unwrap();
1723 /// file.write_all("some modified data...".as_bytes(), 0).unwrap();
1724 /// file.flush().unwrap();
1725 /// drop(file);
1726 ///
1727 /// // reopen to check content
1728 /// let mut buf = vec![0; "some modified data...".len()];
1729 #[doc = concat!("let mut file = AsyncMmapFileMut::open(\"", $filename_prefix, "_open_test.txt\").await.unwrap();")]
1730 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1731 /// assert_eq!(buf.as_slice(), "some modified data...".as_bytes());
1732 /// # })
1733 #[doc = "```"]
1734 ///
1735 /// File does not exists
1736 ///
1737 #[doc = "```ignore"]
1738 #[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileExt, AsyncMmapFileMutExt};")]
1739 /// # use scopeguard::defer;
1740 ///
1741 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
1742 /// // mmap the file
1743 #[doc = concat!("let mut file = AsyncMmapFileMut::open(\"", $filename_prefix, "_open_test.txt\").await.unwrap();")]
1744 #[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_open_test.txt\").unwrap());")]
1745 /// file.truncate(100).await.unwrap();
1746 /// file.write_all("some data...".as_bytes(), 0).unwrap();
1747 /// file.flush().unwrap();
1748 ///
1749 /// let mut buf = vec![0; "some data...".len()];
1750 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1751 /// assert_eq!(buf.as_slice(), "some data...".as_bytes());
1752 ///
1753 /// // modify the file data
1754 /// file.truncate("some modified data...".len() as u64).await.unwrap();
1755 /// file.write_all("some modified data...".as_bytes(), 0).unwrap();
1756 /// file.flush().unwrap();
1757 /// drop(file);
1758 ///
1759 /// // reopen to check content
1760 /// let mut buf = vec![0; "some modified data...".len()];
1761 #[doc = concat!("let mut file = AsyncMmapFileMut::open(\"", $filename_prefix, "_open_test.txt\").await.unwrap();")]
1762 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1763 /// assert_eq!(buf.as_slice(), "some modified data...".as_bytes());
1764 /// # })
1765 #[doc = "```"]
1766 ///
1767 #[doc = concat!("[`open_with_options`]: ", $path_str, "/struct.AsyncMmapFileMut.html#method.open_with_options")]
1768 #[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
1769 pub async fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
1770 Ok(Self::from(AsyncDiskMmapFileMut::open(path).await?))
1771 }
1772
1773 /// Open or Create(if not exists) a file and mmap this file with [`AsyncOptions`].
1774 ///
1775 /// # Examples
1776 ///
1777 /// File already exists
1778 ///
1779 /// ```ignore
1780 #[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileExt, AsyncMmapFileMutExt, AsyncOptions};")]
1781 /// # use scopeguard::defer;
1782 ///
1783 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
1784 #[doc = concat!("# let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_open_with_options_test.txt\").await.unwrap();")]
1785 #[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_open_with_options_test.txt\").unwrap());")]
1786 /// # file.truncate(23).await.unwrap();
1787 /// # file.write_all("sanity text".as_bytes(), 0).unwrap();
1788 /// # file.write_all("some data...".as_bytes(), "sanity text".as_bytes().len()).unwrap();
1789 /// # file.flush().unwrap();
1790 /// # drop(file);
1791 ///
1792 /// // mmap the file
1793 /// let opts = AsyncOptions::new()
1794 /// // allow read
1795 /// .read(true)
1796 /// // allow write
1797 /// .write(true)
1798 /// // allow append
1799 /// .append(true)
1800 /// // truncate to 100
1801 /// .max_size(100)
1802 /// // mmap content after the sanity text
1803 /// .offset("sanity text".as_bytes().len() as u64);
1804 #[doc = concat!("let mut file = AsyncMmapFileMut::open_with_options(\"", $filename_prefix, "_open_with_options_test.txt\", opts).await.unwrap();")]
1805 /// let mut buf = vec![0; "some data...".len()];
1806 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1807 /// assert_eq!(buf.as_slice(), "some data...".as_bytes());
1808 ///
1809 /// // modify the file data
1810 /// file.truncate(("some modified data...".len() + "sanity text".len()) as u64).await.unwrap();
1811 /// file.write_all("some modified data...".as_bytes(), 0).unwrap();
1812 /// file.flush().unwrap();
1813 /// drop(file);
1814 ///
1815 /// // reopen to check content
1816 /// let mut buf = vec![0; "some modified data...".len()];
1817 #[doc = concat!("let mut file = AsyncMmapFileMut::open(\"", $filename_prefix, "_open_with_options_test.txt\").await.unwrap();")]
1818 /// // skip the sanity text
1819 /// file.read_exact(buf.as_mut_slice(), "sanity text".as_bytes().len()).unwrap();
1820 /// assert_eq!(buf.as_slice(), "some modified data...".as_bytes());
1821 /// # })
1822 #[doc = "```"]
1823 ///
1824 /// File does not exists
1825 ///
1826 /// ```ignore
1827 #[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileExt, AsyncMmapFileMutExt, AsyncOptions};")]
1828 /// # use scopeguard::defer;
1829 ///
1830 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
1831 /// // mmap the file with options
1832 /// let opts = AsyncOptions::new()
1833 /// // allow read
1834 /// .read(true)
1835 /// // allow write
1836 /// .write(true)
1837 /// // allow append
1838 /// .append(true)
1839 /// // truncate to 100
1840 /// .max_size(100);
1841 ///
1842 #[doc = concat!("let mut file = AsyncMmapFileMut::open_with_options(\"", $filename_prefix, "_open_with_options_test.txt\", opts).await.unwrap();")]
1843 #[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_open_with_options_test.txt\").unwrap());")]
1844 /// file.write_all("some data...".as_bytes(), 0).unwrap();
1845 ///
1846 /// let mut buf = vec![0; "some data...".len()];
1847 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1848 /// assert_eq!(buf.as_slice(), "some data...".as_bytes());
1849 ///
1850 /// // modify the file data
1851 /// file.truncate("some modified data...".len() as u64).await.unwrap();
1852 /// file.write_all("some modified data...".as_bytes(), 0).unwrap();
1853 /// file.flush().unwrap();
1854 /// drop(file);
1855 ///
1856 /// // reopen to check content
1857 /// let mut buf = vec![0; "some modified data...".len()];
1858 #[doc = concat!("let mut file = AsyncMmapFileMut::open(\"", $filename_prefix, "_open_with_options_test.txt\").await.unwrap();")]
1859 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1860 /// assert_eq!(buf.as_slice(), "some modified data...".as_bytes());
1861 /// # })
1862 #[doc = "```"]
1863 ///
1864 #[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
1865 pub async fn open_with_options<P: AsRef<Path>>(path: P, opts: AsyncOptions) -> Result<Self> {
1866 Ok(Self::from(AsyncDiskMmapFileMut::open_with_options(path, opts).await?))
1867 }
1868
1869 /// Open an existing file and mmap this file
1870 ///
1871 /// # Examples
1872 #[doc = "```ignore"]
1873 #[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileExt, AsyncMmapFileMutExt};")]
1874 /// # use scopeguard::defer;
1875 ///
1876 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
1877 /// // create a temp file
1878 #[doc = concat!("let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_open_existing_test.txt\").await.unwrap();")]
1879 #[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_open_existing_test.txt\").unwrap());")]
1880 /// file.truncate(12).await.unwrap();
1881 /// file.write_all("some data...".as_bytes(), 0).unwrap();
1882 /// file.flush().unwrap();
1883 /// drop(file);
1884 ///
1885 /// // mmap the file
1886 #[doc = concat!("let mut file = AsyncMmapFileMut::open_exist(\"", $filename_prefix, "_open_existing_test.txt\").await.unwrap();")]
1887 /// let mut buf = vec![0; "some data...".len()];
1888 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1889 /// assert_eq!(buf.as_slice(), "some data...".as_bytes());
1890 ///
1891 /// // modify the file data
1892 /// file.truncate("some modified data...".len() as u64).await.unwrap();
1893 /// file.write_all("some modified data...".as_bytes(), 0).unwrap();
1894 /// file.flush().unwrap();
1895 /// drop(file);
1896 ///
1897 ///
1898 /// // reopen to check content
1899 /// let mut buf = vec![0; "some modified data...".len()];
1900 #[doc = concat!("let mut file = AsyncMmapFileMut::open(\"", $filename_prefix, "_open_existing_test.txt\").await.unwrap();")]
1901 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1902 /// assert_eq!(buf.as_slice(), "some modified data...".as_bytes());
1903 /// # })
1904 #[doc = "```"]
1905 ///
1906 #[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
1907 pub async fn open_exist<P: AsRef<Path>>(path: P) -> Result<Self> {
1908 Ok(Self::from(AsyncDiskMmapFileMut::open_exist(path).await?))
1909 }
1910
1911 /// Open an existing file and mmap this file with [`AsyncOptions`]
1912 ///
1913 /// # Examples
1914 ///
1915 /// ```ignore
1916 #[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileExt, AsyncMmapFileMutExt, AsyncOptions};")]
1917 /// # use scopeguard::defer;
1918 ///
1919 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
1920 /// // create a temp file
1921 #[doc = concat!("let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_open_existing_test_with_options.txt\").await.unwrap();")]
1922 #[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_open_existing_test_with_options.txt\").unwrap());")]
1923 /// file.truncate(23).await.unwrap();
1924 /// file.write_all("sanity text".as_bytes(), 0).unwrap();
1925 /// file.write_all("some data...".as_bytes(), "sanity text".as_bytes().len()).unwrap();
1926 /// file.flush().unwrap();
1927 /// drop(file);
1928 ///
1929 /// // mmap the file
1930 /// let opts = AsyncOptions::new()
1931 /// // truncate to 100
1932 /// .max_size(100)
1933 /// // mmap content after the sanity text
1934 /// .offset("sanity text".as_bytes().len() as u64);
1935 ///
1936 #[doc = concat!("let mut file = AsyncMmapFileMut::open_exist_with_options(\"", $filename_prefix, "_open_existing_test_with_options.txt\", opts).await.unwrap();")]
1937 ///
1938 /// let mut buf = vec![0; "some data...".len()];
1939 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1940 /// assert_eq!(buf.as_slice(), "some data...".as_bytes());
1941 ///
1942 /// // modify the file data
1943 /// file.truncate(("some modified data...".len() + "sanity text".len()) as u64).await.unwrap();
1944 /// file.write_all("some modified data...".as_bytes(), 0).unwrap();
1945 /// file.flush().unwrap();
1946 ///
1947 /// // reopen to check content, cow will not change the content.
1948 #[doc = concat!("let mut file = AsyncMmapFileMut::open(\"", $filename_prefix, "_open_existing_test_with_options.txt\").await.unwrap();")]
1949 /// let mut buf = vec![0; "some modified data...".len()];
1950 /// // skip the sanity text
1951 /// // file.read_exact(buf.as_mut_slice(), "sanity text".as_bytes().len()).unwrap();
1952 /// // assert_eq!(buf.as_slice(), "some modified data...".as_bytes());
1953 /// # })
1954 #[doc = "```"]
1955 ///
1956 #[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
1957 pub async fn open_exist_with_options<P: AsRef<Path>>(path: P, opts: AsyncOptions) -> Result<Self> {
1958 Ok(Self::from(AsyncDiskMmapFileMut::open_exist_with_options(path, opts).await?))
1959 }
1960
1961 /// Open and mmap an existing file in copy-on-write mode(copy-on-write memory map backed by a file).
1962 /// Data written to the memory map will not be visible by other processes, and will not be carried through to the underlying file.
1963 ///
1964 /// # Examples
1965 ///
1966 #[doc = "```ignore"]
1967 #[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileExt, AsyncMmapFileMutExt};")]
1968 /// # use scopeguard::defer;
1969 ///
1970 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
1971 /// // create a temp file
1972 #[doc = concat!("let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_open_cow_test.txt\").await.unwrap();")]
1973 #[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_open_cow_test.txt\").unwrap());")]
1974 /// file.truncate(12).await.unwrap();
1975 /// file.write_all("some data...".as_bytes(), 0).unwrap();
1976 /// file.flush().unwrap();
1977 /// drop(file);
1978 ///
1979 /// // mmap the file
1980 #[doc = concat!("let mut file = AsyncMmapFileMut::open_cow(\"", $filename_prefix, "_open_cow_test.txt\").await.unwrap();")]
1981 /// let mut buf = vec![0; "some data...".len()];
1982 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1983 /// assert_eq!(buf.as_slice(), "some data...".as_bytes());
1984 ///
1985 /// // modify the file data
1986 /// file.write_all("some data!!!".as_bytes(), 0).unwrap();
1987 /// file.flush().unwrap();
1988 ///
1989 /// // cow, change will only be seen in current caller
1990 /// assert_eq!(file.as_slice(), "some data!!!".as_bytes());
1991 /// drop(file);
1992 ///
1993 /// // reopen to check content, cow will not change the content.
1994 #[doc = concat!("let mut file = AsyncMmapFileMut::open(\"", $filename_prefix, "_open_cow_test.txt\").await.unwrap();")]
1995 /// let mut buf = vec![0; "some data...".len()];
1996 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
1997 /// assert_eq!(buf.as_slice(), "some data...".as_bytes());
1998 /// # })
1999 #[doc = "```"]
2000 ///
2001 #[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
2002 pub async fn open_cow<P: AsRef<Path>>(path: P) -> Result<Self> {
2003 Ok(Self::from(AsyncDiskMmapFileMut::open_cow(path).await?))
2004 }
2005
2006 /// Open and mmap an existing file in copy-on-write mode(copy-on-write memory map backed by a file) with [`AsyncOptions`].
2007 /// Data written to the memory map will not be visible by other processes, and will not be carried through to the underlying file.
2008 ///
2009 /// # Examples
2010 ///
2011 #[doc = "```ignore"]
2012 #[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileExt, AsyncMmapFileMutExt, AsyncOptions};")]
2013 /// use std::io::SeekFrom;
2014 /// # use scopeguard::defer;
2015 ///
2016 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
2017 /// // create a temp file
2018 #[doc = concat!("let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_open_cow_with_options_test.txt\").await.unwrap();")]
2019 #[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_open_cow_with_options_test.txt\").unwrap());")]
2020 /// file.truncate(23).await.unwrap();
2021 /// file.write_all("sanity text".as_bytes(), 0).unwrap();
2022 /// file.write_all("some data...".as_bytes(), "sanity text".as_bytes().len()).unwrap();
2023 /// file.flush().unwrap();
2024 /// drop(file);
2025 ///
2026 /// // mmap the file
2027 /// let opts = AsyncOptions::new()
2028 /// // mmap content after the sanity text
2029 /// .offset("sanity text".as_bytes().len() as u64);
2030 ///
2031 #[doc = concat!("let mut file = AsyncMmapFileMut::open_cow_with_options(\"", $filename_prefix, "_open_cow_with_options_test.txt\", opts).await.unwrap();")]
2032 /// let mut buf = vec![0; "some data...".len()];
2033 /// file.read_exact(buf.as_mut_slice(), 0).unwrap();
2034 /// assert_eq!(buf.as_slice(), "some data...".as_bytes());
2035 ///
2036 /// // modify the file data
2037 /// file.write_all("some data!!!".as_bytes(), 0).unwrap();
2038 /// file.flush().unwrap();
2039 ///
2040 /// // cow, change will only be seen in current caller
2041 /// assert_eq!(file.as_slice(), "some data!!!".as_bytes());
2042 /// drop(file);
2043 ///
2044 /// // reopen to check content, cow will not change the content.
2045 #[doc = concat!("let mut file = AsyncMmapFileMut::open(\"", $filename_prefix, "_open_cow_with_options_test.txt\").await.unwrap();")]
2046 /// let mut buf = vec![0; "some data...".len()];
2047 /// // skip the sanity text
2048 /// file.read_exact(buf.as_mut_slice(), "sanity text".as_bytes().len()).unwrap();
2049 /// assert_eq!(buf.as_slice(), "some data...".as_bytes());
2050 /// # })
2051 #[doc = "```"]
2052 ///
2053 #[doc = concat!("[`AsyncOptions`]: ", $path_str, "/struct.AsyncOptions.html")]
2054 pub async fn open_cow_with_options<P: AsRef<Path>>(path: P, opts: AsyncOptions) -> Result<Self> {
2055 Ok(Self::from(AsyncDiskMmapFileMut::open_cow_with_options(path, opts).await?))
2056 }
2057
2058 /// Make the mmap file read-only.
2059 ///
2060 /// # Notes
2061 /// If `remove_on_drop` is set to `true`, then the underlying file will not be removed on drop if this function is invoked. [Read more]
2062 ///
2063 /// Returns an immutable version of this memory mapped buffer.
2064 /// If the memory map is file-backed, the file must have been opened with read permissions.
2065 ///
2066 /// # Errors
2067 /// This method returns an error when the underlying system call fails,
2068 /// which can happen for a variety of reasons,
2069 /// such as when the file has not been opened with read permissions.
2070 ///
2071 /// # Examples
2072 ///
2073 #[doc = "```ignore"]
2074 #[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileMutExt};")]
2075 /// # use scopeguard::defer;
2076 ///
2077 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
2078 #[doc = concat!("let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_freeze_test.txt\").await.unwrap();")]
2079 #[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_freeze_test.txt\").unwrap());")]
2080 /// file.truncate(12).await;
2081 /// file.write_all("some data...".as_bytes(), 0).unwrap();
2082 /// file.flush().unwrap();
2083 /// // freeze
2084 /// file.freeze().unwrap();
2085 /// # })
2086 #[doc = "```"]
2087 ///
2088 #[doc = concat!("[Read more]: ", $path_str, "/struct.AsyncMmapFileMut.html#methods.set_remove_on_drop")]
2089 ///
2090 #[inline]
2091 pub fn freeze(mut self) -> Result<AsyncMmapFile> {
2092 let empty = AsyncMmapFileMutInner::Empty(AsyncEmptyMmapFile::default());
2093 // swap the inner to empty
2094 let inner = mem::replace(&mut self.inner, empty);
2095 match inner {
2096 AsyncMmapFileMutInner::Empty(empty) => Ok(AsyncMmapFile::from(empty)), // unreachable, keep this for good measure
2097 AsyncMmapFileMutInner::Memory(memory) => Ok(AsyncMmapFile::from(memory.freeze())),
2098 AsyncMmapFileMutInner::Disk(disk) => Ok(AsyncMmapFile::from(disk.freeze()?)),
2099 }
2100 }
2101
2102 /// Transition the memory map to be readable and executable.
2103 /// If the memory map is file-backed, the file must have been opened with execute permissions.
2104 ///
2105 /// # Notes
2106 /// If `remove_on_drop` is set to `true`, then the underlying file will not be removed on drop if this function is invoked. [Read more]
2107 ///
2108 /// # Errors
2109 /// This method returns an error when the underlying system call fails,
2110 /// which can happen for a variety of reasons,
2111 /// such as when the file has not been opened with execute permissions
2112 ///
2113 /// # Examples
2114 ///
2115 #[doc = "```ignore"]
2116 #[doc = concat!("use fmmap::", $path_str, "::{AsyncMmapFileMut, AsyncMmapFileMutExt};")]
2117 /// # use scopeguard::defer;
2118 ///
2119 #[doc = concat!("# ", $doc_test_runtime, "::block_on(async {")]
2120 #[doc = concat!("let mut file = AsyncMmapFileMut::create(\"", $filename_prefix, "_freeze_exec_test.txt\").await.unwrap();")]
2121 #[doc = concat!("# defer!(std::fs::remove_file(\"", $filename_prefix, "_freeze_exec_test.txt\").unwrap());")]
2122 /// file.truncate(12).await;
2123 /// file.write_all("some data...".as_bytes(), 0).unwrap();
2124 /// file.flush().unwrap();
2125 /// // freeze_exec
2126 /// file.freeze_exec().unwrap();
2127 /// # })
2128 #[doc = "```"]
2129 ///
2130 #[doc = concat!("[Read more]: ", $path_str, "/struct.AsyncMmapFileMut.html#methods.set_remove_on_drop")]
2131 ///
2132 #[inline]
2133 pub fn freeze_exec(mut self) -> Result<AsyncMmapFile> {
2134 let empty = AsyncMmapFileMutInner::Empty(AsyncEmptyMmapFile::default());
2135 // swap the inner to empty
2136 let inner = mem::replace(&mut self.inner, empty);
2137 match inner {
2138 AsyncMmapFileMutInner::Empty(empty) => Ok(AsyncMmapFile::from(empty)), // unreachable, keep this for good measure
2139 AsyncMmapFileMutInner::Memory(memory) => Ok(AsyncMmapFile::from(memory.freeze())),
2140 AsyncMmapFileMutInner::Disk(disk) => Ok(AsyncMmapFile::from(disk.freeze_exec()?)),
2141 }
2142 }
2143
2144 /// Returns whether remove the underlying file on drop.
2145 #[inline]
2146 pub fn get_remove_on_drop(&self) -> bool {
2147 self.remove_on_drop
2148 }
2149
2150 /// Whether remove the underlying file on drop.
2151 /// Default is false.
2152 ///
2153 /// # Notes
2154 /// If invoke [`AsyncMmapFileMut::freeze`], then the file will
2155 /// not be removed even though the field `remove_on_drop` is true.
2156 ///
2157 /// [`AsyncMmapFileMut::freeze`]: structs.AsyncMmapFileMut.html#methods.freeze
2158 #[inline]
2159 pub fn set_remove_on_drop(&mut self, val: bool) {
2160 self.remove_on_drop = val;
2161 }
2162
2163 /// Close the file. It would also truncate the file if max_sz >= 0.
2164 #[inline]
2165 pub async fn close(&mut self, max_sz: i64) -> Result<()> {
2166 let empty = AsyncMmapFileMutInner::Empty(AsyncEmptyMmapFile::default());
2167 // swap the inner to empty
2168 let inner = mem::replace(&mut self.inner, empty);
2169 match inner {
2170 AsyncMmapFileMutInner::Disk(disk) => {
2171 disk.flush()?;
2172 if max_sz >= 0 {
2173 disk.file.set_len(max_sz as u64).await.map_err(From::from)
2174 } else {
2175 Ok(())
2176 }
2177 },
2178 _ => Ok(()),
2179 }
2180 }
2181
2182 /// Remove the underlying file without dropping, leaving an [`AsyncEmptyMmapFile`].
2183 #[inline]
2184 pub async fn remove(&mut self) -> Result<()> {
2185 let empty = AsyncMmapFileMutInner::Empty(AsyncEmptyMmapFile::default());
2186 // swap the inner to empty
2187 let inner = mem::replace(&mut self.inner, empty);
2188 match inner {
2189 AsyncMmapFileMutInner::Disk(disk) => {
2190 let path = disk.path;
2191 drop(disk.mmap);
2192 disk.file
2193 .set_len(0)
2194 .await?;
2195 drop(disk.file);
2196 remove_file(path)
2197 .await
2198 .map_err(From::from)
2199 },
2200 _ => Ok(()),
2201 }
2202 }
2203 }
2204
2205 impl_constructor_for_memory_mmap_file_mut!(AsyncMemoryMmapFileMut, AsyncMmapFileMut, "AsyncMmapFileMut", $path_str);
2206
2207 impl_drop!(AsyncMmapFileMut, AsyncMmapFileMutInner, AsyncEmptyMmapFile);
2208 };
2209 }
2210
2211 macro_rules! file_lock_tests {
2212 ($filename_prefix: literal, $runtime: meta) => {
2213 #[$runtime]
2214 async fn test_flush() {
2215 let path = concat!($filename_prefix, "_flush.txt");
2216 let mut file1 = AsyncMmapFileMut::create_with_options(path, AsyncOptions::new().max_size(100)).await.unwrap();
2217 file1.set_remove_on_drop(true);
2218 file1.write_all(vec![1; 100].as_slice(), 0).unwrap();
2219 file1.flush_range(0, 10).unwrap();
2220 file1.flush_async_range(11, 20).unwrap();
2221 file1.flush_async().unwrap();
2222 }
2223
2224 #[$runtime]
2225 async fn test_lock_shared() {
2226 let path = concat!($filename_prefix, "_lock_shared.txt");
2227 let file1 = AsyncMmapFileMut::open(path).await.unwrap();
2228 let file2 = AsyncMmapFileMut::open(path).await.unwrap();
2229 let file3 = AsyncMmapFileMut::open(path).await.unwrap();
2230 defer!(std::fs::remove_file(path).unwrap());
2231
2232 // Concurrent shared access is OK, but not shared and exclusive.
2233 file1.lock_shared().unwrap();
2234 file2.lock_shared().unwrap();
2235 assert!(file3.try_lock_exclusive().is_err());
2236 file1.unlock().unwrap();
2237 assert!(file3.try_lock_exclusive().is_err());
2238
2239 // Once all shared file locks are dropped, an exclusive lock may be created;
2240 file2.unlock().unwrap();
2241 file3.lock_exclusive().unwrap();
2242 }
2243 };
2244 }
2245}
2246
2247cfg_async_std!(
2248 pub(crate) mod async_std_impl;
2249);
2250
2251cfg_smol!(
2252 pub(crate) mod smol_impl;
2253);
2254
2255cfg_tokio!(
2256 pub(crate) mod tokio_impl;
2257);