table: borrow entry immutably or mutably

This commit is contained in:
Pat Hickey
2020-12-16 15:55:30 -08:00
parent dbe0f4f284
commit af8bdf8933
3 changed files with 65 additions and 45 deletions

View File

@@ -13,18 +13,14 @@ pub trait WasiDir {
oflags: OFlags, oflags: OFlags,
caps: FileCaps, caps: FileCaps,
) -> Result<Box<dyn WasiFile>, Error>; ) -> Result<Box<dyn WasiFile>, Error>;
fn open_dir(&self, symlink_follow: bool, path: &str) -> Result<Box<dyn WasiDir>, Error>; fn open_dir(&self, symlink_follow: bool, path: &str) -> Result<Box<dyn WasiDir>, Error>;
fn create_dir(&self, path: &str) -> Result<(), Error>; fn create_dir(&self, path: &str) -> Result<(), Error>;
fn readdir( fn readdir(
&self, &self,
cursor: ReaddirCursor, cursor: ReaddirCursor,
) -> Result<Box<dyn Iterator<Item = Result<(ReaddirEntity, String), Error>>>, Error>; ) -> Result<Box<dyn Iterator<Item = Result<(ReaddirEntity, String), Error>>>, Error>;
fn symlink(&self, old_path: &str, new_path: &str) -> Result<(), Error>;
fn remove_dir(&self, path: &str) -> Result<(), Error>; fn remove_dir(&self, path: &str) -> Result<(), Error>;
fn unlink_file(&self, path: &str) -> Result<(), Error>; fn unlink_file(&self, path: &str) -> Result<(), Error>;
} }
@@ -166,7 +162,7 @@ pub trait TableDirExt {
impl TableDirExt for crate::table::Table { impl TableDirExt for crate::table::Table {
fn is_preopen(&self, fd: u32) -> bool { fn is_preopen(&self, fd: u32) -> bool {
if self.is::<DirEntry>(fd) { if self.is::<DirEntry>(fd) {
let dir_entry: std::cell::RefMut<DirEntry> = self.get(fd).unwrap(); let dir_entry: std::cell::Ref<DirEntry> = self.get(fd).unwrap();
dir_entry.preopen_path.is_some() dir_entry.preopen_path.is_some()
} else { } else {
false false
@@ -220,15 +216,14 @@ impl WasiDir for cap_std::fs::Dir {
if oflags.contains(&OFlags::TRUNCATE) { if oflags.contains(&OFlags::TRUNCATE) {
opts.truncate(true); opts.truncate(true);
} }
if caps.contains(&FileCaps::READ) {
opts.read(true);
}
if caps.contains(&FileCaps::WRITE) if caps.contains(&FileCaps::WRITE)
|| caps.contains(&FileCaps::DATASYNC) || caps.contains(&FileCaps::DATASYNC)
|| caps.contains(&FileCaps::ALLOCATE) || caps.contains(&FileCaps::ALLOCATE)
|| caps.contains(&FileCaps::FILESTAT_SET_SIZE) || caps.contains(&FileCaps::FILESTAT_SET_SIZE)
{ {
opts.write(true); opts.write(true);
} else {
opts.read(true);
} }
if symlink_follow { if symlink_follow {
opts.follow(FollowSymlinks::Yes); opts.follow(FollowSymlinks::Yes);
@@ -287,6 +282,10 @@ impl WasiDir for cap_std::fs::Dir {
}))) })))
} }
fn symlink(&self, src_path: &str, dest_path: &str) -> Result<(), Error> {
self.symlink(Path::new(src_path), Path::new(dest_path))?;
Ok(())
}
fn remove_dir(&self, path: &str) -> Result<(), Error> { fn remove_dir(&self, path: &str) -> Result<(), Error> {
self.remove_dir(Path::new(path))?; self.remove_dir(Path::new(path))?;
Ok(()) Ok(())

View File

@@ -3,7 +3,7 @@ use crate::dir::{DirCaps, DirEntry, DirStat, ReaddirCursor, TableDirExt};
use crate::file::{FdFlags, FdStat, FileCaps, FileEntry, Filestat, Filetype, OFlags}; use crate::file::{FdFlags, FdStat, FileCaps, FileEntry, Filestat, Filetype, OFlags};
use crate::{Error, WasiCtx}; use crate::{Error, WasiCtx};
use fs_set_times::SystemTimeSpec; use fs_set_times::SystemTimeSpec;
use std::cell::RefMut; use std::cell::{Ref, RefMut};
use std::convert::TryFrom; use std::convert::TryFrom;
use std::io::{IoSlice, IoSliceMut}; use std::io::{IoSlice, IoSliceMut};
use std::ops::Deref; use std::ops::Deref;
@@ -145,7 +145,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
advice: types::Advice, advice: types::Advice,
) -> Result<(), Error> { ) -> Result<(), Error> {
let table = self.table(); let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?; let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::ADVISE)?; let f = file_entry.get_cap(FileCaps::ADVISE)?;
f.advise(offset, len, advice.into())?; f.advise(offset, len, advice.into())?;
Ok(()) Ok(())
@@ -158,7 +158,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
len: types::Filesize, len: types::Filesize,
) -> Result<(), Error> { ) -> Result<(), Error> {
let table = self.table(); let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?; let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::ALLOCATE)?; let f = file_entry.get_cap(FileCaps::ALLOCATE)?;
f.allocate(offset, len)?; f.allocate(offset, len)?;
Ok(()) Ok(())
@@ -177,7 +177,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
let _ = table.delete(fd); let _ = table.delete(fd);
} else if table.is::<DirEntry>(fd) { } else if table.is::<DirEntry>(fd) {
// We cannot close preopened directories // We cannot close preopened directories
let dir_entry: RefMut<DirEntry> = table.get(fd).unwrap(); let dir_entry: Ref<DirEntry> = table.get(fd).unwrap();
if dir_entry.preopen_path().is_some() { if dir_entry.preopen_path().is_some() {
return Err(Error::Notsup); return Err(Error::Notsup);
} }
@@ -193,7 +193,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
fn fd_datasync(&self, fd: types::Fd) -> Result<(), Error> { fn fd_datasync(&self, fd: types::Fd) -> Result<(), Error> {
let table = self.table(); let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?; let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::DATASYNC)?; let f = file_entry.get_cap(FileCaps::DATASYNC)?;
f.datasync()?; f.datasync()?;
Ok(()) Ok(())
@@ -203,11 +203,11 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
let table = self.table(); let table = self.table();
let fd = u32::from(fd); let fd = u32::from(fd);
if table.is::<FileEntry>(fd) { if table.is::<FileEntry>(fd) {
let file_entry: RefMut<FileEntry> = table.get(fd)?; let file_entry: Ref<FileEntry> = table.get(fd)?;
let fdstat = file_entry.get_fdstat()?; let fdstat = file_entry.get_fdstat()?;
Ok(types::Fdstat::from(&fdstat)) Ok(types::Fdstat::from(&fdstat))
} else if table.is::<DirEntry>(fd) { } else if table.is::<DirEntry>(fd) {
let dir_entry: RefMut<DirEntry> = table.get(fd)?; let dir_entry: Ref<DirEntry> = table.get(fd)?;
let dirstat = dir_entry.get_dirstat(); let dirstat = dir_entry.get_dirstat();
Ok(types::Fdstat::from(&dirstat)) Ok(types::Fdstat::from(&dirstat))
} else { } else {
@@ -217,7 +217,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
fn fd_fdstat_set_flags(&self, fd: types::Fd, flags: types::Fdflags) -> Result<(), Error> { fn fd_fdstat_set_flags(&self, fd: types::Fd, flags: types::Fdflags) -> Result<(), Error> {
let table = self.table(); let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?; let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::FDSTAT_SET_FLAGS)?; let f = file_entry.get_cap(FileCaps::FDSTAT_SET_FLAGS)?;
f.set_fdflags(FdFlags::from(&flags))?; f.set_fdflags(FdFlags::from(&flags))?;
Ok(()) Ok(())
@@ -232,11 +232,11 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
let table = self.table(); let table = self.table();
let fd = u32::from(fd); let fd = u32::from(fd);
if table.is::<FileEntry>(fd) { if table.is::<FileEntry>(fd) {
let mut file_entry: RefMut<FileEntry> = table.get(fd)?; let mut file_entry: RefMut<FileEntry> = table.get_mut(fd)?;
let file_caps = FileCaps::from(&fs_rights_base); let file_caps = FileCaps::from(&fs_rights_base);
file_entry.drop_caps_to(file_caps) file_entry.drop_caps_to(file_caps)
} else if table.is::<DirEntry>(fd) { } else if table.is::<DirEntry>(fd) {
let mut dir_entry: RefMut<DirEntry> = table.get(fd)?; let mut dir_entry: RefMut<DirEntry> = table.get_mut(fd)?;
let dir_caps = DirCaps::from(&fs_rights_base); let dir_caps = DirCaps::from(&fs_rights_base);
let file_caps = FileCaps::from(&fs_rights_inheriting); let file_caps = FileCaps::from(&fs_rights_inheriting);
dir_entry.drop_caps_to(dir_caps, file_caps) dir_entry.drop_caps_to(dir_caps, file_caps)
@@ -247,7 +247,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
fn fd_filestat_get(&self, fd: types::Fd) -> Result<types::Filestat, Error> { fn fd_filestat_get(&self, fd: types::Fd) -> Result<types::Filestat, Error> {
let table = self.table(); let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?; let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::FILESTAT_GET)?; let f = file_entry.get_cap(FileCaps::FILESTAT_GET)?;
let filestat = f.get_filestat()?; let filestat = f.get_filestat()?;
Ok(filestat.into()) Ok(filestat.into())
@@ -255,7 +255,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
fn fd_filestat_set_size(&self, fd: types::Fd, size: types::Filesize) -> Result<(), Error> { fn fd_filestat_set_size(&self, fd: types::Fd, size: types::Filesize) -> Result<(), Error> {
let table = self.table(); let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?; let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::FILESTAT_SET_SIZE)?; let f = file_entry.get_cap(FileCaps::FILESTAT_SET_SIZE)?;
f.set_filestat_size(size)?; f.set_filestat_size(size)?;
Ok(()) Ok(())
@@ -270,7 +270,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
) -> Result<(), Error> { ) -> Result<(), Error> {
use std::time::{Duration, UNIX_EPOCH}; use std::time::{Duration, UNIX_EPOCH};
let table = self.table(); let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?; let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::FILESTAT_SET_TIMES)?; let f = file_entry.get_cap(FileCaps::FILESTAT_SET_TIMES)?;
// Validate flags, transform into well-structured arguments // Validate flags, transform into well-structured arguments
@@ -306,7 +306,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
fn fd_read(&self, fd: types::Fd, iovs: &types::IovecArray<'_>) -> Result<types::Size, Error> { fn fd_read(&self, fd: types::Fd, iovs: &types::IovecArray<'_>) -> Result<types::Size, Error> {
let table = self.table(); let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?; let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::READ)?; let f = file_entry.get_cap(FileCaps::READ)?;
let mut guest_slices: Vec<wiggle::GuestSliceMut<u8>> = iovs let mut guest_slices: Vec<wiggle::GuestSliceMut<u8>> = iovs
@@ -334,7 +334,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
offset: types::Filesize, offset: types::Filesize,
) -> Result<types::Size, Error> { ) -> Result<types::Size, Error> {
let table = self.table(); let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?; let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::READ | FileCaps::SEEK)?; let f = file_entry.get_cap(FileCaps::READ | FileCaps::SEEK)?;
let mut guest_slices: Vec<wiggle::GuestSliceMut<u8>> = iovs let mut guest_slices: Vec<wiggle::GuestSliceMut<u8>> = iovs
@@ -361,7 +361,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
ciovs: &types::CiovecArray<'_>, ciovs: &types::CiovecArray<'_>,
) -> Result<types::Size, Error> { ) -> Result<types::Size, Error> {
let table = self.table(); let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?; let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::WRITE)?; let f = file_entry.get_cap(FileCaps::WRITE)?;
let guest_slices: Vec<wiggle::GuestSlice<u8>> = ciovs let guest_slices: Vec<wiggle::GuestSlice<u8>> = ciovs
@@ -389,7 +389,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
offset: types::Filesize, offset: types::Filesize,
) -> Result<types::Size, Error> { ) -> Result<types::Size, Error> {
let table = self.table(); let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?; let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::WRITE | FileCaps::SEEK)?; let f = file_entry.get_cap(FileCaps::WRITE | FileCaps::SEEK)?;
let guest_slices: Vec<wiggle::GuestSlice<u8>> = ciovs let guest_slices: Vec<wiggle::GuestSlice<u8>> = ciovs
@@ -412,7 +412,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
fn fd_prestat_get(&self, fd: types::Fd) -> Result<types::Prestat, Error> { fn fd_prestat_get(&self, fd: types::Fd) -> Result<types::Prestat, Error> {
let table = self.table(); let table = self.table();
let dir_entry: RefMut<DirEntry> = table.get(u32::from(fd)).map_err(|_| Error::Badf)?; let dir_entry: Ref<DirEntry> = table.get(u32::from(fd)).map_err(|_| Error::Badf)?;
if let Some(ref preopen) = dir_entry.preopen_path() { if let Some(ref preopen) = dir_entry.preopen_path() {
let path_str = preopen.to_str().ok_or(Error::Notsup)?; let path_str = preopen.to_str().ok_or(Error::Notsup)?;
let pr_name_len = let pr_name_len =
@@ -430,7 +430,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
path_max_len: types::Size, path_max_len: types::Size,
) -> Result<(), Error> { ) -> Result<(), Error> {
let table = self.table(); let table = self.table();
let dir_entry: RefMut<DirEntry> = table.get(u32::from(fd)).map_err(|_| Error::Notdir)?; let dir_entry: Ref<DirEntry> = table.get(u32::from(fd)).map_err(|_| Error::Notdir)?;
if let Some(ref preopen) = dir_entry.preopen_path() { if let Some(ref preopen) = dir_entry.preopen_path() {
let path_bytes = preopen.to_str().ok_or(Error::Notsup)?.as_bytes(); let path_bytes = preopen.to_str().ok_or(Error::Notsup)?.as_bytes();
let path_len = path_bytes.len(); let path_len = path_bytes.len();
@@ -479,7 +479,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}; };
let table = self.table(); let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?; let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(required_caps)?; let f = file_entry.get_cap(required_caps)?;
let newoffset = f.seek(match whence { let newoffset = f.seek(match whence {
types::Whence::Cur => SeekFrom::Current(offset), types::Whence::Cur => SeekFrom::Current(offset),
@@ -491,7 +491,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
fn fd_sync(&self, fd: types::Fd) -> Result<(), Error> { fn fd_sync(&self, fd: types::Fd) -> Result<(), Error> {
let table = self.table(); let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?; let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::SYNC)?; let f = file_entry.get_cap(FileCaps::SYNC)?;
f.sync()?; f.sync()?;
Ok(()) Ok(())
@@ -499,7 +499,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
fn fd_tell(&self, fd: types::Fd) -> Result<types::Filesize, Error> { fn fd_tell(&self, fd: types::Fd) -> Result<types::Filesize, Error> {
let table = self.table(); let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?; let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::TELL)?; let f = file_entry.get_cap(FileCaps::TELL)?;
let offset = f.seek(std::io::SeekFrom::Current(0))?; let offset = f.seek(std::io::SeekFrom::Current(0))?;
Ok(offset) Ok(offset)
@@ -513,7 +513,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
cookie: types::Dircookie, cookie: types::Dircookie,
) -> Result<types::Size, Error> { ) -> Result<types::Size, Error> {
let table = self.table(); let table = self.table();
let dir_entry: RefMut<DirEntry> = table.get(u32::from(dirfd))?; let dir_entry: Ref<DirEntry> = table.get(u32::from(dirfd))?;
let d = dir_entry.get_cap(DirCaps::READDIR)?; let d = dir_entry.get_cap(DirCaps::READDIR)?;
for pair in d.readdir(ReaddirCursor::from(cookie))? { for pair in d.readdir(ReaddirCursor::from(cookie))? {
let (entity, name) = pair?; let (entity, name) = pair?;
@@ -528,7 +528,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
path: &GuestPtr<'_, str>, path: &GuestPtr<'_, str>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let table = self.table(); let table = self.table();
let dir_entry: RefMut<DirEntry> = table.get(u32::from(dirfd))?; let dir_entry: Ref<DirEntry> = table.get(u32::from(dirfd))?;
let dir = dir_entry.get_cap(DirCaps::CREATE_DIRECTORY)?; let dir = dir_entry.get_cap(DirCaps::CREATE_DIRECTORY)?;
let path = path.as_str()?; let path = path.as_str()?;
dir.create_dir(path.deref()) dir.create_dir(path.deref())
@@ -577,7 +577,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
fdflags: types::Fdflags, fdflags: types::Fdflags,
) -> Result<types::Fd, Error> { ) -> Result<types::Fd, Error> {
let mut table = self.table(); let mut table = self.table();
let dir_entry: RefMut<DirEntry> = table.get(u32::from(dirfd))?; let dir_entry: Ref<DirEntry> = table.get(u32::from(dirfd))?;
let symlink_follow = dirflags.contains(&types::Lookupflags::SYMLINK_FOLLOW); let symlink_follow = dirflags.contains(&types::Lookupflags::SYMLINK_FOLLOW);
@@ -633,7 +633,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
path: &GuestPtr<'_, str>, path: &GuestPtr<'_, str>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let table = self.table(); let table = self.table();
let dir_entry: RefMut<DirEntry> = table.get(u32::from(dirfd))?; let dir_entry: Ref<DirEntry> = table.get(u32::from(dirfd))?;
let dir = dir_entry.get_cap(DirCaps::REMOVE_DIRECTORY)?; let dir = dir_entry.get_cap(DirCaps::REMOVE_DIRECTORY)?;
let path = path.as_str()?; let path = path.as_str()?;
dir.remove_dir(path.deref()) dir.remove_dir(path.deref())
@@ -651,16 +651,21 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
fn path_symlink( fn path_symlink(
&self, &self,
old_path: &GuestPtr<'_, str>, src_path: &GuestPtr<'_, str>,
dirfd: types::Fd, dirfd: types::Fd,
new_path: &GuestPtr<'_, str>, dest_path: &GuestPtr<'_, str>,
) -> Result<(), Error> { ) -> Result<(), Error> {
unimplemented!() let table = self.table();
let dir_entry: Ref<DirEntry> = table.get(u32::from(dirfd))?;
let dir = dir_entry.get_cap(DirCaps::SYMLINK)?;
let src_path = src_path.as_str()?;
let dest_path = dest_path.as_str()?;
dir.symlink(src_path.deref(), dest_path.deref())
} }
fn path_unlink_file(&self, dirfd: types::Fd, path: &GuestPtr<'_, str>) -> Result<(), Error> { fn path_unlink_file(&self, dirfd: types::Fd, path: &GuestPtr<'_, str>) -> Result<(), Error> {
let table = self.table(); let table = self.table();
let dir_entry: RefMut<DirEntry> = table.get(u32::from(dirfd))?; let dir_entry: Ref<DirEntry> = table.get(u32::from(dirfd))?;
let dir = dir_entry.get_cap(DirCaps::UNLINK_FILE)?; let dir = dir_entry.get_cap(DirCaps::UNLINK_FILE)?;
let path = path.as_str()?; let path = path.as_str()?;
dir.unlink_file(path.deref()) dir.unlink_file(path.deref())

View File

@@ -1,6 +1,6 @@
use crate::Error; use crate::Error;
use std::any::Any; use std::any::Any;
use std::cell::{RefCell, RefMut}; use std::cell::{Ref, RefCell, RefMut};
use std::collections::HashMap; use std::collections::HashMap;
pub struct Table { pub struct Table {
@@ -49,12 +49,28 @@ impl Table {
false false
} }
} }
// Todo: we can refine these errors and translate them to Exist at abi
pub fn get<T: Any + Sized>(&self, key: u32) -> Result<RefMut<T>, Error> { pub fn get<T: Any + Sized>(&self, key: u32) -> Result<Ref<T>, Error> {
if let Some(refcell) = self.map.get(&key) { if let Some(refcell) = self.map.get(&key) {
if let Ok(refmut) = refcell.try_borrow_mut() { if let Ok(r) = refcell.try_borrow() {
if refmut.is::<T>() { if r.is::<T>() {
Ok(RefMut::map(refmut, |r| r.downcast_mut::<T>().unwrap())) Ok(Ref::map(r, |r| r.downcast_ref::<T>().unwrap()))
} else {
Err(Error::Exist) // Exists at another type
}
} else {
Err(Error::Exist) // Does exist, but borrowed
}
} else {
Err(Error::Exist) // Does not exist
}
}
pub fn get_mut<T: Any + Sized>(&self, key: u32) -> Result<RefMut<T>, Error> {
if let Some(refcell) = self.map.get(&key) {
if let Ok(r) = refcell.try_borrow_mut() {
if r.is::<T>() {
Ok(RefMut::map(r, |r| r.downcast_mut::<T>().unwrap()))
} else { } else {
Err(Error::Exist) // Exists at another type Err(Error::Exist) // Exists at another type
} }