Skip to content

Commit

Permalink
feat: move all public bounds into traits except spawn
Browse files Browse the repository at this point in the history
  • Loading branch information
c-git committed Jan 5, 2025
1 parent d4405c6 commit d4776f6
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 18 deletions.
1 change: 0 additions & 1 deletion src/data_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use thiserror::Error;
use tracing::{error, warn};

/// Provides a common way to specify the bounds errors are expected to meet
/// (note it is compatible with anyhow::Error)
pub trait ErrorBounds: Display + Send + Sync + 'static {}
impl<T: Display + Send + Sync + 'static> ErrorBounds for T {}

Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,13 @@

mod data_state;
mod platform;
mod traits;
#[cfg(feature = "yield_now")]
mod yield_;

pub use data_state::{Awaiting, DataState, DataStateError, ErrorBounds};
pub use platform::{fetch, fetch_plus, spawn};
pub use traits::{BoundedFuture, DoneHandler, ResponseHandler, UiCallBack, ValidReturn};
#[cfg(feature = "yield_now")]
pub use yield_::yield_now;

Expand Down
16 changes: 7 additions & 9 deletions src/platform.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
//! Stores the wrapper functions that can be called from either native or wasm
//! code
use std::{fmt::Debug, future::Future};
use tracing::error;

#[cfg(not(target_arch = "wasm32"))]
mod native;
#[cfg(target_arch = "wasm32")]
mod wasm;

// Using * imports to bring them up to this level
use crate::{BoundedFuture, ResponseHandler, UiCallBack, ValidReturn};
#[cfg(not(target_arch = "wasm32"))]
pub use native::*;
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -43,20 +42,19 @@ pub fn fetch_plus<FResponseHandler, FNotify, Fut, Ret>(
req: reqwest::RequestBuilder,
response_handler: FResponseHandler,
ui_notify: FNotify,
) -> crate::oneshot::Receiver<anyhow::Result<Ret>>
) -> crate::oneshot::Receiver<Ret>
where
FResponseHandler: FnOnce(reqwest::Result<reqwest::Response>) -> Fut + Send + 'static,
Fut: Future<Output = anyhow::Result<Ret>> + Send,
Ret: Send + 'static,
Fut::Output: Debug,
FNotify: FnOnce() + Send + 'static,
FResponseHandler: ResponseHandler<Fut, Ret>,
Fut: BoundedFuture<Ret>,
Ret: ValidReturn,
FNotify: UiCallBack,
{
let (tx, rx) = crate::oneshot::channel();
let on_done = move |resp: reqwest::Result<reqwest::Response>| async {
let output = response_handler(resp).await;
match tx.send(output) {
Ok(()) => {}
Err(handler_output) => error!(?handler_output, "failed to send output from handler"),
Err(_output) => error!("failed to send output from handler"),
};
ui_notify();
};
Expand Down
19 changes: 11 additions & 8 deletions src/platform/native.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
//! Stores the code specific to native compilations
// but the comments are for both because these are the ones that show on docs.rs

use crate::{BoundedFuture, DoneHandler};

#[cfg(not(feature = "native-tokio"))]
compile_error!("Must chose a native runtime by enabling a feature flag. Right now only tokio is supported. If you have a different runtime that you want please create an issue on github.");

/// Performs a HTTP requests and calls the given callback when done with the
/// result of the request. This is a more flexible API but requires more
/// boilerplate, see [fetch_plus] which wraps a lot more of the boilerplate
/// especially if you need a "wake_up" function. NB: Needs to use a callback to
/// prevent blocking on the thread that initiates the fetch. Note: Instead of
/// calling get like in the example you can use post, put, etc. (See
/// [reqwest::Client]). Also see the examples
/// boilerplate, see [fetch_plus][crate::fetch_plus] which wraps a lot more of
/// the boilerplate especially if you need a "wake_up" function. NB: Needs to
/// use a callback to prevent blocking on the thread that initiates the fetch.
/// Note: Instead of calling get like in the example you can use post, put, etc.
/// (See [reqwest::Client]). Also see the examples
/// [folder](https://github.com/c-git/reqwest-cross/tree/main/examples)
/// for more complete examples.
///
Expand Down Expand Up @@ -40,8 +42,8 @@ compile_error!("Must chose a native runtime by enabling a feature flag. Right no
/// ```
pub fn fetch<F, O>(request: reqwest::RequestBuilder, on_done: F)
where
F: 'static + Send + FnOnce(reqwest::Result<reqwest::Response>) -> O,
O: futures::Future<Output = ()> + Send,
F: DoneHandler<O>,
O: BoundedFuture<()>,
{
let future = async move {
let result = request.send().await;
Expand All @@ -50,7 +52,8 @@ where
spawn(future);
}

/// Spawns a future on the underlying runtime in a cross platform way
/// Spawns a future on the underlying runtime in a cross platform way (NB: the
/// Send bound is removed in WASM)
#[cfg(feature = "native-tokio")]
pub fn spawn<F>(future: F)
where
Expand Down
29 changes: 29 additions & 0 deletions src/traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//! Provides an easy way for calling functions to reuse bounds of public
//! functions except [spawn][crate::spawn] for which I couldn't foresee the use
//! case. If you have a use case reach out, don't mind adding it if it adds
//! value. All these traits come with automatic impls so they are automatically
//! implemented for any function that meets the bounds functions that are
//! conditionally compiled by target
// Unable to actually include this text for docs.rs because when this module is

// public the traits it includes do not show up as Traits at the top level of
// the crate.

#[cfg(not(target_arch = "wasm32"))]
mod native;
#[cfg(target_arch = "wasm32")]
mod wasm;

#[cfg(not(target_arch = "wasm32"))]
pub use native::*;
#[cfg(target_arch = "wasm32")]
pub use wasm::*;

/// A function able to be used as a Call Back to notify the UI that the request
/// is ready
pub trait UiCallBack: 'static + Send + FnOnce() {}
impl<T> UiCallBack for T where T: 'static + Send + FnOnce() {}

/// Allowed return types
pub trait ValidReturn: Send + 'static {}
impl<T: Send + 'static> ValidReturn for T {}
33 changes: 33 additions & 0 deletions src/traits/native.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use std::future::Future;

/// An async func that accepts a [reqwest::Response]
/// and returns a generic value
pub trait ResponseHandler<Fut, O>:
Send + 'static + FnOnce(reqwest::Result<reqwest::Response>) -> Fut
where
Fut: BoundedFuture<O>,
{
}
impl<T, Fut, O> ResponseHandler<Fut, O> for T
where
T: Send + 'static + FnOnce(reqwest::Result<reqwest::Response>) -> Fut,
Fut: BoundedFuture<O>,
{
}

/// A function that receives the [reqwest::Response]
/// and returns it to the application via some means (See examples for way it
/// can be done)
pub trait DoneHandler<O>: 'static + Send + FnOnce(reqwest::Result<reqwest::Response>) -> O
where
O: BoundedFuture<()>,
{
}
impl<T, O: BoundedFuture<()>> DoneHandler<O> for T where
T: 'static + Send + FnOnce(reqwest::Result<reqwest::Response>) -> O
{
}

/// A future with the required bounds for the platform
pub trait BoundedFuture<O>: Future<Output = O> + Send {}
impl<T, O> BoundedFuture<O> for T where T: Future<Output = O> + Send {}
30 changes: 30 additions & 0 deletions src/traits/wasm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use std::future::Future;

/// dox
pub trait ResponseHandler<Fut, O>:
'static + FnOnce(reqwest::Result<reqwest::Response>) -> Fut
where
Fut: BoundedFuture<O>,
{
}
impl<T, Fut, O> ResponseHandler<Fut, O> for T
where
T: 'static + FnOnce(reqwest::Result<reqwest::Response>) -> Fut,
Fut: BoundedFuture<O>,
{
}

/// dox
pub trait BoundedFuture<O>: Future<Output = O> {}
impl<T, O> BoundedFuture<O> for T where T: Future<Output = O> {}

/// dox
pub trait DoneHandler<O>: 'static + FnOnce(reqwest::Result<reqwest::Response>) -> O
where
O: BoundedFuture<()>,
{
}
impl<T, O: BoundedFuture<()>> DoneHandler<O> for T where
T: 'static + FnOnce(reqwest::Result<reqwest::Response>) -> O
{
}

0 comments on commit d4776f6

Please sign in to comment.