use rong::*;
use std::{fs, time::SystemTime};
#[js_export]
pub(crate) struct FileInfo {
is_file: bool,
is_directory: bool,
is_symlink: bool,
size: f64,
modified: Option<SystemTime>,
accessed: Option<SystemTime>,
created: Option<SystemTime>,
mode: Option<u32>,
}
impl FileInfo {
pub(crate) fn from_metadata(metadata: fs::Metadata) -> Self {
#[cfg(unix)]
let mode = {
use std::os::unix::fs::MetadataExt;
Some(metadata.mode())
};
#[cfg(not(unix))]
let mode = None;
Self {
is_file: metadata.is_file(),
is_directory: metadata.is_dir(),
is_symlink: metadata.is_symlink(),
size: metadata.len() as f64,
modified: metadata.modified().ok(),
accessed: metadata.accessed().ok(),
created: metadata.created().ok(),
mode,
}
}
}
#[js_class]
impl FileInfo {
#[js_method(constructor)]
fn new() -> JSResult<Self> {
rong::illegal_constructor(
"FileInfo cannot be constructed directly. Use stat(), lstat(), or FileHandle.stat().",
)
}
#[js_method(getter, rename = "isFile")]
fn is_file(&self) -> bool {
self.is_file
}
#[js_method(getter, rename = "isDirectory")]
fn is_directory(&self) -> bool {
self.is_directory
}
#[js_method(getter, rename = "isSymlink")]
fn is_symlink(&self) -> bool {
self.is_symlink
}
#[js_method(getter)]
fn size(&self) -> f64 {
self.size
}
#[js_method(getter)]
fn modified(&self) -> Option<f64> {
self.modified
.and_then(|t| t.duration_since(SystemTime::UNIX_EPOCH).ok())
.map(|d| d.as_millis() as f64)
}
#[js_method(getter)]
fn accessed(&self) -> Option<f64> {
self.accessed
.and_then(|t| t.duration_since(SystemTime::UNIX_EPOCH).ok())
.map(|d| d.as_millis() as f64)
}
#[js_method(getter)]
fn created(&self) -> Option<f64> {
self.created
.and_then(|t| t.duration_since(SystemTime::UNIX_EPOCH).ok())
.map(|d| d.as_millis() as f64)
}
#[js_method(getter)]
fn mode(&self) -> Option<u32> {
self.mode
}
#[js_method(gc_mark)]
fn gc_mark_with<F>(&self, _mark_fn: F)
where
F: FnMut(&JSValue),
{
}
}
pub(crate) fn init(ctx: &JSContext) -> JSResult<()> {
ctx.register_hidden_class::<FileInfo>()?;
Ok(())
}