cap_primitives/fs/
metadata.rs1use crate::fs::{FileType, ImplFileTypeExt, ImplMetadataExt, Permissions};
2use crate::time::SystemTime;
3use std::{fs, io};
4
5#[derive(Debug, Clone)]
14pub struct Metadata {
15 pub(crate) file_type: FileType,
16 pub(crate) len: u64,
17 pub(crate) permissions: Permissions,
18 pub(crate) modified: Option<SystemTime>,
19 pub(crate) accessed: Option<SystemTime>,
20 pub(crate) created: Option<SystemTime>,
21 pub(crate) ext: ImplMetadataExt,
22}
23
24#[allow(clippy::len_without_is_empty)]
25impl Metadata {
26 #[inline]
28 pub fn from_file(file: &fs::File) -> io::Result<Self> {
29 let std = file.metadata()?;
30 let ext = ImplMetadataExt::from(file, &std)?;
31 let file_type = ImplFileTypeExt::from(file, &std)?;
32 Ok(Self::from_parts(std, ext, file_type))
33 }
34
35 #[inline]
43 pub fn from_just_metadata(std: fs::Metadata) -> Self {
44 let ext = ImplMetadataExt::from_just_metadata(&std);
45 let file_type = ImplFileTypeExt::from_just_metadata(&std);
46 Self::from_parts(std, ext, file_type)
47 }
48
49 #[inline]
50 fn from_parts(std: fs::Metadata, ext: ImplMetadataExt, file_type: FileType) -> Self {
51 Self {
52 file_type,
53 len: std.len(),
54 permissions: Permissions::from_std(std.permissions()),
55 modified: std.modified().ok().map(SystemTime::from_std),
56 accessed: std.accessed().ok().map(SystemTime::from_std),
57 created: std.created().ok().map(SystemTime::from_std),
58 ext,
59 }
60 }
61
62 #[inline]
66 pub const fn file_type(&self) -> FileType {
67 self.file_type
68 }
69
70 #[inline]
74 pub fn is_dir(&self) -> bool {
75 self.file_type.is_dir()
76 }
77
78 #[inline]
82 pub fn is_file(&self) -> bool {
83 self.file_type.is_file()
84 }
85
86 #[inline]
90 pub fn is_symlink(&self) -> bool {
91 self.file_type.is_symlink()
92 }
93
94 #[inline]
98 pub const fn len(&self) -> u64 {
99 self.len
100 }
101
102 #[inline]
106 pub fn permissions(&self) -> Permissions {
107 self.permissions.clone()
108 }
109
110 #[inline]
114 pub fn modified(&self) -> io::Result<SystemTime> {
115 #[cfg(io_error_uncategorized)]
116 {
117 self.modified.ok_or_else(|| {
118 io::Error::new(
119 io::ErrorKind::Unsupported,
120 "modified time metadata not available on this platform",
121 )
122 })
123 }
124 #[cfg(not(io_error_uncategorized))]
125 {
126 self.modified.ok_or_else(|| {
127 io::Error::new(
128 io::ErrorKind::Other,
129 "modified time metadata not available on this platform",
130 )
131 })
132 }
133 }
134
135 #[inline]
139 pub fn accessed(&self) -> io::Result<SystemTime> {
140 #[cfg(io_error_uncategorized)]
141 {
142 self.accessed.ok_or_else(|| {
143 io::Error::new(
144 io::ErrorKind::Unsupported,
145 "accessed time metadata not available on this platform",
146 )
147 })
148 }
149 #[cfg(not(io_error_uncategorized))]
150 {
151 self.accessed.ok_or_else(|| {
152 io::Error::new(
153 io::ErrorKind::Other,
154 "accessed time metadata not available on this platform",
155 )
156 })
157 }
158 }
159
160 #[inline]
164 pub fn created(&self) -> io::Result<SystemTime> {
165 #[cfg(io_error_uncategorized)]
166 {
167 self.created.ok_or_else(|| {
168 io::Error::new(
169 io::ErrorKind::Unsupported,
170 "created time metadata not available on this platform",
171 )
172 })
173 }
174 #[cfg(not(io_error_uncategorized))]
175 {
176 self.created.ok_or_else(|| {
177 io::Error::new(
178 io::ErrorKind::Other,
179 "created time metadata not available on this platform",
180 )
181 })
182 }
183 }
184
185 #[cfg(any(not(windows), windows_by_handle))]
188 pub(crate) fn is_same_file(&self, other: &Self) -> bool {
189 self.ext.is_same_file(&other.ext)
190 }
191
192 #[cfg(windows)]
195 #[inline]
196 pub(crate) fn file_attributes(&self) -> u32 {
197 self.ext.file_attributes()
198 }
199}
200
201#[cfg(any(unix, target_os = "vxworks"))]
205pub trait MetadataExt {
206 fn dev(&self) -> u64;
208 fn ino(&self) -> u64;
210 fn mode(&self) -> u32;
212 fn nlink(&self) -> u64;
214 fn uid(&self) -> u32;
216 fn gid(&self) -> u32;
218 fn rdev(&self) -> u64;
220 fn size(&self) -> u64;
222 fn atime(&self) -> i64;
224 fn atime_nsec(&self) -> i64;
226 fn mtime(&self) -> i64;
228 fn mtime_nsec(&self) -> i64;
230 fn ctime(&self) -> i64;
232 fn ctime_nsec(&self) -> i64;
234 fn blksize(&self) -> u64;
236 fn blocks(&self) -> u64;
238 #[cfg(target_os = "vxworks")]
239 fn attrib(&self) -> u8;
240}
241
242#[cfg(target_os = "wasi")]
246pub trait MetadataExt {
247 fn dev(&self) -> u64;
249 fn ino(&self) -> u64;
251 fn nlink(&self) -> u64;
253 fn size(&self) -> u64;
255 fn atim(&self) -> u64;
257 fn mtim(&self) -> u64;
259 fn ctim(&self) -> u64;
261}
262
263#[cfg(windows)]
267pub trait MetadataExt {
268 fn file_attributes(&self) -> u32;
270 fn creation_time(&self) -> u64;
272 fn last_access_time(&self) -> u64;
274 fn last_write_time(&self) -> u64;
276 fn file_size(&self) -> u64;
278 #[cfg(windows_by_handle)]
280 fn volume_serial_number(&self) -> Option<u32>;
281 #[cfg(windows_by_handle)]
283 fn number_of_links(&self) -> Option<u32>;
284 #[cfg(windows_by_handle)]
286 fn file_index(&self) -> Option<u64>;
287}
288
289#[cfg(unix)]
290impl MetadataExt for Metadata {
291 #[inline]
292 fn dev(&self) -> u64 {
293 crate::fs::MetadataExt::dev(&self.ext)
294 }
295
296 #[inline]
297 fn ino(&self) -> u64 {
298 crate::fs::MetadataExt::ino(&self.ext)
299 }
300
301 #[inline]
302 fn mode(&self) -> u32 {
303 crate::fs::MetadataExt::mode(&self.ext)
304 }
305
306 #[inline]
307 fn nlink(&self) -> u64 {
308 crate::fs::MetadataExt::nlink(&self.ext)
309 }
310
311 #[inline]
312 fn uid(&self) -> u32 {
313 crate::fs::MetadataExt::uid(&self.ext)
314 }
315
316 #[inline]
317 fn gid(&self) -> u32 {
318 crate::fs::MetadataExt::gid(&self.ext)
319 }
320
321 #[inline]
322 fn rdev(&self) -> u64 {
323 crate::fs::MetadataExt::rdev(&self.ext)
324 }
325
326 #[inline]
327 fn size(&self) -> u64 {
328 crate::fs::MetadataExt::size(&self.ext)
329 }
330
331 #[inline]
332 fn atime(&self) -> i64 {
333 crate::fs::MetadataExt::atime(&self.ext)
334 }
335
336 #[inline]
337 fn atime_nsec(&self) -> i64 {
338 crate::fs::MetadataExt::atime_nsec(&self.ext)
339 }
340
341 #[inline]
342 fn mtime(&self) -> i64 {
343 crate::fs::MetadataExt::mtime(&self.ext)
344 }
345
346 #[inline]
347 fn mtime_nsec(&self) -> i64 {
348 crate::fs::MetadataExt::mtime_nsec(&self.ext)
349 }
350
351 #[inline]
352 fn ctime(&self) -> i64 {
353 crate::fs::MetadataExt::ctime(&self.ext)
354 }
355
356 #[inline]
357 fn ctime_nsec(&self) -> i64 {
358 crate::fs::MetadataExt::ctime_nsec(&self.ext)
359 }
360
361 #[inline]
362 fn blksize(&self) -> u64 {
363 crate::fs::MetadataExt::blksize(&self.ext)
364 }
365
366 #[inline]
367 fn blocks(&self) -> u64 {
368 crate::fs::MetadataExt::blocks(&self.ext)
369 }
370}
371
372#[cfg(target_os = "wasi")]
373impl MetadataExt for Metadata {
374 #[inline]
375 fn dev(&self) -> u64 {
376 crate::fs::MetadataExt::dev(&self.ext)
377 }
378
379 #[inline]
380 fn ino(&self) -> u64 {
381 crate::fs::MetadataExt::ino(&self.ext)
382 }
383
384 #[inline]
385 fn nlink(&self) -> u64 {
386 crate::fs::MetadataExt::nlink(&self.ext)
387 }
388
389 #[inline]
390 fn size(&self) -> u64 {
391 crate::fs::MetadataExt::size(&self.ext)
392 }
393
394 #[inline]
395 fn atim(&self) -> u64 {
396 crate::fs::MetadataExt::atim(&self.ext)
397 }
398
399 #[inline]
400 fn mtim(&self) -> u64 {
401 crate::fs::MetadataExt::mtim(&self.ext)
402 }
403
404 #[inline]
405 fn ctim(&self) -> u64 {
406 crate::fs::MetadataExt::ctim(&self.ext)
407 }
408}
409
410#[cfg(target_os = "vxworks")]
411impl MetadataExt for Metadata {
412 #[inline]
413 fn dev(&self) -> u64 {
414 self.ext.dev()
415 }
416
417 #[inline]
418 fn ino(&self) -> u64 {
419 self.ext.ino()
420 }
421
422 #[inline]
423 fn mode(&self) -> u32 {
424 self.ext.mode()
425 }
426
427 #[inline]
428 fn nlink(&self) -> u64 {
429 self.ext.nlink()
430 }
431
432 #[inline]
433 fn uid(&self) -> u32 {
434 self.ext.uid()
435 }
436
437 #[inline]
438 fn gid(&self) -> u32 {
439 self.ext.gid()
440 }
441
442 #[inline]
443 fn rdev(&self) -> u64 {
444 self.ext.rdev()
445 }
446
447 #[inline]
448 fn size(&self) -> u64 {
449 self.ext.size()
450 }
451
452 #[inline]
453 fn atime(&self) -> i64 {
454 self.ext.atime()
455 }
456
457 #[inline]
458 fn atime_nsec(&self) -> i64 {
459 self.ext.atime_nsec()
460 }
461
462 #[inline]
463 fn mtime(&self) -> i64 {
464 self.ext.mtime()
465 }
466
467 #[inline]
468 fn mtime_nsec(&self) -> i64 {
469 self.ext.mtime_nsec()
470 }
471
472 #[inline]
473 fn ctime(&self) -> i64 {
474 self.ext.ctime()
475 }
476
477 #[inline]
478 fn ctime_nsec(&self) -> i64 {
479 self.ext.ctime_nsec()
480 }
481
482 #[inline]
483 fn blksize(&self) -> u64 {
484 self.ext.blksize()
485 }
486
487 #[inline]
488 fn blocks(&self) -> u64 {
489 self.ext.blocks()
490 }
491}
492
493#[cfg(windows)]
494impl MetadataExt for Metadata {
495 #[inline]
496 fn file_attributes(&self) -> u32 {
497 self.ext.file_attributes()
498 }
499
500 #[inline]
501 fn creation_time(&self) -> u64 {
502 self.ext.creation_time()
503 }
504
505 #[inline]
506 fn last_access_time(&self) -> u64 {
507 self.ext.last_access_time()
508 }
509
510 #[inline]
511 fn last_write_time(&self) -> u64 {
512 self.ext.last_write_time()
513 }
514
515 #[inline]
516 fn file_size(&self) -> u64 {
517 self.ext.file_size()
518 }
519
520 #[inline]
521 #[cfg(windows_by_handle)]
522 fn volume_serial_number(&self) -> Option<u32> {
523 self.ext.volume_serial_number()
524 }
525
526 #[inline]
527 #[cfg(windows_by_handle)]
528 fn number_of_links(&self) -> Option<u32> {
529 self.ext.number_of_links()
530 }
531
532 #[inline]
533 #[cfg(windows_by_handle)]
534 fn file_index(&self) -> Option<u64> {
535 self.ext.file_index()
536 }
537}
538
539#[cfg(windows)]
545#[doc(hidden)]
546pub trait _WindowsByHandle {
547 fn file_attributes(&self) -> u32;
548 fn volume_serial_number(&self) -> Option<u32>;
549 fn number_of_links(&self) -> Option<u32>;
550 fn file_index(&self) -> Option<u64>;
551}