Skip to content

Commit

Permalink
Merge pull request #380 from cunarist/no-unwrap-or-expect
Browse files Browse the repository at this point in the history
Make `get_dart_signal_receiver` return `Result`
  • Loading branch information
temeddix committed Jun 17, 2024
2 parents e2c0e2e + bed667c commit c16674e
Show file tree
Hide file tree
Showing 13 changed files with 189 additions and 145 deletions.
28 changes: 10 additions & 18 deletions documentation/docs/frequently-asked-questions.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,9 @@ There might be various Rust codes with these attribute above:

```rust title="Rust"
#[cfg(target_family = "wasm")]
...
{}
#[cfg(not(target_family = "wasm"))]
...
{}
```

Since the environments of the web and native platforms are so different, there are times when you need to use these attributes to include and exclude parts of the code depending on whether they are targeting web or not.
Expand All @@ -148,6 +148,8 @@ By default, Rust-analyzer runs in native mode. To make it run in webassembly mod
target = "wasm32-unknown-unknown"
```

You need to restart Rust language server for this to take effect.

### CMake cache is broken after I moved the app folder

```title="Output"
Expand All @@ -171,12 +173,9 @@ If you are using older Android versions, you may encounter errors due to issues
To address this, you can modify `AndroidManifest.xml` files under `./android/app/src/` as follows.

```xml title="android/app/src/**/AndroidManifest.xml"
...
<application
android:extractNativeLibs="true"
...
>
...
```

### How can I await a response?
Expand All @@ -188,7 +187,7 @@ However, if you really need to store some state in a Flutter widget, you can ach
```proto title="messages/tutorial_resource.proto"
syntax = "proto3";
package tutorial_resource;
...
// [RINF:DART-SIGNAL]
message MyUniqueInput {
int32 interaction_id = 1;
Expand All @@ -203,29 +202,24 @@ message MyUniqueOutput {
```

```dart title="lib/main.dart"
...
import 'dart:async';
import 'package:example_app/messages/tutorial_resource.pb.dart';
var currentInteractionId = 0;
final myUniqueOutputs = Map<int, Completer<MyUniqueOutput>>();
void main() async {
...
MyUniqueOutput.rustSignalStream.listen((rustSignal) {
final myUniqueInput = rustSignal.message;
myUniqueOutputs[myUniqueInput.interactionId]!.complete(myUniqueInput);
});
...
}
...
```

```dart title="lib/main.dart"
...
import 'dart:async';
import 'package:example_app/messages/tutorial_resource.pb.dart';
...
onPressed: () async {
final completer = Completer<MyUniqueOutput>();
myUniqueOutputs[currentInteractionId] = completer;
Expand All @@ -236,14 +230,13 @@ onPressed: () async {
currentInteractionId += 1;
final myUniqueOutput = await completer.future;
},
...
```

```rust title="native/hub/src/sample_functions.rs"
pub async fn respond() {
pub async fn respond() -> Result<()> {
use messages::tutorial_resource::*;

let mut receiver = MyUniqueInput::get_dart_signal_receiver();
let mut receiver = MyUniqueInput::get_dart_signal_receiver()?;
while let Some(dart_signal) = receiver.recv().await {
let my_unique_input = dart_signal.message;
MyUniqueOutput {
Expand All @@ -252,12 +245,13 @@ pub async fn respond() {
}
.send_signal_to_dart();
}

Ok(())
}
```

```rust title="native/hub/src/lib.rs"
async fn main() {
...
tokio::spawn(sample_functions::respond());
}
```
Expand Down Expand Up @@ -324,9 +318,7 @@ import './messages/generated.dart';
async void main() {
await initializeRust(compiledLibPath: "/path/to/library/libhub.so");
...
}
...
```

This provided path will be used for finding dynamic library files on native platforms with Dart's `DynamicLibrary.open([compiledLibPath])`, and for loading the JavaScript module on the web with `import init, * as wasmBindings from "[compiledLibPath]"`.
3 changes: 1 addition & 2 deletions documentation/docs/graceful-shutdown.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ In some cases, you might need to run some finalization code in Rust before the a
```dart title="lib/main.dart"
import 'dart:ui';
import 'package:flutter/material.dart';
...
class MyApp extends StatefulWidget {
const MyApp({super.key});
Expand Down Expand Up @@ -39,7 +39,6 @@ class _MyAppState extends State<MyApp> {
);
}
}
...
```

It's worth noting that `AppLifecycleListener` or `dispose` cannot always be relied upon for app closings. Below is a text snippet quoted from the official [Flutter docs](https://api.flutter.dev/flutter/widgets/State/dispose.html):
Expand Down
96 changes: 54 additions & 42 deletions documentation/docs/messaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,86 +2,98 @@

There are 2 types of special comments that you can mark messages with.

## 📭 Dart Signal
## 📢 Rust Signal

`[RINF:DART-SIGNAL]` generates a channel from Dart to Rust.
`[RINF:RUST-SIGNAL]` generates a channel from Rust to Dart.

```proto title="Protobuf"
// [RINF:DART-SIGNAL]
message MyDataInput { ... }
// [RINF:RUST-SIGNAL]
message MyDataOutput { ... }
```

```dart title="Dart"
MyDataInput( ... ).sendSignalToRust();
StreamBuilder(
stream: MyDataOutput.rustSignalStream,
builder: (context, snapshot) {
final rustSignal = snapshot.data;
if (rustSignal == null) {
// Return an empty widget.
}
MyDataOutput message = rustSignal.message;
// Return a filled widget.
},
)
```

```rust title="Rust"
let mut receiver = MyDataInput::get_dart_signal_receiver();
while let Some(dart_signal) = receiver.recv().await {
let message: MyDataInput = dart_signal.message;
// Custom Rust logic here
}
MyDataOutput { ... }.send_signal_to_dart();
```

Use `[RINF:DART-SIGNAL-BINARY]` to include binary data without the overhead of serialization.
Use `[RINF:RUST-SIGNAL-BINARY]` to include binary data without the overhead of serialization.

```proto title="Protobuf"
// [RINF:DART-SIGNAL-BINARY]
message MyDataInput { ... }
// [RINF:RUST-SIGNAL-BINARY]
message MyDataOutput { ... }
```

```dart title="Dart"
final binary = Uint8List(64);
MyDataInput( ... ).sendSignalToRust(binary);
StreamBuilder(
stream: MyDataOutput.rustSignalStream,
builder: (context, snapshot) {
final rustSignal = snapshot.data;
if (rustSignal == null) {
// Return an empty widget.
}
MyDataOutput message = rustSignal.message;
Uint8List binary = rustSignal.binary;
// Return a filled widget.
},
)
```

```rust title="Rust"
let mut receiver = MyDataInput::get_dart_signal_receiver();
while let Some(dart_signal) = receiver.recv().await {
let message: MyDataInput = dart_signal.message;
let binary: Vec<u8> = dart_signal.binary;
// Custom Rust logic here
}
let binary: Vec<u8> = vec![0; 64];
MyDataOutput { ... }.send_signal_to_dart(binary);
```

## 📢 Rust Signal
## 📭 Dart Signal

`[RINF:RUST-SIGNAL]` generates a channel from Rust to Dart.
`[RINF:DART-SIGNAL]` generates a channel from Dart to Rust.

```proto title="Protobuf"
// [RINF:RUST-SIGNAL]
message MyDataOutput { ... }
// [RINF:DART-SIGNAL]
message MyDataInput { ... }
```

```dart title="Dart"
final stream = MyDataOutput.rustSignalStream;
await for (final rustSignal in stream) {
MyDataOutput message = rustSignal.message;
// Custom Dart logic here
}
MyDataInput( ... ).sendSignalToRust();
```

```rust title="Rust"
MyDataOutput { ... }.send_signal_to_dart();
let mut receiver = MyDataInput::get_dart_signal_receiver()?;
while let Some(dart_signal) = receiver.recv().await {
let message: MyDataInput = dart_signal.message;
// Custom Rust logic here
}
```

Use `[RINF:RUST-SIGNAL-BINARY]` to include binary data without the overhead of serialization.
Use `[RINF:DART-SIGNAL-BINARY]` to include binary data without the overhead of serialization.

```proto title="Protobuf"
// [RINF:RUST-SIGNAL-BINARY]
message MyDataOutput { ... }
// [RINF:DART-SIGNAL-BINARY]
message MyDataInput { ... }
```

```dart title="Dart"
final stream = MyDataOutput.rustSignalStream;
await for (final rustSignal in stream) {
MyDataOutput message = rustSignal.message;
Uint8List binary = rustSignal.binary;
// Custom Dart logic here
}
final binary = Uint8List(64);
MyDataInput( ... ).sendSignalToRust(binary);
```

```rust title="Rust"
let binary: Vec<u8> = vec![0; 64];
MyDataOutput { ... }.send_signal_to_dart(binary);
let mut receiver = MyDataInput::get_dart_signal_receiver()?;
while let Some(dart_signal) = receiver.recv().await {
let message: MyDataInput = dart_signal.message;
let binary: Vec<u8> = dart_signal.binary;
// Custom Rust logic here
}
```
Loading

0 comments on commit c16674e

Please sign in to comment.