Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slim bridge code #199

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,14 @@ use std::panic::{RefUnwindSafe, UnwindSafe};

use crate::bridge::bridge_engine::ffi::{IntoDart, MessagePort};

use crate::bridge::bridge_engine::rust2dart::{IntoIntoDart, Rust2Dart, TaskCallback};
use crate::bridge::bridge_engine::support::WireSyncReturn;
use crate::bridge::bridge_engine::SyncReturn;
use crate::bridge::bridge_engine::rust_to_dart::{IntoIntoDart, Rust2Dart, TaskCallback};
use crate::spawn_bridge_task;

/// The types of return values for a particular Rust function.
#[derive(Copy, Clone)]
pub enum FfiCallMode {
/// The default mode, returns a Dart `Future<T>`.
Normal,
/// Used by `SyncReturn<T>` to skip spawning workers.
Sync,
/// Returns a Dart `Stream<T>`.
Stream,
}
Expand All @@ -41,26 +37,12 @@ pub trait Handler {
///
/// The generated code depends on the fact that `PrepareFn` is synchronous to maintain
/// correctness, therefore implementors of [`Handler`] must also uphold this property.
///
/// If a Rust function returns [`SyncReturn`], it must be called with
/// [`wrap_sync`](Handler::wrap_sync) instead.
fn wrap<PrepareFn, TaskFn, TaskRet, D>(&self, wrap_info: WrapInfo, prepare: PrepareFn)
where
PrepareFn: FnOnce() -> TaskFn + UnwindSafe,
TaskFn: FnOnce(TaskCallback) -> Result<TaskRet, BridgeError> + Send + UnwindSafe + 'static,
TaskRet: IntoIntoDart<D>,
D: IntoDart;

/// Same as [`wrap`][Handler::wrap], but the Rust function must return a [SyncReturn] and
/// need not implement [Send].
fn wrap_sync<SyncTaskFn, TaskRet>(
&self,
wrap_info: WrapInfo,
sync_task: SyncTaskFn,
) -> WireSyncReturn
where
SyncTaskFn: FnOnce() -> Result<SyncReturn<TaskRet>, BridgeError> + UnwindSafe,
TaskRet: IntoDart;
}

/// The simple handler uses a simple thread pool to execute tasks.
Expand Down Expand Up @@ -119,34 +101,6 @@ impl<E: Executor, EH: ErrorHandler> Handler for SimpleHandler<E, EH> {
}
});
}

fn wrap_sync<SyncTaskFn, TaskRet>(
&self,
wrap_info: WrapInfo,
sync_task: SyncTaskFn,
) -> WireSyncReturn
where
TaskRet: IntoDart,
SyncTaskFn: FnOnce() -> Result<SyncReturn<TaskRet>, BridgeError> + UnwindSafe,
{
// NOTE This extra [catch_unwind] **SHOULD** be put outside **ALL** code!
// For reason, see comments in [wrap]
panic::catch_unwind(move || {
let catch_unwind_result = panic::catch_unwind(move || {
match self.executor.execute_sync(wrap_info, sync_task) {
Ok(data) => wire_sync_from_data(data.0, true),
Err(_err) => self
.error_handler
.handle_error_sync(BridgeError::ResultError),
}
});
catch_unwind_result.unwrap_or_else(|error| {
self.error_handler
.handle_error_sync(BridgeError::Panic(error))
})
})
.unwrap_or_else(|_| wire_sync_from_data(None::<()>, false))
}
}

/// An executor model for Rust functions.
Expand All @@ -161,16 +115,6 @@ pub trait Executor: RefUnwindSafe {
TaskFn: FnOnce(TaskCallback) -> Result<TaskRet, BridgeError> + Send + UnwindSafe + 'static,
TaskRet: IntoIntoDart<D>,
D: IntoDart;

/// Executes a Rust function that returns a [SyncReturn].
fn execute_sync<SyncTaskFn, TaskRet>(
&self,
wrap_info: WrapInfo,
sync_task: SyncTaskFn,
) -> Result<SyncReturn<TaskRet>, BridgeError>
where
SyncTaskFn: FnOnce() -> Result<SyncReturn<TaskRet>, BridgeError> + UnwindSafe,
TaskRet: IntoDart;
}

/// The default executor used.
Expand Down Expand Up @@ -215,9 +159,6 @@ impl<EH: ErrorHandler> Executor for BridgeTaskExecutor<EH> {
FfiCallMode::Stream => {
// nothing - ignore the return value of a Stream-typed function
}
FfiCallMode::Sync => {
panic!("FfiCallMode::Sync should not call execute, please call execute_sync instead")
}
}
}
Err(_error) => {
Expand All @@ -231,18 +172,6 @@ impl<EH: ErrorHandler> Executor for BridgeTaskExecutor<EH> {
}
});
}

fn execute_sync<SyncTaskFn, TaskRet>(
&self,
_wrap_info: WrapInfo,
sync_task: SyncTaskFn,
) -> Result<SyncReturn<TaskRet>, BridgeError>
where
SyncTaskFn: FnOnce() -> Result<SyncReturn<TaskRet>, BridgeError> + UnwindSafe,
TaskRet: IntoDart,
{
sync_task()
}
}

/// Errors that occur from normal code execution.
Expand Down Expand Up @@ -286,9 +215,6 @@ impl BridgeError {
pub trait ErrorHandler: UnwindSafe + RefUnwindSafe + Copy + Send + 'static {
/// The default error handler.
fn handle_error(&self, port: MessagePort, error: BridgeError);

/// Special handler only used for synchronous code.
fn handle_error_sync(&self, error: BridgeError) -> WireSyncReturn;
}

/// The default error handler used by generated code.
Expand All @@ -299,18 +225,4 @@ impl ErrorHandler for ReportDartErrorHandler {
fn handle_error(&self, port: MessagePort, error: BridgeError) {
Rust2Dart::new(port).error(error.code().to_string(), error.message());
}

fn handle_error_sync(&self, error: BridgeError) -> WireSyncReturn {
wire_sync_from_data(format!("{}: {}", error.code(), error.message()), false)
}
}

fn wire_sync_from_data<T: IntoDart>(data: T, success: bool) -> WireSyncReturn {
let sync_return = vec![data.into_dart(), success.into_dart()].into_dart();

#[cfg(not(target_family = "wasm"))]
return crate::bridge::bridge_engine::support::new_leak_box_ptr(sync_return);

#[cfg(target_family = "wasm")]
return sync_return;
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
use std::panic::{RefUnwindSafe, UnwindSafe};

pub use handler::{FfiCallMode, Handler, WrapInfo};
pub use rust2dart::StreamSink;
pub use rust_to_dart::StreamSink;
pub mod ffi;
pub use ffi::*;
pub mod handler;
mod into_into_dart;
mod macros;
pub mod rust2dart;
pub mod rust_to_dart;
pub mod support;

#[cfg(target_family = "wasm")]
pub mod wasm_bindgen_src;

/// Use this struct in return type of your function, in order to tell the code generator
/// the function should return synchronously. Otherwise, it is by default asynchronously.
pub struct SyncReturn<T>(pub T);

/// Marker trait for types that are safe to share with Dart and can be dropped
/// safely in case of a panic.
pub trait DartSafe: UnwindSafe + RefUnwindSafe {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,3 @@ pub fn slice_from_byte_buffer<T: bytemuck::Pod>(buffer: Vec<u8>) -> Box<[T]> {
}
}
}

#[cfg(not(target_family = "wasm"))]
use allo_isolate::ffi::DartCObject;

#[cfg(not(target_family = "wasm"))]
pub type WireSyncReturn = *mut DartCObject;

#[cfg(target_family = "wasm")]
pub type WireSyncReturn = wasm_bindgen::JsValue;
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,3 @@ impl Default for wire_RustRequestUnique {
Self::new_with_null_ptr()
}
}

// Section: sync execution mode utility

#[no_mangle]
pub extern "C" fn free_WireSyncReturn(ptr: support::WireSyncReturn) {
unsafe {
let _ = support::box_from_leak_ptr(ptr);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// Generated by flutter_rust_bridge_codegen@ 1.80.1.

use crate::bridge::api::*;
use crate::bridge::bridge_engine::rust2dart::IntoIntoDart;
use crate::bridge::bridge_engine::rust_to_dart::IntoIntoDart;
use crate::bridge::bridge_engine::*;
use core::panic::UnwindSafe;
use std::ffi::c_void;
Expand Down Expand Up @@ -186,7 +186,7 @@ impl support::IntoDart for RustResponse {
}
}
impl support::IntoDartExceptPrimitive for RustResponse {}
impl rust2dart::IntoIntoDart<RustResponse> for RustResponse {
impl rust_to_dart::IntoIntoDart<RustResponse> for RustResponse {
fn into_into_dart(self) -> Self {
self
}
Expand All @@ -202,7 +202,7 @@ impl support::IntoDart for RustResponseUnique {
}
}
impl support::IntoDartExceptPrimitive for RustResponseUnique {}
impl rust2dart::IntoIntoDart<RustResponseUnique> for RustResponseUnique {
impl rust_to_dart::IntoIntoDart<RustResponseUnique> for RustResponseUnique {
fn into_into_dart(self) -> Self {
self
}
Expand All @@ -219,7 +219,7 @@ impl support::IntoDart for RustSignal {
}
}
impl support::IntoDartExceptPrimitive for RustSignal {}
impl rust2dart::IntoIntoDart<RustSignal> for RustSignal {
impl rust_to_dart::IntoIntoDart<RustSignal> for RustSignal {
fn into_into_dart(self) -> Self {
self
}
Expand Down
2 changes: 1 addition & 1 deletion flutter_ffi_plugin/lib/src/bridge_engine/basic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class _DropIdPortGenerator {
String create() => '__frb_dart_opaque_drop_${nextPort++}';
}

/// Base class for generated bindings of Flutter Rust Bridge.
/// Base class for generated bindings of the bridge.
/// Normally, users do not extend this class manually. Instead,
/// users should directly use the generated class.
abstract class FlutterRustBridgeBase<T extends FlutterRustBridgeWireBase> {
Expand Down