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}
254
255#[cfg(windows)]
259pub trait MetadataExt {
260 fn file_attributes(&self) -> u32;
262 fn creation_time(&self) -> u64;
264 fn last_access_time(&self) -> u64;
266 fn last_write_time(&self) -> u64;
268 fn file_size(&self) -> u64;
270 #[cfg(windows_by_handle)]
272 fn volume_serial_number(&self) -> Option<u32>;
273 #[cfg(windows_by_handle)]
275 fn number_of_links(&self) -> Option<u32>;
276 #[cfg(windows_by_handle)]
278 fn file_index(&self) -> Option<u64>;
279}
280
281#[cfg(unix)]
282impl MetadataExt for Metadata {
283 #[inline]
284 fn dev(&self) -> u64 {
285 crate::fs::MetadataExt::dev(&self.ext)
286 }
287
288 #[inline]
289 fn ino(&self) -> u64 {
290 crate::fs::MetadataExt::ino(&self.ext)
291 }
292
293 #[inline]
294 fn mode(&self) -> u32 {
295 crate::fs::MetadataExt::mode(&self.ext)
296 }
297
298 #[inline]
299 fn nlink(&self) -> u64 {
300 crate::fs::MetadataExt::nlink(&self.ext)
301 }
302
303 #[inline]
304 fn uid(&self) -> u32 {
305 crate::fs::MetadataExt::uid(&self.ext)
306 }
307
308 #[inline]
309 fn gid(&self) -> u32 {
310 crate::fs::MetadataExt::gid(&self.ext)
311 }
312
313 #[inline]
314 fn rdev(&self) -> u64 {
315 crate::fs::MetadataExt::rdev(&self.ext)
316 }
317
318 #[inline]
319 fn size(&self) -> u64 {
320 crate::fs::MetadataExt::size(&self.ext)
321 }
322
323 #[inline]
324 fn atime(&self) -> i64 {
325 crate::fs::MetadataExt::atime(&self.ext)
326 }
327
328 #[inline]
329 fn atime_nsec(&self) -> i64 {
330 crate::fs::MetadataExt::atime_nsec(&self.ext)
331 }
332
333 #[inline]
334 fn mtime(&self) -> i64 {
335 crate::fs::MetadataExt::mtime(&self.ext)
336 }
337
338 #[inline]
339 fn mtime_nsec(&self) -> i64 {
340 crate::fs::MetadataExt::mtime_nsec(&self.ext)
341 }
342
343 #[inline]
344 fn ctime(&self) -> i64 {
345 crate::fs::MetadataExt::ctime(&self.ext)
346 }
347
348 #[inline]
349 fn ctime_nsec(&self) -> i64 {
350 crate::fs::MetadataExt::ctime_nsec(&self.ext)
351 }
352
353 #[inline]
354 fn blksize(&self) -> u64 {
355 crate::fs::MetadataExt::blksize(&self.ext)
356 }
357
358 #[inline]
359 fn blocks(&self) -> u64 {
360 crate::fs::MetadataExt::blocks(&self.ext)
361 }
362}
363
364#[cfg(target_os = "wasi")]
365impl MetadataExt for Metadata {
366 #[inline]
367 fn dev(&self) -> u64 {
368 crate::fs::MetadataExt::dev(&self.ext)
369 }
370
371 #[inline]
372 fn ino(&self) -> u64 {
373 crate::fs::MetadataExt::ino(&self.ext)
374 }
375
376 #[inline]
377 fn nlink(&self) -> u64 {
378 crate::fs::MetadataExt::nlink(&self.ext)
379 }
380}
381
382#[cfg(target_os = "vxworks")]
383impl MetadataExt for Metadata {
384 #[inline]
385 fn dev(&self) -> u64 {
386 self.ext.dev()
387 }
388
389 #[inline]
390 fn ino(&self) -> u64 {
391 self.ext.ino()
392 }
393
394 #[inline]
395 fn mode(&self) -> u32 {
396 self.ext.mode()
397 }
398
399 #[inline]
400 fn nlink(&self) -> u64 {
401 self.ext.nlink()
402 }
403
404 #[inline]
405 fn uid(&self) -> u32 {
406 self.ext.uid()
407 }
408
409 #[inline]
410 fn gid(&self) -> u32 {
411 self.ext.gid()
412 }
413
414 #[inline]
415 fn rdev(&self) -> u64 {
416 self.ext.rdev()
417 }
418
419 #[inline]
420 fn size(&self) -> u64 {
421 self.ext.size()
422 }
423
424 #[inline]
425 fn atime(&self) -> i64 {
426 self.ext.atime()
427 }
428
429 #[inline]
430 fn atime_nsec(&self) -> i64 {
431 self.ext.atime_nsec()
432 }
433
434 #[inline]
435 fn mtime(&self) -> i64 {
436 self.ext.mtime()
437 }
438
439 #[inline]
440 fn mtime_nsec(&self) -> i64 {
441 self.ext.mtime_nsec()
442 }
443
444 #[inline]
445 fn ctime(&self) -> i64 {
446 self.ext.ctime()
447 }
448
449 #[inline]
450 fn ctime_nsec(&self) -> i64 {
451 self.ext.ctime_nsec()
452 }
453
454 #[inline]
455 fn blksize(&self) -> u64 {
456 self.ext.blksize()
457 }
458
459 #[inline]
460 fn blocks(&self) -> u64 {
461 self.ext.blocks()
462 }
463}
464
465#[cfg(windows)]
466impl MetadataExt for Metadata {
467 #[inline]
468 fn file_attributes(&self) -> u32 {
469 self.ext.file_attributes()
470 }
471
472 #[inline]
473 fn creation_time(&self) -> u64 {
474 self.ext.creation_time()
475 }
476
477 #[inline]
478 fn last_access_time(&self) -> u64 {
479 self.ext.last_access_time()
480 }
481
482 #[inline]
483 fn last_write_time(&self) -> u64 {
484 self.ext.last_write_time()
485 }
486
487 #[inline]
488 fn file_size(&self) -> u64 {
489 self.ext.file_size()
490 }
491
492 #[inline]
493 #[cfg(windows_by_handle)]
494 fn volume_serial_number(&self) -> Option<u32> {
495 self.ext.volume_serial_number()
496 }
497
498 #[inline]
499 #[cfg(windows_by_handle)]
500 fn number_of_links(&self) -> Option<u32> {
501 self.ext.number_of_links()
502 }
503
504 #[inline]
505 #[cfg(windows_by_handle)]
506 fn file_index(&self) -> Option<u64> {
507 self.ext.file_index()
508 }
509}
510
511#[cfg(windows)]
517#[doc(hidden)]
518pub trait _WindowsByHandle {
519 fn file_attributes(&self) -> u32;
520 fn volume_serial_number(&self) -> Option<u32>;
521 fn number_of_links(&self) -> Option<u32>;
522 fn file_index(&self) -> Option<u64>;
523}