Skip to main content

flutter_rust_bridge/handler/
handler.rs

1use crate::codec::sse::Dart2RustMessageSse;
2use crate::codec::BaseCodec;
3use crate::codec::Rust2DartMessageTrait;
4use crate::platform_types::DartAbi;
5use crate::platform_types::MessagePort;
6use std::future::Future;
7
8/// Provide your own handler to customize how to execute your function calls, etc.
9///
10/// This API is not guaranteed to be stable following semver (since things are going to be
11/// added, and for every addition/change, it is a breaking change for this trait).
12pub trait Handler {
13    /// Prepares the arguments, executes a Rust function and sets up its return value.
14    ///
15    /// Why separate `PrepareFn` and `TaskFn`: because some things cannot be [`Send`] (e.g. raw
16    /// pointers), so those can be done in `PrepareFn`, while the real work is done in `TaskFn` with [`Send`].
17    ///
18    /// The generated code depends on the fact that `PrepareFn` is synchronous to maintain
19    /// correctness, therefore implementors of [`Handler`] must also uphold this property.
20    ///
21    /// If a Rust function is marked `sync`, it must be called with
22    /// [`wrap_sync`](Handler::wrap_sync) instead.
23    #[cfg(feature = "thread-pool")]
24    fn wrap_normal<Rust2DartCodec, PrepareFn, TaskFn>(
25        &self,
26        task_info: TaskInfo,
27        prepare: PrepareFn,
28    ) where
29        PrepareFn: FnOnce() -> TaskFn,
30        TaskFn: FnOnce(TaskContext) -> Result<Rust2DartCodec::Message, Rust2DartCodec::Message>
31            + Send
32            + 'static,
33        Rust2DartCodec: BaseCodec;
34
35    /// Same as [`wrap`][Handler::wrap], but the Rust function will be called synchronously and
36    /// need not implement [Send].
37    fn wrap_sync<Rust2DartCodec, SyncTaskFn>(
38        &self,
39        task_info: TaskInfo,
40        sync_task: SyncTaskFn,
41    ) -> <Rust2DartCodec::Message as Rust2DartMessageTrait>::WireSyncRust2DartType
42    where
43        SyncTaskFn: FnOnce() -> Result<Rust2DartCodec::Message, Rust2DartCodec::Message>,
44        Rust2DartCodec: BaseCodec;
45
46    /// Same as [`wrap`][Handler::wrap], but for async Rust.
47    #[cfg(feature = "rust-async")]
48    fn wrap_async<Rust2DartCodec, PrepareFn, TaskFn, TaskRetFut>(
49        &self,
50        task_info: TaskInfo,
51        prepare: PrepareFn,
52    ) where
53        PrepareFn: FnOnce() -> TaskFn,
54        TaskFn: FnOnce(TaskContext) -> TaskRetFut + Send + 'static,
55        TaskRetFut: Future<Output = Result<Rust2DartCodec::Message, Rust2DartCodec::Message>>
56            + TaskRetFutTrait,
57        Rust2DartCodec: BaseCodec;
58
59    #[cfg(all(feature = "rust-async", feature = "dart-opaque"))]
60    fn dart_fn_invoke(
61        &self,
62        dart_fn: crate::dart_opaque::DartOpaque,
63        args: Vec<DartAbi>,
64    ) -> crate::dart_fn::DartFnFuture<Dart2RustMessageSse>;
65
66    #[cfg(all(feature = "rust-async", feature = "dart-opaque"))]
67    fn dart_fn_handle_output(&self, call_id: i32, message: Dart2RustMessageSse);
68}
69
70/// Supporting information for a task
71#[derive(Clone)]
72pub struct TaskInfo {
73    /// A Dart `SendPort`. [None] if the mode is [FfiCallMode::Sync].
74    pub port: Option<MessagePort>,
75    /// Usually the name of the function.
76    pub debug_name: &'static str,
77    /// The call mode of this function.
78    pub mode: FfiCallMode,
79}
80
81/// The types of return values for a particular Rust function.
82#[derive(Copy, Clone, PartialEq, Eq)]
83pub enum FfiCallMode {
84    /// The default mode, returns a Dart `Future<T>`.
85    Normal,
86    /// Used by `SyncReturn<T>` to skip spawning workers.
87    Sync,
88}
89
90#[cfg(not(target_family = "wasm"))]
91pub trait TaskRetFutTrait: Send {}
92#[cfg(not(target_family = "wasm"))]
93impl<T: Send> TaskRetFutTrait for T {}
94
95#[cfg(target_family = "wasm")]
96pub trait TaskRetFutTrait {}
97#[cfg(target_family = "wasm")]
98impl<T> TaskRetFutTrait for T {}
99
100// Originally there were things for StreamSink, but it was moved, so now it is empty
101/// A context for task execution
102pub struct TaskContext {}
103
104// frb-coverage:ignore-start
105impl Default for TaskContext {
106    fn default() -> Self {
107        Self::new()
108    }
109}
110// frb-coverage:ignore-end
111
112impl TaskContext {
113    pub fn new() -> Self {
114        Self {}
115    }
116}