Implement lsdir and file info functions

This commit is contained in:
lumi 2025-06-26 22:46:27 +10:00
parent 549f96d4dc
commit 679ffed807
Signed by: luaneko
GPG Key ID: 406809B8763FF07A

View File

@ -1,14 +1,21 @@
//! Filesystem library
//! # File system library
//!
//! The `lb:fs` library provides synchronous and asynchronous utilities for interacting with the
//! file system.
//!
//! ## Asynchronous by default
//!
//! File system operations are blocking by nature; to provide asynchronicity, luby performs blocking
//! operations in a background thread pool by default. Synchronous complements to all asynchronous
//! functions are always provided.
//!
//! ## Exports
//!
//! See [`lb_fslib`] for items exported by this library.
use derive_more::From;
use luaffi::{cdef, metatype};
use std::time::SystemTime;
use thiserror::Error;
use tokio::fs;
/// Errors that can be thrown by this library.
///
@ -41,7 +48,7 @@ impl lb_fslib {
}
pub async extern "Lua-C" fn read(&self, path: &str) -> Result<Vec<u8>> {
Ok(fs::read(path).await?)
Ok(tokio::fs::read(path).await?)
}
pub extern "Lua-C" fn read_sync(&self, path: &str) -> Result<Vec<u8>> {
@ -49,14 +56,231 @@ impl lb_fslib {
}
pub async extern "Lua-C" fn write(&self, path: &str, contents: &[u8]) -> Result<()> {
Ok(fs::write(path, contents).await?)
Ok(tokio::fs::write(path, contents).await?)
}
pub extern "Lua-C" fn write_sync(&self, path: &str, contents: &[u8]) -> Result<()> {
Ok(std::fs::write(path, contents)?)
}
pub extern "Lua-C" fn readdir_sync(&self, _path: &str) -> Result<()> {
Ok(())
pub async extern "Lua-C" fn lsdir(&self, path: &str) -> Result<lb_lsdir> {
Ok(tokio::fs::read_dir(path).await?.into())
}
pub extern "Lua-C" fn lsdir_sync(&self, path: &str) -> Result<lb_lsdir_sync> {
Ok(std::fs::read_dir(path)?.into())
}
}
/// Iterator over the entries in a directory.
#[derive(Debug, From)]
#[cdef]
pub struct lb_lsdir(#[opaque] tokio::fs::ReadDir);
#[metatype]
impl lb_lsdir {
#[call]
pub async extern "Lua-C" fn next(&mut self) -> Result<Option<lb_dirent>> {
Ok(self.0.next_entry().await?.map(Into::into))
}
}
/// Synchronous version of [`lb_lsdir`].
#[derive(Debug, From)]
#[cdef]
pub struct lb_lsdir_sync(#[opaque] std::fs::ReadDir);
#[metatype]
impl lb_lsdir_sync {
#[call]
pub extern "Lua-C" fn next(&mut self) -> Result<Option<lb_dirent_sync>> {
Ok(self.0.next().transpose()?.map(Into::into))
}
}
#[derive(Debug, From)]
#[cdef]
pub struct lb_dirent(#[opaque] tokio::fs::DirEntry);
#[metatype]
impl lb_dirent {
pub extern "Lua-C" fn path(&self) -> String {
self.0.path().to_string_lossy().into()
}
pub extern "Lua-C" fn name(&self) -> String {
self.0.file_name().to_string_lossy().into()
}
pub async extern "Lua-C" fn r#type(&self) -> Result<lb_file_type> {
Ok(self.0.file_type().await?.into())
}
pub async extern "Lua-C" fn metadata(&self) -> Result<lb_file_meta> {
Ok(self.0.metadata().await?.into())
}
#[cfg(unix)]
pub extern "Lua-C" fn ino(&self) -> u64 {
self.0.ino()
}
#[tostring]
pub extern "Lua" fn tostring(&self) -> String {
self.path()
}
}
#[derive(Debug, From)]
#[cdef]
pub struct lb_dirent_sync(#[opaque] std::fs::DirEntry);
#[metatype]
impl lb_dirent_sync {
pub extern "Lua-C" fn path(&self) -> String {
self.0.path().to_string_lossy().into()
}
pub extern "Lua-C" fn name(&self) -> String {
self.0.file_name().to_string_lossy().into()
}
pub extern "Lua-C" fn r#type(&self) -> Result<lb_file_type> {
Ok(self.0.file_type()?.into())
}
pub extern "Lua-C" fn metadata(&self) -> Result<lb_file_meta> {
Ok(self.0.metadata()?.into())
}
#[cfg(unix)]
pub extern "Lua-C" fn ino(&self) -> u64 {
use std::os::unix::fs::DirEntryExt;
self.0.ino()
}
#[tostring]
pub extern "Lua" fn tostring(&self) -> String {
self.path()
}
}
#[derive(Debug, From)]
#[cdef]
pub struct lb_file_type(#[opaque] std::fs::FileType);
#[metatype]
impl lb_file_type {
pub extern "Lua-C" fn is_dir(&self) -> bool {
self.0.is_dir()
}
pub extern "Lua-C" fn is_file(&self) -> bool {
self.0.is_file()
}
pub extern "Lua-C" fn is_symlink(&self) -> bool {
self.0.is_file()
}
#[tostring]
pub extern "Lua-C" fn tostring(&self) -> String {
if self.0.is_file() {
"file"
} else if self.0.is_dir() {
"dir"
} else if self.0.is_symlink() {
"symlink"
} else {
"other"
}
.into()
}
}
#[derive(Debug, From)]
#[cdef]
pub struct lb_file_meta(#[opaque] std::fs::Metadata);
#[metatype]
impl lb_file_meta {
pub extern "Lua-C" fn is_dir(&self) -> bool {
self.0.is_dir()
}
pub extern "Lua-C" fn is_file(&self) -> bool {
self.0.is_file()
}
pub extern "Lua-C" fn is_symlink(&self) -> bool {
self.0.is_file()
}
pub extern "Lua-C" fn r#type(&self) -> lb_file_type {
self.0.file_type().into()
}
pub extern "Lua-C" fn size(&self) -> u64 {
self.0.len()
}
pub extern "Lua-C" fn perms(&self) -> lb_file_perms {
self.0.permissions().into()
}
pub extern "Lua-C" fn created(&self) -> Result<f64> {
Ok(self
.0
.created()?
.duration_since(SystemTime::UNIX_EPOCH)
.map(|dur| dur.as_secs_f64())
.unwrap_or(0.))
}
pub extern "Lua-C" fn modified(&self) -> Result<f64> {
Ok(self
.0
.modified()?
.duration_since(SystemTime::UNIX_EPOCH)
.map(|dur| dur.as_secs_f64())
.unwrap_or(0.))
}
pub extern "Lua-C" fn accessed(&self) -> Result<f64> {
Ok(self
.0
.accessed()?
.duration_since(SystemTime::UNIX_EPOCH)
.map(|dur| dur.as_secs_f64())
.unwrap_or(0.))
}
#[tostring]
pub extern "Lua-C" fn tostring(&self) -> String {
let ty = self.0.file_type();
if ty.is_file() {
format!("file {}", self.0.len())
} else if ty.is_dir() {
"dir".into()
} else if ty.is_symlink() {
"symlink".into()
} else {
"other".into()
}
}
}
#[derive(Debug, From)]
#[cdef]
pub struct lb_file_perms(#[opaque] std::fs::Permissions);
#[metatype]
impl lb_file_perms {
pub extern "Lua-C" fn readonly(&self) -> bool {
self.0.readonly()
}
pub extern "Lua-C" fn set_readonly(&mut self, readonly: bool) {
self.0.set_readonly(readonly);
}
}