1use std::os::unix::fs::MetadataExt;
2use std::time::{SystemTime, UNIX_EPOCH};
3use crate::error::{Error, ErrorKind, Result};
4use crate::MetaData;
5use crate::metadata::{DiskMetaData, EmptyMetaData, MemoryMetaData};
6
7#[enum_dispatch]
9pub trait MetaDataExt {
10 fn accessed(&self) -> std::result::Result<SystemTime, Error>;
18
19 fn created(&self) -> std::result::Result<SystemTime, Error>;
25
26 fn is_file(&self) -> bool;
36
37 #[cfg(feature = "nightly")]
39 #[cfg_attr(docsrs, doc(cfg(feature = "nightly")))]
40 fn is_symlink(&self) -> bool;
41
42 fn len(&self) -> u64;
44
45 fn modified(&self) -> std::result::Result<SystemTime, Error>;
54
55 fn dev(&self) -> u64;
57
58 fn ino(&self) -> u64;
60
61 fn mode(&self) -> u32;
63
64 fn nlink(&self) -> u64;
66
67 fn uid(&self) -> u32;
69
70 fn gid(&self) -> u32;
72
73 fn rdev(&self) -> u64;
75
76 fn size(&self) -> u64;
78
79 fn atime(&self) -> i64;
81
82 fn atime_nsec(&self) -> i64;
84
85 fn mtime(&self) -> i64;
87
88 fn mtime_nsec(&self) -> i64;
90
91 fn ctime(&self) -> i64;
93
94 fn ctime_nsec(&self) -> i64;
96
97 fn blksize(&self) -> u64;
99
100 fn blocks(&self) -> u64;
104}
105
106impl MetaDataExt for MemoryMetaData {
107 fn accessed(&self) -> Result<SystemTime> {
108 Ok(self.create_at)
109 }
110
111 #[inline]
112 fn created(&self) -> Result<SystemTime> {
113 Ok(self.create_at)
114 }
115
116 fn is_file(&self) -> bool {
117 false
118 }
119
120 #[cfg(feature = "nightly")]
121 fn is_symlink(&self) -> bool {
122 false
123 }
124
125 #[inline]
126 fn len(&self) -> u64 {
127 self.size
128 }
129
130 fn modified(&self) -> Result<SystemTime> {
131 Ok(self.create_at)
132 }
133
134 fn dev(&self) -> u64 {
135 0
136 }
137
138 fn ino(&self) -> u64 {
139 0
140 }
141
142 fn mode(&self) -> u32 {
143 0
144 }
145
146 fn nlink(&self) -> u64 {
147 0
148 }
149
150 fn uid(&self) -> u32 {
151 0
152 }
153
154 fn gid(&self) -> u32 {
155 0
156 }
157
158 fn rdev(&self) -> u64 {
159 0
160 }
161
162 fn size(&self) -> u64 {
163 self.size
164 }
165
166 fn atime(&self) -> i64 {
167 self.create_at.duration_since(UNIX_EPOCH).unwrap().as_secs() as i64
168 }
169
170 fn atime_nsec(&self) -> i64 {
171 self.create_at.duration_since(UNIX_EPOCH).unwrap().as_nanos() as i64
172 }
173
174 fn mtime(&self) -> i64 {
175 self.create_at.duration_since(UNIX_EPOCH).unwrap().as_secs() as i64
176 }
177
178 fn mtime_nsec(&self) -> i64 {
179 self.create_at.duration_since(UNIX_EPOCH).unwrap().as_nanos() as i64
180 }
181
182 fn ctime(&self) -> i64 {
183 self.create_at.duration_since(UNIX_EPOCH).unwrap().as_secs() as i64
184 }
185
186 fn ctime_nsec(&self) -> i64 {
187 self.create_at.duration_since(UNIX_EPOCH).unwrap().as_nanos() as i64
188 }
189
190 fn blksize(&self) -> u64 {
191 0
192 }
193
194 fn blocks(&self) -> u64 {
195 0
196 }
197}
198
199impl MetaDataExt for DiskMetaData {
200 fn accessed(&self) -> Result<SystemTime> {
201 self.inner.accessed().map_err(|e| Error::new(ErrorKind::IO, e))
202 }
203
204 fn created(&self) -> Result<SystemTime> {
205 self.inner.created().map_err(|e| Error::new(ErrorKind::IO, e))
206 }
207
208 fn is_file(&self) -> bool {
209 self.inner.is_file()
210 }
211
212 #[cfg(feature = "nightly")]
213 #[cfg_attr(docsrs, doc(cfg(feature = "nightly")))]
214 fn is_symlink(&self) -> bool {
215 self.inner.is_symlink()
216 }
217
218 fn len(&self) -> u64 {
219 self.inner.len()
220 }
221
222 fn modified(&self) -> Result<SystemTime> {
223 self.inner.modified().map_err(|e| Error::new(ErrorKind::IO, e))
224 }
225
226 fn dev(&self) -> u64 {
227 self.inner.dev()
228 }
229
230 fn ino(&self) -> u64 {
231 self.inner.ino()
232 }
233
234 fn mode(&self) -> u32 {
235 self.inner.mode()
236 }
237
238 fn nlink(&self) -> u64 {
239 self.inner.nlink()
240 }
241
242 fn uid(&self) -> u32 {
243 self.inner.uid()
244 }
245
246 fn gid(&self) -> u32 {
247 self.inner.gid()
248 }
249
250 fn rdev(&self) -> u64 {
251 self.inner.rdev()
252 }
253
254 fn size(&self) -> u64 {
255 self.inner.size()
256 }
257
258 fn atime(&self) -> i64 {
259 self.inner.atime()
260 }
261
262 fn atime_nsec(&self) -> i64 {
263 self.inner.atime_nsec()
264 }
265
266 fn mtime(&self) -> i64 {
267 self.inner.mtime()
268 }
269
270 fn mtime_nsec(&self) -> i64 {
271 self.inner.mtime_nsec()
272 }
273
274 fn ctime(&self) -> i64 {
275 self.inner.ctime()
276 }
277
278 fn ctime_nsec(&self) -> i64 {
279 self.inner.ctime_nsec()
280 }
281
282 fn blksize(&self) -> u64 {
283 self.inner.blksize()
284 }
285
286 fn blocks(&self) -> u64 {
287 self.inner.blocks()
288 }
289}
290
291impl MetaDataExt for EmptyMetaData {
292 fn accessed(&self) -> Result<SystemTime> {
293 Ok(UNIX_EPOCH)
294 }
295
296 fn created(&self) -> Result<SystemTime> {
297 Ok(UNIX_EPOCH)
298 }
299
300 fn is_file(&self) -> bool {
301 false
302 }
303
304 #[cfg(feature = "nightly")]
305 #[cfg_attr(docsrs, doc(cfg(feature = "nightly")))]
306 fn is_symlink(&self) -> bool {
307 false
308 }
309
310 fn len(&self) -> u64 {
311 0
312 }
313
314 fn modified(&self) -> Result<SystemTime> {
315 Ok(UNIX_EPOCH)
316 }
317
318 fn dev(&self) -> u64 {
319 0
320 }
321
322 fn ino(&self) -> u64 {
323 0
324 }
325
326 fn mode(&self) -> u32 {
327 0
328 }
329
330 fn nlink(&self) -> u64 {
331 0
332 }
333
334 fn uid(&self) -> u32 {
335 0
336 }
337
338 fn gid(&self) -> u32 {
339 0
340 }
341
342 fn rdev(&self) -> u64 {
343 0
344 }
345
346 fn size(&self) -> u64 {
347 0
348 }
349
350 fn atime(&self) -> i64 {
351 0
352 }
353
354 fn atime_nsec(&self) -> i64 {
355 0
356 }
357
358 fn mtime(&self) -> i64 {
359 0
360 }
361
362 fn mtime_nsec(&self) -> i64 {
363 0
364 }
365
366 fn ctime(&self) -> i64 {
367 0
368 }
369
370 fn ctime_nsec(&self) -> i64 {
371 0
372 }
373
374 fn blksize(&self) -> u64 {
375 0
376 }
377
378 fn blocks(&self) -> u64 {
379 0
380 }
381}
382
383impl MetaDataExt for MetaData {
384 fn accessed(&self) -> std::result::Result<SystemTime, Error> {
385 self.inner.accessed()
386 }
387
388 fn created(&self) -> std::result::Result<SystemTime, Error> {
389 self.inner.created()
390 }
391
392 fn is_file(&self) -> bool {
393 self.inner.is_file()
394 }
395
396 #[cfg(feature = "nightly")]
397 #[cfg_attr(docsrs, doc(cfg(feature = "nightly")))]
398 fn is_symlink(&self) -> bool {
399 self.inner.is_symlink()
400 }
401
402 fn len(&self) -> u64 {
403 self.inner.len()
404 }
405
406 fn modified(&self) -> std::result::Result<SystemTime, Error> {
407 self.inner.modified()
408 }
409
410 fn dev(&self) -> u64 {
411 self.inner.dev()
412 }
413
414 fn ino(&self) -> u64 {
415 self.inner.ino()
416 }
417
418 fn mode(&self) -> u32 {
419 self.inner.mode()
420 }
421
422 fn nlink(&self) -> u64 {
423 self.inner.nlink()
424 }
425
426 fn uid(&self) -> u32 {
427 self.inner.uid()
428 }
429
430 fn gid(&self) -> u32 {
431 self.inner.gid()
432 }
433
434 fn rdev(&self) -> u64 {
435 self.inner.rdev()
436 }
437
438 fn size(&self) -> u64 {
439 self.inner.size()
440 }
441
442 fn atime(&self) -> i64 {
443 self.inner.atime()
444 }
445
446 fn atime_nsec(&self) -> i64 {
447 self.inner.atime_nsec()
448 }
449
450 fn mtime(&self) -> i64 {
451 self.inner.mtime()
452 }
453
454 fn mtime_nsec(&self) -> i64 {
455 self.inner.mtime_nsec()
456 }
457
458 fn ctime(&self) -> i64 {
459 self.inner.ctime()
460 }
461
462 fn ctime_nsec(&self) -> i64 {
463 self.inner.ctime_nsec()
464 }
465
466 fn blksize(&self) -> u64 {
467 self.inner.blksize()
468 }
469
470 fn blocks(&self) -> u64 {
471 self.inner.blocks()
472 }
473}
474
475
476#[cfg(test)]
477mod tests {
478 use bytes::Bytes;
479 use crate::empty::EmptyMmapFile;
480 use crate::{MmapFileExt, MmapFileMutExt, Options};
481 use crate::raw::MemoryMmapFile;
482 use crate::tests::get_random_filename;
483 use super::*;
484
485 macro_rules! metadata_test {
486 ($expr: expr) => {
487 let meta = $expr;
488 meta.accessed().unwrap();
489 meta.created().unwrap();
490 assert!(meta.is_file());
491 #[cfg(feature = "nightly")]
492 assert!(!meta.is_symlink());
493 assert_eq!(meta.len(), "Hello, fmmap!".len() as u64);
494 assert_eq!(meta.size(), "Hello, fmmap!".len() as u64);
495 meta.modified().unwrap();
496 meta.dev();
497 meta.ino();
498 meta.mode();
499 meta.nlink();
500 meta.uid();
501 meta.gid();
502 meta.rdev();
503 meta.size();
504 meta.atime();
505 meta.atime_nsec();
506 meta.mtime();
507 meta.mtime_nsec();
508 meta.ctime();
509 meta.ctime_nsec();
510 meta.blocks();
511 meta.blksize();
512 };
513 }
514
515 #[test]
516 fn test_metadata() {
517 let mut file = Options::new()
518 .max_size("Hello, fmmap!".len() as u64)
519 .create_mmap_file_mut(get_random_filename())
520 .unwrap();
521 file.set_remove_on_drop(true);
522 file.write_all("Hello, fmmap!".as_bytes(), 0).unwrap();
523 metadata_test!(file.metadata().unwrap());
524
525 }
551
552 #[cfg(feature = "tokio")]
553 #[tokio::test]
554 async fn test_async_metadata() {
555 use crate::tokio::{AsyncMmapFileExt, AsyncMmapFileMutExt, AsyncOptions};
556 let mut file = AsyncOptions::new()
557 .max_size("Hello, fmmap!".len() as u64)
558 .create_mmap_file_mut(get_random_filename())
559 .await
560 .unwrap();
561 file.set_remove_on_drop(true);
562 file.write_all("Hello, fmmap!".as_bytes(), 0).unwrap();
563 metadata_test!(file.metadata().await.unwrap());
564
565 }
591
592 #[test]
593 fn test_memory_metadata() {
594 let file = MemoryMmapFile::new("test.mem", Bytes::from("Hello, fmmap!"));
595 let meta = file.metadata().unwrap();
596
597 assert!(!meta.is_file());
598 #[cfg(feature = "nightly")]
599 assert!(!meta.is_symlink());
600 assert_eq!(meta.len(), "Hello, fmmap!".len() as u64);
601 assert_eq!(meta.size(), "Hello, fmmap!".len() as u64);
602 assert!(meta.modified().unwrap() == meta.created().unwrap() && meta.created().unwrap() == meta.accessed().unwrap());
603 assert!(meta.atime() == meta.mtime() && meta.mtime() == meta.ctime());
604 assert!(meta.atime_nsec() == meta.mtime_nsec() && meta.mtime_nsec() == meta.ctime_nsec());
605 assert_eq!(meta.dev(), 0);
606 assert_eq!(meta.ino(), 0);
607 assert_eq!(meta.mode(), 0);
608 assert_eq!(meta.nlink(), 0);
609 assert_eq!(meta.uid(), 0);
610 assert_eq!(meta.gid(), 0);
611 assert_eq!(meta.rdev(), 0);
612 assert_eq!(meta.blocks(), 0);
613 assert_eq!(meta.blksize(), 0);
614 }
615
616 #[test]
617 fn test_empty_metadata() {
618 let file = EmptyMmapFile::default();
619 let meta = file.metadata().unwrap();
620
621 assert_eq!(meta.accessed().unwrap(), UNIX_EPOCH);
622 assert_eq!(meta.created().unwrap(), UNIX_EPOCH);
623 assert!(!meta.is_file());
624 #[cfg(feature = "nightly")]
625 assert!(!meta.is_symlink());
626 assert_eq!(meta.len(), 0);
627 assert_eq!(meta.modified().unwrap(), UNIX_EPOCH);
628 assert_eq!(meta.dev(), 0);
629 assert_eq!(meta.ino(), 0);
630 assert_eq!(meta.mode(), 0);
631 assert_eq!(meta.nlink(), 0);
632 assert_eq!(meta.uid(), 0);
633 assert_eq!(meta.gid(), 0);
634 assert_eq!(meta.rdev(), 0);
635 assert_eq!(meta.size(), 0);
636 assert_eq!(meta.atime(), 0);
637 assert_eq!(meta.atime_nsec(), 0);
638 assert_eq!(meta.mtime(), 0);
639 assert_eq!(meta.mtime_nsec(), 0);
640 assert_eq!(meta.ctime(), 0);
641 assert_eq!(meta.ctime_nsec(), 0);
642 assert_eq!(meta.blocks(), 0);
643 assert_eq!(meta.blksize(), 0);
644 }
645}