support sync and async on flowy-sys & add dart-ffi

This commit is contained in:
appflowy 2021-06-28 22:56:15 +08:00
parent 42b8add240
commit 8d2bdf1149
38 changed files with 360 additions and 2106 deletions

View File

@ -7,6 +7,8 @@
<sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-derive/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-sys/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-sys/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/rust-lib/dart-ffi/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-sdk/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/.pub" />
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/build" />

View File

@ -44,7 +44,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/async-2.6.1/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/async-2.5.0-nullsafety.3/lib" />
</list>
</value>
</entry>
@ -59,7 +58,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0-nullsafety.3/lib" />
</list>
</value>
</entry>
@ -131,7 +129,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0-nullsafety.5/lib" />
</list>
</value>
</entry>
@ -139,7 +136,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.2.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.2.0-nullsafety.3/lib" />
</list>
</value>
</entry>
@ -161,7 +157,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0-nullsafety.3/lib" />
</list>
</value>
</entry>
@ -177,7 +172,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0-nullsafety.5/lib" />
</list>
</value>
</entry>
@ -229,7 +223,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0-nullsafety.3/lib" />
</list>
</value>
</entry>
@ -255,7 +248,6 @@
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/fixnum-1.0.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/fixnum-0.10.11/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/fixnum-1.0.0-nullsafety.0/lib" />
</list>
</value>
</entry>
@ -422,7 +414,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10-nullsafety.3/lib" />
</list>
</value>
</entry>
@ -430,7 +421,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.3.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.3.0-nullsafety.6/lib" />
</list>
</value>
</entry>
@ -460,7 +450,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/path-1.8.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/path-1.8.0-nullsafety.3/lib" />
</list>
</value>
</entry>
@ -540,7 +529,6 @@
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/protobuf-2.0.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/protobuf-1.1.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/protobuf-2.0.0-nullsafety.1/lib" />
</list>
</value>
</entry>
@ -606,7 +594,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.1/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.0-nullsafety.4/lib" />
</list>
</value>
</entry>
@ -614,7 +601,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0-nullsafety.6/lib" />
</list>
</value>
</entry>
@ -622,7 +608,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0-nullsafety.3/lib" />
</list>
</value>
</entry>
@ -637,7 +622,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0-nullsafety.3/lib" />
</list>
</value>
</entry>
@ -652,7 +636,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0-nullsafety.3/lib" />
</list>
</value>
</entry>
@ -660,7 +643,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.3.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.2.19-nullsafety.6/lib" />
</list>
</value>
</entry>
@ -690,7 +672,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0-nullsafety.5/lib" />
</list>
</value>
</entry>
@ -705,7 +686,6 @@
<value>
<list>
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0/lib" />
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0-nullsafety.5/lib" />
</list>
</value>
</entry>
@ -778,10 +758,8 @@
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/archive-3.1.2/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/args-1.6.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/args-2.1.1/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/async-2.5.0-nullsafety.3/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/async-2.6.1/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/bloc-7.0.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0-nullsafety.3/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/build-2.0.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/build-2.0.2/lib" />
@ -799,17 +777,13 @@
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/built_collection-5.1.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/built_value-7.1.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/built_value-8.1.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0-nullsafety.5/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.2.0-nullsafety.3/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.2.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/checked_yaml-2.0.1/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/cli_util-0.3.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0-nullsafety.3/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/code_builder-3.6.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/code_builder-4.0.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0-nullsafety.5/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/convert-3.0.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/crypto-3.0.1/lib" />
@ -819,7 +793,6 @@
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/dart_style-2.0.1/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/dartz-0.10.0-nullsafety.2/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/equatable-2.0.3/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0-nullsafety.3/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/ffi-1.0.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/ffi-1.1.2/lib" />
@ -827,7 +800,6 @@
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/file-6.1.1/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/file-6.1.2/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/fixnum-0.10.11/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/fixnum-1.0.0-nullsafety.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/fixnum-1.0.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/flutter_bloc-7.0.1/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/flutter_lints-1.0.3/lib" />
@ -851,15 +823,12 @@
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/lints-1.0.1/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/logger-1.0.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/logging-1.0.1/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10-nullsafety.3/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.3.0-nullsafety.6/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.3.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/mime-0.9.7/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/mime-1.0.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/nested-1.0.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/package_config-2.0.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/path-1.8.0-nullsafety.3/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/path-1.8.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-2.0.0/lib" />
@ -873,7 +842,6 @@
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/pool-1.5.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/process-4.2.1/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/protobuf-1.1.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/protobuf-2.0.0-nullsafety.1/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/protobuf-2.0.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/provider-5.0.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/pub_semver-2.0.0/lib" />
@ -884,28 +852,20 @@
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/shelf_web_socket-0.2.3/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/shelf_web_socket-1.0.1/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/source_gen-1.0.2/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.0-nullsafety.4/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.1/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0-nullsafety.6/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0-nullsafety.3/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/stream_transform-2.0.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0-nullsafety.3/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/sync_http-0.3.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0-nullsafety.3/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.2.19-nullsafety.6/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.3.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/textstyle_extensions-2.0.0-nullsafety/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/time-2.0.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/timing-0.1.1+3/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/timing-1.0.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0-nullsafety.5/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/uuid-3.0.4/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0-nullsafety.5/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/vm_service-6.2.0/lib" />
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/watcher-1.0.0/lib" />

75
Makefile.toml Normal file
View File

@ -0,0 +1,75 @@
extend = [
{ path = "scripts/makefile/desktop.toml" },
]
[env]
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
CARGO_MAKE_CRATE_NAME = "dart-ffi"
DEV = true
LIB_OUT_DIR = "debug"
RELEASE = false
TARGET_OS = "unknown"
[tasks.setup-crate-type]
private = true
script = [
"""
toml = readfile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml
crate_type = set ""
os = get_env TARGET_OS
is_android = eq ${os} "android"
is_ios = eq ${os} "ios"
is_macos = eq ${os} "macos"
is_pad = eq ${os} "pad"
if ${is_android}
crate_type = set "cdylib"
elseif ${is_ios}
crate_type = set "staticlib"
elseif ${is_macos}
crate_type = set "cdylib"
elseif ${is_pad}
crate_type = set "cdylib"
else
crate_type = set "rlib"
end
val = replace ${toml} "rlib" ${crate_type}
result = writefile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml ${val}
assert ${result}
""",
]
script_runner = "@duckscript"
[tasks.restore-crate-type]
private = true
script = [
"""
toml = readfile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml
crate_type = set ""
os = get_env TARGET_OS
is_android = eq ${os} "android"
is_ios = eq ${os} "ios"
is_macos = eq ${os} "macos"
is_pad = eq ${os} "pad"
if ${is_android}
crate_type = set "cdylib"
elseif ${is_ios}
crate_type = set "staticlib"
elseif ${is_macos}
crate_type = set "cdylib"
elseif ${is_pad}
crate_type = set "cdylib"
else
crate_type = set "rlib"
end
val = replace ${toml} ${crate_type} "rlib"
result = writefile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml ${val}
assert ${result}
""",
]
script_runner = "@duckscript"

View File

@ -24,7 +24,7 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/window_size/macos
SPEC CHECKSUMS:
flowy_sdk: 12d2c047ed260a0aa8788a0b9616da46e2312025
flowy_sdk: c302ac0a22dea596db0df8073b9637b2bf2ff6fd
FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424
path_provider_macos: a0a3fd666cb7cd0448e936fb4abad4052961002b
window_size: 339dafa0b27a95a62a843042038fa6c3c48de195

View File

@ -20,5 +20,5 @@ A new flutter plugin project.
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
s.swift_version = '5.0'
s.vendored_libraries = "libflowy_ffi.dylib"
s.vendored_libraries = "libdart_ffi.dylib"
end

File diff suppressed because it is too large Load Diff

View File

@ -1,55 +0,0 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_protobuf/remote.dart';
import 'package:infra/uuid.dart';
import 'dart:typed_data';
import 'package:flowy_protobuf/all.dart';
import 'util.dart';
part 'auto_gen.dart';
class FlowyError {
late StatusCode _statusCode;
late String _error;
late bool _has_error;
StatusCode get statusCode {
return _statusCode;
}
String get error {
return _error;
}
bool get has_error {
return _has_error;
}
String toString() {
return "$_statusCode: $_error";
}
@override
bool operator ==(other) {
if (other is FlowyError) {
return (this.statusCode == other.statusCode &&
this._error == other._error);
} else {
return false;
}
}
FlowyError({required StatusCode statusCode, required String error}) {
_statusCode = statusCode;
_error = error;
_has_error = true;
}
factory FlowyError.from(ResponsePacket resp) {
return FlowyError(statusCode: resp.statusCode, error: resp.err)
.._has_error = resp.hasErr();
}
factory FlowyError.fromError(String error, StatusCode statusCode) {
return FlowyError(statusCode: statusCode, error: error);
}
}

View File

@ -1,77 +0,0 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_protobuf/remote.dart';
// ignore: import_of_legacy_library_into_null_safe
import 'package:protobuf/protobuf.dart';
import 'package:flowy_sdk/ffi/adaptor.dart';
import 'dart:typed_data';
import 'package:flowy_logger/flowy_logger.dart';
Either<Uint8List, String> protobufToBytes<T extends GeneratedMessage>(
T? message) {
try {
if (message != null) {
return left(message.writeToBuffer());
} else {
return left(Uint8List.fromList([]));
}
} catch (e, s) {
return right(
'FlowyFFI syncRequest error: ${e.runtimeType}. Stack trace: $s');
}
}
Future<ResponsePacket> asyncCommand(RequestPacket request) {
try {
return FFIAdaptor.asyncRequest(request).future.then((value) {
try {
final resp = ResponsePacket.fromBuffer(value);
return Future.microtask(() => resp);
} catch (e, s) {
Log.error('FlowyFFI asyncRequest error: ${e.runtimeType}\n');
Log.error('Stack trace \n $s');
final resp = responseFromRequest(
request, "FlowyFFI asyncRequest error: ${e.runtimeType}");
return Future.microtask(() => resp);
}
});
} catch (e, s) {
Log.error('FlowyFFI asyncRequest error: ${e.runtimeType}\n');
Log.error('Stack trace \n $s');
final resp = responseFromRequest(
request, "FlowyFFI asyncRequest error: ${e.runtimeType}");
return Future.microtask(() => resp);
}
}
Future<ResponsePacket> asyncQuery(RequestPacket request) {
try {
return FFIAdaptor.asyncQuery(request).future.then((value) {
try {
final resp = ResponsePacket.fromBuffer(value);
return Future.microtask(() => resp);
} catch (e, s) {
Log.error('FlowyFFI asyncRequest error: ${e.runtimeType}\n');
Log.error('Stack trace \n $s');
final resp = responseFromRequest(
request, "FlowyFFI asyncRequest error: ${e.runtimeType}");
return Future.microtask(() => resp);
}
});
} catch (e, s) {
Log.error('FlowyFFI asyncRequest error: ${e.runtimeType}\n');
Log.error('Stack trace \n $s');
final resp = responseFromRequest(
request, "FlowyFFI asyncRequest error: ${e.runtimeType}");
return Future.microtask(() => resp);
}
}
ResponsePacket responseFromRequest(RequestPacket request, String message) {
var resp = ResponsePacket();
resp.id = request.id;
resp.statusCode = StatusCode.Fail;
resp.command = request.command;
resp.err = message;
return resp;
}

View File

@ -42,88 +42,5 @@ class FFIAdaptor {
return completer;
}
static Completer<Uint8List> asyncQuery(RequestPacket request) {
Uint8List bytes = request.writeToBuffer();
assert(bytes.isEmpty == false);
if (bytes.isEmpty) {
throw FFIAdaptorException(FFIExceptionType.RequestPacketIsEmpty);
}
final Pointer<Uint8> input = calloc.allocate<Uint8>(bytes.length);
final list = input.asTypedList(bytes.length);
list.setAll(0, bytes);
final completer = Completer<Uint8List>();
final port = singleCompletePort(completer);
ffi.async_query(port.nativePort, input, bytes.length);
calloc.free(input);
return completer;
}
//https://suragch.medium.com/working-with-bytes-in-dart-6ece83455721
static FFISafeUint8Wrapper syncRequest(RequestPacket request) {
Uint8List bytes;
try {
bytes = request.writeToBuffer();
} catch (e, s) {
//TODO nathan: upload the log
print('Sync RequestPacket writeToBuffer error: ${e.runtimeType}');
print('Stack trace \n $s');
rethrow;
}
assert(bytes.isEmpty == false);
if (bytes.isEmpty) {
throw FFIAdaptorException(FFIExceptionType.RequestPacketIsEmpty);
}
final Pointer<Uint8> dartPtr = _pointerFromBytes(bytes);
Pointer<Uint8> rustPtr = ffi.sync_command(dartPtr, bytes.length);
calloc.free(dartPtr);
FFISafeUint8Wrapper safeWrapper;
try {
safeWrapper = FFISafeUint8Wrapper(rustPtr);
} catch (_) {
rethrow;
}
return safeWrapper;
}
// inline?
static Pointer<Uint8> _pointerFromBytes(Uint8List bytes) {
final Pointer<Uint8> ptr = calloc.allocate<Uint8>(bytes.length);
final list = ptr.asTypedList(bytes.length);
list.setAll(0, bytes);
return ptr;
}
}
class FFISafeUint8Wrapper {
Pointer<Uint8> _ptr;
int _responseBytesLen = 0;
int _markerBytesLen = 4;
FFISafeUint8Wrapper(this._ptr) {
try {
this._responseBytesLen =
ByteData.sublistView(_ptr.asTypedList(_markerBytesLen))
.getUint32(0, Endian.big);
} catch (_) {
throw FFIAdaptorException(FFIExceptionType.RequestPacketIsEmpty);
}
if (this._responseBytesLen < _markerBytesLen) {
throw FFIAdaptorException(FFIExceptionType.ResponsePacketIsInvalid);
}
}
void destroy() {
ffi.free_rust(_ptr, _responseBytesLen + _markerBytesLen);
}
Uint8List buffer() {
Pointer<Uint8> respPtr = _ptr.elementAt(_markerBytesLen);
return respPtr.asTypedList(_responseBytesLen);
}
}

View File

@ -1,4 +1,4 @@
/// bindings for `libflowy_ffi`
/// bindings for `libdart_ffi`
import 'dart:ffi';
import 'dart:io';
@ -14,9 +14,9 @@ final DynamicLibrary dl = _dl;
DynamicLibrary _open() {
if (is_tester()) {
return DynamicLibrary.open(
'${Directory.systemTemp.path}/app_flowy/libflowy_ffi.dylib');
'${Directory.systemTemp.path}/app_flowy/libdart_ffi.dylib');
} else {
if (Platform.isAndroid) return DynamicLibrary.open('libflowy_ffi.so');
if (Platform.isAndroid) return DynamicLibrary.open('libdart_ffi.so');
if (Platform.isMacOS) return DynamicLibrary.executable();
if (Platform.isIOS) return DynamicLibrary.executable();
throw UnsupportedError('This platform is not supported.');
@ -45,92 +45,6 @@ typedef _invoke_async_Dart = void Function(
int len,
);
/// C function `command_sync`.
Pointer<Uint8> sync_command(
Pointer<Uint8> input,
int len,
) {
return _invoke_sync(input, len);
}
final _invoke_sync_Dart _invoke_sync =
_dl.lookupFunction<_invoke_sync_C, _invoke_sync_Dart>('sync_command');
typedef _invoke_sync_C = Pointer<Uint8> Function(
Pointer<Uint8> input,
Uint64 len,
);
typedef _invoke_sync_Dart = Pointer<Uint8> Function(
Pointer<Uint8> input,
int len,
);
/// C function `async_query`.
void async_query(
int port,
Pointer<Uint8> input,
int len,
) {
_invoke_async_query(port, input, len);
}
final _invoke_async_query_Dart _invoke_async_query =
_dl.lookupFunction<_invoke_async_query_C, _invoke_async_query_Dart>(
'async_query');
typedef _invoke_async_query_C = Void Function(
Int64 port,
Pointer<Uint8> input,
Uint64 len,
);
typedef _invoke_async_query_Dart = void Function(
int port,
Pointer<Uint8> input,
int len,
);
/// C function `free_rust`.
void free_rust(
Pointer<Uint8> input,
int len,
) {
_free_rust(input, len);
}
final _free_rust_Dart _free_rust =
_dl.lookupFunction<_free_rust_C, _free_rust_Dart>('free_rust');
typedef _free_rust_C = Void Function(
Pointer<Uint8> input,
Uint64 len,
);
typedef _free_rust_Dart = void Function(
Pointer<Uint8> input,
int len,
);
/// C function `init_stream`.
int init_stream(int port) {
return _init_stream(port);
}
final _init_stream_Dart _init_stream =
_dl.lookupFunction<_init_stream_C, _init_stream_Dart>('init_stream');
typedef _init_stream_C = Int32 Function(
Int64 port,
);
typedef _init_stream_Dart = int Function(
int port,
);
/// C function `init_logger`.
int init_logger() {
return _init_logger();
}
final _init_logger_Dart _init_logger =
_dl.lookupFunction<_init_logger_C, _init_logger_Dart>('init_logger');
typedef _init_logger_C = Int64 Function();
typedef _init_logger_Dart = int Function();
/// C function `init_sdk`.
int init_sdk(
Pointer<ffi.Utf8> path,
@ -174,22 +88,6 @@ typedef _store_dart_post_cobject_Dart = void Function(
Pointer<NativeFunction<Int8 Function(Int64, Pointer<Dart_CObject>)>> ptr,
);
/// C function `setup_logger`.
void setup_logger(
Pointer ptr,
) {
_setup_logger(ptr);
}
final _setup_logger_Dart _setup_logger =
_dl.lookupFunction<_setup_logger_C, _setup_logger_Dart>('setup_logger');
typedef _setup_logger_C = Void Function(
Pointer ptr,
);
typedef _setup_logger_Dart = void Function(
Pointer ptr,
);
bool is_tester() {
if (Foundation.kDebugMode) {
// ignore: unnecessary_null_comparison

View File

@ -1,54 +0,0 @@
import 'dart:isolate';
import 'dart:async';
import 'dart:typed_data';
import 'dart:ffi';
import 'package:flowy_logger/flowy_logger.dart';
import 'package:flowy_protobuf/model/observable.pb.dart';
typedef ObserverCallback = void Function(ObservableSubject observable);
class R2FStream {
static R2FStream shared = R2FStream._internal();
late RawReceivePort _ffiPort;
late StreamController<Uint8List> _streamController;
late StreamController<ObservableSubject> _observableController;
late StreamSubscription<Uint8List> _ffiSubscription;
int get port => _ffiPort.sendPort.nativePort;
StreamController<ObservableSubject> get observable => _observableController;
R2FStream._internal() {
_ffiPort = RawReceivePort();
_streamController = StreamController();
_observableController = StreamController.broadcast();
_ffiPort.handler = _streamController.add;
_ffiSubscription = _streamController.stream.listen(streamCallback);
}
factory R2FStream() {
return shared;
}
static listen(void Function(ObservableSubject subject) callback) {
R2FStream.shared.observable.stream.listen(callback);
}
void streamCallback(Uint8List bytes) {
try {
final observable = ObservableSubject.fromBuffer(bytes);
_observableController.add(observable);
} catch (e, s) {
Log.error('FFIStream handleReceviedBytes error: ${e.runtimeType}');
Log.error('Stack trace \n $s');
rethrow;
}
}
Future<void> dispose() async {
await _ffiSubscription.cancel();
await _streamController.close();
await _observableController.close();
_ffiPort.close();
}
}

View File

@ -1,11 +1,9 @@
export 'cqrs/cqrs.dart';
export 'package:async/async.dart';
import 'dart:io';
import 'dart:async';
import 'package:flutter/services.dart';
import 'dart:ffi';
import 'ffi/rust_to_flutter_stream.dart';
import 'ffi/ffi.dart' as ffi;
import 'package:ffi/ffi.dart';
@ -19,16 +17,11 @@ class FlowySDK {
const FlowySDK();
void dispose() {
R2FStream.shared.dispose();
}
Future<void> init(Directory sdkDir) async {
final port = R2FStream.shared.port;
ffi.init_stream(port);
ffi.init_logger();
ffi.store_dart_post_cobject(NativeApi.postCObject);
print("Application document directory: ${sdkDir.absolute}");
ffi.init_sdk(sdkDir.path.toNativeUtf8());
}
}

View File

@ -3,20 +3,9 @@
#include <stdint.h>
#include <stdlib.h>
int64_t init_logger();
int64_t init_sdk(char *path);
int32_t init_stream(int64_t port);
void async_command(int64_t port, const uint8_t *input, uintptr_t len);
void async_query(int64_t port, const uint8_t *input, uintptr_t len);
const uint8_t *sync_command(const uint8_t *input, uintptr_t len);
void free_rust(
uint8_t *ptr,
uint32_t length);
void link_me_please(void);

View File

@ -20,5 +20,5 @@ A new flutter plugin project.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
s.swift_version = '5.0'
# s.static_framework = true
s.vendored_libraries = "libflowy_ffi.dylib"
s.vendored_libraries = "libdart_ffi.dylib"
end

View File

@ -1,6 +1,8 @@
[workspace]
members = [
"flowy-sys",
"flowy-sdk",
"dart-ffi",
]
[profile.dev]

View File

@ -0,0 +1,27 @@
[package]
name = "dart-ffi"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "dart_ffi"
# this value will change depending on the target os
# for iOS it would be `rlib`
# for Macos it would be `rlib`
# for android it would be `c-dylib`
# default rlib
crate-type = ["rlib"]
[dependencies]
allo-isolate = {version = "^0.1", features = ["catch-unwind",]}
byteorder = {version = "1.3.4"}
ffi-support = {version = "0.4.2"}
protobuf = {version = "2.20.0"}
lazy_static = {version = "1.4.0"}
tokio = { version = "1", features = ["sync"] }
log = "0.4.14"
flowy-sys = {path = "../flowy-sys"}
flowy-sdk = {path = "../flowy-sdk"}

View File

@ -0,0 +1,11 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
int64_t init_sdk(char *path);
void async_command(int64_t port, const uint8_t *input, uintptr_t len);
void link_me_please(void);

View File

@ -0,0 +1,46 @@
use flowy_sys::prelude::*;
use std::{cell::RefCell, ffi::CStr, os::raw::c_char};
#[no_mangle]
pub extern "C" fn init_sdk(path: *mut c_char) -> i64 {
let c_str: &CStr = unsafe { CStr::from_ptr(path) };
let path: &str = c_str.to_str().unwrap();
println!("{}", path);
return 1;
}
#[no_mangle]
pub extern "C" fn async_command(port: i64, input: *const u8, len: usize) {
let bytes = unsafe { std::slice::from_raw_parts(input, len) }.to_vec();
let request = EventRequest::from_data(bytes);
let stream_data = StreamData::new(port, Some(request)).with_callback(Box::new(|_config, response| {
log::info!("async resp: {:?}", response);
}));
async_send(stream_data);
}
#[inline(never)]
#[no_mangle]
pub extern "C" fn link_me_please() {}
thread_local!(
static STREAM_SENDER: RefCell<Option<CommandStream<i64>>> = RefCell::new(None);
);
pub fn sync_send(data: StreamData<i64>) -> EventResponse {
STREAM_SENDER.with(|cell| match &*cell.borrow() {
Some(stream) => stream.sync_send(data),
None => panic!(""),
})
}
pub fn async_send(data: StreamData<i64>) {
STREAM_SENDER.with(|cell| match &*cell.borrow() {
Some(stream) => {
stream.async_send(data);
},
None => panic!(""),
});
}

View File

@ -0,0 +1,8 @@
[package]
name = "flowy-sdk"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@ -0,0 +1 @@

View File

@ -13,7 +13,7 @@ futures-channel = "0.3.15"
futures = "0.3.15"
futures-util = "0.3.15"
bytes = "0.5"
tokio = { version = "1", features = ["sync"] }
tokio = { version = "1", features = ["full"] }
uuid = { version = "0.8", features = ["serde", "v4"] }
log = "0.4.14"
env_logger = "0.8"
@ -21,17 +21,9 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_with = "1.9.4"
thread-id = "3.3.0"
#optional crate
allo-isolate = {version = "^0.1", features = ["catch-unwind",], optional = true}
byteorder = {version = "1.3.4", optional = true}
ffi-support = {version = "0.4.2", optional = true}
protobuf = {version = "2.20.0", optional = true}
lazy_static = {version = "1.4.0", optional = true}
lazy_static = "1.4.0"
dyn-clone = "1.0"
[dev-dependencies]
tokio = { version = "1", features = ["full"] }
futures-util = "0.3.15"
[features]
dart_ffi = ["ffi-support", "allo-isolate", "byteorder", "protobuf", "lazy_static"]

View File

@ -1,93 +0,0 @@
use crate::{
module::Module,
request::EventRequest,
response::EventResponse,
rt::SystemCommand,
stream::*,
system::FlowySystem,
};
use futures_core::ready;
use lazy_static::lazy_static;
use protobuf::Message;
use std::{
cell::RefCell,
future::Future,
sync::{Arc, RwLock},
task::Context,
};
use tokio::{
macros::support::{Pin, Poll},
sync::{mpsc::UnboundedSender, oneshot},
};
#[no_mangle]
pub extern "C" fn async_command(port: i64, input: *const u8, len: usize) {
let bytes = unsafe { std::slice::from_raw_parts(input, len) }.to_vec();
let request = EventRequest::from_data(bytes);
let stream_data = StreamData::new(port, Some(request), Box::new(|port, response| {}));
send(stream_data);
}
#[no_mangle]
pub extern "C" fn free_rust(ptr: *mut u8, length: u32) { reclaim_rust(ptr, length) }
#[no_mangle]
pub extern "C" fn init_stream(port: i64) -> i32 { return 0; }
#[allow(unused_attributes)]
pub fn reclaim_rust(ptr: *mut u8, length: u32) {
unsafe {
let len: usize = length as usize;
Vec::from_raw_parts(ptr, len, len);
}
}
thread_local!(
static STREAM_SENDER: RefCell<Option<UnboundedSender<StreamData<i64>>>> = RefCell::new(None);
);
pub fn send(data: StreamData<i64>) {
STREAM_SENDER.with(|cell| match &*cell.borrow() {
Some(tx) => {
tx.send(data);
},
None => panic!(""),
});
}
pub fn init_dart<F>(modules: Vec<Module>, f: F)
where
F: FnOnce() + 'static,
{
let mut stream = CommandStream::<i64>::new();
let stream = CommandStream::<i64>::new();
let tx = stream.tx();
STREAM_SENDER.with(|cell| {
*cell.borrow_mut() = Some(tx);
});
FlowySystem::construct(|| modules, stream)
.spawn(async { f() })
.run()
.unwrap();
// FlowySystem::construct(|| modules, stream)
// .spawn(async move {
// let request = EventRequest::new("1".to_string());
// let stream_data = StreamData::new(
// 1,
// Some(request),
// Box::new(|config, response| {
// log::info!("😁{:?}", response);
// }),
// );
//
// send(stream_data);
//
// FlowySystem::current().stop();
// })
// .run()
// .unwrap();
}

View File

@ -1,4 +0,0 @@
#[cfg(feature = "dart_ffi")]
mod ffi;
pub use ffi::*;

View File

@ -2,19 +2,23 @@ use crate::{
request::EventRequest,
response::{EventResponse, EventResponseBuilder, StatusCode},
};
use dyn_clone::DynClone;
use std::{fmt, option::NoneError};
use tokio::sync::mpsc::error::SendError;
pub trait Error: fmt::Debug + fmt::Display {
pub trait Error: fmt::Debug + fmt::Display + DynClone {
fn status_code(&self) -> StatusCode;
fn as_response(&self) -> EventResponse { EventResponse::new(self.status_code()) }
}
dyn_clone::clone_trait_object!(Error);
impl<T: Error + 'static> From<T> for SystemError {
fn from(err: T) -> SystemError { SystemError { inner: Box::new(err) } }
}
#[derive(Clone)]
pub struct SystemError {
inner: Box<dyn Error>,
}
@ -37,15 +41,13 @@ impl std::error::Error for SystemError {
fn cause(&self) -> Option<&dyn std::error::Error> { None }
}
impl<T> From<SendError<T>> for SystemError
where
T: fmt::Display + fmt::Debug + 'static,
{
fn from(err: SendError<T>) -> Self { InternalError { inner: err }.into() }
}
impl From<SendError<EventRequest>> for SystemError {
fn from(err: SendError<EventRequest>) -> Self { InternalError { inner: err }.into() }
fn from(err: SendError<EventRequest>) -> Self {
InternalError {
inner: format!("{}", err),
}
.into()
}
}
impl From<NoneError> for SystemError {
@ -61,31 +63,32 @@ impl From<SystemError> for EventResponse {
fn from(err: SystemError) -> Self { err.inner_error().as_response() }
}
pub struct InternalError<T> {
#[derive(Clone)]
pub struct InternalError<T: Clone> {
inner: T,
}
impl<T> InternalError<T> {
impl<T: Clone> InternalError<T> {
pub fn new(inner: T) -> Self { InternalError { inner } }
}
impl<T> fmt::Debug for InternalError<T>
where
T: fmt::Debug + 'static,
T: fmt::Debug + 'static + Clone,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.inner, f) }
}
impl<T> fmt::Display for InternalError<T>
where
T: fmt::Display + 'static,
T: fmt::Debug + fmt::Display + 'static + Clone,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.inner, f) }
}
impl<T> Error for InternalError<T>
where
T: fmt::Debug + fmt::Display + 'static,
T: fmt::Debug + fmt::Display + 'static + Clone,
{
fn status_code(&self) -> StatusCode { StatusCode::Err }

View File

@ -11,7 +11,6 @@ use crate::{
error::InternalError,
request::{payload::Payload, EventRequest},
response::EventResponse,
rt::SystemCommand,
service::{factory, BoxServiceFactory, HandlerService},
};
use futures_core::{future::LocalBoxFuture, ready};
@ -21,7 +20,6 @@ use std::{
future::Future,
pin::Pin,
rc::Rc,
sync::Arc,
task::{Context, Poll},
};
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};

View File

@ -31,7 +31,7 @@ impl EventRequest {
pub fn get_id(&self) -> &str { &self.id }
pub fn from_data(data: Vec<u8>) -> Self { unimplemented!() }
pub fn from_data(_data: Vec<u8>) -> Self { unimplemented!() }
}
pub trait FromRequest: Sized {

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use std::{fmt, fmt::Formatter};
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum ResponseData {
Bytes(Vec<u8>),
None,

View File

@ -14,7 +14,7 @@ pub enum StatusCode {
}
// serde user guide: https://serde.rs/field-attrs.html
#[derive(Serialize, Debug)]
#[derive(Serialize, Debug, Clone)]
pub struct EventResponse {
#[serde(serialize_with = "serialize_data")]
pub data: ResponseData,

View File

@ -1,5 +1,4 @@
pub use runtime::*;
pub use crate::system::*;
mod runtime;
pub mod runtime;

View File

@ -1,18 +1,39 @@
use crate::{
error::{InternalError, SystemError},
module::{Event, Module},
request::EventRequest,
response::EventResponse,
service::{BoxService, Service, ServiceFactory},
system::ModuleServiceMap,
system::ModuleMap,
};
use futures_core::{future::LocalBoxFuture, ready, task::Context};
use std::{collections::HashMap, future::Future, rc::Rc};
use std::future::Future;
use tokio::{
macros::support::{Pin, Poll},
sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
};
macro_rules! service_factor_impl {
($name:ident) => {
#[allow(non_snake_case, missing_docs)]
impl<T> ServiceFactory<StreamData<T>> for $name<T>
where
T: 'static,
{
type Response = EventResponse;
type Error = SystemError;
type Service = BoxService<StreamData<T>, Self::Response, Self::Error>;
type Config = ();
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
fn new_service(&self, _cfg: Self::Config) -> Self::Future {
let module_map = self.module_map.clone();
let service = Box::new(CommandStreamService { module_map });
Box::pin(async move { Ok(service as Self::Service) })
}
}
};
}
pub type BoxStreamCallback<T> = Box<dyn FnOnce(T, EventResponse) + 'static + Send + Sync>;
pub struct StreamData<T>
where
@ -20,46 +41,75 @@ where
{
config: T,
request: Option<EventRequest>,
callback: BoxStreamCallback<T>,
callback: Option<BoxStreamCallback<T>>,
}
impl<T> StreamData<T> {
pub fn new(config: T, request: Option<EventRequest>, callback: BoxStreamCallback<T>) -> Self {
pub fn new(config: T, request: Option<EventRequest>) -> Self {
Self {
config,
request,
callback,
callback: None,
}
}
pub fn with_callback(mut self, callback: BoxStreamCallback<T>) -> Self {
self.callback = Some(callback);
self
}
}
pub struct CommandStream<T>
where
T: 'static,
{
module_map: Option<ModuleServiceMap>,
module_map: ModuleMap,
data_tx: UnboundedSender<StreamData<T>>,
data_rx: Option<UnboundedReceiver<StreamData<T>>>,
}
service_factor_impl!(CommandStream);
impl<T> CommandStream<T> {
pub fn new(module_map: ModuleMap) -> Self {
let (data_tx, data_rx) = unbounded_channel::<StreamData<T>>();
Self {
module_map,
data_tx,
data_rx: Some(data_rx),
}
}
pub fn async_send(&self, data: StreamData<T>) { let _ = self.data_tx.send(data); }
pub fn sync_send(&self, data: StreamData<T>) -> EventResponse {
let factory = self.new_service(());
futures::executor::block_on(async {
let service = factory.await.unwrap();
service.call(data).await.unwrap()
})
}
pub fn tx(&self) -> UnboundedSender<StreamData<T>> { self.data_tx.clone() }
pub fn take_data_rx(&mut self) -> UnboundedReceiver<StreamData<T>> { self.data_rx.take().unwrap() }
}
pub struct CommandStreamFuture<T: 'static> {
module_map: ModuleMap,
data_rx: UnboundedReceiver<StreamData<T>>,
}
impl<T> CommandStream<T> {
pub fn new() -> Self {
let (data_tx, data_rx) = unbounded_channel::<StreamData<T>>();
Self {
module_map: None,
data_tx,
data_rx,
service_factor_impl!(CommandStreamFuture);
impl<T: 'static> CommandStreamFuture<T> {
pub fn new(module_map: ModuleMap, data_rx: UnboundedReceiver<StreamData<T>>) -> Self {
Self { module_map, data_rx }
}
}
pub fn send(&self, data: StreamData<T>) { let _ = self.data_tx.send(data); }
pub fn module_service_map(&mut self, map: ModuleServiceMap) { self.module_map = Some(map) }
pub fn tx(&self) -> UnboundedSender<StreamData<T>> { self.data_tx.clone() }
}
impl<T> Future for CommandStream<T>
impl<T> Future for CommandStreamFuture<T>
where
T: 'static,
{
@ -80,41 +130,20 @@ where
}
}
impl<T> ServiceFactory<StreamData<T>> for CommandStream<T>
where
T: 'static,
{
type Response = ();
type Error = SystemError;
type Service = BoxService<StreamData<T>, Self::Response, Self::Error>;
type Config = ();
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
fn new_service(&self, _cfg: Self::Config) -> Self::Future {
let module_map = self.module_map.as_ref().unwrap().clone();
let service = Box::new(CommandStreamService { module_map });
Box::pin(async move { Ok(service as Self::Service) })
}
}
pub struct CommandStreamService {
module_map: ModuleServiceMap,
module_map: ModuleMap,
}
impl<T> Service<StreamData<T>> for CommandStreamService
where
T: 'static,
{
type Response = ();
impl<T: 'static> Service<StreamData<T>> for CommandStreamService {
type Response = EventResponse;
type Error = SystemError;
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
fn call(&self, mut data: StreamData<T>) -> Self::Future {
let module_map = self.module_map.clone();
let fut = async move {
let request = data.request.take().unwrap();
let result = || async {
let fut = async move {
let result = {
match module_map.get(request.get_event()) {
Some(module) => {
let config = request.get_id().to_owned();
@ -129,12 +158,12 @@ where
}
};
match result().await {
Ok(resp) => (data.callback)(data.config, resp),
Err(e) => log::error!("{:?}", e),
let response = result.unwrap_or_else(|e| e.into());
if let Some(callback) = data.callback {
callback(data.config, response.clone());
}
Ok(())
Ok(response)
};
Box::pin(fut)
}

View File

@ -1,10 +1,7 @@
use crate::{
error::SystemError,
module::{Event, Module},
request::EventRequest,
response::EventResponse,
rt::Runtime,
stream::{CommandStream, CommandStreamService, StreamData},
stream::CommandStreamFuture,
};
use futures_core::{ready, task::Context};
use std::{cell::RefCell, collections::HashMap, future::Future, io, rc::Rc, sync::Arc};
@ -23,19 +20,19 @@ thread_local!(
#[derive(Debug)]
pub enum SystemCommand {
Exit(i8),
Response(EventResponse),
}
pub type ModuleServiceMap = Rc<HashMap<Event, Rc<Module>>>;
pub type ModuleMap = Rc<HashMap<Event, Rc<Module>>>;
pub struct FlowySystem {
sys_cmd_tx: UnboundedSender<SystemCommand>,
module_map: ModuleServiceMap,
}
impl FlowySystem {
pub fn construct<F, T>(module_factory: F, mut stream: CommandStream<T>) -> SystemRunner
pub fn construct<F, S, T>(module_factory: F, stream_factory: S) -> SystemRunner
where
F: FnOnce() -> Vec<Module>,
S: FnOnce(ModuleMap) -> CommandStreamFuture<T>,
T: 'static,
{
let runtime = Runtime::new().unwrap();
let (sys_cmd_tx, sys_cmd_rx) = unbounded_channel::<SystemCommand>();
@ -47,25 +44,18 @@ impl FlowySystem {
});
let factory = module_factory();
let mut module_service_map = HashMap::new();
let mut module_map = HashMap::new();
factory.into_iter().for_each(|m| {
let events = m.events();
let rc_module = Rc::new(m);
events.into_iter().for_each(|e| {
module_service_map.insert(e, rc_module.clone());
module_map.insert(e, rc_module.clone());
});
});
let mut system = Self {
sys_cmd_tx: sys_cmd_tx.clone(),
module_map: Rc::new(HashMap::default()),
};
let map = Rc::new(module_service_map);
system.module_map = map.clone();
stream.module_service_map(map.clone());
runtime.spawn(stream);
let system = Self { sys_cmd_tx };
let stream_fut = stream_factory(Rc::new(module_map));
runtime.spawn(stream_fut);
FlowySystem::set_current(system);
let runner = SystemRunner { rt: runtime, stop_rx };
@ -81,8 +71,6 @@ impl FlowySystem {
}
}
pub fn module_map(&self) -> ModuleServiceMap { self.module_map.clone() }
#[doc(hidden)]
pub fn set_current(sys: FlowySystem) {
CURRENT.with(|cell| {
@ -115,9 +103,6 @@ impl Future for SystemController {
let _ = tx.send(code);
}
},
SystemCommand::Response(resp) => {
log::debug!("Response: {:?}", resp);
},
},
}
}

View File

@ -1,34 +0,0 @@
use crate::helper::*;
use flowy_sys::{dart_ffi::*, prelude::*};
pub async fn no_params() -> String { "no params function call".to_string() }
pub async fn one_params(_s: String) -> String { "one params function call".to_string() }
pub async fn two_params(_s1: String, _s2: String) -> String { "two params function call".to_string() }
#[test]
fn test_init() {
setup_env();
let no_params_command = "no params".to_string();
let one_params_command = "one params".to_string();
let two_params_command = "two params".to_string();
let modules = vec![Module::new()
.event(no_params_command.clone(), no_params)
.event(one_params_command.clone(), one_params)
.event(two_params_command.clone(), two_params)];
init_dart(modules, || {
let request = EventRequest::new(no_params_command);
let stream_data = StreamData::new(
1,
Some(request),
Box::new(|config, response| {
log::info!("😁😁😁 {:?}", response);
}),
);
send(stream_data);
FlowySystem::current().stop();
});
}

View File

@ -1,10 +1,15 @@
use std::sync::Once;
use flowy_sys::prelude::{CommandStream, CommandStreamFuture, EventResponse, FlowySystem, Module, StreamData};
use std::{
cell::RefCell,
sync::{Once, RwLock},
task::Context,
};
#[allow(dead_code)]
pub fn setup_env() {
static INIT: Once = Once::new();
INIT.call_once(|| {
std::env::set_var("RUST_LOG", "flowy_sys=trace,trace");
std::env::set_var("RUST_LOG", "flowy_sys=debug,debug");
env_logger::init();
});
}
@ -14,3 +19,47 @@ pub struct ExecutorAction {
}
pub struct FlowySystemExecutor {}
thread_local!(
static STREAM_SENDER: RefCell<Option<CommandStream<i64>>> = RefCell::new(None);
);
pub fn sync_send(data: StreamData<i64>) -> EventResponse {
STREAM_SENDER.with(|cell| match &*cell.borrow() {
Some(stream) => stream.sync_send(data),
None => panic!(""),
})
}
pub fn async_send(data: StreamData<i64>) {
STREAM_SENDER.with(|cell| match &*cell.borrow() {
Some(stream) => {
stream.async_send(data);
},
None => panic!(""),
});
}
pub fn stop_system() { FlowySystem::current().stop(); }
pub fn init_system<F>(modules: Vec<Module>, f: F)
where
F: FnOnce() + 'static,
{
FlowySystem::construct(
|| modules,
|module_map| {
let mut stream = CommandStream::<i64>::new(module_map.clone());
let stream_fut = CommandStreamFuture::new(module_map, stream.take_data_rx());
STREAM_SENDER.with(|cell| {
*cell.borrow_mut() = Some(stream);
});
stream_fut
},
)
.spawn(async { f() })
.run()
.unwrap();
}

View File

@ -1,3 +1,2 @@
mod dart_ffi;
mod helper;
mod module_event;

View File

@ -6,36 +6,27 @@ pub async fn one_params(_s: String) -> String { "one params function call".to_st
pub async fn two_params(_s1: String, _s2: String) -> String { "two params function call".to_string() }
#[test]
fn test() {
fn test_init() {
setup_env();
let no_params_command = "no params".to_string();
let one_params_command = "one params".to_string();
let two_params_command = "two params".to_string();
let stream = CommandStream::<i64>::new();
let tx = stream.tx();
FlowySystem::construct(
|| {
vec![Module::new()
let modules = vec![Module::new()
.event(no_params_command.clone(), no_params)
.event(one_params_command.clone(), one_params)
.event(two_params_command.clone(), two_params)]
},
stream,
)
.spawn(async move {
let request = EventRequest::new(no_params_command.clone());
let stream_data = StreamData::new(
1,
Some(request),
Box::new(|config, response| {
log::info!("{:?}", response);
}),
);
tx.send(stream_data);
FlowySystem::current().stop();
})
.run()
.unwrap();
.event(two_params_command.clone(), two_params)];
init_system(modules, || {
let request = EventRequest::new(no_params_command);
let stream_data = StreamData::new(1, Some(request)).with_callback(Box::new(|_config, response| {
log::info!("async resp: {:?}", response);
}));
let resp = sync_send(stream_data);
log::info!("sync resp: {:?}", resp);
stop_system();
});
}

View File

@ -1,8 +0,0 @@
[tasks.setup-diesel]
script = [
"""
brew install sqlite3
cargo install diesel_cli --no-default-features --features sqlite
""",
]
script_runner = "@shell"

View File

@ -1,7 +1,7 @@
[tasks.desktop]
category = "Build"
dependencies = ["cqrs_gen", "desktop-debug", "desktop-release", "post-desktop"]
dependencies = ["desktop-debug", "desktop-release", "post-desktop"]
description = "Build desktop targets"
[tasks.desktop-debug]
@ -18,16 +18,14 @@ private = true
run_task = "desktop-build"
[tasks.desktop-build]
# args = ["build", "--target", "${DESKTOP_TARGET}"]
category = "Build"
# command = "cargo"
condition = { platforms = ["mac"], env_true = ["DEV"] }
dependencies = ["export-env", "setup-crate-type-macos"]
description = "Build desktop targets."
script = [
"""
cd rust-lib/
cargo build --package=flowy-ffi --target ${DESKTOP_TARGET}
cargo build --package=dart-ffi --target ${DESKTOP_TARGET}
cd ../
""",
]
@ -37,12 +35,13 @@ condition = { platforms = ["mac"] }
dependencies = ["restore-crate-type"]
script = [
"""
echo ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}
cp ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/target/x86_64-apple-darwin/${LIB_OUT_DIR}/lib${CARGO_MAKE_CRATE_FS_NAME}.dylib \
${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/flutter-lib/packages/flowy_sdk/macos/lib${CARGO_MAKE_CRATE_FS_NAME}.dylib
${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages/flowy_sdk/macos/lib${CARGO_MAKE_CRATE_FS_NAME}.dylib
""",
"""
cp ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/binding.h \
${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/flutter-lib/packages/flowy_sdk/macos/Classes/binding.h
${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages/flowy_sdk/macos/Classes/binding.h
""",
]
script_runner = "@duckscript"
@ -55,13 +54,6 @@ run_task = "setup-crate-type"
[tasks.export-env]
script = [
"""
# Try to fix the issue
# ld: warning: dylib (/Users/vedon/Documents/Private/RustProject/App-Flowy/app_flowy/flutter-lib/packages/flowy_sdk/macos/libflowy_ffi.dylib) was built for newer macOS version (10.15) than being linked (10.11)
# ld: warning: dylib (/Users/vedon/Documents/Private/RustProject/App-Flowy/app_flowy/flutter-lib/packages/flowy_sdk/macos/libflowy_ffi.dylib) was built for newer macOS version (10.15) than being linked (10.11)
# https://users.rust-lang.org/t/compile-rust-binary-for-older-versions-of-mac-osx/38695/3
# https://stackoverflow.com/questions/43216273/object-file-was-built-for-newer-osx-version-than-being-linked
export MACOSX_DEPLOYMENT_TARGET=10.11
""",
]
@ -71,7 +63,7 @@ script_runner = "@shell"
condition = { platforms = ["mac"] }
script = [
"""
target_path = set ${TMPDIR}/app_flowy/lib${CARGO_MAKE_CRATE_FS_NAME}.dylib
target_path = set ${TMPDIR}/appflowy_client/lib${CARGO_MAKE_CRATE_FS_NAME}.dylib
echo "remove old dylib"
rm ${target_path}
echo "copy new dylib to system"
@ -91,13 +83,3 @@ script = [
script_runner = "@shell"
[tasks.cqrs_gen]
script = [
"""
manifest_path=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/scripts/tool/rust-tool/Cargo.toml
cqrs_file=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-store/src/entities/command.rs
output_file=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/flutter-lib/packages/flowy_sdk/lib/cqrs/auto_gen.dart
cargo run --manifest-path ${manifest_path} flutter --cqrs=${cqrs_file} --output=${output_file}
""",
]
script_runner = "@shell"

View File

@ -1,49 +0,0 @@
[tasks.pb_init_setup_dev]
description = "Setup protobuf"
script = [
"""
brew tap dart-lang/dart
brew install dart
pub global activate protoc_plugin
cargo install --force --version 2.18.0 protobuf-codegen
""",
]
script_runner = "@shell"
[tasks.gen_pb_file]
script = [
"""
pb_gen_exec=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/scripts/tool/rust-tool/Cargo.toml
proto_source_file=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-store/src/entities/
proto_define_dir=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-protobuf/define
derive_file=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-ast/src/auto_gen_file/category_from_str.rs
rust_mod_file=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-protobuf/src/model/mod.rs
flutter_mod_file=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/flutter-lib/packages/flowy_protobuf/lib/all.dart
cargo run --manifest-path ${pb_gen_exec} pb-gen -i=${proto_source_file} --derive_file=${derive_file} --proto_define_dir=${proto_define_dir} --rust_mod_file=${rust_mod_file} --flutter_mod_file=${flutter_mod_file}
""",
]
script_runner = "@shell"
[tasks.gen_rust_pb]
script = [
"""
protoc --rust_out=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-protobuf/src/model \
--proto_path=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-protobuf/define \
${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-protobuf/define/*.proto
""",
]
script_runner = "@shell"
[tasks.gen_dart_pb]
script = [
"""
dart_path=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/flutter-lib/packages/flowy_protobuf/lib/model
pb_define_path=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-protobuf/define
pb_proto_files=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-protobuf/define/*.proto
rm -rf ${dart_path}/*
protoc --dart_out=${dart_path} --proto_path=${pb_define_path} ${pb_proto_files}
""",
]
script_runner = "@shell"