use std::fs::{Metadata, Permissions};
use cfg_if::cfg_if;
use crate::{Error, IoResultToFsResultExt, Result};
#[derive(Debug, Clone)]
pub struct FileMetadata {
pub is_file: bool,
pub is_directory: bool,
pub is_symlink: bool,
pub atime_ms: u64,
pub mtime_ms: u64,
pub ctime_ms: u64,
pub size: u64,
}
impl FileMetadata {
#[allow(unused_variables)]
fn get_ctime_ms(metadata: &Metadata) -> u64 {
#[cfg(unix)]
{
let ctime = std::os::unix::fs::MetadataExt::ctime(metadata);
let ctime_nsec = std::os::unix::fs::MetadataExt::ctime_nsec(metadata);
let ctime_ms = ctime * 1000 + ctime_nsec / 1_000_000;
return ctime_ms as u64;
}
#[allow(unreachable_code)]
0u64
}
}
impl TryFrom<Metadata> for FileMetadata {
type Error = Error;
fn try_from(metadata: Metadata) -> Result<Self> {
let mtime_ms = metadata
.modified()
.to_fs_result()?
.duration_since(std::time::UNIX_EPOCH)
.expect("mtime is before unix epoch")
.as_millis() as u64;
let atime_ms = metadata
.accessed()
.to_fs_result()?
.duration_since(std::time::UNIX_EPOCH)
.expect("atime is before unix epoch")
.as_millis() as u64;
let ctime_ms = Self::get_ctime_ms(&metadata);
Ok(Self {
is_directory: metadata.is_dir(),
is_file: metadata.is_file(),
is_symlink: metadata.is_symlink(),
size: metadata.len(),
mtime_ms,
ctime_ms,
atime_ms,
})
}
}
#[derive(Debug, Clone)]
pub struct FilePermissions(#[cfg(target_family = "unix")] u32);
impl FilePermissions {
cfg_if! {
if #[cfg(target_family = "unix")] {
pub fn from_mode(mode: u32) -> Self {
Self(mode)
}
pub fn into_mode(self) -> Option<u32> {
Some(self.0)
}
pub fn from_std(perm: Permissions) -> Self {
use std::os::unix::fs::PermissionsExt;
Self(perm.mode())
}
pub fn into_std(self) -> Option<Permissions> {
use std::os::unix::fs::PermissionsExt;
Some(Permissions::from_mode(self.0))
}
} else {
pub fn from_mode(_mode: u32) -> Self {
Self()
}
pub fn into_mode(self) -> Option<u32> {
None
}
pub fn from_std(_perm: Permissions) -> Self {
Self()
}
pub fn into_std(self) -> Option<Permissions> {
None
}
}
}
}