use CapturedError as dioxus::Ok() so resources still function as expected (#4851)
This commit is contained in:
1 parent
9f0bacc85c
commit
281f68faf5
14 files changed
+200
-54
No files matched your search
@@ -42,7 +42,7 @@ pub fn NavBar() -> Element {
|
||||
#[component]
|
||||
pub fn DogView() -> Element {
|
||||
let mut img_src = use_loader(|| async move {
|
||||
anyhow::Ok(
|
||||
dioxus::Ok(
|
||||
reqwest::get("https://dog.ceo/api/breeds/image/random")
|
||||
.await?
|
||||
.json::<serde_json::Value>()
|
||||
|
||||
@@ -41,7 +41,7 @@ fn app() -> Element {
|
||||
events.push(event);
|
||||
}
|
||||
|
||||
anyhow::Ok(())
|
||||
dioxus::Ok(())
|
||||
});
|
||||
|
||||
rsx! {
|
||||
|
||||
@@ -77,8 +77,11 @@ pub(crate) mod innerlude {
|
||||
|
||||
pub use anyhow::anyhow;
|
||||
pub use anyhow::Context as AnyhowContext;
|
||||
pub use anyhow::Error;
|
||||
pub use anyhow::Result;
|
||||
// pub use anyhow::Error as AnyhowError;
|
||||
// pub type Error = CapturedError;
|
||||
|
||||
/// A result type with a default error of [`CapturedError`].
|
||||
pub type Result<T, E = CapturedError> = std::result::Result<T, E>;
|
||||
|
||||
/// An [`Element`] is a possibly-none [`VNode`] created by calling `render` on [`ScopeId`] or [`ScopeState`].
|
||||
///
|
||||
@@ -97,7 +100,7 @@ pub use crate::innerlude::{
|
||||
suspend, throw_error, try_consume_context, use_after_render, use_before_render, use_drop,
|
||||
use_hook, use_hook_with_cleanup, with_owner, AnyValue, AnyhowContext, Attribute,
|
||||
AttributeValue, Callback, CapturedError, Component, ComponentFunction, DynamicNode, Element,
|
||||
ElementId, Error, ErrorBoundary, ErrorContext, Event, EventHandler, Fragment, HasAttributes,
|
||||
ElementId, ErrorBoundary, ErrorContext, Event, EventHandler, Fragment, HasAttributes,
|
||||
IntoAttributeValue, IntoDynNode, LaunchConfig, ListenerCallback, MarkerWrapper, Mutation,
|
||||
Mutations, NoOpMutations, OptionStringFromMarker, Properties, ReactiveContext, RenderError,
|
||||
Result, Runtime, RuntimeGuard, ScopeId, ScopeState, SpawnIfAsync, SubscriberList, Subscribers,
|
||||
@@ -106,5 +109,27 @@ pub use crate::innerlude::{
|
||||
VNodeInner, VPlaceholder, VText, VirtualDom, WriteMutations,
|
||||
};
|
||||
|
||||
pub use anyhow::Ok;
|
||||
/// Equivalent to `Ok::<_, dioxus::CapturedError>(value)`.
|
||||
///
|
||||
/// This simplifies creation of an `dioxus::Result` in places where type
|
||||
/// inference cannot deduce the `E` type of the result — without needing
|
||||
/// to write`Ok::<_, dioxus::CapturedError>(value)`.
|
||||
///
|
||||
/// One might think that `dioxus::Result::Ok(value)` would work in such cases
|
||||
/// but it does not.
|
||||
///
|
||||
/// ```console
|
||||
/// error[E0282]: type annotations needed for `std::result::Result<i32, E>`
|
||||
/// --> src/main.rs:11:13
|
||||
/// |
|
||||
/// 11 | let _ = dioxus::Result::Ok(1);
|
||||
/// | - ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `E` declared on the enum `Result`
|
||||
/// | |
|
||||
/// | consider giving this pattern the explicit type `std::result::Result<i32, E>`, where the type parameter `E` is specified
|
||||
/// ```
|
||||
#[allow(non_snake_case)]
|
||||
pub fn Ok<T>(value: T) -> Result<T, CapturedError> {
|
||||
Result::Ok(value)
|
||||
}
|
||||
|
||||
pub use const_format;
|
||||
@@ -51,7 +51,7 @@ impl From<CapturedError> for RenderError {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Into<Error>> From<E> for RenderError {
|
||||
impl<E: Into<anyhow::Error>> From<E> for RenderError {
|
||||
fn from(e: E) -> Self {
|
||||
let anyhow_err = e.into();
|
||||
|
||||
@@ -69,13 +69,44 @@ impl<E: Into<Error>> From<E> for RenderError {
|
||||
|
||||
/// An `anyhow::Error` wrapped in an `Arc` so it can be cheaply cloned and passed around.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CapturedError(pub Arc<Error>);
|
||||
pub struct CapturedError(pub Arc<anyhow::Error>);
|
||||
|
||||
impl CapturedError {
|
||||
/// Create a `CapturedError` from anything that implements `Display`.
|
||||
pub fn from_display(t: impl Display) -> Self {
|
||||
Self(Arc::new(anyhow::anyhow!(t.to_string())))
|
||||
}
|
||||
|
||||
/// Create a `CapturedError` from anything that implements `std::error::Error`.
|
||||
pub fn new<E>(error: E) -> Self
|
||||
where
|
||||
E: std::error::Error + Send + Sync + 'static,
|
||||
{
|
||||
anyhow::Error::new(error).into()
|
||||
}
|
||||
|
||||
/// Create a `CapturedError` from anything that implements `Display` and `Debug`.
|
||||
pub fn msg<M>(t: M) -> Self
|
||||
where
|
||||
M: Display + Debug + Send + Sync + 'static,
|
||||
{
|
||||
anyhow::Error::msg(t).into()
|
||||
}
|
||||
|
||||
/// Create a `CapturedError` from a boxed `std::error::Error`.
|
||||
pub fn from_boxed(boxed_error: Box<dyn std::error::Error + Send + Sync + 'static>) -> Self {
|
||||
anyhow::Error::from_boxed(boxed_error).into()
|
||||
}
|
||||
|
||||
/// Returns the strong count of the underlying error.
|
||||
pub fn _strong_count(&self) -> usize {
|
||||
std::sync::Arc::strong_count(&self.0)
|
||||
}
|
||||
|
||||
/// Try to unwrap the underlying error if this is the only reference to it.
|
||||
pub fn into_inner(self) -> Option<anyhow::Error> {
|
||||
Arc::try_unwrap(self.0).ok()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
@@ -100,14 +131,14 @@ impl<'de> serde::Deserialize<'de> for CapturedError {
|
||||
}
|
||||
|
||||
impl std::ops::Deref for CapturedError {
|
||||
type Target = Error;
|
||||
type Target = anyhow::Error;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Into<Error>> From<E> for CapturedError {
|
||||
impl<E: Into<anyhow::Error>> From<E> for CapturedError {
|
||||
fn from(e: E) -> Self {
|
||||
Self(Arc::new(e.into()))
|
||||
}
|
||||
|
||||
@@ -331,7 +331,10 @@ impl NativeFileData for DesktopFileData {
|
||||
fn read_bytes(
|
||||
&self,
|
||||
) -> std::pin::Pin<
|
||||
Box<dyn std::future::Future<Output = Result<bytes::Bytes, dioxus_core::Error>> + 'static>,
|
||||
Box<
|
||||
dyn std::future::Future<Output = Result<bytes::Bytes, dioxus_core::CapturedError>>
|
||||
+ 'static,
|
||||
>,
|
||||
> {
|
||||
let path = self.0.clone();
|
||||
Box::pin(async move { Ok(bytes::Bytes::from(std::fs::read(&path)?)) })
|
||||
@@ -340,7 +343,7 @@ impl NativeFileData for DesktopFileData {
|
||||
fn read_string(
|
||||
&self,
|
||||
) -> std::pin::Pin<
|
||||
Box<dyn std::future::Future<Output = Result<String, dioxus_core::Error>> + 'static>,
|
||||
Box<dyn std::future::Future<Output = Result<String, dioxus_core::CapturedError>> + 'static>,
|
||||
> {
|
||||
let path = self.0.clone();
|
||||
Box::pin(async move { Ok(std::fs::read_to_string(&path)?) })
|
||||
@@ -358,7 +361,7 @@ impl NativeFileData for DesktopFileData {
|
||||
&self,
|
||||
) -> std::pin::Pin<
|
||||
Box<
|
||||
dyn futures_util::Stream<Item = Result<bytes::Bytes, dioxus_core::Error>>
|
||||
dyn futures_util::Stream<Item = Result<bytes::Bytes, dioxus_core::CapturedError>>
|
||||
+ 'static
|
||||
+ Send,
|
||||
>,
|
||||
@@ -374,7 +377,7 @@ impl NativeFileData for DesktopFileData {
|
||||
// let n = file
|
||||
// .read(&mut buf)
|
||||
// .await
|
||||
// .map_err(|e| dioxus_core::Error::from(e))?;
|
||||
// .map_err(|e| dioxus_core::CapturedError::from(e))?;
|
||||
// if n == 0 {
|
||||
// Ok(None)
|
||||
// } else {
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
pub use dioxus_core;
|
||||
#[doc(inline)]
|
||||
pub use dioxus_core::{CapturedError, Error, Ok, Result};
|
||||
pub use dioxus_core::{CapturedError, Ok, Result};
|
||||
|
||||
#[cfg(feature = "launch")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "launch")))]
|
||||
|
||||
@@ -33,7 +33,7 @@ pub fn use_loader<F, T, E>(mut future: impl FnMut() -> F + 'static) -> Result<Lo
|
||||
where
|
||||
F: Future<Output = Result<T, E>> + 'static,
|
||||
T: 'static + PartialEq + Serialize + DeserializeOwned,
|
||||
E: Into<dioxus_core::Error> + 'static,
|
||||
E: Into<CapturedError> + 'static,
|
||||
{
|
||||
let serialize_context = use_hook(crate::transport::serialize_context);
|
||||
|
||||
@@ -101,8 +101,8 @@ where
|
||||
// Remap the error to the captured error type so it's cheap to clone and pass out, just
|
||||
// slightly more cumbersome to access the inner error.
|
||||
let out = out.map_err(|e| {
|
||||
let anyhow_err: anyhow::Error = e.into();
|
||||
anyhow_err.into()
|
||||
let anyhow_err: CapturedError = e.into();
|
||||
anyhow_err
|
||||
});
|
||||
|
||||
// If this is the first run and we are on the server, cache the data in the slot we reserved for it
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use base64::Engine;
|
||||
use dioxus_core::CapturedError;
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use std::{cell::RefCell, io::Cursor, rc::Rc, sync::Arc};
|
||||
use std::{cell::RefCell, io::Cursor, rc::Rc};
|
||||
|
||||
#[cfg(feature = "web")]
|
||||
thread_local! {
|
||||
@@ -429,15 +429,15 @@ pub fn head_element_hydration_entry() -> SerializeContextEntry<bool> {
|
||||
|
||||
/// A `Transportable` type can be safely transported from the server to the client, and be used for
|
||||
/// hydration. Not all types can sensibly be transported, but many can. This trait makes it possible
|
||||
/// to customize how types are transported which helps for non-serializable types like `dioxus_core::Error`.
|
||||
/// to customize how types are transported which helps for non-serializable types like `dioxus_core::CapturedError`.
|
||||
///
|
||||
/// By default, all types that implement `Serialize` and `DeserializeOwned` are transportable.
|
||||
///
|
||||
/// You can also implement `Transportable` for `Result<T, dioxus_core::Error>` where `T` is
|
||||
/// You can also implement `Transportable` for `Result<T, dioxus_core::CapturedError>` where `T` is
|
||||
/// `Serialize` and `DeserializeOwned` to allow transporting results that may contain errors.
|
||||
///
|
||||
/// Note that transporting a `Result<T, dioxus_core::Error>` will lose various aspects of the original
|
||||
/// `dioxus_core::Error` such as backtraces and source errors, but will preserve the error message.
|
||||
/// Note that transporting a `Result<T, dioxus_core::CapturedError>` will lose various aspects of the original
|
||||
/// `dioxus_core::CapturedError` such as backtraces and source errors, but will preserve the error message.
|
||||
pub trait Transportable<M = ()>: 'static {
|
||||
/// Serialize the type to a byte vector for transport
|
||||
fn transport_to_bytes(&self) -> Vec<u8>;
|
||||
@@ -474,7 +474,7 @@ struct TransportResultErr<T> {
|
||||
#[doc(hidden)]
|
||||
pub struct TransportViaErrMarker;
|
||||
|
||||
impl<T> Transportable<TransportViaErrMarker> for Result<T, dioxus_core::Error>
|
||||
impl<T> Transportable<TransportViaErrMarker> for Result<T, anyhow::Error>
|
||||
where
|
||||
T: Serialize + DeserializeOwned + 'static,
|
||||
{
|
||||
@@ -497,7 +497,7 @@ where
|
||||
let err: TransportResultErr<T> = ciborium::from_reader(Cursor::new(bytes))?;
|
||||
match err.error {
|
||||
Ok(value) => Ok(Ok(value)),
|
||||
Err(captured) => Ok(Err(dioxus_core::Error::msg(captured.to_string()))),
|
||||
Err(captured) => Ok(Err(anyhow::Error::msg(captured.to_string()))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -525,8 +525,6 @@ impl Transportable<TransportCapturedError> for CapturedError {
|
||||
Self: Sized,
|
||||
{
|
||||
let err: TransportError = ciborium::from_reader(Cursor::new(bytes))?;
|
||||
Ok(CapturedError(Arc::new(dioxus_core::Error::msg::<String>(
|
||||
err.error,
|
||||
))))
|
||||
Ok(dioxus_core::CapturedError::msg::<String>(err.error))
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#![allow(clippy::needless_return)]
|
||||
|
||||
use dioxus_core::CapturedError;
|
||||
use std::{hint::black_box, prelude::rust_2024::Future, sync::atomic::AtomicBool};
|
||||
|
||||
/// `Lazy` is a thread-safe, lazily-initialized global variable.
|
||||
@@ -14,7 +15,7 @@ use std::{hint::black_box, prelude::rust_2024::Future, sync::atomic::AtomicBool}
|
||||
pub struct Lazy<T> {
|
||||
value: std::sync::OnceLock<T>,
|
||||
started_initialization: AtomicBool,
|
||||
constructor: Option<fn() -> Result<T, dioxus_core::Error>>,
|
||||
constructor: Option<fn() -> Result<T, CapturedError>>,
|
||||
_phantom: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
@@ -36,7 +37,7 @@ impl<T: Send + Sync + 'static> Lazy<T> {
|
||||
where
|
||||
F: Fn() -> G + Copy,
|
||||
G: Future<Output = Result<T, E>> + Send + 'static,
|
||||
E: Into<dioxus_core::Error>,
|
||||
E: Into<CapturedError>,
|
||||
{
|
||||
if std::mem::size_of::<F>() != 0 {
|
||||
panic!("The constructor function must be a zero-sized type (ZST). Consider using a function pointer or a closure without captured variables.");
|
||||
@@ -57,10 +58,10 @@ impl<T: Send + Sync + 'static> Lazy<T> {
|
||||
///
|
||||
/// This should only be called once during the server setup phase, typically inside `dioxus::serve`.
|
||||
/// Future calls to this method will return an error containing the provided value.
|
||||
pub fn set(&self, pool: T) -> Result<(), dioxus_core::Error> {
|
||||
pub fn set(&self, pool: T) -> Result<(), CapturedError> {
|
||||
let res = self.value.set(pool);
|
||||
if res.is_err() {
|
||||
return Err(anyhow::anyhow!("Lazy value is already initialized."));
|
||||
return Err(anyhow::anyhow!("Lazy value is already initialized.").into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -71,7 +72,7 @@ impl<T: Send + Sync + 'static> Lazy<T> {
|
||||
}
|
||||
|
||||
/// Initialize the value of the `Lazy` instance if it hasn't been initialized yet.
|
||||
pub fn initialize(&self) -> Result<(), dioxus_core::Error> {
|
||||
pub fn initialize(&self) -> Result<(), CapturedError> {
|
||||
if let Some(constructor) = self.constructor {
|
||||
// If we're already initializing this value, wait on the receiver.
|
||||
if self
|
||||
@@ -115,12 +116,12 @@ impl<T: Send + Sync + 'static> std::ops::Deref for Lazy<T> {
|
||||
///
|
||||
/// We call the `rust-call` method of the zero-sized constructor function. This is safe because we're
|
||||
/// not actually dereferencing any unsafe data, just calling its vtable entry to get the future.
|
||||
fn blocking_initialize<T, F, G, E>() -> Result<T, dioxus_core::Error>
|
||||
fn blocking_initialize<T, F, G, E>() -> Result<T, CapturedError>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
F: Fn() -> G + Copy,
|
||||
G: Future<Output = Result<T, E>> + Send + 'static,
|
||||
E: Into<dioxus_core::Error>,
|
||||
E: Into<CapturedError>,
|
||||
{
|
||||
assert_eq!(std::mem::size_of::<F>(), 0, "The constructor function must be a zero-sized type (ZST). Consider using a function pointer or a closure without captured variables.");
|
||||
|
||||
|
||||
@@ -566,6 +566,7 @@ mod resp {
|
||||
|
||||
use super::*;
|
||||
use axum::response::Response;
|
||||
use dioxus_core::CapturedError;
|
||||
use http::HeaderValue;
|
||||
|
||||
/// A trait for converting the result of the Server Function into an Axum response.
|
||||
@@ -661,6 +662,71 @@ mod resp {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> MakeAxumError<CapturedError> for &&ServerFnDecoder<Result<T, CapturedError>> {
|
||||
fn make_axum_error(
|
||||
self,
|
||||
result: Result<Response, CapturedError>,
|
||||
) -> Result<Response, Response> {
|
||||
match result {
|
||||
Ok(res) => Ok(res),
|
||||
|
||||
// Optimize the case where we have sole ownership of the error
|
||||
Err(errr) if errr._strong_count() == 1 => {
|
||||
let err = errr.into_inner().unwrap();
|
||||
<&&ServerFnDecoder<Result<T, anyhow::Error>> as MakeAxumError<anyhow::Error>>::make_axum_error(
|
||||
&&ServerFnDecoder::new(),
|
||||
Err(err),
|
||||
)
|
||||
}
|
||||
|
||||
Err(errr) => {
|
||||
// The `WithHttpError` trait emits ServerFnErrors so we can downcast them here
|
||||
// to create richer responses.
|
||||
let payload = match errr.downcast_ref::<ServerFnError>() {
|
||||
Some(ServerFnError::ServerError {
|
||||
message,
|
||||
code,
|
||||
details,
|
||||
}) => ErrorPayload {
|
||||
message: message.clone(),
|
||||
code: *code,
|
||||
data: details.clone(),
|
||||
},
|
||||
Some(other) => ErrorPayload {
|
||||
message: other.to_string(),
|
||||
code: 500,
|
||||
data: None,
|
||||
},
|
||||
None => match errr.downcast_ref::<HttpError>() {
|
||||
Some(http_err) => ErrorPayload {
|
||||
message: http_err
|
||||
.message
|
||||
.clone()
|
||||
.unwrap_or_else(|| http_err.status.to_string()),
|
||||
code: http_err.status.as_u16(),
|
||||
data: None,
|
||||
},
|
||||
None => ErrorPayload {
|
||||
code: 500,
|
||||
message: errr.to_string(),
|
||||
data: None,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&payload).unwrap();
|
||||
let mut resp = Response::new(body.into());
|
||||
resp.headers_mut().insert(
|
||||
http::header::CONTENT_TYPE,
|
||||
HeaderValue::from_static("application/json"),
|
||||
);
|
||||
*resp.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
Err(resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> MakeAxumError<anyhow::Error> for &&ServerFnDecoder<Result<T, anyhow::Error>> {
|
||||
fn make_axum_error(
|
||||
self,
|
||||
|
||||
@@ -61,7 +61,7 @@ use {
|
||||
pub fn use_websocket<
|
||||
In: 'static,
|
||||
Out: 'static,
|
||||
E: Into<dioxus_core::Error> + 'static,
|
||||
E: Into<CapturedError> + 'static,
|
||||
F: Future<Output = Result<Websocket<In, Out, Enc>, E>> + 'static,
|
||||
Enc: Encoding,
|
||||
>(
|
||||
@@ -72,7 +72,7 @@ pub fn use_websocket<
|
||||
let status_read = use_hook(|| ReadSignal::new(status));
|
||||
|
||||
let connection = use_resource(move || {
|
||||
let connection = connect_to_websocket().map_err(|e| CapturedError::from(e.into()));
|
||||
let connection = connect_to_websocket().map_err(|e| e.into());
|
||||
async move {
|
||||
let connection = connection.await;
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ impl<T, E> std::future::Future for ServerFnRequest<Result<T, E>> {
|
||||
#[diagnostic::on_unimplemented(
|
||||
message = "The return type of a server function must be `Result<T, E>`",
|
||||
note = "`T` is either `impl IntoResponse` *or* `impl Serialize`",
|
||||
note = "`E` is either `From<ServerFnError> + Serialize`, `dioxus::Error` or `StatusCode`."
|
||||
note = "`E` is either `From<ServerFnError> + Serialize`, `dioxus::CapturedError` or `StatusCode`."
|
||||
)]
|
||||
pub trait AssertIsResult {}
|
||||
impl<T, E> AssertIsResult for Result<T, E> {}
|
||||
|
||||
@@ -30,17 +30,18 @@ impl FileData {
|
||||
self.inner.last_modified()
|
||||
}
|
||||
|
||||
pub async fn read_bytes(&self) -> Result<Bytes, dioxus_core::Error> {
|
||||
pub async fn read_bytes(&self) -> Result<Bytes, dioxus_core::CapturedError> {
|
||||
self.inner.read_bytes().await
|
||||
}
|
||||
|
||||
pub async fn read_string(&self) -> Result<String, dioxus_core::Error> {
|
||||
pub async fn read_string(&self) -> Result<String, dioxus_core::CapturedError> {
|
||||
self.inner.read_string().await
|
||||
}
|
||||
|
||||
pub fn byte_stream(
|
||||
&self,
|
||||
) -> Pin<Box<dyn Stream<Item = Result<Bytes, dioxus_core::Error>> + Send + 'static>> {
|
||||
) -> Pin<Box<dyn Stream<Item = Result<Bytes, dioxus_core::CapturedError>> + Send + 'static>>
|
||||
{
|
||||
self.inner.byte_stream()
|
||||
}
|
||||
|
||||
@@ -70,13 +71,19 @@ pub trait NativeFileData: Send + Sync {
|
||||
fn content_type(&self) -> Option<String>;
|
||||
fn read_bytes(
|
||||
&self,
|
||||
) -> Pin<Box<dyn Future<Output = Result<Bytes, dioxus_core::Error>> + 'static>>;
|
||||
) -> Pin<Box<dyn Future<Output = Result<Bytes, dioxus_core::CapturedError>> + 'static>>;
|
||||
fn byte_stream(
|
||||
&self,
|
||||
) -> Pin<Box<dyn futures_util::Stream<Item = Result<Bytes, dioxus_core::Error>> + 'static + Send>>;
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn futures_util::Stream<Item = Result<Bytes, dioxus_core::CapturedError>>
|
||||
+ 'static
|
||||
+ Send,
|
||||
>,
|
||||
>;
|
||||
fn read_string(
|
||||
&self,
|
||||
) -> Pin<Box<dyn Future<Output = Result<String, dioxus_core::Error>> + 'static>>;
|
||||
) -> Pin<Box<dyn Future<Output = Result<String, dioxus_core::CapturedError>> + 'static>>;
|
||||
fn inner(&self) -> &dyn std::any::Any;
|
||||
}
|
||||
|
||||
@@ -143,7 +150,8 @@ mod serialize {
|
||||
|
||||
fn read_bytes(
|
||||
&self,
|
||||
) -> Pin<Box<dyn Future<Output = Result<Bytes, dioxus_core::Error>> + 'static>> {
|
||||
) -> Pin<Box<dyn Future<Output = Result<Bytes, dioxus_core::CapturedError>> + 'static>>
|
||||
{
|
||||
let contents = self.contents.clone();
|
||||
let path = self.path.clone();
|
||||
|
||||
@@ -157,13 +165,16 @@ mod serialize {
|
||||
return Ok(std::fs::read(path).map(Bytes::from)?);
|
||||
}
|
||||
|
||||
Err(dioxus_core::Error::msg("File contents not available"))
|
||||
Err(dioxus_core::CapturedError::msg(
|
||||
"File contents not available",
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
fn read_string(
|
||||
&self,
|
||||
) -> Pin<Box<dyn Future<Output = Result<String, dioxus_core::Error>> + 'static>> {
|
||||
) -> Pin<Box<dyn Future<Output = Result<String, dioxus_core::CapturedError>> + 'static>>
|
||||
{
|
||||
let contents = self.contents.clone();
|
||||
let path = self.path.clone();
|
||||
|
||||
@@ -177,7 +188,9 @@ mod serialize {
|
||||
return Ok(std::fs::read_to_string(path)?);
|
||||
}
|
||||
|
||||
Err(dioxus_core::Error::msg("File contents not available"))
|
||||
Err(dioxus_core::CapturedError::msg(
|
||||
"File contents not available",
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -185,7 +198,9 @@ mod serialize {
|
||||
&self,
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn futures_util::Stream<Item = Result<Bytes, dioxus_core::Error>> + 'static + Send,
|
||||
dyn futures_util::Stream<Item = Result<Bytes, dioxus_core::CapturedError>>
|
||||
+ 'static
|
||||
+ Send,
|
||||
>,
|
||||
> {
|
||||
let contents = self.contents.clone();
|
||||
@@ -201,7 +216,9 @@ mod serialize {
|
||||
return Ok(std::fs::read(path).map(Bytes::from)?);
|
||||
}
|
||||
|
||||
Err(dioxus_core::Error::msg("File contents not available"))
|
||||
Err(dioxus_core::CapturedError::msg(
|
||||
"File contents not available",
|
||||
))
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ impl NativeFileData for WebFileData {
|
||||
|
||||
fn read_bytes(
|
||||
&self,
|
||||
) -> Pin<Box<dyn Future<Output = Result<Bytes, dioxus_core::Error>> + 'static>> {
|
||||
) -> Pin<Box<dyn Future<Output = Result<Bytes, dioxus_core::CapturedError>> + 'static>> {
|
||||
let file_reader = self.reader.clone();
|
||||
let file_reader_ = self.reader.clone();
|
||||
let file = self.file.clone();
|
||||
@@ -72,7 +72,7 @@ impl NativeFileData for WebFileData {
|
||||
|
||||
fn read_string(
|
||||
&self,
|
||||
) -> Pin<Box<dyn Future<Output = Result<String, dioxus_core::Error>> + 'static>> {
|
||||
) -> Pin<Box<dyn Future<Output = Result<String, dioxus_core::CapturedError>> + 'static>> {
|
||||
let file_reader = self.reader.clone();
|
||||
let file_reader_ = self.reader.clone();
|
||||
let file = self.file.clone();
|
||||
@@ -113,8 +113,13 @@ impl NativeFileData for WebFileData {
|
||||
/// We should maybe update these APIs to use our own custom `ByteBuffer` type to avoid going through `Vec<u8>`?
|
||||
fn byte_stream(
|
||||
&self,
|
||||
) -> Pin<Box<dyn futures_util::Stream<Item = Result<Bytes, dioxus_core::Error>> + 'static + Send>>
|
||||
{
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn futures_util::Stream<Item = Result<Bytes, dioxus_core::CapturedError>>
|
||||
+ 'static
|
||||
+ Send,
|
||||
>,
|
||||
> {
|
||||
let file = self.file.dyn_ref::<web_sys::Blob>().unwrap().clone();
|
||||
Box::pin(SendWrapper::new(futures_util::stream::once(async move {
|
||||
let array_buff = wasm_bindgen_futures::JsFuture::from(file.array_buffer())
|
||||
|
||||
Reference in new issue
Block a user