Define API for vfs modules extensions

This commit is contained in:
PThorpe92
2025-03-06 14:40:12 -05:00
parent 25ed6a2985
commit 20f92fdacf
4 changed files with 129 additions and 3 deletions

16
Cargo.lock generated
View File

@@ -336,16 +336,16 @@ checksum = "18758054972164c3264f7c8386f5fc6da6114cb46b619fd365d4e3b2dc3ae487"
[[package]]
name = "chrono"
version = "0.4.39"
version = "0.4.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets 0.52.6",
"windows-link",
]
[[package]]
@@ -1043,8 +1043,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"wasi 0.13.3+wasi-0.2.2",
"wasm-bindgen",
"windows-targets 0.52.6",
]
@@ -1709,6 +1711,8 @@ dependencies = [
name = "limbo_ext"
version = "0.0.16"
dependencies = [
"chrono",
"getrandom 0.3.1",
"limbo_macros",
]
@@ -3614,6 +3618,12 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-link"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3"
[[package]]
name = "windows-sys"
version = "0.45.0"

View File

@@ -12,4 +12,6 @@ core_only = []
static = []
[dependencies]
chrono = "0.4.40"
getrandom = { version = "0.3.1", features = ["wasm_js"] }
limbo_macros = { workspace = true }

View File

@@ -1,4 +1,5 @@
mod types;
mod vfs_modules;
pub use limbo_macros::{register_extension, scalar, AggregateDerive, VTabModuleDerive};
use std::{
fmt::Display,

View File

@@ -0,0 +1,113 @@
use crate::{ExtResult, ResultCode};
use std::ffi::{c_char, c_void};
#[cfg(not(target_family = "wasm"))]
pub trait VfsExtension: Default {
const NAME: &'static str;
type File: VfsFile;
fn open_file(&self, path: &str, flags: i32, direct: bool) -> ExtResult<Self::File>;
fn run_once(&self) -> ExtResult<()> {
Ok(())
}
fn close(&self, _file: Self::File) -> ExtResult<()> {
Ok(())
}
fn generate_random_number(&self) -> i64 {
let mut buf = [0u8; 8];
getrandom::fill(&mut buf).unwrap();
i64::from_ne_bytes(buf)
}
fn get_current_time(&self) -> String {
chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string()
}
}
#[cfg(not(target_family = "wasm"))]
pub trait VfsFile: Sized {
fn lock(&mut self, _exclusive: bool) -> ExtResult<()> {
Ok(())
}
fn unlock(&self) -> ExtResult<()> {
Ok(())
}
fn read(&mut self, buf: &mut [u8], count: usize, offset: i64) -> ExtResult<i32>;
fn write(&mut self, buf: &[u8], count: usize, offset: i64) -> ExtResult<i32>;
fn sync(&self) -> ExtResult<()>;
fn size(&self) -> i64;
}
#[repr(C)]
pub struct VfsImpl {
pub name: *const c_char,
pub vfs: *const c_void,
pub open: VfsOpen,
pub close: VfsClose,
pub read: VfsRead,
pub write: VfsWrite,
pub sync: VfsSync,
pub lock: VfsLock,
pub unlock: VfsUnlock,
pub size: VfsSize,
pub run_once: VfsRunOnce,
pub current_time: VfsGetCurrentTime,
pub gen_random_number: VfsGenerateRandomNumber,
}
pub type RegisterVfsFn =
unsafe extern "C" fn(name: *const c_char, vfs: *const VfsImpl) -> ResultCode;
pub type VfsOpen = unsafe extern "C" fn(
ctx: *const c_void,
path: *const c_char,
flags: i32,
direct: bool,
) -> *const c_void;
pub type VfsClose = unsafe extern "C" fn(file: *const c_void) -> ResultCode;
pub type VfsRead =
unsafe extern "C" fn(file: *const c_void, buf: *mut u8, count: usize, offset: i64) -> i32;
pub type VfsWrite =
unsafe extern "C" fn(file: *const c_void, buf: *const u8, count: usize, offset: i64) -> i32;
pub type VfsSync = unsafe extern "C" fn(file: *const c_void) -> i32;
pub type VfsLock = unsafe extern "C" fn(file: *const c_void, exclusive: bool) -> ResultCode;
pub type VfsUnlock = unsafe extern "C" fn(file: *const c_void) -> ResultCode;
pub type VfsSize = unsafe extern "C" fn(file: *const c_void) -> i64;
pub type VfsRunOnce = unsafe extern "C" fn(file: *const c_void) -> ResultCode;
pub type VfsGetCurrentTime = unsafe extern "C" fn() -> *const c_char;
pub type VfsGenerateRandomNumber = unsafe extern "C" fn() -> i64;
#[repr(C)]
pub struct VfsFileImpl {
pub file: *const c_void,
pub vfs: *const VfsImpl,
}
impl VfsFileImpl {
pub fn new(file: *const c_void, vfs: *const VfsImpl) -> ExtResult<Self> {
if file.is_null() || vfs.is_null() {
return Err(ResultCode::Error);
}
Ok(Self { file, vfs })
}
}
impl Drop for VfsFileImpl {
fn drop(&mut self) {
if self.vfs.is_null() || self.file.is_null() {
return;
}
let vfs = unsafe { &*self.vfs };
unsafe {
(vfs.close)(self.file);
}
}
}