use std::any::Any;
use std::any::TypeId;
use std::any::type_name;
use std::borrow::Cow;
use std::rc::Rc;
use deno_error::JsErrorBox;
use deno_error::JsErrorClass;
use crate::ResourceHandle;
use crate::ResourceHandleFd;
use crate::io::AsyncResult;
use crate::io::BufMutView;
use crate::io::BufView;
use crate::io::WriteOutcome;
pub trait Resource: Any + 'static {
fn name(&self) -> Cow<'_, str> {
type_name::<Self>().into()
}
fn read(self: Rc<Self>, limit: usize) -> AsyncResult<BufView> {
_ = limit;
Box::pin(std::future::ready(Err(JsErrorBox::not_supported())))
}
fn read_byob(
self: Rc<Self>,
mut buf: BufMutView,
) -> AsyncResult<(usize, BufMutView)> {
Box::pin(async move {
let read = self.read(buf.len()).await?;
let nread = read.len();
buf[..nread].copy_from_slice(&read);
Ok((nread, buf))
})
}
fn write_error(self: Rc<Self>, _error: &dyn JsErrorClass) -> AsyncResult<()> {
Box::pin(std::future::ready(Err(JsErrorBox::not_supported())))
}
fn write(self: Rc<Self>, buf: BufView) -> AsyncResult<WriteOutcome> {
_ = buf;
Box::pin(std::future::ready(Err(JsErrorBox::not_supported())))
}
fn write_all(self: Rc<Self>, view: BufView) -> AsyncResult<()> {
Box::pin(async move {
let mut view = view;
let this = self;
while !view.is_empty() {
let resp = this.clone().write(view).await?;
match resp {
WriteOutcome::Partial {
nwritten,
view: new_view,
} => {
view = new_view;
view.advance_cursor(nwritten);
}
WriteOutcome::Full { .. } => break,
}
}
Ok(())
})
}
fn read_byob_sync(
self: Rc<Self>,
data: &mut [u8],
) -> Result<usize, JsErrorBox> {
_ = data;
Err(JsErrorBox::not_supported())
}
fn write_sync(self: Rc<Self>, data: &[u8]) -> Result<usize, JsErrorBox> {
_ = data;
Err(JsErrorBox::not_supported())
}
fn shutdown(self: Rc<Self>) -> AsyncResult<()> {
Box::pin(std::future::ready(Err(JsErrorBox::not_supported())))
}
fn close(self: Rc<Self>) {}
fn cancel_read_ops(self: Rc<Self>) {}
fn backing_handle(self: Rc<Self>) -> Option<ResourceHandle> {
#[allow(deprecated, reason = "needed for compatibility")]
self.backing_fd().map(ResourceHandle::Fd)
}
#[deprecated = "Use backing_handle"]
fn backing_fd(self: Rc<Self>) -> Option<ResourceHandleFd> {
None
}
fn size_hint(&self) -> (u64, Option<u64>) {
(0, None)
}
fn transfer(
self: Rc<Self>,
) -> Result<Box<dyn TransferredResource>, JsErrorBox> {
Err(JsErrorBox::not_supported())
}
}
impl dyn Resource {
#[inline(always)]
fn is<T: Resource>(&self) -> bool {
self.type_id() == TypeId::of::<T>()
}
#[inline(always)]
#[allow(
clippy::needless_lifetimes,
reason = "explicit lifetimes improve clarity"
)]
pub fn downcast_rc<'a, T: Resource>(self: &'a Rc<Self>) -> Option<&'a Rc<T>> {
if self.is::<T>() {
let ptr = self as *const Rc<_> as *const Rc<T>;
#[allow(
clippy::undocumented_unsafe_blocks,
reason = "safety comment on the containing block"
)]
Some(unsafe { &*ptr })
} else {
None
}
}
}
#[macro_export]
macro_rules! impl_readable_byob {
() => {
fn read(
self: ::std::rc::Rc<Self>,
limit: ::core::primitive::usize,
) -> AsyncResult<$crate::BufView> {
::std::boxed::Box::pin(async move {
let mut vec = ::std::vec![0; limit];
let nread = self.read(&mut vec).await.map_err(::deno_error::JsErrorBox::from_err)?;
if nread != vec.len() {
vec.truncate(nread);
}
let view = $crate::BufView::from(vec);
::std::result::Result::Ok(view)
})
}
fn read_byob(
self: ::std::rc::Rc<Self>,
mut buf: $crate::BufMutView,
) -> AsyncResult<(::core::primitive::usize, $crate::BufMutView)> {
::std::boxed::Box::pin(async move {
let nread = self.read(buf.as_mut()).await.map_err(::deno_error::JsErrorBox::from_err)?;
::std::result::Result::Ok((nread, buf))
})
}
};
}
#[macro_export]
macro_rules! impl_writable {
(__write) => {
fn write(
self: ::std::rc::Rc<Self>,
view: $crate::BufView,
) -> $crate::AsyncResult<$crate::WriteOutcome> {
::std::boxed::Box::pin(async move {
let nwritten = self
.write(&view)
.await
.map_err(::deno_error::JsErrorBox::from_err)?;
::std::result::Result::Ok($crate::WriteOutcome::Partial {
nwritten,
view,
})
})
}
};
(__write_all) => {
fn write_all(
self: ::std::rc::Rc<Self>,
view: $crate::BufView,
) -> $crate::AsyncResult<()> {
::std::boxed::Box::pin(async move {
self
.write_all(&view)
.await
.map_err(::deno_error::JsErrorBox::from_err)?;
::std::result::Result::Ok(())
})
}
};
() => {
$crate::impl_writable!(__write);
};
(with_all) => {
$crate::impl_writable!(__write);
$crate::impl_writable!(__write_all);
};
}
pub trait TransferredResource: Send {
fn receive(self: Box<Self>) -> Rc<dyn Resource>;
}
impl dyn TransferredResource {}