wasm work

This commit is contained in:
John Smith 2022-03-15 23:02:24 -04:00
parent 736e7a0cb0
commit a39b38cc16
8 changed files with 86 additions and 58 deletions

View File

@ -89,7 +89,7 @@ class _MyAppState extends State<MyApp> with UiLoggy {
// Platform messages may fail, so we use a try/catch PlatformException. // Platform messages may fail, so we use a try/catch PlatformException.
// We also handle the message potentially returning null. // We also handle the message potentially returning null.
try { try {
veilidVersion = Veilid.instance.veilidVersionString(); veilidVersion = await Veilid.instance.veilidVersionString();
} on Exception { } on Exception {
veilidVersion = 'Failed to get veilid version.'; veilidVersion = 'Failed to get veilid version.';
} }

View File

@ -149,6 +149,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.7.0" version: "1.7.0"
mutex:
dependency: transitive
description:
name: mutex
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
path: path:
dependency: transitive dependency: transitive
description: description:
@ -301,6 +308,13 @@ packages:
relative: true relative: true
source: path source: path
version: "0.0.1" version: "0.0.1"
wasm_interop:
dependency: transitive
description:
name: wasm_interop
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
win32: win32:
dependency: transitive dependency: transitive
description: description:

View File

@ -996,6 +996,6 @@ abstract class Veilid {
Future<void> changeLogLevel(VeilidConfigLogLevel logLevel); Future<void> changeLogLevel(VeilidConfigLogLevel logLevel);
Future<void> shutdownVeilidCore(); Future<void> shutdownVeilidCore();
Future<String> debug(String command); Future<String> debug(String command);
String veilidVersionString(); Future<String> veilidVersionString();
VeilidVersion veilidVersion(); Future<VeilidVersion> veilidVersion();
} }

View File

@ -326,7 +326,7 @@ class VeilidFFI implements Veilid {
} }
@override @override
String veilidVersionString() { Future<String> veilidVersionString() async {
final versionString = _veilidVersionString(); final versionString = _veilidVersionString();
String ret = versionString.toDartString(); String ret = versionString.toDartString();
_freeString(versionString); _freeString(versionString);
@ -334,7 +334,7 @@ class VeilidFFI implements Veilid {
} }
@override @override
VeilidVersion veilidVersion() { Future<VeilidVersion> veilidVersion() async {
final version = _veilidVersion(); final version = _veilidVersion();
return VeilidVersion( return VeilidVersion(
version.major, version.major,

View File

@ -1,46 +1,82 @@
import 'veilid.dart'; import 'veilid.dart';
import 'dart:js'; import 'dart:js';
import 'dart:js_util';
import 'dart:async'; import 'dart:async';
import 'dart:typed_data'; import 'dart:convert';
import 'package:flutter/services.dart' show NetworkAssetBundle;
import 'package:wasm_interop/wasm_interop.dart';
import 'package:mutex/mutex.dart';
////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////
Veilid getVeilid() => VeilidJS(); Veilid getVeilid() => VeilidJS();
Instance? _wasmInstance;
final _wasmInstanceMutex = Mutex();
Future<Instance> getWasmInstance() async {
await _wasmInstanceMutex.acquire();
var _wi = _wasmInstance;
if (_wi == null) {
final bytes = await http???.get(Uri.parse("/wasm/veilid_wasm.wasm"));
_wi = await Instance.fromBufferAsync(bytes.buffer);
_wasmInstance = _wi;
}
_wasmInstanceMutex.release();
return _wi;
}
class VeilidJS implements Veilid { class VeilidJS implements Veilid {
@override @override
Stream<VeilidUpdate> startupVeilidCore(VeilidConfig config) { Stream<VeilidUpdate> startupVeilidCore(VeilidConfig config) async* {
throw UnimplementedError(); var wasm = (await getWasmInstance());
var streamController = StreamController<VeilidUpdate>();
await promiseToFuture(
wasm.functions["startup_veilid_core"]!.call((String update) {
streamController.add(VeilidUpdate.fromJson(jsonDecode(update)));
}, jsonEncode(config.json, toEncodable: veilidApiToEncodable)));
yield* streamController.stream;
} }
@override @override
Future<VeilidState> getVeilidState() { Future<VeilidState> getVeilidState() async {
throw UnimplementedError(); var wasm = (await getWasmInstance());
return VeilidState.fromJson(jsonDecode(
await promiseToFuture(wasm.functions["get_veilid_state"]!.call())));
} }
@override @override
Future<void> changeLogLevel(VeilidConfigLogLevel logLevel) { Future<void> changeLogLevel(VeilidConfigLogLevel logLevel) async {
throw UnimplementedError(); var wasm = (await getWasmInstance());
await promiseToFuture(wasm.functions["change_log_level"]!
.call(jsonEncode(logLevel.json, toEncodable: veilidApiToEncodable)));
} }
@override @override
Future<void> shutdownVeilidCore() { Future<void> shutdownVeilidCore() async {
throw UnimplementedError(); var wasm = (await getWasmInstance());
await promiseToFuture(wasm.functions["shutdown_veilid_core"]!.call());
} }
@override @override
Future<String> debug(String command) { Future<String> debug(String command) async {
throw UnimplementedError(); var wasm = (await getWasmInstance());
return await promiseToFuture(wasm.functions["debug"]!.call(command));
} }
@override @override
String veilidVersionString() { Future<String> veilidVersionString() async {
throw UnimplementedError(); var wasm = (await getWasmInstance());
return await promiseToFuture(wasm.functions["debug"]!.call());
} }
@override @override
VeilidVersion veilidVersion() { Future<VeilidVersion> veilidVersion() async {
throw UnimplementedError(); var wasm = (await getWasmInstance());
var jsonVersion = jsonDecode(
await promiseToFuture(wasm.functions["get_veilid_state"]!.call()));
return VeilidVersion(
jsonVersion["major"], jsonVersion["minor"], jsonVersion["patch"]);
} }
} }

View File

@ -1,41 +1,17 @@
import 'dart:async'; import 'dart:async';
// In order to *not* need this ignore, consider extracting the "web" version
// of your plugin as a separate package, instead of inlining it in the same
// package as the core of your plugin.
// ignore: avoid_web_libraries_in_flutter
import 'dart:html' as html show window;
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart';
// xxx link in WASM version of veilid-flutter /// A stub web implementation of the Veilid plugin
/// Because everything is done with FFI or WASM, we don't use this interface
/// A web implementation of the Veilid plugin.
class VeilidPluginStubWeb { class VeilidPluginStubWeb {
static void registerWith(Registrar registrar) { static void registerWith(Registrar registrar) {}
// final MethodChannel channel = MethodChannel(
// 'veilid',
// const StandardMethodCodec(),
// registrar,
// );
// final pluginInstance = VeilidWeb();
// channel.setMethodCallHandler(pluginInstance.handleMethodCall);
}
/// Handles method calls over the MethodChannel of this plugin.
/// Note: Check the "federated" architecture for a new way of doing this:
/// https://flutter.dev/go/federated-plugins
Future<dynamic> handleMethodCall(MethodCall call) async { Future<dynamic> handleMethodCall(MethodCall call) async {
// switch (call.method) { throw PlatformException(
// case 'getPlatformVersion': code: 'Unimplemented',
// return getPlatformVersion(); details: 'Veilid for Web doesn\'t implement \'${call.method}\'',
// default: );
throw PlatformException(
code: 'Unimplemented',
details: 'veilid for web doesn\'t implement \'${call.method}\'',
);
// }
} }
} }

View File

@ -17,6 +17,8 @@ dependencies:
change_case: ^1.0.1 change_case: ^1.0.1
path_provider: ^2.0.9 path_provider: ^2.0.9
path: ^1.8.0 path: ^1.8.0
wasm_interop: ^2.0.1
mutex: ^3.0.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View File

@ -100,12 +100,12 @@ where
// WASM Bindings // WASM Bindings
#[wasm_bindgen(js_namespace = veilid)] #[wasm_bindgen()]
pub fn initialize_veilid_wasm() { pub fn initialize_veilid_wasm() {
console_error_panic_hook::set_once(); console_error_panic_hook::set_once();
} }
#[wasm_bindgen(js_namespace = veilid)] #[wasm_bindgen()]
pub fn startup_veilid_core(update_callback: Function, json_config: String) -> Promise { pub fn startup_veilid_core(update_callback: Function, json_config: String) -> Promise {
wrap_api_future(async move { wrap_api_future(async move {
let update_callback = Arc::new(move |update: VeilidUpdate| { let update_callback = Arc::new(move |update: VeilidUpdate| {
@ -129,7 +129,7 @@ pub fn startup_veilid_core(update_callback: Function, json_config: String) -> Pr
}) })
} }
#[wasm_bindgen(js_namespace = veilid)] #[wasm_bindgen()]
pub fn get_veilid_state() -> Promise { pub fn get_veilid_state() -> Promise {
wrap_api_future(async move { wrap_api_future(async move {
let veilid_api = get_veilid_api()?; let veilid_api = get_veilid_api()?;
@ -148,7 +148,7 @@ pub fn change_log_level(log_level: String) -> Promise {
}) })
} }
#[wasm_bindgen(js_namespace = veilid)] #[wasm_bindgen()]
pub fn shutdown_veilid_core() -> Promise { pub fn shutdown_veilid_core() -> Promise {
wrap_api_future(async move { wrap_api_future(async move {
let veilid_api = take_veilid_api()?; let veilid_api = take_veilid_api()?;
@ -157,7 +157,7 @@ pub fn shutdown_veilid_core() -> Promise {
}) })
} }
#[wasm_bindgen(js_namespace = veilid)] #[wasm_bindgen()]
pub fn debug(command: String) -> Promise { pub fn debug(command: String) -> Promise {
wrap_api_future(async move { wrap_api_future(async move {
let veilid_api = get_veilid_api()?; let veilid_api = get_veilid_api()?;
@ -166,7 +166,7 @@ pub fn debug(command: String) -> Promise {
}) })
} }
#[wasm_bindgen(js_namespace = veilid)] #[wasm_bindgen()]
pub fn veilid_version_string() -> String { pub fn veilid_version_string() -> String {
veilid_core::veilid_version_string() veilid_core::veilid_version_string()
} }
@ -178,7 +178,7 @@ pub struct VeilidVersion {
pub patch: u32, pub patch: u32,
} }
#[wasm_bindgen(js_namespace = veilid)] #[wasm_bindgen()]
pub fn veilid_version() -> JsValue { pub fn veilid_version() -> JsValue {
let (major, minor, patch) = veilid_core::veilid_version(); let (major, minor, patch) = veilid_core::veilid_version();
let vv = VeilidVersion { let vv = VeilidVersion {