Skip to content

Commit

Permalink
all: feat async and memory safe high level API
Browse files Browse the repository at this point in the history
Async Communication

- posting messages to dart via isolate via response channel on dart side
- response channel provides useful error for dangling replies
- rwlock to protect Store access
- including store.runLocked convenience Dart function
- timeout warn logs for msg calls

Memory Safe API

- pointers wrap `RawStruct` Dart classes which have a safer `Struct`
  version returned via safer API
- including rid widget helpers in generated code
- derive DartObject implementation for all `rid::model`s and `rid::store`s
- dart class includes equality operators and `toString`
- rendering `toDart` method for disposable vec
- store lock/unlock is logged on Dart end

Macros

- added store, related trait and message reply
- requiring that #[rid::store] struct be named 'Store'
- adding RidStore trait making it easier to implement needed Store
  methods
- `rid::model` detects `Debug` and `Clone`, debug is exposed to Dart for
  structs and enums

Added Type Support

- `Option<T>` return type represented as `T?` on Dart end
- bool args handled correctly
- rewriting binding.h to work around ffigen issues with type aliases
- Enums are converted to Dart with same name as they had in Rust, args
  and returned enums now have same type

Fixes

- fix hot restart

Examples

- clock example to demonstrate threading
- todo example adapted to latest API

Closes: #3
Closes: #2
  • Loading branch information
thlorenz committed Jul 5, 2021
1 parent 1b0214c commit 0a5f33a
Show file tree
Hide file tree
Showing 162 changed files with 7,554 additions and 2,032 deletions.
98 changes: 5 additions & 93 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ members=[
"rid-ffi",
"rid-macro",
"rid-macro-impl",
"examples/dart/todo"
]
exclude = [
"examples/dart/clock",
"examples/dart/todo",
"examples/dart/wip",
]

[dependencies]
Expand Down
18 changes: 18 additions & 0 deletions examples/dart/clock/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
lib/generated/*

**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
**/generated_plugin_registrant.dart
.packages
.pub-cache/
.pub/
build/
flutter_*.png
linked_*.ds
unlinked.ds
unlinked_spec.ds

target/
Cargo.lock
23 changes: 23 additions & 0 deletions examples/dart/clock/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "clock"
version = "0.1.0"
authors = ["Thorsten Lorenz <[email protected]>"]
edition = "2018"

[lib]
name = "clock"
crate-type = ["cdylib"]
path = "src/lib.rs"
doctest = false
test = false

[[bin]]
name = "rid_build"
path = "rid_build.rs"

[dependencies]
rid = { path = "../../../" }
rid_build = { path = "../../../rid-build" }

[build-dependencies]
rid_build = { path = "../../../rid-build" }
67 changes: 67 additions & 0 deletions examples/dart/clock/lib/keyboard_handler.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import 'dart:io';

import 'package:clock/generated/rid_generated.dart';
import 'package:clock/stop_watch.dart';

class KeyboardHandler {
final StopWatch stopWatch;
final Store store;

KeyboardHandler(this.store, this.stopWatch);

printStatus() {
print('${store.raw.debug(true)}');
}

void printCommands() {
print("\nPlease select one of the below:\n");
print(" a -- to start clock");
print(" o -- to stop clock");
print(" r -- to reset clock");
print(" q -- to quit");
}

Future<bool> handleCommand(String cmd) async {
switch (cmd) {
case "a":
await stopWatch.startTimer();
break;
case "o":
await stopWatch.stopTimer();
break;
case "r":
await stopWatch.resetTimer();
break;
case "q":
return false;
default:
print("\nUnknown command '$cmd'\n");
return false;
}
return true;
}

void resetScreen() {
print("\x1B[2J\x1B[0;0H");
printStatus();
printCommands();
stdout.write("\n> ");
}

void start() async {
resetScreen();
replyChannel.stream.where((res) => res.type == Reply.Tick).listen((_) {
ridStoreLock();
resetScreen();
ridStoreUnlock();
});
stdin.listen((bytes) async {
final cmd = String.fromCharCode(bytes.first);
final ok = await handleCommand(cmd);
if (!ok || cmd == "q") {
exit(0);
}
resetScreen();
});
}
}
13 changes: 13 additions & 0 deletions examples/dart/clock/lib/main.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'dart:async';

import 'package:clock/generated/rid_generated.dart';
import 'package:clock/keyboard_handler.dart';
import 'package:clock/stop_watch.dart';

Future<void> main() async {
final store = Store.instance;
final stopWatch = StopWatch(store);
final handler = new KeyboardHandler(store, stopWatch);
handler.start();
print("Waiting for the response, but life goes on\n");
}
22 changes: 22 additions & 0 deletions examples/dart/clock/lib/stop_watch.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import 'package:clock/generated/rid_generated.dart';

class StopWatch {
final Store store;

StopWatch(this.store);

Future<void> startTimer() async {
final res = await store.msgStart();
print('$res');
}

Future<void> stopTimer() async {
final res = await store.msgStop();
print('$res');
}

Future<void> resetTimer() async {
final res = await store.msgReset();
print('$res');
}
}
Loading

0 comments on commit 0a5f33a

Please sign in to comment.