use crate::filesystem::primitives::{FileType, ImplFileTypeExt, ImplMetadataExt};
use std::time::SystemTime;
use std::{fs, io};
#[derive(Debug, Clone)]
pub struct Metadata {
pub(crate) file_type: FileType,
pub(crate) len: u64,
pub(crate) modified: Option<SystemTime>,
pub(crate) accessed: Option<SystemTime>,
pub(crate) created: Option<SystemTime>,
pub(crate) ext: ImplMetadataExt,
}
#[allow(clippy::len_without_is_empty)]
impl Metadata {
#[inline]
pub fn from_file(file: &fs::File) -> io::Result<Self> {
let std = file.metadata()?;
let ext = ImplMetadataExt::from(file, &std)?;
let file_type = ImplFileTypeExt::from(file, &std)?;
Ok(Self::from_parts(std, ext, file_type))
}
#[cfg(windows)]
#[inline]
pub fn from_just_metadata(std: fs::Metadata) -> Self {
let ext = ImplMetadataExt::from_just_metadata(&std);
let file_type = ImplFileTypeExt::from_just_metadata(&std);
Self::from_parts(std, ext, file_type)
}
#[inline]
fn from_parts(std: fs::Metadata, ext: ImplMetadataExt, file_type: FileType) -> Self {
Self {
file_type,
len: std.len(),
modified: std.modified().ok(),
accessed: std.accessed().ok(),
created: std.created().ok(),
ext,
}
}
#[inline]
pub const fn file_type(&self) -> FileType {
self.file_type
}
#[inline]
pub fn is_dir(&self) -> bool {
self.file_type.is_dir()
}
#[inline]
pub const fn len(&self) -> u64 {
self.len
}
#[inline]
pub fn modified(&self) -> io::Result<SystemTime> {
self.modified.ok_or_else(|| {
io::Error::new(
io::ErrorKind::Other,
"modified time metadata not available on this platform",
)
})
}
#[inline]
pub fn accessed(&self) -> io::Result<SystemTime> {
self.accessed.ok_or_else(|| {
io::Error::new(
io::ErrorKind::Other,
"accessed time metadata not available on this platform",
)
})
}
#[inline]
pub fn created(&self) -> io::Result<SystemTime> {
self.created.ok_or_else(|| {
io::Error::new(
io::ErrorKind::Other,
"created time metadata not available on this platform",
)
})
}
#[cfg(windows)]
#[inline]
pub(crate) fn file_attributes(&self) -> u32 {
self.ext.file_attributes()
}
}
#[cfg(any(unix, target_os = "vxworks"))]
pub trait MetadataExt {
fn dev(&self) -> u64;
fn ino(&self) -> u64;
fn nlink(&self) -> u64;
#[cfg(target_os = "vxworks")]
fn attrib(&self) -> u8;
}
#[cfg(target_os = "wasi")]
pub trait MetadataExt {
fn dev(&self) -> u64;
fn ino(&self) -> u64;
fn nlink(&self) -> u64;
}
#[cfg(windows)]
pub trait MetadataExt {
fn file_attributes(&self) -> u32;
}
#[cfg(unix)]
impl MetadataExt for Metadata {
#[inline]
fn dev(&self) -> u64 {
crate::filesystem::primitives::MetadataExt::dev(&self.ext)
}
#[inline]
fn ino(&self) -> u64 {
crate::filesystem::primitives::MetadataExt::ino(&self.ext)
}
#[inline]
fn nlink(&self) -> u64 {
crate::filesystem::primitives::MetadataExt::nlink(&self.ext)
}
}
#[cfg(target_os = "wasi")]
impl MetadataExt for Metadata {
#[inline]
fn dev(&self) -> u64 {
crate::filesystem::primitives::MetadataExt::dev(&self.ext)
}
#[inline]
fn ino(&self) -> u64 {
crate::filesystem::primitives::MetadataExt::ino(&self.ext)
}
#[inline]
fn nlink(&self) -> u64 {
crate::filesystem::primitives::MetadataExt::nlink(&self.ext)
}
}
#[cfg(target_os = "vxworks")]
impl MetadataExt for Metadata {
#[inline]
fn dev(&self) -> u64 {
self.ext.dev()
}
#[inline]
fn ino(&self) -> u64 {
self.ext.ino()
}
#[inline]
fn nlink(&self) -> u64 {
self.ext.nlink()
}
}
#[cfg(windows)]
impl MetadataExt for Metadata {
#[inline]
fn file_attributes(&self) -> u32 {
self.ext.file_attributes()
}
}
#[cfg(windows)]
#[doc(hidden)]
pub trait _WindowsByHandle {
fn number_of_links(&self) -> Option<u32>;
}