refactor(ext/fs): abstract FS via FileSystem trait (#18599)

This commit abstracts out the specifics of the underlying system calls
FS operations behind a new `FileSystem` and `File` trait in the
`ext/fs` extension.

This allows other embedders to re-use ext/fs, but substituting in a
different FS backend.

This is likely not the final form of these traits. Eventually they will
be entirely `deno_core::Resource` agnostic, and will live in a seperate
crate.

---------

Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit is contained in:
Luca Casonato 2023-04-12 15:13:32 +02:00 committed by GitHub
parent 0e3f62d444
commit f90caa821c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 3350 additions and 2488 deletions

View file

@ -20,6 +20,7 @@ use once_cell::sync::Lazy;
use std::borrow::Cow;
use std::cell::RefCell;
use std::fs::File as StdFile;
use std::io;
use std::io::ErrorKind;
use std::io::Read;
use std::io::Write;
@ -452,21 +453,21 @@ impl StdFileResource {
}
}
fn with_inner_and_metadata<TResult>(
fn with_inner_and_metadata<TResult, E>(
&self,
action: impl FnOnce(
&mut StdFileResourceInner,
&Arc<Mutex<FileMetadata>>,
) -> Result<TResult, AnyError>,
) -> Result<TResult, AnyError> {
) -> Result<TResult, E>,
) -> Option<Result<TResult, E>> {
match self.cell.try_borrow_mut() {
Ok(mut cell) => {
let mut file = cell.take().unwrap();
let result = action(&mut file.inner, &file.meta_data);
cell.replace(file);
result
Some(result)
}
Err(_) => Err(resource_unavailable()),
Err(_) => None,
}
}
@ -537,11 +538,16 @@ impl StdFileResource {
}
fn read_byob_sync(&self, buf: &mut [u8]) -> Result<usize, AnyError> {
self.with_inner_and_metadata(|inner, _| inner.read(buf).map_err(Into::into))
self
.with_inner_and_metadata(|inner, _| inner.read(buf))
.ok_or_else(resource_unavailable)?
.map_err(Into::into)
}
fn write_sync(&self, data: &[u8]) -> Result<usize, AnyError> {
self.with_inner_and_metadata(|inner, _| inner.write_and_maybe_flush(data))
self
.with_inner_and_metadata(|inner, _| inner.write_and_maybe_flush(data))
.ok_or_else(resource_unavailable)?
}
fn with_resource<F, R>(
@ -565,10 +571,19 @@ impl StdFileResource {
F: FnOnce(&mut StdFile) -> Result<R, AnyError>,
{
Self::with_resource(state, rid, move |resource| {
resource.with_inner_and_metadata(move |inner, _| inner.with_file(f))
resource
.with_inner_and_metadata(move |inner, _| inner.with_file(f))
.ok_or_else(resource_unavailable)?
})
}
pub fn with_file2<F, R>(self: Rc<Self>, f: F) -> Option<Result<R, io::Error>>
where
F: FnOnce(&mut StdFile) -> Result<R, io::Error>,
{
self.with_inner_and_metadata(move |inner, _| inner.with_file(f))
}
pub fn with_file_and_metadata<F, R>(
state: &mut OpState,
rid: ResourceId,
@ -578,9 +593,11 @@ impl StdFileResource {
F: FnOnce(&mut StdFile, &Arc<Mutex<FileMetadata>>) -> Result<R, AnyError>,
{
Self::with_resource(state, rid, move |resource| {
resource.with_inner_and_metadata(move |inner, metadata| {
inner.with_file(move |file| f(file, metadata))
})
resource
.with_inner_and_metadata(move |inner, metadata| {
inner.with_file(move |file| f(file, metadata))
})
.ok_or_else(resource_unavailable)?
})
}
@ -602,6 +619,18 @@ impl StdFileResource {
.await
}
pub async fn with_file_blocking_task2<F, R: Send + 'static>(
self: Rc<Self>,
f: F,
) -> Result<R, io::Error>
where
F: (FnOnce(&mut StdFile) -> Result<R, io::Error>) + Send + 'static,
{
self
.with_inner_blocking_task(move |inner| inner.with_file(f))
.await
}
pub fn clone_file(
state: &mut OpState,
rid: ResourceId,
@ -616,13 +645,15 @@ impl StdFileResource {
rid: u32,
) -> Result<std::process::Stdio, AnyError> {
Self::with_resource(state, rid, |resource| {
resource.with_inner_and_metadata(|inner, _| match inner.kind {
StdFileResourceKind::File => {
let file = inner.file.try_clone()?;
Ok(file.into())
}
_ => Ok(std::process::Stdio::inherit()),
})
resource
.with_inner_and_metadata(|inner, _| match inner.kind {
StdFileResourceKind::File => {
let file = inner.file.try_clone()?;
Ok(file.into())
}
_ => Ok(std::process::Stdio::inherit()),
})
.ok_or_else(resource_unavailable)?
})
}
}
@ -679,8 +710,8 @@ impl Resource for StdFileResource {
use std::os::unix::io::AsRawFd;
self
.with_inner_and_metadata(move |std_file, _| {
Ok(std_file.with_file(|f| f.as_raw_fd()))
})
Ok::<_, ()>(std_file.with_file(|f| f.as_raw_fd()))
})?
.ok()
}
}
@ -694,9 +725,11 @@ pub fn op_print(
) -> Result<(), AnyError> {
let rid = if is_err { 2 } else { 1 };
StdFileResource::with_resource(state, rid, move |resource| {
resource.with_inner_and_metadata(|inner, _| {
inner.write_all_and_maybe_flush(msg.as_bytes())?;
Ok(())
})
resource
.with_inner_and_metadata(|inner, _| {
inner.write_all_and_maybe_flush(msg.as_bytes())?;
Ok(())
})
.ok_or_else(resource_unavailable)?
})
}