diff --git a/lib/core/bridge.dart b/lib/core/bridge.dart index 91657918..d7b6740a 100644 --- a/lib/core/bridge.dart +++ b/lib/core/bridge.dart @@ -5,20 +5,36 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; -import 'database/contact.dart'; import 'frb_generated.dart'; -// These functions are ignored because they are not marked as `pub`: `get_workspace` -// These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `Twonly` +// These functions are ignored because they are not marked as `pub`: `get_twonly_flutter` +// These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `TwonlyFlutter` -Future initializeTwonly({required TwonlyConfig config}) => - RustLib.instance.api.crateBridgeInitializeTwonly(config: config); +Future initializeTwonlyFlutter({required TwonlyConfig config}) => + RustLib.instance.api.crateBridgeInitializeTwonlyFlutter(config: config); -Future> getAllContacts() => - RustLib.instance.api.crateBridgeGetAllContacts(); +class AnnouncedUser { + const AnnouncedUser({ + required this.userId, + required this.publicKey, + required this.publicId, + }); + final PlatformInt64 userId; + final Uint8List publicKey; + final PlatformInt64 publicId; -Future loadPromotions() => - RustLib.instance.api.crateBridgeLoadPromotions(); + @override + int get hashCode => userId.hashCode ^ publicKey.hashCode ^ publicId.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is AnnouncedUser && + runtimeType == other.runtimeType && + userId == other.userId && + publicKey == other.publicKey && + publicId == other.publicId; +} class OtherPromotion { const OtherPromotion({ diff --git a/lib/core/bridge/callbacks.dart b/lib/core/bridge/callbacks.dart new file mode 100644 index 00000000..28859ca4 --- /dev/null +++ b/lib/core/bridge/callbacks.dart @@ -0,0 +1,58 @@ +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.12.0. + +// ignore_for_file: invalid_use_of_internal_member + +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; + +import '../bridge.dart'; +import '../frb_generated.dart'; + +// These functions are ignored because they are not marked as `pub`: `get_callbacks` +// These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `FlutterCallbacks`, `Logging`, `UserDiscoveryCallbacks` + +Future initFlutterCallbacks({ + required FutureOr> Function() loggingGetStreamSink, + required FutureOr Function(Uint8List) userDiscoverySignData, + required FutureOr Function(Uint8List, Uint8List, Uint8List) + userDiscoveryVerifySignature, + required FutureOr Function(PlatformInt64, Uint8List) + userDiscoveryVerifyStoredPubkey, + required FutureOr Function(List) userDiscoverySetShares, + required FutureOr Function(PlatformInt64) + userDiscoveryGetShareForContact, + required FutureOr Function(PlatformInt64, PlatformInt64, Uint8List) + userDiscoveryPushOwnPromotion, + required FutureOr?> Function(PlatformInt64) + userDiscoveryGetOwnPromotionsAfterVersion, + required FutureOr Function(OtherPromotion) + userDiscoveryStoreOtherPromotion, + required FutureOr?> Function(PlatformInt64) + userDiscoveryGetOtherPromotionsByPublicId, + required FutureOr Function(PlatformInt64) + userDiscoveryGetAnnouncedUserByPublicId, + required FutureOr Function(PlatformInt64) + userDiscoveryGetContactVersion, + required FutureOr Function(PlatformInt64, Uint8List) + userDiscoverySetContactVersion, + required FutureOr Function(PlatformInt64, AnnouncedUser, PlatformInt64?) + userDiscoveryPushNewUserRelation, +}) => RustLib.instance.api.crateBridgeCallbacksInitFlutterCallbacks( + loggingGetStreamSink: loggingGetStreamSink, + userDiscoverySignData: userDiscoverySignData, + userDiscoveryVerifySignature: userDiscoveryVerifySignature, + userDiscoveryVerifyStoredPubkey: userDiscoveryVerifyStoredPubkey, + userDiscoverySetShares: userDiscoverySetShares, + userDiscoveryGetShareForContact: userDiscoveryGetShareForContact, + userDiscoveryPushOwnPromotion: userDiscoveryPushOwnPromotion, + userDiscoveryGetOwnPromotionsAfterVersion: + userDiscoveryGetOwnPromotionsAfterVersion, + userDiscoveryStoreOtherPromotion: userDiscoveryStoreOtherPromotion, + userDiscoveryGetOtherPromotionsByPublicId: + userDiscoveryGetOtherPromotionsByPublicId, + userDiscoveryGetAnnouncedUserByPublicId: + userDiscoveryGetAnnouncedUserByPublicId, + userDiscoveryGetContactVersion: userDiscoveryGetContactVersion, + userDiscoverySetContactVersion: userDiscoverySetContactVersion, + userDiscoveryPushNewUserRelation: userDiscoveryPushNewUserRelation, +); diff --git a/lib/core/bridge/wrapper/user_discovery.dart b/lib/core/bridge/wrapper/user_discovery.dart new file mode 100644 index 00000000..b4d4edf3 --- /dev/null +++ b/lib/core/bridge/wrapper/user_discovery.dart @@ -0,0 +1,61 @@ +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.12.0. + +// ignore_for_file: invalid_use_of_internal_member + +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; + +import '../../frb_generated.dart'; + +class FlutterUserDiscovery { + const FlutterUserDiscovery(); + + static Future getCurrentVersion() => RustLib.instance.api + .crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryGetCurrentVersion(); + + static Future> getNewMessages({ + required PlatformInt64 contactId, + required List receivedVersion, + }) => RustLib.instance.api + .crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryGetNewMessages( + contactId: contactId, + receivedVersion: receivedVersion, + ); + + static Future handleUserDiscoveryMessages({ + required PlatformInt64 contactId, + required List messages, + }) => RustLib.instance.api + .crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryHandleUserDiscoveryMessages( + contactId: contactId, + messages: messages, + ); + + static Future initializeOrUpdate({ + required int threshold, + required PlatformInt64 userId, + required List publicKey, + }) => RustLib.instance.api + .crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryInitializeOrUpdate( + threshold: threshold, + userId: userId, + publicKey: publicKey, + ); + + static Future shouldRequestNewMessages({ + required PlatformInt64 contactId, + required List version, + }) => RustLib.instance.api + .crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryShouldRequestNewMessages( + contactId: contactId, + version: version, + ); + + @override + int get hashCode => 0; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is FlutterUserDiscovery && runtimeType == other.runtimeType; +} diff --git a/lib/core/database/contact.dart b/lib/core/database/contact.dart deleted file mode 100644 index 42799c8d..00000000 --- a/lib/core/database/contact.dart +++ /dev/null @@ -1,28 +0,0 @@ -// This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. - -// ignore_for_file: unused_import - -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; - -import '../frb_generated.dart'; - -class Contact { - const Contact({ - required this.userId, - required this.username, - }); - final PlatformInt64 userId; - final String username; - - @override - int get hashCode => userId.hashCode ^ username.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is Contact && - runtimeType == other.runtimeType && - userId == other.userId && - username == other.username; -} diff --git a/lib/core/frb_generated.dart b/lib/core/frb_generated.dart index c49fc9c7..a1248a9a 100644 --- a/lib/core/frb_generated.dart +++ b/lib/core/frb_generated.dart @@ -9,7 +9,8 @@ import 'dart:convert'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'bridge.dart'; -import 'database/contact.dart'; +import 'bridge/callbacks.dart'; +import 'bridge/wrapper/user_discovery.dart'; import 'frb_generated.dart'; import 'frb_generated.io.dart' if (dart.library.js_interop) 'frb_generated.web.dart'; @@ -70,7 +71,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => 776002844; + int get rustContentHash => 523281685; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -81,11 +82,69 @@ class RustLib extends BaseEntrypoint { } abstract class RustLibApi extends BaseApi { - Future> crateBridgeGetAllContacts(); + Future + crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryGetCurrentVersion(); - Future crateBridgeInitializeTwonly({required TwonlyConfig config}); + Future> + crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryGetNewMessages({ + required PlatformInt64 contactId, + required List receivedVersion, + }); - Future crateBridgeLoadPromotions(); + Future + crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryHandleUserDiscoveryMessages({ + required PlatformInt64 contactId, + required List messages, + }); + + Future + crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryInitializeOrUpdate({ + required int threshold, + required PlatformInt64 userId, + required List publicKey, + }); + + Future + crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryShouldRequestNewMessages({ + required PlatformInt64 contactId, + required List version, + }); + + Future crateBridgeCallbacksInitFlutterCallbacks({ + required FutureOr> Function() loggingGetStreamSink, + required FutureOr Function(Uint8List) userDiscoverySignData, + required FutureOr Function(Uint8List, Uint8List, Uint8List) + userDiscoveryVerifySignature, + required FutureOr Function(PlatformInt64, Uint8List) + userDiscoveryVerifyStoredPubkey, + required FutureOr Function(List) userDiscoverySetShares, + required FutureOr Function(PlatformInt64) + userDiscoveryGetShareForContact, + required FutureOr Function(PlatformInt64, PlatformInt64, Uint8List) + userDiscoveryPushOwnPromotion, + required FutureOr?> Function(PlatformInt64) + userDiscoveryGetOwnPromotionsAfterVersion, + required FutureOr Function(OtherPromotion) + userDiscoveryStoreOtherPromotion, + required FutureOr?> Function(PlatformInt64) + userDiscoveryGetOtherPromotionsByPublicId, + required FutureOr Function(PlatformInt64) + userDiscoveryGetAnnouncedUserByPublicId, + required FutureOr Function(PlatformInt64) + userDiscoveryGetContactVersion, + required FutureOr Function(PlatformInt64, Uint8List) + userDiscoverySetContactVersion, + required FutureOr Function( + PlatformInt64, + AnnouncedUser, + PlatformInt64?, + ) + userDiscoveryPushNewUserRelation, + }); + + Future crateBridgeInitializeTwonlyFlutter({ + required TwonlyConfig config, + }); } class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @@ -97,7 +156,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { }); @override - Future> crateBridgeGetAllContacts() { + Future + crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryGetCurrentVersion() { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -110,28 +170,36 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); }, codec: SseCodec( - decodeSuccessData: sse_decode_list_contact, + decodeSuccessData: sse_decode_list_prim_u_8_strict, decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateBridgeGetAllContactsConstMeta, + constMeta: + kCrateBridgeWrapperUserDiscoveryFlutterUserDiscoveryGetCurrentVersionConstMeta, argValues: [], apiImpl: this, ), ); } - TaskConstMeta get kCrateBridgeGetAllContactsConstMeta => const TaskConstMeta( - debugName: 'get_all_contacts', - argNames: [], - ); + TaskConstMeta + get kCrateBridgeWrapperUserDiscoveryFlutterUserDiscoveryGetCurrentVersionConstMeta => + const TaskConstMeta( + debugName: 'flutter_user_discovery_get_current_version', + argNames: [], + ); @override - Future crateBridgeInitializeTwonly({required TwonlyConfig config}) { + Future> + crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryGetNewMessages({ + required PlatformInt64 contactId, + required List receivedVersion, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_twonly_config(config, serializer); + sse_encode_i_64(contactId, serializer); + sse_encode_list_prim_u_8_loose(receivedVersion, serializer); pdeCallFfi( generalizedFrbRustBinding, serializer, @@ -140,28 +208,36 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); }, codec: SseCodec( - decodeSuccessData: sse_decode_unit, + decodeSuccessData: sse_decode_list_list_prim_u_8_strict, decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateBridgeInitializeTwonlyConstMeta, - argValues: [config], + constMeta: + kCrateBridgeWrapperUserDiscoveryFlutterUserDiscoveryGetNewMessagesConstMeta, + argValues: [contactId, receivedVersion], apiImpl: this, ), ); } - TaskConstMeta get kCrateBridgeInitializeTwonlyConstMeta => + TaskConstMeta + get kCrateBridgeWrapperUserDiscoveryFlutterUserDiscoveryGetNewMessagesConstMeta => const TaskConstMeta( - debugName: 'initialize_twonly', - argNames: ['config'], + debugName: 'flutter_user_discovery_get_new_messages', + argNames: ['contactId', 'receivedVersion'], ); @override - Future crateBridgeLoadPromotions() { + Future + crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryHandleUserDiscoveryMessages({ + required PlatformInt64 contactId, + required List messages, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_i_64(contactId, serializer); + sse_encode_list_list_prim_u_8_strict(messages, serializer); pdeCallFfi( generalizedFrbRustBinding, serializer, @@ -170,20 +246,709 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); }, codec: SseCodec( - decodeSuccessData: sse_decode_other_promotion, - decodeErrorData: null, + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateBridgeLoadPromotionsConstMeta, - argValues: [], + constMeta: + kCrateBridgeWrapperUserDiscoveryFlutterUserDiscoveryHandleUserDiscoveryMessagesConstMeta, + argValues: [contactId, messages], apiImpl: this, ), ); } - TaskConstMeta get kCrateBridgeLoadPromotionsConstMeta => const TaskConstMeta( - debugName: 'load_promotions', - argNames: [], - ); + TaskConstMeta + get kCrateBridgeWrapperUserDiscoveryFlutterUserDiscoveryHandleUserDiscoveryMessagesConstMeta => + const TaskConstMeta( + debugName: 'flutter_user_discovery_handle_user_discovery_messages', + argNames: ['contactId', 'messages'], + ); + + @override + Future + crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryInitializeOrUpdate({ + required int threshold, + required PlatformInt64 userId, + required List publicKey, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_8(threshold, serializer); + sse_encode_i_64(userId, serializer); + sse_encode_list_prim_u_8_loose(publicKey, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 4, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: + kCrateBridgeWrapperUserDiscoveryFlutterUserDiscoveryInitializeOrUpdateConstMeta, + argValues: [threshold, userId, publicKey], + apiImpl: this, + ), + ); + } + + TaskConstMeta + get kCrateBridgeWrapperUserDiscoveryFlutterUserDiscoveryInitializeOrUpdateConstMeta => + const TaskConstMeta( + debugName: 'flutter_user_discovery_initialize_or_update', + argNames: ['threshold', 'userId', 'publicKey'], + ); + + @override + Future + crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryShouldRequestNewMessages({ + required PlatformInt64 contactId, + required List version, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_i_64(contactId, serializer); + sse_encode_list_prim_u_8_loose(version, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 5, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: + kCrateBridgeWrapperUserDiscoveryFlutterUserDiscoveryShouldRequestNewMessagesConstMeta, + argValues: [contactId, version], + apiImpl: this, + ), + ); + } + + TaskConstMeta + get kCrateBridgeWrapperUserDiscoveryFlutterUserDiscoveryShouldRequestNewMessagesConstMeta => + const TaskConstMeta( + debugName: 'flutter_user_discovery_should_request_new_messages', + argNames: ['contactId', 'version'], + ); + + @override + Future crateBridgeCallbacksInitFlutterCallbacks({ + required FutureOr> Function() loggingGetStreamSink, + required FutureOr Function(Uint8List) userDiscoverySignData, + required FutureOr Function(Uint8List, Uint8List, Uint8List) + userDiscoveryVerifySignature, + required FutureOr Function(PlatformInt64, Uint8List) + userDiscoveryVerifyStoredPubkey, + required FutureOr Function(List) userDiscoverySetShares, + required FutureOr Function(PlatformInt64) + userDiscoveryGetShareForContact, + required FutureOr Function(PlatformInt64, PlatformInt64, Uint8List) + userDiscoveryPushOwnPromotion, + required FutureOr?> Function(PlatformInt64) + userDiscoveryGetOwnPromotionsAfterVersion, + required FutureOr Function(OtherPromotion) + userDiscoveryStoreOtherPromotion, + required FutureOr?> Function(PlatformInt64) + userDiscoveryGetOtherPromotionsByPublicId, + required FutureOr Function(PlatformInt64) + userDiscoveryGetAnnouncedUserByPublicId, + required FutureOr Function(PlatformInt64) + userDiscoveryGetContactVersion, + required FutureOr Function(PlatformInt64, Uint8List) + userDiscoverySetContactVersion, + required FutureOr Function( + PlatformInt64, + AnnouncedUser, + PlatformInt64?, + ) + userDiscoveryPushNewUserRelation, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_DartFn_Inputs__Output_StreamSink_String_Sse_AnyhowException( + loggingGetStreamSink, + serializer, + ); + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_opt_list_prim_u_8_strict_AnyhowException( + userDiscoverySignData, + serializer, + ); + sse_encode_DartFn_Inputs_list_prim_u_8_strict_list_prim_u_8_strict_list_prim_u_8_strict_Output_bool_AnyhowException( + userDiscoveryVerifySignature, + serializer, + ); + sse_encode_DartFn_Inputs_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + userDiscoveryVerifyStoredPubkey, + serializer, + ); + sse_encode_DartFn_Inputs_list_list_prim_u_8_strict_Output_bool_AnyhowException( + userDiscoverySetShares, + serializer, + ); + sse_encode_DartFn_Inputs_i_64_Output_opt_list_prim_u_8_strict_AnyhowException( + userDiscoveryGetShareForContact, + serializer, + ); + sse_encode_DartFn_Inputs_i_64_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + userDiscoveryPushOwnPromotion, + serializer, + ); + sse_encode_DartFn_Inputs_i_64_Output_opt_list_list_prim_u_8_strict_AnyhowException( + userDiscoveryGetOwnPromotionsAfterVersion, + serializer, + ); + sse_encode_DartFn_Inputs_other_promotion_Output_bool_AnyhowException( + userDiscoveryStoreOtherPromotion, + serializer, + ); + sse_encode_DartFn_Inputs_i_64_Output_opt_list_other_promotion_AnyhowException( + userDiscoveryGetOtherPromotionsByPublicId, + serializer, + ); + sse_encode_DartFn_Inputs_i_64_Output_opt_box_autoadd_announced_user_AnyhowException( + userDiscoveryGetAnnouncedUserByPublicId, + serializer, + ); + sse_encode_DartFn_Inputs_i_64_Output_opt_list_prim_u_8_strict_AnyhowException( + userDiscoveryGetContactVersion, + serializer, + ); + sse_encode_DartFn_Inputs_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + userDiscoverySetContactVersion, + serializer, + ); + sse_encode_DartFn_Inputs_i_64_announced_user_opt_box_autoadd_i_64_Output_bool_AnyhowException( + userDiscoveryPushNewUserRelation, + serializer, + ); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 6, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateBridgeCallbacksInitFlutterCallbacksConstMeta, + argValues: [ + loggingGetStreamSink, + userDiscoverySignData, + userDiscoveryVerifySignature, + userDiscoveryVerifyStoredPubkey, + userDiscoverySetShares, + userDiscoveryGetShareForContact, + userDiscoveryPushOwnPromotion, + userDiscoveryGetOwnPromotionsAfterVersion, + userDiscoveryStoreOtherPromotion, + userDiscoveryGetOtherPromotionsByPublicId, + userDiscoveryGetAnnouncedUserByPublicId, + userDiscoveryGetContactVersion, + userDiscoverySetContactVersion, + userDiscoveryPushNewUserRelation, + ], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateBridgeCallbacksInitFlutterCallbacksConstMeta => + const TaskConstMeta( + debugName: 'init_flutter_callbacks', + argNames: [ + 'loggingGetStreamSink', + 'userDiscoverySignData', + 'userDiscoveryVerifySignature', + 'userDiscoveryVerifyStoredPubkey', + 'userDiscoverySetShares', + 'userDiscoveryGetShareForContact', + 'userDiscoveryPushOwnPromotion', + 'userDiscoveryGetOwnPromotionsAfterVersion', + 'userDiscoveryStoreOtherPromotion', + 'userDiscoveryGetOtherPromotionsByPublicId', + 'userDiscoveryGetAnnouncedUserByPublicId', + 'userDiscoveryGetContactVersion', + 'userDiscoverySetContactVersion', + 'userDiscoveryPushNewUserRelation', + ], + ); + + @override + Future crateBridgeInitializeTwonlyFlutter({ + required TwonlyConfig config, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_twonly_config(config, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 7, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateBridgeInitializeTwonlyFlutterConstMeta, + argValues: [config], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateBridgeInitializeTwonlyFlutterConstMeta => + const TaskConstMeta( + debugName: 'initialize_twonly_flutter', + argNames: ['config'], + ); + + Future Function( + int, + ) + encode_DartFn_Inputs__Output_StreamSink_String_Sse_AnyhowException( + FutureOr> Function() raw, + ) { + return ( + callId, + ) async { + Box>? rawOutput; + Box? rawError; + try { + rawOutput = Box(await raw()); + } catch (e, s) { + rawError = Box(AnyhowException('$e\n\n$s')); + } + + final serializer = SseSerializer(generalizedFrbRustBinding); + assert((rawOutput != null) ^ (rawError != null)); + if (rawOutput != null) { + serializer.buffer.putUint8(0); + sse_encode_StreamSink_String_Sse(rawOutput.value, serializer); + } else { + serializer.buffer.putUint8(1); + sse_encode_AnyhowException(rawError!.value, serializer); + } + final output = serializer.intoRaw(); + + generalizedFrbRustBinding.dartFnDeliverOutput( + callId: callId, + ptr: output.ptr, + rustVecLen: output.rustVecLen, + dataLen: output.dataLen, + ); + }; + } + + Future Function(int, dynamic) + encode_DartFn_Inputs_i_64_Output_opt_box_autoadd_announced_user_AnyhowException( + FutureOr Function(PlatformInt64) raw, + ) { + return (callId, rawArg0) async { + final arg0 = dco_decode_i_64(rawArg0); + + Box? rawOutput; + Box? rawError; + try { + rawOutput = Box(await raw(arg0)); + } catch (e, s) { + rawError = Box(AnyhowException('$e\n\n$s')); + } + + final serializer = SseSerializer(generalizedFrbRustBinding); + assert((rawOutput != null) ^ (rawError != null)); + if (rawOutput != null) { + serializer.buffer.putUint8(0); + sse_encode_opt_box_autoadd_announced_user(rawOutput.value, serializer); + } else { + serializer.buffer.putUint8(1); + sse_encode_AnyhowException(rawError!.value, serializer); + } + final output = serializer.intoRaw(); + + generalizedFrbRustBinding.dartFnDeliverOutput( + callId: callId, + ptr: output.ptr, + rustVecLen: output.rustVecLen, + dataLen: output.dataLen, + ); + }; + } + + Future Function(int, dynamic) + encode_DartFn_Inputs_i_64_Output_opt_list_list_prim_u_8_strict_AnyhowException( + FutureOr?> Function(PlatformInt64) raw, + ) { + return (callId, rawArg0) async { + final arg0 = dco_decode_i_64(rawArg0); + + Box?>? rawOutput; + Box? rawError; + try { + rawOutput = Box(await raw(arg0)); + } catch (e, s) { + rawError = Box(AnyhowException('$e\n\n$s')); + } + + final serializer = SseSerializer(generalizedFrbRustBinding); + assert((rawOutput != null) ^ (rawError != null)); + if (rawOutput != null) { + serializer.buffer.putUint8(0); + sse_encode_opt_list_list_prim_u_8_strict(rawOutput.value, serializer); + } else { + serializer.buffer.putUint8(1); + sse_encode_AnyhowException(rawError!.value, serializer); + } + final output = serializer.intoRaw(); + + generalizedFrbRustBinding.dartFnDeliverOutput( + callId: callId, + ptr: output.ptr, + rustVecLen: output.rustVecLen, + dataLen: output.dataLen, + ); + }; + } + + Future Function(int, dynamic) + encode_DartFn_Inputs_i_64_Output_opt_list_other_promotion_AnyhowException( + FutureOr?> Function(PlatformInt64) raw, + ) { + return (callId, rawArg0) async { + final arg0 = dco_decode_i_64(rawArg0); + + Box?>? rawOutput; + Box? rawError; + try { + rawOutput = Box(await raw(arg0)); + } catch (e, s) { + rawError = Box(AnyhowException('$e\n\n$s')); + } + + final serializer = SseSerializer(generalizedFrbRustBinding); + assert((rawOutput != null) ^ (rawError != null)); + if (rawOutput != null) { + serializer.buffer.putUint8(0); + sse_encode_opt_list_other_promotion(rawOutput.value, serializer); + } else { + serializer.buffer.putUint8(1); + sse_encode_AnyhowException(rawError!.value, serializer); + } + final output = serializer.intoRaw(); + + generalizedFrbRustBinding.dartFnDeliverOutput( + callId: callId, + ptr: output.ptr, + rustVecLen: output.rustVecLen, + dataLen: output.dataLen, + ); + }; + } + + Future Function(int, dynamic) + encode_DartFn_Inputs_i_64_Output_opt_list_prim_u_8_strict_AnyhowException( + FutureOr Function(PlatformInt64) raw, + ) { + return (callId, rawArg0) async { + final arg0 = dco_decode_i_64(rawArg0); + + Box? rawOutput; + Box? rawError; + try { + rawOutput = Box(await raw(arg0)); + } catch (e, s) { + rawError = Box(AnyhowException('$e\n\n$s')); + } + + final serializer = SseSerializer(generalizedFrbRustBinding); + assert((rawOutput != null) ^ (rawError != null)); + if (rawOutput != null) { + serializer.buffer.putUint8(0); + sse_encode_opt_list_prim_u_8_strict(rawOutput.value, serializer); + } else { + serializer.buffer.putUint8(1); + sse_encode_AnyhowException(rawError!.value, serializer); + } + final output = serializer.intoRaw(); + + generalizedFrbRustBinding.dartFnDeliverOutput( + callId: callId, + ptr: output.ptr, + rustVecLen: output.rustVecLen, + dataLen: output.dataLen, + ); + }; + } + + Future Function(int, dynamic, dynamic, dynamic) + encode_DartFn_Inputs_i_64_announced_user_opt_box_autoadd_i_64_Output_bool_AnyhowException( + FutureOr Function(PlatformInt64, AnnouncedUser, PlatformInt64?) raw, + ) { + return (callId, rawArg0, rawArg1, rawArg2) async { + final arg0 = dco_decode_i_64(rawArg0); + final arg1 = dco_decode_announced_user(rawArg1); + final arg2 = dco_decode_opt_box_autoadd_i_64(rawArg2); + + Box? rawOutput; + Box? rawError; + try { + rawOutput = Box(await raw(arg0, arg1, arg2)); + } catch (e, s) { + rawError = Box(AnyhowException('$e\n\n$s')); + } + + final serializer = SseSerializer(generalizedFrbRustBinding); + assert((rawOutput != null) ^ (rawError != null)); + if (rawOutput != null) { + serializer.buffer.putUint8(0); + sse_encode_bool(rawOutput.value, serializer); + } else { + serializer.buffer.putUint8(1); + sse_encode_AnyhowException(rawError!.value, serializer); + } + final output = serializer.intoRaw(); + + generalizedFrbRustBinding.dartFnDeliverOutput( + callId: callId, + ptr: output.ptr, + rustVecLen: output.rustVecLen, + dataLen: output.dataLen, + ); + }; + } + + Future Function(int, dynamic, dynamic, dynamic) + encode_DartFn_Inputs_i_64_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(PlatformInt64, PlatformInt64, Uint8List) raw, + ) { + return (callId, rawArg0, rawArg1, rawArg2) async { + final arg0 = dco_decode_i_64(rawArg0); + final arg1 = dco_decode_i_64(rawArg1); + final arg2 = dco_decode_list_prim_u_8_strict(rawArg2); + + Box? rawOutput; + Box? rawError; + try { + rawOutput = Box(await raw(arg0, arg1, arg2)); + } catch (e, s) { + rawError = Box(AnyhowException('$e\n\n$s')); + } + + final serializer = SseSerializer(generalizedFrbRustBinding); + assert((rawOutput != null) ^ (rawError != null)); + if (rawOutput != null) { + serializer.buffer.putUint8(0); + sse_encode_bool(rawOutput.value, serializer); + } else { + serializer.buffer.putUint8(1); + sse_encode_AnyhowException(rawError!.value, serializer); + } + final output = serializer.intoRaw(); + + generalizedFrbRustBinding.dartFnDeliverOutput( + callId: callId, + ptr: output.ptr, + rustVecLen: output.rustVecLen, + dataLen: output.dataLen, + ); + }; + } + + Future Function(int, dynamic, dynamic) + encode_DartFn_Inputs_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(PlatformInt64, Uint8List) raw, + ) { + return (callId, rawArg0, rawArg1) async { + final arg0 = dco_decode_i_64(rawArg0); + final arg1 = dco_decode_list_prim_u_8_strict(rawArg1); + + Box? rawOutput; + Box? rawError; + try { + rawOutput = Box(await raw(arg0, arg1)); + } catch (e, s) { + rawError = Box(AnyhowException('$e\n\n$s')); + } + + final serializer = SseSerializer(generalizedFrbRustBinding); + assert((rawOutput != null) ^ (rawError != null)); + if (rawOutput != null) { + serializer.buffer.putUint8(0); + sse_encode_bool(rawOutput.value, serializer); + } else { + serializer.buffer.putUint8(1); + sse_encode_AnyhowException(rawError!.value, serializer); + } + final output = serializer.intoRaw(); + + generalizedFrbRustBinding.dartFnDeliverOutput( + callId: callId, + ptr: output.ptr, + rustVecLen: output.rustVecLen, + dataLen: output.dataLen, + ); + }; + } + + Future Function(int, dynamic) + encode_DartFn_Inputs_list_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(List) raw, + ) { + return (callId, rawArg0) async { + final arg0 = dco_decode_list_list_prim_u_8_strict(rawArg0); + + Box? rawOutput; + Box? rawError; + try { + rawOutput = Box(await raw(arg0)); + } catch (e, s) { + rawError = Box(AnyhowException('$e\n\n$s')); + } + + final serializer = SseSerializer(generalizedFrbRustBinding); + assert((rawOutput != null) ^ (rawError != null)); + if (rawOutput != null) { + serializer.buffer.putUint8(0); + sse_encode_bool(rawOutput.value, serializer); + } else { + serializer.buffer.putUint8(1); + sse_encode_AnyhowException(rawError!.value, serializer); + } + final output = serializer.intoRaw(); + + generalizedFrbRustBinding.dartFnDeliverOutput( + callId: callId, + ptr: output.ptr, + rustVecLen: output.rustVecLen, + dataLen: output.dataLen, + ); + }; + } + + Future Function(int, dynamic) + encode_DartFn_Inputs_list_prim_u_8_strict_Output_opt_list_prim_u_8_strict_AnyhowException( + FutureOr Function(Uint8List) raw, + ) { + return (callId, rawArg0) async { + final arg0 = dco_decode_list_prim_u_8_strict(rawArg0); + + Box? rawOutput; + Box? rawError; + try { + rawOutput = Box(await raw(arg0)); + } catch (e, s) { + rawError = Box(AnyhowException('$e\n\n$s')); + } + + final serializer = SseSerializer(generalizedFrbRustBinding); + assert((rawOutput != null) ^ (rawError != null)); + if (rawOutput != null) { + serializer.buffer.putUint8(0); + sse_encode_opt_list_prim_u_8_strict(rawOutput.value, serializer); + } else { + serializer.buffer.putUint8(1); + sse_encode_AnyhowException(rawError!.value, serializer); + } + final output = serializer.intoRaw(); + + generalizedFrbRustBinding.dartFnDeliverOutput( + callId: callId, + ptr: output.ptr, + rustVecLen: output.rustVecLen, + dataLen: output.dataLen, + ); + }; + } + + Future Function(int, dynamic, dynamic, dynamic) + encode_DartFn_Inputs_list_prim_u_8_strict_list_prim_u_8_strict_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(Uint8List, Uint8List, Uint8List) raw, + ) { + return (callId, rawArg0, rawArg1, rawArg2) async { + final arg0 = dco_decode_list_prim_u_8_strict(rawArg0); + final arg1 = dco_decode_list_prim_u_8_strict(rawArg1); + final arg2 = dco_decode_list_prim_u_8_strict(rawArg2); + + Box? rawOutput; + Box? rawError; + try { + rawOutput = Box(await raw(arg0, arg1, arg2)); + } catch (e, s) { + rawError = Box(AnyhowException('$e\n\n$s')); + } + + final serializer = SseSerializer(generalizedFrbRustBinding); + assert((rawOutput != null) ^ (rawError != null)); + if (rawOutput != null) { + serializer.buffer.putUint8(0); + sse_encode_bool(rawOutput.value, serializer); + } else { + serializer.buffer.putUint8(1); + sse_encode_AnyhowException(rawError!.value, serializer); + } + final output = serializer.intoRaw(); + + generalizedFrbRustBinding.dartFnDeliverOutput( + callId: callId, + ptr: output.ptr, + rustVecLen: output.rustVecLen, + dataLen: output.dataLen, + ); + }; + } + + Future Function(int, dynamic) + encode_DartFn_Inputs_other_promotion_Output_bool_AnyhowException( + FutureOr Function(OtherPromotion) raw, + ) { + return (callId, rawArg0) async { + final arg0 = dco_decode_other_promotion(rawArg0); + + Box? rawOutput; + Box? rawError; + try { + rawOutput = Box(await raw(arg0)); + } catch (e, s) { + rawError = Box(AnyhowException('$e\n\n$s')); + } + + final serializer = SseSerializer(generalizedFrbRustBinding); + assert((rawOutput != null) ^ (rawError != null)); + if (rawOutput != null) { + serializer.buffer.putUint8(0); + sse_encode_bool(rawOutput.value, serializer); + } else { + serializer.buffer.putUint8(1); + sse_encode_AnyhowException(rawError!.value, serializer); + } + final output = serializer.intoRaw(); + + generalizedFrbRustBinding.dartFnDeliverOutput( + callId: callId, + ptr: output.ptr, + rustVecLen: output.rustVecLen, + dataLen: output.dataLen, + ); + }; + } @protected AnyhowException dco_decode_AnyhowException(dynamic raw) { @@ -191,12 +956,157 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return AnyhowException(raw as String); } + @protected + FutureOr> Function() + dco_decode_DartFn_Inputs__Output_StreamSink_String_Sse_AnyhowException( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(''); + } + + @protected + FutureOr Function(PlatformInt64) + dco_decode_DartFn_Inputs_i_64_Output_opt_box_autoadd_announced_user_AnyhowException( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(''); + } + + @protected + FutureOr?> Function(PlatformInt64) + dco_decode_DartFn_Inputs_i_64_Output_opt_list_list_prim_u_8_strict_AnyhowException( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(''); + } + + @protected + FutureOr?> Function(PlatformInt64) + dco_decode_DartFn_Inputs_i_64_Output_opt_list_other_promotion_AnyhowException( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(''); + } + + @protected + FutureOr Function(PlatformInt64) + dco_decode_DartFn_Inputs_i_64_Output_opt_list_prim_u_8_strict_AnyhowException( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(''); + } + + @protected + FutureOr Function(PlatformInt64, AnnouncedUser, PlatformInt64?) + dco_decode_DartFn_Inputs_i_64_announced_user_opt_box_autoadd_i_64_Output_bool_AnyhowException( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(''); + } + + @protected + FutureOr Function(PlatformInt64, PlatformInt64, Uint8List) + dco_decode_DartFn_Inputs_i_64_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(''); + } + + @protected + FutureOr Function(PlatformInt64, Uint8List) + dco_decode_DartFn_Inputs_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(''); + } + + @protected + FutureOr Function(List) + dco_decode_DartFn_Inputs_list_list_prim_u_8_strict_Output_bool_AnyhowException( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(''); + } + + @protected + FutureOr Function(Uint8List) + dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_opt_list_prim_u_8_strict_AnyhowException( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(''); + } + + @protected + FutureOr Function(Uint8List, Uint8List, Uint8List) + dco_decode_DartFn_Inputs_list_prim_u_8_strict_list_prim_u_8_strict_list_prim_u_8_strict_Output_bool_AnyhowException( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(''); + } + + @protected + FutureOr Function(OtherPromotion) + dco_decode_DartFn_Inputs_other_promotion_Output_bool_AnyhowException( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(''); + } + + @protected + Object dco_decode_DartOpaque(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return decodeDartOpaque(raw, generalizedFrbRustBinding); + } + + @protected + RustStreamSink dco_decode_StreamSink_String_Sse(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(); + } + @protected String dco_decode_String(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return raw as String; } + @protected + AnnouncedUser dco_decode_announced_user(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + return AnnouncedUser( + userId: dco_decode_i_64(arr[0]), + publicKey: dco_decode_list_prim_u_8_strict(arr[1]), + publicId: dco_decode_i_64(arr[2]), + ); + } + + @protected + bool dco_decode_bool(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as bool; + } + + @protected + AnnouncedUser dco_decode_box_autoadd_announced_user(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return dco_decode_announced_user(raw); + } + @protected PlatformInt64 dco_decode_box_autoadd_i_64(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -210,15 +1120,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - Contact dco_decode_contact(dynamic raw) { + FlutterUserDiscovery dco_decode_flutter_user_discovery(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) - throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); - return Contact( - userId: dco_decode_i_64(arr[0]), - username: dco_decode_String(arr[1]), - ); + if (arr.isNotEmpty) + throw Exception('unexpected arr length: expect 0 but see ${arr.length}'); + return const FlutterUserDiscovery(); } @protected @@ -228,9 +1135,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List dco_decode_list_contact(dynamic raw) { + PlatformInt64 dco_decode_isize(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs - return (raw as List).map(dco_decode_contact).toList(); + return dcoDecodeI64(raw); + } + + @protected + List dco_decode_list_list_prim_u_8_strict(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_list_prim_u_8_strict).toList(); + } + + @protected + List dco_decode_list_other_promotion(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_other_promotion).toList(); + } + + @protected + List dco_decode_list_prim_u_8_loose(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as List; } @protected @@ -239,12 +1164,36 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return raw as Uint8List; } + @protected + AnnouncedUser? dco_decode_opt_box_autoadd_announced_user(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_box_autoadd_announced_user(raw); + } + @protected PlatformInt64? dco_decode_opt_box_autoadd_i_64(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return raw == null ? null : dco_decode_box_autoadd_i_64(raw); } + @protected + List? dco_decode_opt_list_list_prim_u_8_strict(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_list_list_prim_u_8_strict(raw); + } + + @protected + List? dco_decode_opt_list_other_promotion(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_list_other_promotion(raw); + } + + @protected + Uint8List? dco_decode_opt_list_prim_u_8_strict(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_list_prim_u_8_strict(raw); + } + @protected OtherPromotion dco_decode_other_promotion(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -291,6 +1240,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return; } + @protected + BigInt dco_decode_usize(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return dcoDecodeU64(raw); + } + @protected AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -298,6 +1253,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return AnyhowException(inner); } + @protected + Object sse_decode_DartOpaque(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + final inner = sse_decode_isize(deserializer); + return decodeDartOpaque(inner, generalizedFrbRustBinding); + } + + @protected + RustStreamSink sse_decode_StreamSink_String_Sse( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + throw UnimplementedError('Unreachable ()'); + } + @protected String sse_decode_String(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -305,6 +1275,33 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return utf8.decoder.convert(inner); } + @protected + AnnouncedUser sse_decode_announced_user(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + final var_userId = sse_decode_i_64(deserializer); + final var_publicKey = sse_decode_list_prim_u_8_strict(deserializer); + final var_publicId = sse_decode_i_64(deserializer); + return AnnouncedUser( + userId: var_userId, + publicKey: var_publicKey, + publicId: var_publicId, + ); + } + + @protected + bool sse_decode_bool(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return deserializer.buffer.getUint8() != 0; + } + + @protected + AnnouncedUser sse_decode_box_autoadd_announced_user( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + return sse_decode_announced_user(deserializer); + } + @protected PlatformInt64 sse_decode_box_autoadd_i_64(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -320,11 +1317,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - Contact sse_decode_contact(SseDeserializer deserializer) { + FlutterUserDiscovery sse_decode_flutter_user_discovery( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs - final var_userId = sse_decode_i_64(deserializer); - final var_username = sse_decode_String(deserializer); - return Contact(userId: var_userId, username: var_username); + return const FlutterUserDiscovery(); } @protected @@ -334,17 +1331,46 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List sse_decode_list_contact(SseDeserializer deserializer) { + PlatformInt64 sse_decode_isize(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return deserializer.buffer.getPlatformInt64(); + } + + @protected + List sse_decode_list_list_prim_u_8_strict( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs final len_ = sse_decode_i_32(deserializer); - final ans_ = []; + final ans_ = []; for (var idx_ = 0; idx_ < len_; ++idx_) { - ans_.add(sse_decode_contact(deserializer)); + ans_.add(sse_decode_list_prim_u_8_strict(deserializer)); } return ans_; } + @protected + List sse_decode_list_other_promotion( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + + final len_ = sse_decode_i_32(deserializer); + final ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_other_promotion(deserializer)); + } + return ans_; + } + + @protected + List sse_decode_list_prim_u_8_loose(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + final len_ = sse_decode_i_32(deserializer); + return deserializer.buffer.getUint8List(len_); + } + @protected Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -352,6 +1378,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return deserializer.buffer.getUint8List(len_); } + @protected + AnnouncedUser? sse_decode_opt_box_autoadd_announced_user( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return sse_decode_box_autoadd_announced_user(deserializer); + } else { + return null; + } + } + @protected PlatformInt64? sse_decode_opt_box_autoadd_i_64(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -363,6 +1402,43 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + List? sse_decode_opt_list_list_prim_u_8_strict( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return sse_decode_list_list_prim_u_8_strict(deserializer); + } else { + return null; + } + } + + @protected + List? sse_decode_opt_list_other_promotion( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return sse_decode_list_other_promotion(deserializer); + } else { + return null; + } + } + + @protected + Uint8List? sse_decode_opt_list_prim_u_8_strict(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return sse_decode_list_prim_u_8_strict(deserializer); + } else { + return null; + } + } + @protected OtherPromotion sse_decode_other_promotion(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -413,15 +1489,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - int sse_decode_i_32(SseDeserializer deserializer) { + BigInt sse_decode_usize(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return deserializer.buffer.getInt32(); + return deserializer.buffer.getBigUint64(); } @protected - bool sse_decode_bool(SseDeserializer deserializer) { + int sse_decode_i_32(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return deserializer.buffer.getUint8() != 0; + return deserializer.buffer.getInt32(); } @protected @@ -433,12 +1509,241 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(self.message, serializer); } + @protected + void sse_encode_DartFn_Inputs__Output_StreamSink_String_Sse_AnyhowException( + FutureOr> Function() self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_DartOpaque( + encode_DartFn_Inputs__Output_StreamSink_String_Sse_AnyhowException(self), + serializer, + ); + } + + @protected + void + sse_encode_DartFn_Inputs_i_64_Output_opt_box_autoadd_announced_user_AnyhowException( + FutureOr Function(PlatformInt64) self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_DartOpaque( + encode_DartFn_Inputs_i_64_Output_opt_box_autoadd_announced_user_AnyhowException( + self, + ), + serializer, + ); + } + + @protected + void + sse_encode_DartFn_Inputs_i_64_Output_opt_list_list_prim_u_8_strict_AnyhowException( + FutureOr?> Function(PlatformInt64) self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_DartOpaque( + encode_DartFn_Inputs_i_64_Output_opt_list_list_prim_u_8_strict_AnyhowException( + self, + ), + serializer, + ); + } + + @protected + void + sse_encode_DartFn_Inputs_i_64_Output_opt_list_other_promotion_AnyhowException( + FutureOr?> Function(PlatformInt64) self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_DartOpaque( + encode_DartFn_Inputs_i_64_Output_opt_list_other_promotion_AnyhowException( + self, + ), + serializer, + ); + } + + @protected + void + sse_encode_DartFn_Inputs_i_64_Output_opt_list_prim_u_8_strict_AnyhowException( + FutureOr Function(PlatformInt64) self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_DartOpaque( + encode_DartFn_Inputs_i_64_Output_opt_list_prim_u_8_strict_AnyhowException( + self, + ), + serializer, + ); + } + + @protected + void + sse_encode_DartFn_Inputs_i_64_announced_user_opt_box_autoadd_i_64_Output_bool_AnyhowException( + FutureOr Function(PlatformInt64, AnnouncedUser, PlatformInt64?) self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_DartOpaque( + encode_DartFn_Inputs_i_64_announced_user_opt_box_autoadd_i_64_Output_bool_AnyhowException( + self, + ), + serializer, + ); + } + + @protected + void + sse_encode_DartFn_Inputs_i_64_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(PlatformInt64, PlatformInt64, Uint8List) self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_DartOpaque( + encode_DartFn_Inputs_i_64_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + self, + ), + serializer, + ); + } + + @protected + void + sse_encode_DartFn_Inputs_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(PlatformInt64, Uint8List) self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_DartOpaque( + encode_DartFn_Inputs_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + self, + ), + serializer, + ); + } + + @protected + void + sse_encode_DartFn_Inputs_list_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(List) self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_DartOpaque( + encode_DartFn_Inputs_list_list_prim_u_8_strict_Output_bool_AnyhowException( + self, + ), + serializer, + ); + } + + @protected + void + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_opt_list_prim_u_8_strict_AnyhowException( + FutureOr Function(Uint8List) self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_DartOpaque( + encode_DartFn_Inputs_list_prim_u_8_strict_Output_opt_list_prim_u_8_strict_AnyhowException( + self, + ), + serializer, + ); + } + + @protected + void + sse_encode_DartFn_Inputs_list_prim_u_8_strict_list_prim_u_8_strict_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(Uint8List, Uint8List, Uint8List) self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_DartOpaque( + encode_DartFn_Inputs_list_prim_u_8_strict_list_prim_u_8_strict_list_prim_u_8_strict_Output_bool_AnyhowException( + self, + ), + serializer, + ); + } + + @protected + void sse_encode_DartFn_Inputs_other_promotion_Output_bool_AnyhowException( + FutureOr Function(OtherPromotion) self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_DartOpaque( + encode_DartFn_Inputs_other_promotion_Output_bool_AnyhowException(self), + serializer, + ); + } + + @protected + void sse_encode_DartOpaque(Object self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_isize( + PlatformPointerUtil.ptrToPlatformInt64( + encodeDartOpaque( + self, + portManager.dartHandlerPort, + generalizedFrbRustBinding, + ), + ), + serializer, + ); + } + + @protected + void sse_encode_StreamSink_String_Sse( + RustStreamSink self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String( + self.setupAndSerialize( + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + ), + serializer, + ); + } + @protected void sse_encode_String(String self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_list_prim_u_8_strict(utf8.encoder.convert(self), serializer); } + @protected + void sse_encode_announced_user(AnnouncedUser self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_64(self.userId, serializer); + sse_encode_list_prim_u_8_strict(self.publicKey, serializer); + sse_encode_i_64(self.publicId, serializer); + } + + @protected + void sse_encode_bool(bool self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putUint8(self ? 1 : 0); + } + + @protected + void sse_encode_box_autoadd_announced_user( + AnnouncedUser self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_announced_user(self, serializer); + } + @protected void sse_encode_box_autoadd_i_64( PlatformInt64 self, @@ -458,10 +1763,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_contact(Contact self, SseSerializer serializer) { + void sse_encode_flutter_user_discovery( + FlutterUserDiscovery self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_i_64(self.userId, serializer); - sse_encode_String(self.username, serializer); } @protected @@ -471,14 +1777,47 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_contact(List self, SseSerializer serializer) { + void sse_encode_isize(PlatformInt64 self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putPlatformInt64(self); + } + + @protected + void sse_encode_list_list_prim_u_8_strict( + List self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { - sse_encode_contact(item, serializer); + sse_encode_list_prim_u_8_strict(item, serializer); } } + @protected + void sse_encode_list_other_promotion( + List self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_other_promotion(item, serializer); + } + } + + @protected + void sse_encode_list_prim_u_8_loose( + List self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + serializer.buffer.putUint8List( + self is Uint8List ? self : Uint8List.fromList(self), + ); + } + @protected void sse_encode_list_prim_u_8_strict( Uint8List self, @@ -489,6 +1828,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { serializer.buffer.putUint8List(self); } + @protected + void sse_encode_opt_box_autoadd_announced_user( + AnnouncedUser? self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_box_autoadd_announced_user(self, serializer); + } + } + @protected void sse_encode_opt_box_autoadd_i_64( PlatformInt64? self, @@ -502,6 +1854,45 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_opt_list_list_prim_u_8_strict( + List? self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_list_list_prim_u_8_strict(self, serializer); + } + } + + @protected + void sse_encode_opt_list_other_promotion( + List? self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_list_other_promotion(self, serializer); + } + } + + @protected + void sse_encode_opt_list_prim_u_8_strict( + Uint8List? self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_list_prim_u_8_strict(self, serializer); + } + } + @protected void sse_encode_other_promotion( OtherPromotion self, @@ -543,15 +1934,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { // Codec=Sse (Serialization based), see doc to use other codecs } + @protected + void sse_encode_usize(BigInt self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putBigUint64(self); + } + @protected void sse_encode_i_32(int self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs serializer.buffer.putInt32(self); } - - @protected - void sse_encode_bool(bool self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - serializer.buffer.putUint8(self ? 1 : 0); - } } diff --git a/lib/core/frb_generated.io.dart b/lib/core/frb_generated.io.dart index 2216764d..77c9a8a1 100644 --- a/lib/core/frb_generated.io.dart +++ b/lib/core/frb_generated.io.dart @@ -1,7 +1,7 @@ // This file is automatically generated, so please do not edit it. // @generated by `flutter_rust_bridge`@ 2.12.0. -// ignore_for_file: unused_import, non_constant_identifier_names, unused_field +// ignore_for_file: unused_import, unnecessary_import, non_constant_identifier_names, unused_field import 'dart:async'; import 'dart:convert'; @@ -10,7 +10,8 @@ import 'dart:ffi' as ffi; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_io.dart'; import 'bridge.dart'; -import 'database/contact.dart'; +import 'bridge/callbacks.dart'; +import 'bridge/wrapper/user_discovery.dart'; import 'frb_generated.dart'; abstract class RustLibApiImplPlatform extends BaseApiImpl { @@ -24,9 +25,96 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected AnyhowException dco_decode_AnyhowException(dynamic raw); + @protected + FutureOr> Function() + dco_decode_DartFn_Inputs__Output_StreamSink_String_Sse_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(PlatformInt64) + dco_decode_DartFn_Inputs_i_64_Output_opt_box_autoadd_announced_user_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr?> Function(PlatformInt64) + dco_decode_DartFn_Inputs_i_64_Output_opt_list_list_prim_u_8_strict_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr?> Function(PlatformInt64) + dco_decode_DartFn_Inputs_i_64_Output_opt_list_other_promotion_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(PlatformInt64) + dco_decode_DartFn_Inputs_i_64_Output_opt_list_prim_u_8_strict_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(PlatformInt64, AnnouncedUser, PlatformInt64?) + dco_decode_DartFn_Inputs_i_64_announced_user_opt_box_autoadd_i_64_Output_bool_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(PlatformInt64, PlatformInt64, Uint8List) + dco_decode_DartFn_Inputs_i_64_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(PlatformInt64, Uint8List) + dco_decode_DartFn_Inputs_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(List) + dco_decode_DartFn_Inputs_list_list_prim_u_8_strict_Output_bool_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(Uint8List) + dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_opt_list_prim_u_8_strict_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(Uint8List, Uint8List, Uint8List) + dco_decode_DartFn_Inputs_list_prim_u_8_strict_list_prim_u_8_strict_list_prim_u_8_strict_Output_bool_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(OtherPromotion) + dco_decode_DartFn_Inputs_other_promotion_Output_bool_AnyhowException( + dynamic raw, + ); + + @protected + Object dco_decode_DartOpaque(dynamic raw); + + @protected + RustStreamSink dco_decode_StreamSink_String_Sse(dynamic raw); + @protected String dco_decode_String(dynamic raw); + @protected + AnnouncedUser dco_decode_announced_user(dynamic raw); + + @protected + bool dco_decode_bool(dynamic raw); + + @protected + AnnouncedUser dco_decode_box_autoadd_announced_user(dynamic raw); + @protected PlatformInt64 dco_decode_box_autoadd_i_64(dynamic raw); @@ -34,20 +122,41 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { TwonlyConfig dco_decode_box_autoadd_twonly_config(dynamic raw); @protected - Contact dco_decode_contact(dynamic raw); + FlutterUserDiscovery dco_decode_flutter_user_discovery(dynamic raw); @protected PlatformInt64 dco_decode_i_64(dynamic raw); @protected - List dco_decode_list_contact(dynamic raw); + PlatformInt64 dco_decode_isize(dynamic raw); + + @protected + List dco_decode_list_list_prim_u_8_strict(dynamic raw); + + @protected + List dco_decode_list_other_promotion(dynamic raw); + + @protected + List dco_decode_list_prim_u_8_loose(dynamic raw); @protected Uint8List dco_decode_list_prim_u_8_strict(dynamic raw); + @protected + AnnouncedUser? dco_decode_opt_box_autoadd_announced_user(dynamic raw); + @protected PlatformInt64? dco_decode_opt_box_autoadd_i_64(dynamic raw); + @protected + List? dco_decode_opt_list_list_prim_u_8_strict(dynamic raw); + + @protected + List? dco_decode_opt_list_other_promotion(dynamic raw); + + @protected + Uint8List? dco_decode_opt_list_prim_u_8_strict(dynamic raw); + @protected OtherPromotion dco_decode_other_promotion(dynamic raw); @@ -63,12 +172,34 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void dco_decode_unit(dynamic raw); + @protected + BigInt dco_decode_usize(dynamic raw); + @protected AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); + @protected + Object sse_decode_DartOpaque(SseDeserializer deserializer); + + @protected + RustStreamSink sse_decode_StreamSink_String_Sse( + SseDeserializer deserializer, + ); + @protected String sse_decode_String(SseDeserializer deserializer); + @protected + AnnouncedUser sse_decode_announced_user(SseDeserializer deserializer); + + @protected + bool sse_decode_bool(SseDeserializer deserializer); + + @protected + AnnouncedUser sse_decode_box_autoadd_announced_user( + SseDeserializer deserializer, + ); + @protected PlatformInt64 sse_decode_box_autoadd_i_64(SseDeserializer deserializer); @@ -78,20 +209,53 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { ); @protected - Contact sse_decode_contact(SseDeserializer deserializer); + FlutterUserDiscovery sse_decode_flutter_user_discovery( + SseDeserializer deserializer, + ); @protected PlatformInt64 sse_decode_i_64(SseDeserializer deserializer); @protected - List sse_decode_list_contact(SseDeserializer deserializer); + PlatformInt64 sse_decode_isize(SseDeserializer deserializer); + + @protected + List sse_decode_list_list_prim_u_8_strict( + SseDeserializer deserializer, + ); + + @protected + List sse_decode_list_other_promotion( + SseDeserializer deserializer, + ); + + @protected + List sse_decode_list_prim_u_8_loose(SseDeserializer deserializer); @protected Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer); + @protected + AnnouncedUser? sse_decode_opt_box_autoadd_announced_user( + SseDeserializer deserializer, + ); + @protected PlatformInt64? sse_decode_opt_box_autoadd_i_64(SseDeserializer deserializer); + @protected + List? sse_decode_opt_list_list_prim_u_8_strict( + SseDeserializer deserializer, + ); + + @protected + List? sse_decode_opt_list_other_promotion( + SseDeserializer deserializer, + ); + + @protected + Uint8List? sse_decode_opt_list_prim_u_8_strict(SseDeserializer deserializer); + @protected OtherPromotion sse_decode_other_promotion(SseDeserializer deserializer); @@ -108,10 +272,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_decode_unit(SseDeserializer deserializer); @protected - int sse_decode_i_32(SseDeserializer deserializer); + BigInt sse_decode_usize(SseDeserializer deserializer); @protected - bool sse_decode_bool(SseDeserializer deserializer); + int sse_decode_i_32(SseDeserializer deserializer); @protected void sse_encode_AnyhowException( @@ -119,9 +283,112 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_DartFn_Inputs__Output_StreamSink_String_Sse_AnyhowException( + FutureOr> Function() self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_i_64_Output_opt_box_autoadd_announced_user_AnyhowException( + FutureOr Function(PlatformInt64) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_i_64_Output_opt_list_list_prim_u_8_strict_AnyhowException( + FutureOr?> Function(PlatformInt64) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_i_64_Output_opt_list_other_promotion_AnyhowException( + FutureOr?> Function(PlatformInt64) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_i_64_Output_opt_list_prim_u_8_strict_AnyhowException( + FutureOr Function(PlatformInt64) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_i_64_announced_user_opt_box_autoadd_i_64_Output_bool_AnyhowException( + FutureOr Function(PlatformInt64, AnnouncedUser, PlatformInt64?) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_i_64_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(PlatformInt64, PlatformInt64, Uint8List) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(PlatformInt64, Uint8List) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_list_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(List) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_opt_list_prim_u_8_strict_AnyhowException( + FutureOr Function(Uint8List) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_list_prim_u_8_strict_list_prim_u_8_strict_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(Uint8List, Uint8List, Uint8List) self, + SseSerializer serializer, + ); + + @protected + void sse_encode_DartFn_Inputs_other_promotion_Output_bool_AnyhowException( + FutureOr Function(OtherPromotion) self, + SseSerializer serializer, + ); + + @protected + void sse_encode_DartOpaque(Object self, SseSerializer serializer); + + @protected + void sse_encode_StreamSink_String_Sse( + RustStreamSink self, + SseSerializer serializer, + ); + @protected void sse_encode_String(String self, SseSerializer serializer); + @protected + void sse_encode_announced_user(AnnouncedUser self, SseSerializer serializer); + + @protected + void sse_encode_bool(bool self, SseSerializer serializer); + + @protected + void sse_encode_box_autoadd_announced_user( + AnnouncedUser self, + SseSerializer serializer, + ); + @protected void sse_encode_box_autoadd_i_64( PlatformInt64 self, @@ -135,13 +402,31 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { ); @protected - void sse_encode_contact(Contact self, SseSerializer serializer); + void sse_encode_flutter_user_discovery( + FlutterUserDiscovery self, + SseSerializer serializer, + ); @protected void sse_encode_i_64(PlatformInt64 self, SseSerializer serializer); @protected - void sse_encode_list_contact(List self, SseSerializer serializer); + void sse_encode_isize(PlatformInt64 self, SseSerializer serializer); + + @protected + void sse_encode_list_list_prim_u_8_strict( + List self, + SseSerializer serializer, + ); + + @protected + void sse_encode_list_other_promotion( + List self, + SseSerializer serializer, + ); + + @protected + void sse_encode_list_prim_u_8_loose(List self, SseSerializer serializer); @protected void sse_encode_list_prim_u_8_strict( @@ -149,12 +434,36 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_opt_box_autoadd_announced_user( + AnnouncedUser? self, + SseSerializer serializer, + ); + @protected void sse_encode_opt_box_autoadd_i_64( PlatformInt64? self, SseSerializer serializer, ); + @protected + void sse_encode_opt_list_list_prim_u_8_strict( + List? self, + SseSerializer serializer, + ); + + @protected + void sse_encode_opt_list_other_promotion( + List? self, + SseSerializer serializer, + ); + + @protected + void sse_encode_opt_list_prim_u_8_strict( + Uint8List? self, + SseSerializer serializer, + ); + @protected void sse_encode_other_promotion( OtherPromotion self, @@ -174,10 +483,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_unit(void self, SseSerializer serializer); @protected - void sse_encode_i_32(int self, SseSerializer serializer); + void sse_encode_usize(BigInt self, SseSerializer serializer); @protected - void sse_encode_bool(bool self, SseSerializer serializer); + void sse_encode_i_32(int self, SseSerializer serializer); } // Section: wire_class diff --git a/lib/core/frb_generated.web.dart b/lib/core/frb_generated.web.dart index b658ac73..d56eac0e 100644 --- a/lib/core/frb_generated.web.dart +++ b/lib/core/frb_generated.web.dart @@ -1,7 +1,7 @@ // This file is automatically generated, so please do not edit it. // @generated by `flutter_rust_bridge`@ 2.12.0. -// ignore_for_file: unused_import, non_constant_identifier_names +// ignore_for_file: unused_import, unnecessary_import, non_constant_identifier_names // Static analysis wrongly picks the IO variant, thus ignore this @@ -11,7 +11,8 @@ import 'dart:convert'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_web.dart'; import 'bridge.dart'; -import 'database/contact.dart'; +import 'bridge/callbacks.dart'; +import 'bridge/wrapper/user_discovery.dart'; import 'frb_generated.dart'; abstract class RustLibApiImplPlatform extends BaseApiImpl { @@ -25,9 +26,96 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected AnyhowException dco_decode_AnyhowException(dynamic raw); + @protected + FutureOr> Function() + dco_decode_DartFn_Inputs__Output_StreamSink_String_Sse_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(PlatformInt64) + dco_decode_DartFn_Inputs_i_64_Output_opt_box_autoadd_announced_user_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr?> Function(PlatformInt64) + dco_decode_DartFn_Inputs_i_64_Output_opt_list_list_prim_u_8_strict_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr?> Function(PlatformInt64) + dco_decode_DartFn_Inputs_i_64_Output_opt_list_other_promotion_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(PlatformInt64) + dco_decode_DartFn_Inputs_i_64_Output_opt_list_prim_u_8_strict_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(PlatformInt64, AnnouncedUser, PlatformInt64?) + dco_decode_DartFn_Inputs_i_64_announced_user_opt_box_autoadd_i_64_Output_bool_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(PlatformInt64, PlatformInt64, Uint8List) + dco_decode_DartFn_Inputs_i_64_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(PlatformInt64, Uint8List) + dco_decode_DartFn_Inputs_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(List) + dco_decode_DartFn_Inputs_list_list_prim_u_8_strict_Output_bool_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(Uint8List) + dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_opt_list_prim_u_8_strict_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(Uint8List, Uint8List, Uint8List) + dco_decode_DartFn_Inputs_list_prim_u_8_strict_list_prim_u_8_strict_list_prim_u_8_strict_Output_bool_AnyhowException( + dynamic raw, + ); + + @protected + FutureOr Function(OtherPromotion) + dco_decode_DartFn_Inputs_other_promotion_Output_bool_AnyhowException( + dynamic raw, + ); + + @protected + Object dco_decode_DartOpaque(dynamic raw); + + @protected + RustStreamSink dco_decode_StreamSink_String_Sse(dynamic raw); + @protected String dco_decode_String(dynamic raw); + @protected + AnnouncedUser dco_decode_announced_user(dynamic raw); + + @protected + bool dco_decode_bool(dynamic raw); + + @protected + AnnouncedUser dco_decode_box_autoadd_announced_user(dynamic raw); + @protected PlatformInt64 dco_decode_box_autoadd_i_64(dynamic raw); @@ -35,20 +123,41 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { TwonlyConfig dco_decode_box_autoadd_twonly_config(dynamic raw); @protected - Contact dco_decode_contact(dynamic raw); + FlutterUserDiscovery dco_decode_flutter_user_discovery(dynamic raw); @protected PlatformInt64 dco_decode_i_64(dynamic raw); @protected - List dco_decode_list_contact(dynamic raw); + PlatformInt64 dco_decode_isize(dynamic raw); + + @protected + List dco_decode_list_list_prim_u_8_strict(dynamic raw); + + @protected + List dco_decode_list_other_promotion(dynamic raw); + + @protected + List dco_decode_list_prim_u_8_loose(dynamic raw); @protected Uint8List dco_decode_list_prim_u_8_strict(dynamic raw); + @protected + AnnouncedUser? dco_decode_opt_box_autoadd_announced_user(dynamic raw); + @protected PlatformInt64? dco_decode_opt_box_autoadd_i_64(dynamic raw); + @protected + List? dco_decode_opt_list_list_prim_u_8_strict(dynamic raw); + + @protected + List? dco_decode_opt_list_other_promotion(dynamic raw); + + @protected + Uint8List? dco_decode_opt_list_prim_u_8_strict(dynamic raw); + @protected OtherPromotion dco_decode_other_promotion(dynamic raw); @@ -64,12 +173,34 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void dco_decode_unit(dynamic raw); + @protected + BigInt dco_decode_usize(dynamic raw); + @protected AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); + @protected + Object sse_decode_DartOpaque(SseDeserializer deserializer); + + @protected + RustStreamSink sse_decode_StreamSink_String_Sse( + SseDeserializer deserializer, + ); + @protected String sse_decode_String(SseDeserializer deserializer); + @protected + AnnouncedUser sse_decode_announced_user(SseDeserializer deserializer); + + @protected + bool sse_decode_bool(SseDeserializer deserializer); + + @protected + AnnouncedUser sse_decode_box_autoadd_announced_user( + SseDeserializer deserializer, + ); + @protected PlatformInt64 sse_decode_box_autoadd_i_64(SseDeserializer deserializer); @@ -79,20 +210,53 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { ); @protected - Contact sse_decode_contact(SseDeserializer deserializer); + FlutterUserDiscovery sse_decode_flutter_user_discovery( + SseDeserializer deserializer, + ); @protected PlatformInt64 sse_decode_i_64(SseDeserializer deserializer); @protected - List sse_decode_list_contact(SseDeserializer deserializer); + PlatformInt64 sse_decode_isize(SseDeserializer deserializer); + + @protected + List sse_decode_list_list_prim_u_8_strict( + SseDeserializer deserializer, + ); + + @protected + List sse_decode_list_other_promotion( + SseDeserializer deserializer, + ); + + @protected + List sse_decode_list_prim_u_8_loose(SseDeserializer deserializer); @protected Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer); + @protected + AnnouncedUser? sse_decode_opt_box_autoadd_announced_user( + SseDeserializer deserializer, + ); + @protected PlatformInt64? sse_decode_opt_box_autoadd_i_64(SseDeserializer deserializer); + @protected + List? sse_decode_opt_list_list_prim_u_8_strict( + SseDeserializer deserializer, + ); + + @protected + List? sse_decode_opt_list_other_promotion( + SseDeserializer deserializer, + ); + + @protected + Uint8List? sse_decode_opt_list_prim_u_8_strict(SseDeserializer deserializer); + @protected OtherPromotion sse_decode_other_promotion(SseDeserializer deserializer); @@ -109,10 +273,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_decode_unit(SseDeserializer deserializer); @protected - int sse_decode_i_32(SseDeserializer deserializer); + BigInt sse_decode_usize(SseDeserializer deserializer); @protected - bool sse_decode_bool(SseDeserializer deserializer); + int sse_decode_i_32(SseDeserializer deserializer); @protected void sse_encode_AnyhowException( @@ -120,9 +284,112 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_DartFn_Inputs__Output_StreamSink_String_Sse_AnyhowException( + FutureOr> Function() self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_i_64_Output_opt_box_autoadd_announced_user_AnyhowException( + FutureOr Function(PlatformInt64) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_i_64_Output_opt_list_list_prim_u_8_strict_AnyhowException( + FutureOr?> Function(PlatformInt64) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_i_64_Output_opt_list_other_promotion_AnyhowException( + FutureOr?> Function(PlatformInt64) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_i_64_Output_opt_list_prim_u_8_strict_AnyhowException( + FutureOr Function(PlatformInt64) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_i_64_announced_user_opt_box_autoadd_i_64_Output_bool_AnyhowException( + FutureOr Function(PlatformInt64, AnnouncedUser, PlatformInt64?) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_i_64_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(PlatformInt64, PlatformInt64, Uint8List) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(PlatformInt64, Uint8List) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_list_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(List) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_opt_list_prim_u_8_strict_AnyhowException( + FutureOr Function(Uint8List) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_list_prim_u_8_strict_list_prim_u_8_strict_list_prim_u_8_strict_Output_bool_AnyhowException( + FutureOr Function(Uint8List, Uint8List, Uint8List) self, + SseSerializer serializer, + ); + + @protected + void sse_encode_DartFn_Inputs_other_promotion_Output_bool_AnyhowException( + FutureOr Function(OtherPromotion) self, + SseSerializer serializer, + ); + + @protected + void sse_encode_DartOpaque(Object self, SseSerializer serializer); + + @protected + void sse_encode_StreamSink_String_Sse( + RustStreamSink self, + SseSerializer serializer, + ); + @protected void sse_encode_String(String self, SseSerializer serializer); + @protected + void sse_encode_announced_user(AnnouncedUser self, SseSerializer serializer); + + @protected + void sse_encode_bool(bool self, SseSerializer serializer); + + @protected + void sse_encode_box_autoadd_announced_user( + AnnouncedUser self, + SseSerializer serializer, + ); + @protected void sse_encode_box_autoadd_i_64( PlatformInt64 self, @@ -136,13 +403,31 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { ); @protected - void sse_encode_contact(Contact self, SseSerializer serializer); + void sse_encode_flutter_user_discovery( + FlutterUserDiscovery self, + SseSerializer serializer, + ); @protected void sse_encode_i_64(PlatformInt64 self, SseSerializer serializer); @protected - void sse_encode_list_contact(List self, SseSerializer serializer); + void sse_encode_isize(PlatformInt64 self, SseSerializer serializer); + + @protected + void sse_encode_list_list_prim_u_8_strict( + List self, + SseSerializer serializer, + ); + + @protected + void sse_encode_list_other_promotion( + List self, + SseSerializer serializer, + ); + + @protected + void sse_encode_list_prim_u_8_loose(List self, SseSerializer serializer); @protected void sse_encode_list_prim_u_8_strict( @@ -150,12 +435,36 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_opt_box_autoadd_announced_user( + AnnouncedUser? self, + SseSerializer serializer, + ); + @protected void sse_encode_opt_box_autoadd_i_64( PlatformInt64? self, SseSerializer serializer, ); + @protected + void sse_encode_opt_list_list_prim_u_8_strict( + List? self, + SseSerializer serializer, + ); + + @protected + void sse_encode_opt_list_other_promotion( + List? self, + SseSerializer serializer, + ); + + @protected + void sse_encode_opt_list_prim_u_8_strict( + Uint8List? self, + SseSerializer serializer, + ); + @protected void sse_encode_other_promotion( OtherPromotion self, @@ -175,10 +484,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_unit(void self, SseSerializer serializer); @protected - void sse_encode_i_32(int self, SseSerializer serializer); + void sse_encode_usize(BigInt self, SseSerializer serializer); @protected - void sse_encode_bool(bool self, SseSerializer serializer); + void sse_encode_i_32(int self, SseSerializer serializer); } // Section: wire_class diff --git a/lib/main.dart b/lib/main.dart index 51d3e381..60db82de 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,6 +10,7 @@ import 'package:twonly/app.dart'; import 'package:twonly/core/bridge.dart' as bridge; import 'package:twonly/core/frb_generated.dart'; import 'package:twonly/globals.dart'; +import 'package:twonly/src/callbacks/callbacks.dart'; import 'package:twonly/src/database/twonly.db.dart'; import 'package:twonly/src/providers/connection.provider.dart'; import 'package:twonly/src/providers/image_editor.provider.dart'; @@ -37,7 +38,11 @@ void main() async { globalApplicationSupportDirectory = (await getApplicationSupportDirectory()).path; - await bridge.initializeTwonly( + initLogger(); + + await initFlutterCallbacksForRust(); + + await bridge.initializeTwonlyFlutter( config: bridge.TwonlyConfig( databasePath: '$globalApplicationSupportDirectory/twonly.sqlite', dataDirectory: globalApplicationSupportDirectory, @@ -68,8 +73,6 @@ void main() async { await deleteLocalUserData(); } - initLogger(); - final settingsController = SettingsChangeProvider(); await settingsController.loadSettings(); diff --git a/lib/src/callbacks/callbacks.dart b/lib/src/callbacks/callbacks.dart new file mode 100644 index 00000000..ae062921 --- /dev/null +++ b/lib/src/callbacks/callbacks.dart @@ -0,0 +1,28 @@ +import 'package:twonly/core/bridge/callbacks.dart'; +import 'package:twonly/src/callbacks/logging.callbacks.dart'; +import 'package:twonly/src/callbacks/user_discovery.callbacks.dart'; + +Future initFlutterCallbacksForRust() async { + await initFlutterCallbacks( + loggingGetStreamSink: LoggingCallbacks.getStreamSink, + userDiscoverySetShares: UserDiscoveryCallbacks.setShares, + userDiscoveryGetShareForContact: + UserDiscoveryCallbacks.userDiscoveryGetShareForContact, + userDiscoveryPushOwnPromotion: UserDiscoveryCallbacks.pushOwnPromotion, + userDiscoveryPushNewUserRelation: + UserDiscoveryCallbacks.pushNewUserRelation, + userDiscoveryGetOwnPromotionsAfterVersion: + UserDiscoveryCallbacks.getOwnPromotionsAfterVersion, + userDiscoveryStoreOtherPromotion: + UserDiscoveryCallbacks.storeOtherPromotion, + userDiscoveryGetOtherPromotionsByPublicId: + UserDiscoveryCallbacks.getOtherPromotionsByPublicId, + userDiscoveryGetAnnouncedUserByPublicId: + UserDiscoveryCallbacks.getAnnouncedUserByPublicId, + userDiscoveryGetContactVersion: UserDiscoveryCallbacks.getContactVersion, + userDiscoverySetContactVersion: UserDiscoveryCallbacks.setContactVersion, + userDiscoverySignData: UserDiscoveryCallbacks.signData, + userDiscoveryVerifySignature: UserDiscoveryCallbacks.verifySignature, + userDiscoveryVerifyStoredPubkey: UserDiscoveryCallbacks.verifyStoredPubKey, + ); +} diff --git a/lib/src/callbacks/logging.callbacks.dart b/lib/src/callbacks/logging.callbacks.dart new file mode 100644 index 00000000..bd8e7117 --- /dev/null +++ b/lib/src/callbacks/logging.callbacks.dart @@ -0,0 +1,32 @@ +import 'dart:async'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; +import 'package:twonly/src/utils/log.dart'; + +class LoggingCallbacks { + static Future> getStreamSink() async { + final dartLogSink = RustStreamSink(); + + Timer.periodic(const Duration(milliseconds: 100), (timer) { + try { + dartLogSink.stream.listen( + (log) { + if (log.contains('INFO ')) { + Log.info(log.split('INFO ')[1]); + } else if (log.contains('DEBUG ')) { + Log.info(log.split('DEBUG ')[1]); + } else if (kDebugMode) { + print(log); + } + }, + onDone: () => Log.error('Log stream closed'), + ); + timer.cancel(); + } catch (e) { + // stream not yet initialized + } + }); + + return dartLogSink; + } +} diff --git a/lib/src/callbacks/user_discovery.callbacks.dart b/lib/src/callbacks/user_discovery.callbacks.dart new file mode 100644 index 00000000..8d4964db --- /dev/null +++ b/lib/src/callbacks/user_discovery.callbacks.dart @@ -0,0 +1,294 @@ +import 'package:drift/drift.dart'; +import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart' + show Curve, IdentityKey; +// ignore: implementation_imports +import 'package:libsignal_protocol_dart/src/ecc/ed25519.dart'; +import 'package:twonly/core/bridge.dart'; +import 'package:twonly/globals.dart'; +import 'package:twonly/src/database/twonly.db.dart'; +import 'package:twonly/src/services/signal/identity.signal.dart'; +import 'package:twonly/src/services/signal/session.signal.dart'; +import 'package:twonly/src/utils/log.dart'; +import 'package:twonly/src/utils/misc.dart'; + +class UserDiscoveryCallbacks { + static Future signData( + Uint8List inputData, + ) async { + var privKey = (await getSignalIdentityKeyPair())?.getPrivateKey(); + if (privKey == null) return null; + final random = getRandomUint8List(32); + final signature = sign( + privKey.serialize(), + inputData, + random, + ); + privKey = null; + return signature; + } + + static Future verifySignature( + Uint8List inputData, + Uint8List pubKey, + Uint8List signature, + ) async { + return Curve.verifySignature( + IdentityKey.fromBytes(pubKey, 0).publicKey, + inputData, + signature, + ); + } + + static Future verifyStoredPubKey( + int contactId, + Uint8List pubKey, + ) async { + final storedPublicKey = await getPublicKeyFromContact(contactId); + if (storedPublicKey != null) { + return storedPublicKey == pubKey; + } else { + return false; + } + } + + static Future setShares(List shares) async { + try { + // First remove all old shares then insert all the new shares + await twonlyDB.delete(twonlyDB.userDiscoveryShares).go(); + await twonlyDB.batch((b) { + b.insertAll( + twonlyDB.userDiscoveryShares, + shares + .map((s) => UserDiscoverySharesCompanion(share: Value(s))) + .toList(), + ); + }); + return true; + } catch (e) { + Log.error(e); + return false; + } + } + + static Future userDiscoveryGetShareForContact( + int contactId, + ) async { + return twonlyDB.transaction(() async { + // 1. Check if this contact already has a share assigned + final existing = + await (twonlyDB.select(twonlyDB.userDiscoveryShares) + ..where((tbl) => tbl.contactId.equals(contactId)) + ..limit(1)) + .getSingleOrNull(); + + if (existing != null) { + return existing.share; + } + + // 2. No share found. Find an available one (where contactId is null) + final available = + await (twonlyDB.select(twonlyDB.userDiscoveryShares) + ..where((tbl) => tbl.contactId.isNull()) + ..limit(1)) + .getSingleOrNull(); + + if (available != null) { + // 3. Assign the contactId to this available share + await (twonlyDB.update( + twonlyDB.userDiscoveryShares, + )..where((tbl) => tbl.shareId.equals(available.shareId))).write( + UserDiscoverySharesCompanion( + contactId: Value(contactId), + ), + ); + + return available.share; + } + + return null; // 4. No existing or available shares found + }); + } + + static Future pushOwnPromotion( + int contactId, + int version, // Maps to versionId or logic control + Uint8List promotion, + ) async { + try { + await twonlyDB + .into(twonlyDB.userDiscoveryOwnPromotions) + .insert( + UserDiscoveryOwnPromotionsCompanion.insert( + contactId: contactId, + promotion: promotion, + ), + ); + return true; + } catch (e) { + Log.error(e); + return false; + } + } + + static Future> getOwnPromotionsAfterVersion( + int version, + ) async { + final query = twonlyDB.select(twonlyDB.userDiscoveryOwnPromotions) + ..where((tbl) => tbl.versionId.isBiggerThanValue(version)); + + final rows = await query.get(); + return rows.map((r) => r.promotion).toList(); + } + + static Future storeOtherPromotion( + OtherPromotion promotion, + ) async { + try { + await twonlyDB + .into(twonlyDB.userDiscoveryOtherPromotions) + .insertOnConflictUpdate( + UserDiscoveryOtherPromotionsCompanion( + promotionId: Value(promotion.promotionId), + publicId: Value(promotion.publicId), + fromContactId: Value(promotion.fromContactId), + threshold: Value(promotion.threshold), + announcementShare: Value(promotion.announcementShare), + publicKeyVerifiedTimestamp: Value( + promotion.publicKeyVerifiedTimestamp == null + ? null + : DateTime.fromMillisecondsSinceEpoch( + promotion.publicKeyVerifiedTimestamp!, + ), + ), + ), + ); + return true; + } catch (e) { + Log.error(e); + return false; + } + } + + static Future> getOtherPromotionsByPublicId( + int publicId, + ) async { + final rows = await (twonlyDB.select( + twonlyDB.userDiscoveryOtherPromotions, + )..where((tbl) => tbl.publicId.equals(publicId))).get(); + + return rows + .map( + (row) => OtherPromotion( + promotionId: row.promotionId, + publicId: row.publicId, + fromContactId: row.fromContactId, + threshold: row.threshold, + announcementShare: row.announcementShare, + publicKeyVerifiedTimestamp: + row.publicKeyVerifiedTimestamp?.millisecondsSinceEpoch, + ), + ) + .toList(); + } + + static Future getAnnouncedUserByPublicId( + int publicId, + ) async { + final row = await (twonlyDB.select( + twonlyDB.userDiscoveryAnnouncedUsers, + )..where((tbl) => tbl.publicId.equals(publicId))).getSingleOrNull(); + if (row == null) return null; + return AnnouncedUser( + userId: row.announcedUserId, + publicKey: row.announcedPublicKey, + publicId: row.publicId, + ); + } + + static Future pushNewUserRelation( + int fromContactId, + AnnouncedUser announcedUser, + int? publicKeyVerifiedTimestamp, + ) async { + try { + await twonlyDB.transaction(() async { + // 1. Ensure the user exists in the AnnouncedUsers table + await twonlyDB + .into(twonlyDB.userDiscoveryAnnouncedUsers) + .insertOnConflictUpdate( + UserDiscoveryAnnouncedUser( + announcedUserId: announcedUser.userId, + announcedPublicKey: announcedUser.publicKey, + publicId: announcedUser.publicId, + ), + ); + + // 2. Insert or update the relation + await twonlyDB + .into(twonlyDB.userDiscoveryUserRelations) + .insertOnConflictUpdate( + UserDiscoveryUserRelationsCompanion.insert( + announcedUserId: announcedUser.userId, + fromContactId: fromContactId, + publicKeyVerifiedTimestamp: Value( + publicKeyVerifiedTimestamp != null + ? DateTime.fromMillisecondsSinceEpoch( + publicKeyVerifiedTimestamp, + ) + : null, + ), + ), + ); + }); + return true; + } catch (e) { + Log.error(e); + return false; + } + } + + // static Future>> + // getAllAnnouncedUsers() async { + // final query = twonlyDB.select(twonlyDB.userDiscoveryAnnouncedUsers).join([ + // innerJoin( + // twonlyDB.userDiscoveryUserRelations, + // twonlyDB.userDiscoveryUserRelations.announcedUserId.equalsExp( + // twonlyDB.userDiscoveryAnnouncedUsers.announcedUserId, + // ), + // ), + // ]); + + // final results = await query.get(); + // final map = >{}; + + // for (final row in results) { + // final user = row.readTable(twonlyDB.userDiscoveryAnnouncedUsers); + // final relation = row.readTable(twonlyDB.userDiscoveryUserRelations); + + // map.putIfAbsent(user, () => []).add( + // (relation.fromContactId, relation.publicKeyVerifiedTimestamp), + // ); + // } + + // return map; + // } + + static Future getContactVersion(int contactId) async { + final row = await (twonlyDB.select( + twonlyDB.contacts, + )..where((tbl) => tbl.userId.equals(contactId))).getSingleOrNull(); + return row?.userDiscoveryVersion; + } + + static Future setContactVersion(int contactId, Uint8List update) async { + try { + await (twonlyDB.update(twonlyDB.contacts) + ..where((tbl) => tbl.userId.equals(contactId))) + .write(ContactsCompanion(userDiscoveryVersion: Value(update))); + return true; + } catch (e) { + Log.error(e); + return false; + } + } +} diff --git a/lib/src/constants/routes.keys.dart b/lib/src/constants/routes.keys.dart index 157c27da..66a1fabb 100644 --- a/lib/src/constants/routes.keys.dart +++ b/lib/src/constants/routes.keys.dart @@ -34,6 +34,8 @@ class Routes { static const String settingsPrivacy = '/settings/privacy'; static const String settingsPrivacyBlockUsers = '/settings/privacy/block_users'; + static const String settingsPrivacyUserDiscovery = + '/settings/privacy/user_discovery'; static const String settingsNotification = '/settings/notification'; static const String settingsStorage = '/settings/storage_data'; static const String settingsStorageImport = '/settings/storage_data/import'; diff --git a/lib/src/model/json/userdata.dart b/lib/src/model/json/userdata.dart index 04f52587..f7495472 100644 --- a/lib/src/model/json/userdata.dart +++ b/lib/src/model/json/userdata.dart @@ -96,6 +96,9 @@ class UserData { @JsonKey(defaultValue: false) bool isUserDiscoveryEnabled = false; + @JsonKey(defaultValue: false) + int minimumRequiredImagesExchanged = 4; + // -- Custom DATA -- @JsonKey(defaultValue: 100_000) diff --git a/lib/src/providers/routing.provider.dart b/lib/src/providers/routing.provider.dart index d1eb1b00..cf43cedf 100644 --- a/lib/src/providers/routing.provider.dart +++ b/lib/src/providers/routing.provider.dart @@ -37,7 +37,8 @@ import 'package:twonly/src/views/settings/help/faq/verifybadge.dart'; import 'package:twonly/src/views/settings/help/help.view.dart'; import 'package:twonly/src/views/settings/notification.view.dart'; import 'package:twonly/src/views/settings/privacy.view.dart'; -import 'package:twonly/src/views/settings/privacy_view_block.view.dart'; +import 'package:twonly/src/views/settings/privacy/block_users.view.dart'; +import 'package:twonly/src/views/settings/privacy/user_discovery.view.dart'; import 'package:twonly/src/views/settings/profile/modify_avatar.view.dart'; import 'package:twonly/src/views/settings/profile/profile.view.dart'; import 'package:twonly/src/views/settings/settings_main.view.dart'; @@ -200,7 +201,11 @@ final routerProvider = GoRouter( routes: [ GoRoute( path: 'block_users', - builder: (context, state) => const PrivacyViewBlockUsersView(), + builder: (context, state) => const BlockUsersView(), + ), + GoRoute( + path: 'user_discovery', + builder: (context, state) => const UserDiscoverySettingsView(), ), ], ), diff --git a/lib/src/services/user_discovery.service.dart b/lib/src/services/user_discovery.service.dart new file mode 100644 index 00000000..742cbac3 --- /dev/null +++ b/lib/src/services/user_discovery.service.dart @@ -0,0 +1,26 @@ +import 'package:twonly/core/bridge/wrapper/user_discovery.dart'; +import 'package:twonly/globals.dart'; +import 'package:twonly/src/utils/log.dart'; +import 'package:twonly/src/utils/qr.dart'; +import 'package:twonly/src/utils/storage.dart'; + +Future initializeOrUpdateUserDiscovery({ + required int threshold, + required int minimumRequiredImagesExchanged, +}) async { + try { + await FlutterUserDiscovery.initializeOrUpdate( + threshold: threshold, + userId: gUser.userId, + publicKey: await getUserPublicKey(), + ); + await updateUserdata((u) { + u + ..isUserDiscoveryEnabled = true + ..minimumRequiredImagesExchanged = minimumRequiredImagesExchanged; + return u; + }); + } catch (e) { + Log.error(e); + } +} diff --git a/lib/src/themes/light.dart b/lib/src/themes/light.dart index 88bfc716..a6841cd8 100644 --- a/lib/src/themes/light.dart +++ b/lib/src/themes/light.dart @@ -1,10 +1,32 @@ import 'package:flutter/material.dart'; +final primaryColor = const Color(0xFF57CC99); + final ThemeData lightTheme = ThemeData( colorScheme: ColorScheme.fromSeed( - seedColor: const Color(0xFF57CC99), + seedColor: primaryColor, ), inputDecorationTheme: const InputDecorationTheme( border: OutlineInputBorder(), ), ); + +final ButtonStyle primaryColorButtonStyle = FilledButton.styleFrom( + backgroundColor: primaryColor, + foregroundColor: Colors.black87, + padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16), + // Adjusting the border radius (default is usually 20+) + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), // Lower number = sharper corners + ), +); + +final ButtonStyle secondaryGreyButtonStyle = FilledButton.styleFrom( + backgroundColor: Colors.grey[200], + foregroundColor: Colors.black87, + padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16), + // Adjusting the border radius (default is usually 20+) + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), // Lower number = sharper corners + ), +); diff --git a/lib/src/utils/misc.dart b/lib/src/utils/misc.dart index fb35ec52..606a812d 100644 --- a/lib/src/utils/misc.dart +++ b/lib/src/utils/misc.dart @@ -404,3 +404,50 @@ Future> sha256File(File file) async { converter.close(); return sha256Sink.events.single.bytes; } + +List formattedText(String input) { + // Pattern to find text between asterisks + final regex = RegExp(r'\*(.*?)\*'); + final List spans = []; + + // Track the current position in the string + int lastMatchEnd = 0; + + for (final match in regex.allMatches(input)) { + // Add text before the match (Normal style) + if (match.start > lastMatchEnd) { + spans.add( + TextSpan( + text: input.substring(lastMatchEnd, match.start), + style: const TextStyle(color: Colors.black), + ), + ); + } + + // Add the matched text (Bold style) + // match.group(1) is the text without the asterisks + spans.add( + TextSpan( + text: match.group(1), + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ); + + lastMatchEnd = match.end; + } + + // Add any remaining text after the last match + if (lastMatchEnd < input.length) { + spans.add( + TextSpan( + text: input.substring(lastMatchEnd), + style: const TextStyle(color: Colors.black), + ), + ); + } + + return spans; +} diff --git a/lib/src/views/settings/privacy.view.dart b/lib/src/views/settings/privacy.view.dart index 3607b30a..89a92209 100644 --- a/lib/src/views/settings/privacy.view.dart +++ b/lib/src/views/settings/privacy.view.dart @@ -73,6 +73,13 @@ class _PrivacyViewState extends State { setState(() {}); }, ), + ListTile( + title: const Text('Freunde finden'), + onTap: () async { + await context.push(Routes.settingsPrivacyUserDiscovery); + setState(() {}); + }, + ), const Divider(), ListTile( title: Text(context.lang.settingsTypingIndication), diff --git a/lib/src/views/settings/privacy_view_block.view.dart b/lib/src/views/settings/privacy/block_users.view.dart similarity index 93% rename from lib/src/views/settings/privacy_view_block.view.dart rename to lib/src/views/settings/privacy/block_users.view.dart index d9b835d2..57f55c2c 100644 --- a/lib/src/views/settings/privacy_view_block.view.dart +++ b/lib/src/views/settings/privacy/block_users.view.dart @@ -7,14 +7,14 @@ import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/views/components/avatar_icon.component.dart'; import 'package:twonly/src/views/components/user_context_menu.component.dart'; -class PrivacyViewBlockUsersView extends StatefulWidget { - const PrivacyViewBlockUsersView({super.key}); +class BlockUsersView extends StatefulWidget { + const BlockUsersView({super.key}); @override - State createState() => _PrivacyViewBlockUsers(); + State createState() => _PrivacyViewBlockUsers(); } -class _PrivacyViewBlockUsers extends State { +class _PrivacyViewBlockUsers extends State { late Stream> allUsers; List filteredUsers = []; String filter = ''; diff --git a/lib/src/views/settings/privacy/user_discovery.view.dart b/lib/src/views/settings/privacy/user_discovery.view.dart new file mode 100644 index 00000000..93f9323a --- /dev/null +++ b/lib/src/views/settings/privacy/user_discovery.view.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; +import 'package:twonly/globals.dart'; +import 'package:twonly/src/views/settings/privacy/user_discovery/user_discovery_disabled.component.dart'; +import 'package:twonly/src/views/settings/privacy/user_discovery/user_discovery_enabled.component.dart'; + +class UserDiscoverySettingsView extends StatefulWidget { + const UserDiscoverySettingsView({super.key}); + + @override + State createState() => + _UserDiscoverySettingsViewState(); +} + +class _UserDiscoverySettingsViewState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Freunde finden'), + ), + body: gUser.isUserDiscoveryEnabled + ? UserDiscoveryEnabledComponent(onUpdate: () => setState(() {})) + : UserDiscoveryDisabledComponent(onUpdate: () => setState(() {})), + ); + } +} diff --git a/lib/src/views/settings/privacy/user_discovery/user_discovery_disabled.component.dart b/lib/src/views/settings/privacy/user_discovery/user_discovery_disabled.component.dart new file mode 100644 index 00000000..519f3bb6 --- /dev/null +++ b/lib/src/views/settings/privacy/user_discovery/user_discovery_disabled.component.dart @@ -0,0 +1,93 @@ +import 'package:flutter/material.dart'; +import 'package:twonly/src/services/user_discovery.service.dart'; +import 'package:twonly/src/themes/light.dart'; +import 'package:twonly/src/utils/misc.dart'; + +class UserDiscoveryDisabledComponent extends StatefulWidget { + const UserDiscoveryDisabledComponent({required this.onUpdate, super.key}); + + final VoidCallback onUpdate; + + @override + State createState() => + _UserDiscoveryDisabledComponentState(); +} + +class _UserDiscoveryDisabledComponentState + extends State { + Future initializeUserDiscoveryWithDefaultSettings() async { + await initializeOrUpdateUserDiscovery( + threshold: 2, + minimumRequiredImagesExchanged: 4, + ); + widget.onUpdate(); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 40), + child: ListView( + children: [ + const SizedBox(height: 45), + const Text( + 'twonly verzichten auf Telefonnummern, daher schlagen wir dir Freunde stattdessen über gemeinsame Kontakte vor – sicher und privat.', + textAlign: TextAlign.center, + ), + const SizedBox(height: 30), + RichText( + text: TextSpan( + children: formattedText( + 'Deine Freundesliste ist für *Fremde komplett unsichtbar*. Nur deine Freunde können Teile davon sehen – und zwar nur die Personen, mit denen sie selbst *gemeinsame Freunde* haben.', + ), + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 35), + const Text( + 'Du hast die Kontrolle', + style: TextStyle(fontSize: 17), + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + const Text( + 'Entscheide selbst, wer deine Freunde sehen darf. Du kannst deine Meinung jederzeit ändern oder bestimmte Personen verstecken.', + textAlign: TextAlign.center, + ), + + const SizedBox(height: 50), + + FilledButton( + onPressed: initializeUserDiscoveryWithDefaultSettings, + style: primaryColorButtonStyle.merge( + FilledButton.styleFrom( + padding: EdgeInsets.symmetric(horizontal: 32, vertical: 24), + ), + ), + child: const Text('Mit Standardeinstellungen aktivieren'), + ), + + const SizedBox(height: 20), + + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: FilledButton( + onPressed: () {}, + style: secondaryGreyButtonStyle, + child: const Text('Einstellungen anpassen'), + ), + ), + const SizedBox(height: 15), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: FilledButton( + onPressed: () {}, + style: secondaryGreyButtonStyle, + child: const Text('Mehr erfahren'), + ), + ), + ], + ), + ); + } +} diff --git a/lib/src/views/settings/privacy/user_discovery/user_discovery_enabled.component.dart b/lib/src/views/settings/privacy/user_discovery/user_discovery_enabled.component.dart new file mode 100644 index 00000000..91e50ade --- /dev/null +++ b/lib/src/views/settings/privacy/user_discovery/user_discovery_enabled.component.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; + +class UserDiscoveryEnabledComponent extends StatefulWidget { + const UserDiscoveryEnabledComponent({required this.onUpdate, super.key}); + + final VoidCallback onUpdate; + + @override + State createState() => + _UserDiscoveryEnabledComponentState(); +} + +class _UserDiscoveryEnabledComponentState + extends State { + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(top: 10), + child: ListView( + children: [ + const ExpansionTile( + shape: RoundedRectangleBorder(), + collapsedShape: RoundedRectangleBorder(), + tilePadding: EdgeInsets.symmetric(horizontal: 17), + title: Text('Freunde die du teilst'), + subtitle: Text( + 'Du teilst nur Freunde, die diese Funktion ebenfalls aktiviert haben und die den von dir festgelegten Schwellenwert erreicht haben.', + style: TextStyle(fontSize: 10), + ), + children: [], + ), + ListTile( + title: Text('Einstellungen ändern'), + // onTap: () {}, + ), + const Divider(), + ListTile( + title: Text('Deaktivieren'), + onTap: () {}, + ), + ], + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index e4208c58..09b74374 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -412,26 +412,26 @@ packages: dependency: "direct main" description: name: drift - sha256: "970cd188fddb111b26ea6a9b07a62bf5c2432d74147b8122c67044ae3b97e99e" + sha256: "055c249d1f91be5a47fe447f88afc24c4ca6f4cd6c5ed66767b4797d48acc2e5" url: "https://pub.dev" source: hosted - version: "2.31.0" + version: "2.32.1" drift_dev: dependency: "direct dev" description: name: drift_dev - sha256: "917184b2fb867b70a548a83bf0d36268423b38d39968c06cce4905683da49587" + sha256: "88a9de3af8571518148a6d8a513b57779fd1e60a026d3ab8a481a878fba01d91" url: "https://pub.dev" source: hosted - version: "2.31.0" + version: "2.32.1" drift_flutter: dependency: "direct main" description: name: drift_flutter - sha256: c07120854742a0cae2f7501a0da02493addde550db6641d284983c08762e60a7 + sha256: "887fdec622174dc7eaefd0048403e34ee07cc18626ac8a7544cc3b8a4a172166" url: "https://pub.dev" source: hosted - version: "0.2.8" + version: "0.3.0" ed25519_edwards: dependency: "direct overridden" description: @@ -1809,30 +1809,38 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.0" - sqlite3: - dependency: "direct main" + sqlcipher_flutter_libs: + dependency: transitive description: - name: sqlite3 - sha256: "3145bd74dcdb4fd6f5c6dda4d4e4490a8087d7f286a14dee5d37087290f0f8a2" + name: sqlcipher_flutter_libs + sha256: "38d62d659d2fb8739bf25a42c9a350d1fdd6c29a5a61f13a946778ec75d27929" url: "https://pub.dev" source: hosted - version: "2.9.4" + version: "0.7.0+eol" + sqlite3: + dependency: transitive + description: + name: sqlite3 + sha256: "56da3e13ed7d28a66f930aa2b2b29db6736a233f08283326e96321dd812030f5" + url: "https://pub.dev" + source: hosted + version: "3.3.1" sqlite3_flutter_libs: dependency: transitive description: name: sqlite3_flutter_libs - sha256: eeb9e3a45207649076b808f8a5a74d68770d0b7f26ccef6d5f43106eee5375ad + sha256: "3ed7553eee7bb368f8950f58ba29f634e06e813c029aff6a0d60862b96de8454" url: "https://pub.dev" source: hosted - version: "0.5.42" + version: "0.6.0+eol" sqlparser: dependency: transitive description: name: sqlparser - sha256: "337e9997f7141ffdd054259128553c348635fa318f7ca492f07a4ab76f850d19" + sha256: ab2b467425f1d4f3acfa5fd11a08226f7d6c26ff102c06be1807e1dff34e050b url: "https://pub.dev" source: hosted - version: "0.43.1" + version: "0.44.3" stack_trace: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 2d2d621a..e719188a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -58,9 +58,8 @@ dependencies: json_annotation: ^4.9.0 # google.dev protobuf: ^4.0.0 # google.dev scrollable_positioned_list: ^0.3.8 # google.dev - drift: ^2.25.1 - drift_flutter: ^0.2.4 - sqlite3: ^2.9.4 + drift: ^2.32.0 + drift_flutter: ^0.3.0 # Flutter Favorite diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 5823bc53..0fccb096 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -305,6 +305,15 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-queue" version = "0.3.12" @@ -392,6 +401,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] + [[package]] name = "digest" version = "0.10.7" @@ -1071,9 +1089,9 @@ dependencies = [ [[package]] name = "libsqlite3-sys" -version = "0.35.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "133c182a6a2c87864fe97778797e46c7e999672690dc9fa3ee8e241aa4a9c13f" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" dependencies = [ "cc", "pkg-config", @@ -1107,6 +1125,15 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + [[package]] name = "md-5" version = "0.10.6" @@ -1149,6 +1176,15 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "num-bigint-dig" version = "0.8.6" @@ -1165,6 +1201,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "num-conv" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" + [[package]] name = "num-integer" version = "0.1.46" @@ -1260,6 +1302,12 @@ dependencies = [ "windows-link", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -1340,6 +1388,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1582,7 +1636,7 @@ name = "rust_lib_twonly" version = "0.1.0" dependencies = [ "flutter_rust_bridge", - "parking_lot", + "paste", "pretty_env_logger", "prost-build", "protocols", @@ -1592,6 +1646,8 @@ dependencies = [ "thiserror", "tokio", "tracing", + "tracing-appender", + "tracing-subscriber", ] [[package]] @@ -1725,6 +1781,15 @@ dependencies = [ "digest 0.11.2", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" @@ -2009,6 +2074,12 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "symlink" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" + [[package]] name = "syn" version = "2.0.117" @@ -2073,6 +2144,15 @@ dependencies = [ "syn", ] +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + [[package]] name = "threadpool" version = "1.8.1" @@ -2082,6 +2162,37 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinystr" version = "0.8.3" @@ -2158,6 +2269,19 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-appender" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c" +dependencies = [ + "crossbeam-channel", + "symlink", + "thiserror", + "time", + "tracing-subscriber", +] + [[package]] name = "tracing-attributes" version = "0.1.31" @@ -2176,6 +2300,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] [[package]] @@ -2235,6 +2389,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 274b4676..47ab6cf6 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,3 +1,35 @@ -[workspace] -members = ["protocols", "core"] -resolver = "3" +[package] +name = "rust_lib_twonly" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "staticlib"] + +[dependencies] +flutter_rust_bridge = "=2.12.0" +thiserror = "2.0.18" +sqlx = { version = "0.9.0-alpha.1", default-features = false, features = [ + "runtime-tokio", + "sqlite", + "migrate", + "macros", + "chrono", + "derive", + "json", +] } +tokio = { version = "1.44", features = ["full"] } +tracing = "0.1.44" +rand = "0.10.1" +protocols = { path = "../rust_dependencies/protocols" } +tracing-subscriber = { version = "0.3", features = ["env-filter"] } +tracing-appender = "0.2.5" +paste = "1.0.15" + +[dev-dependencies] +pretty_env_logger = "0.5.0" +tempfile = "3.27.0" + + +[build-dependencies] +prost-build = "0.14.1" diff --git a/rust/src/bridge/callbacks.rs b/rust/src/bridge/callbacks.rs new file mode 100644 index 00000000..297ccb90 --- /dev/null +++ b/rust/src/bridge/callbacks.rs @@ -0,0 +1,47 @@ +pub(crate) mod log; +mod macros; +pub(crate) mod user_discovery; + +use flutter_rust_bridge::DartFnFuture; +use protocols::user_discovery::traits::{AnnouncedUser, OtherPromotion}; + +use super::error::Result; +use crate::{callback_generator, frb_generated::StreamSink}; +use std::sync::{Arc, OnceLock}; + +use crate::bridge::error::TwonlyError; + +static FLUTTER_CALLBACKS: OnceLock = OnceLock::new(); + +// This will also generate the function init_flutter_callbacks which MUST be called from Flutter to initialize the callbacks +callback_generator! { + FlutterCallbacks { + Logging logging { + get_stream_sink: () => StreamSink + }, + UserDiscoveryCallbacks user_discovery { + // UserDiscoveryUtils + sign_data: (Vec) => Option>, + verify_signature: (Vec, Vec, Vec) => bool, + verify_stored_pubkey: (i64, Vec) => bool, + + // UserDiscoveryStore + set_shares: (Vec>) => bool, + get_share_for_contact: (i64) => Option>, + push_own_promotion: (i64, i64, Vec) => bool, + get_own_promotions_after_version: (i64) => Option>>, + store_other_promotion: (OtherPromotion) => bool, + get_other_promotions_by_public_id: (i64) => Option>, + get_announced_user_by_public_id: (i64) => Option, + get_contact_version: (i64) => Option>, + set_contact_version: (i64, Vec) => bool, + push_new_user_relation: (i64, AnnouncedUser, Option) => bool, + } + } +} + +pub(crate) fn get_callbacks() -> Result<&'static FlutterCallbacks> { + FLUTTER_CALLBACKS + .get() + .ok_or(TwonlyError::MissingCallbackInitialization) +} diff --git a/rust/src/bridge/callbacks/log.rs b/rust/src/bridge/callbacks/log.rs new file mode 100644 index 00000000..e1525ed2 --- /dev/null +++ b/rust/src/bridge/callbacks/log.rs @@ -0,0 +1,28 @@ +use crate::frb_generated::StreamSink; +use tracing_subscriber::fmt::MakeWriter; + +#[derive(Clone)] +pub(crate) struct DartWriter { + pub(crate) sink: StreamSink, +} + +impl std::io::Write for DartWriter { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + if let Ok(msg) = std::str::from_utf8(buf) { + let _ = self.sink.add(msg.trim_end().to_string()); + } + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + +impl<'a> MakeWriter<'a> for DartWriter { + type Writer = DartWriter; + + fn make_writer(&'a self) -> Self::Writer { + self.clone() + } +} diff --git a/rust/src/bridge/callbacks/macros.rs b/rust/src/bridge/callbacks/macros.rs new file mode 100644 index 00000000..bd5fa8aa --- /dev/null +++ b/rust/src/bridge/callbacks/macros.rs @@ -0,0 +1,57 @@ +#[macro_export] +macro_rules! callback_generator { + ( + $struct_name:ident { + $( + $sub_struct_name:ident $sub_struct_field:ident { + $( + $fn_name:ident : ($($input:ty),*) => $output:ty + ),* $(,)? + } + ),* $(,)? + } + ) => { + // 1. Generate the Nested Sub-Structs + $( + pub(crate) struct $sub_struct_name { + $( + pub(crate) $fn_name: Arc DartFnFuture<$output> + Send + Sync + 'static>, + )* + } + )* + + // 2. Generate the Main Container Struct + pub(crate) struct $struct_name { + $( + pub(crate) $sub_struct_field: $sub_struct_name, + )* + } + + // 3. Generate the Automated Init Function + paste::paste! { + pub async fn init_flutter_callbacks( + $( + $( + // Parameters: sub-struct_field + _ + fn_name + [<$sub_struct_field _ $fn_name>]: impl Fn($($input),*) -> DartFnFuture<$output> + Send + Sync + 'static, + )* + )* + ) { + let callbacks = $struct_name { + $( + $sub_struct_field: $sub_struct_name { + $( + $fn_name: Arc::new([<$sub_struct_field _ $fn_name>]), + )* + }, + )* + }; + + // Use the static global strictly named FLUTTER_CALLBACKS + FLUTTER_CALLBACKS.set(callbacks).unwrap_or_else(|_| { + println!("Callbacks were already initialized!"); + }); + } + } + }; +} diff --git a/rust/src/bridge/callbacks/user_discovery.rs b/rust/src/bridge/callbacks/user_discovery.rs new file mode 100644 index 00000000..b10fb247 --- /dev/null +++ b/rust/src/bridge/callbacks/user_discovery.rs @@ -0,0 +1,169 @@ +use crate::bridge::callbacks::get_callbacks; +use crate::bridge::error::TwonlyError; +use crate::bridge::get_twonly_flutter; +use protocols::user_discovery::error::{Result, UserDiscoveryError}; +use protocols::user_discovery::traits::UserDiscoveryUtils; +use protocols::user_discovery::traits::{AnnouncedUser, OtherPromotion, UserDiscoveryStore}; +use std::collections::HashMap; +use std::path::PathBuf; + +#[derive(Clone)] +pub(crate) struct UserDiscoveryStoreFlutter {} +pub(crate) struct UserDiscoveryUtilsFlutter {} + +impl UserDiscoveryUtils for UserDiscoveryUtilsFlutter { + async fn sign_data(&self, input_data: &[u8]) -> Result> { + match (get_callbacks()?.user_discovery.sign_data)(input_data.to_vec()).await { + Some(signature) => Ok(signature), + None => Err(TwonlyError::DartError)?, + } + } + + async fn verify_signature( + &self, + input_data: &[u8], + pubkey: &[u8], + signature: &[u8], + ) -> Result { + Ok((get_callbacks()?.user_discovery.verify_signature)( + input_data.to_vec(), + pubkey.to_vec(), + signature.to_vec(), + ) + .await) + } + + async fn verify_stored_pubkey(&self, from_contact_id: i64, pubkey: &[u8]) -> Result { + Ok( + (get_callbacks()?.user_discovery.verify_stored_pubkey)( + from_contact_id, + pubkey.to_vec(), + ) + .await, + ) + } +} + +impl UserDiscoveryStore for UserDiscoveryStoreFlutter { + async fn get_config(&self) -> Result { + let ws = get_twonly_flutter().unwrap(); + let config_path = + PathBuf::from(&ws.config.data_directory).join("user_discovery_config.json"); + + if !config_path.is_file() { + return Err(UserDiscoveryError::NotInitialized); + } + + tracing::debug!("Loading Config from {}", config_path.display()); + Ok(std::fs::read_to_string(&config_path)?) + } + + async fn update_config(&self, update: String) -> Result<()> { + tracing::debug!("Updating configuration file."); + let ws = get_twonly_flutter().unwrap(); + let config_path = + PathBuf::from(&ws.config.data_directory).join("user_discovery_config.json"); + std::fs::write(config_path, &update)?; + Ok(()) + } + + async fn set_shares(&self, shares: Vec>) -> Result<()> { + (get_callbacks()?.user_discovery.set_shares)(shares).await; + Ok(()) + } + + async fn get_share_for_contact(&self, contact_id: i64) -> Result> { + match (get_callbacks()?.user_discovery.get_share_for_contact)(contact_id).await { + Some(share) => Ok(share), + None => Err(UserDiscoveryError::NoSharesLeft), + } + } + + async fn push_own_promotion( + &self, + contact_id: i64, + version: u32, + promotion: Vec, + ) -> Result<()> { + (get_callbacks()?.user_discovery.push_own_promotion)(contact_id, version as i64, promotion) + .await + .then_some(()) + .ok_or(TwonlyError::DartError.into()) + } + + async fn get_own_promotions_after_version(&self, version: u32) -> Result>> { + match (get_callbacks()? + .user_discovery + .get_own_promotions_after_version)(version as i64) + .await + { + Some(share) => Ok(share), + None => Err(TwonlyError::DartError)?, + } + } + + async fn store_other_promotion(&self, promotion: OtherPromotion) -> Result<()> { + (get_callbacks()?.user_discovery.store_other_promotion)(promotion) + .await + .then_some(()) + .ok_or(TwonlyError::DartError.into()) + } + + async fn get_other_promotions_by_public_id( + &self, + public_id: i64, + ) -> Result> { + match (get_callbacks()? + .user_discovery + .get_other_promotions_by_public_id)(public_id) + .await + { + Some(promotions) => Ok(promotions), + None => Err(TwonlyError::DartError)?, + } + } + + async fn get_announced_user_by_public_id( + &self, + public_id: i64, + ) -> Result> { + Ok((get_callbacks()? + .user_discovery + .get_announced_user_by_public_id)(public_id) + .await) + } + + async fn push_new_user_relation( + &self, + from_contact_id: i64, + announced_user: AnnouncedUser, + public_key_verified_timestamp: Option, + ) -> Result<()> { + (get_callbacks()?.user_discovery.push_new_user_relation)( + from_contact_id, + announced_user, + public_key_verified_timestamp, + ) + .await + .then_some(()) + .ok_or(TwonlyError::DartError.into()) + } + + async fn get_all_announced_users( + &self, + ) -> Result)>>> { + // This is never called from the RUST code. + Err(TwonlyError::DartError)? + } + + async fn get_contact_version(&self, contact_id: i64) -> Result>> { + Ok((get_callbacks()?.user_discovery.get_contact_version)(contact_id).await) + } + + async fn set_contact_version(&self, contact_id: i64, update: Vec) -> Result<()> { + (get_callbacks()?.user_discovery.set_contact_version)(contact_id, update) + .await + .then_some(()) + .ok_or(TwonlyError::DartError.into()) + } +} diff --git a/rust/src/bridge/error.rs b/rust/src/bridge/error.rs index b77e8f03..7ad74628 100644 --- a/rust/src/bridge/error.rs +++ b/rust/src/bridge/error.rs @@ -7,9 +7,15 @@ pub type Result = core::result::Result; pub enum TwonlyError { #[error("global twonly is not initialized")] Initialization, + #[error("init_flutter_callbacks was not called")] + MissingCallbackInitialization, #[error("Could not find the given database")] DatabaseNotFound, #[error("{0}")] + UserDiscoveryError(#[from] UserDiscoveryError), + #[error("Error in dart callback")] + DartError, + #[error("{0}")] SqliteError(#[from] sqlx::Error), } diff --git a/rust/src/bridge/log.rs b/rust/src/bridge/log.rs new file mode 100644 index 00000000..db6a0935 --- /dev/null +++ b/rust/src/bridge/log.rs @@ -0,0 +1,73 @@ +use crate::bridge::callbacks::{get_callbacks, log::DartWriter}; +use std::sync::{Mutex, OnceLock}; +use tracing_appender::non_blocking::{NonBlocking, WorkerGuard}; +use tracing_subscriber::{ + fmt::Layer, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Registry, +}; + +static TRACING_GUARDS: OnceLock>> = OnceLock::new(); +static TRACING_INIT: OnceLock<()> = OnceLock::new(); + +pub(crate) async fn init_tracing(logs_dir: &std::path::Path, is_dart_available: bool) { + let _ = std::fs::create_dir_all(logs_dir); + + let mut dart_sink = None; + + if is_dart_available { + if let Ok(callbacks) = get_callbacks() { + dart_sink = Some((callbacks.logging.get_stream_sink)().await); + } + } + + TRACING_INIT.get_or_init(|| { + let (non_blocking_stdout, _non_blocking_file) = build_writers(logs_dir); + + let stdout_layer = Layer::new() + .with_writer(non_blocking_stdout) + .with_ansi(true) + .with_target(true); + + // let file_layer = Layer::new() + // .with_writer(non_blocking_file) + // .with_ansi(false) + // .with_target(true); + + // Replace stdout with our new DartWriter! + + let registry = Registry::default() + .with( + EnvFilter::try_from_default_env() + .unwrap_or_else(|_| EnvFilter::new("debug,refinery_core=warn,refinery=warn")), + ) + .with(stdout_layer); + + if let Some(sink) = dart_sink { + let dart_writer = DartWriter { sink }; + let dart_layer = tracing_subscriber::fmt::Layer::new() + .with_writer(dart_writer) + .with_ansi(false) + .with_target(true); + let _ = registry.with(dart_layer).try_init(); + } else { + let _ = registry.try_init(); + } + }); +} + +fn build_writers(logs_dir: &std::path::Path) -> (NonBlocking, NonBlocking) { + let file_appender = tracing_appender::rolling::RollingFileAppender::builder() + .rotation(tracing_appender::rolling::Rotation::DAILY) + .filename_prefix("twonly") + .filename_suffix("log") + .build(logs_dir) + .expect("Failed to create file appender"); + + let (non_blocking_file, file_guard) = tracing_appender::non_blocking(file_appender); + let (non_blocking_stdout, stdout_guard) = tracing_appender::non_blocking(std::io::stdout()); + + TRACING_GUARDS + .set(Mutex::new(Some((file_guard, stdout_guard)))) + .ok(); + + (non_blocking_stdout, non_blocking_file) +} diff --git a/rust/src/bridge/log/mod.rs b/rust/src/bridge/log/mod.rs deleted file mode 100644 index 528f989b..00000000 --- a/rust/src/bridge/log/mod.rs +++ /dev/null @@ -1,44 +0,0 @@ -static TRACING_INIT: OnceLock<()> = OnceLock::new(); - -pub(crate) fn init_tracing(logs_dir: &std::path::Path) { - TRACING_INIT.get_or_init(|| { - let (non_blocking_stdout, non_blocking_file) = build_writers(logs_dir); - - let stdout_layer = Layer::new() - .with_writer(non_blocking_stdout) - .with_ansi(true) - .with_target(true); - - let file_layer = Layer::new() - .with_writer(non_blocking_file) - .with_ansi(false) - .with_target(true); - - Registry::default() - .with( - EnvFilter::try_from_default_env() - .unwrap_or_else(|_| EnvFilter::new("info,refinery_core=warn,refinery=warn")), - ) - .with(stdout_layer) - .with(file_layer) - .init(); - }); -} - -fn build_writers(logs_dir: &std::path::Path) -> (NonBlocking, NonBlocking) { - let file_appender = tracing_appender::rolling::RollingFileAppender::builder() - .rotation(tracing_appender::rolling::Rotation::DAILY) - .filename_prefix("twonly") - .filename_suffix("log") - .build(logs_dir) - .expect("Failed to create file appender"); - - let (non_blocking_file, file_guard) = tracing_appender::non_blocking(file_appender); - let (non_blocking_stdout, stdout_guard) = tracing_appender::non_blocking(std::io::stdout()); - - TRACING_GUARDS - .set(Mutex::new(Some((file_guard, stdout_guard)))) - .ok(); - - (non_blocking_stdout, non_blocking_file) -} diff --git a/rust/src/bridge/mod.rs b/rust/src/bridge/mod.rs index fdb518dc..5b5c6422 100644 --- a/rust/src/bridge/mod.rs +++ b/rust/src/bridge/mod.rs @@ -1,18 +1,22 @@ #![allow(unexpected_cfgs)] +pub mod callbacks; pub mod error; -mod user_discovery_utils; -use crate::bridge::user_discovery_utils::UserDiscoveryUtilsFlutter; -use crate::database::contact::Contact; -use crate::database::Database; -use crate::user_discovery_store::UserDiscoveryDatabaseStore; +pub mod log; +pub mod wrapper; + +use crate::bridge::callbacks::user_discovery::{ + UserDiscoveryStoreFlutter, UserDiscoveryUtilsFlutter, +}; +use crate::bridge::log::init_tracing; use crate::utils::Shared; use error::Result; use error::TwonlyError; use flutter_rust_bridge::frb; use protocols::user_discovery::UserDiscovery; -use std::sync::Arc; +use std::path::PathBuf; use tokio::sync::OnceCell; +pub use protocols::user_discovery::traits::AnnouncedUser; pub use protocols::user_discovery::traits::OtherPromotion; #[frb(mirror(OtherPromotion))] @@ -25,34 +29,56 @@ pub struct _OtherPromotion { pub public_key_verified_timestamp: Option, } +#[frb(mirror(AnnouncedUser))] +pub struct _AnnouncedUser { + pub user_id: i64, + pub public_key: Vec, + pub public_id: i64, +} + pub struct TwonlyConfig { pub database_path: String, pub data_directory: String, } -pub(crate) struct Twonly { +pub(crate) struct TwonlyFlutter { #[allow(dead_code)] pub(crate) config: TwonlyConfig, - pub(crate) database: Arc, + // /// Rust runs in the same process as drift, the database can only be opened in readonly mode + // pub(crate) twonly_db_readonly: Arc, pub(crate) user_discovery: - Shared>>, + Shared>, } -static GLOBAL_TWONLY: OnceCell = OnceCell::const_new(); +static GLOBAL_TWONLY: OnceCell = OnceCell::const_new(); -pub(crate) fn get_workspace() -> Result<&'static Twonly> { +pub(super) fn get_twonly_flutter() -> Result<&'static TwonlyFlutter> { GLOBAL_TWONLY.get().ok_or(TwonlyError::Initialization) } -pub async fn initialize_twonly(config: TwonlyConfig) -> Result<()> { - tracing::debug!("Initialized twonly workspace."); - let twonly_res: Result<&'static Twonly> = GLOBAL_TWONLY +pub async fn initialize_twonly_flutter(config: TwonlyConfig) -> Result<()> { + let log_dir = PathBuf::from(&config.data_directory).join("log"); + init_tracing(&log_dir, true).await; + tracing::info!("Initialized twonly workspace."); + let twonly_res: Result<&'static TwonlyFlutter> = GLOBAL_TWONLY .get_or_try_init(|| async { - let database = Arc::new(Database::new(&config.database_path).await?); - Ok(Twonly { + // let database_dir = PathBuf::from(&config.database_path.clone()); + // let Some(rust_db_path) = database_dir.parent() else { + // return Err(TwonlyError::DatabaseNotFound); + // }; + // let rust_db_path = rust_db_path.join("rust_db.sqlite").display().to_string(); + + // let twonly_db_readonly = Arc::new(Database::new(&config.database_path, true).await?); + // let rust_db = Arc::new(Database::new(&rust_db_path, false).await?); + + Ok(TwonlyFlutter { config, - database, - user_discovery: Shared::default(), + // twonly_db_readonly, + // rust_db, + user_discovery: Shared::new(UserDiscovery::new( + UserDiscoveryStoreFlutter {}, + UserDiscoveryUtilsFlutter {}, + )?), }) }) .await; @@ -61,102 +87,3 @@ pub async fn initialize_twonly(config: TwonlyConfig) -> Result<()> { Ok(()) } - -pub async fn get_all_contacts() -> Result> { - let twonly = get_workspace()?; - Contact::get_all_contacts(twonly.database.as_ref()).await -} - -pub fn load_promotions() -> OtherPromotion { - todo!() -} - -#[cfg(test)] -pub(crate) mod tests { - use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions}; - use tempfile::{NamedTempFile, TempDir}; - use tokio::sync::OnceCell; - - use crate::{database::Database, utils::Shared}; - - use super::error::Result; - use super::Twonly; - use std::{path::PathBuf, sync::Arc}; - use tokio::sync::Mutex; - - use super::{get_workspace, initialize_twonly, TwonlyConfig}; - - static TWONLY_TESTING: [OnceCell; 10] = [ - OnceCell::const_new(), - OnceCell::const_new(), - OnceCell::const_new(), - OnceCell::const_new(), - OnceCell::const_new(), - OnceCell::const_new(), - OnceCell::const_new(), - OnceCell::const_new(), - OnceCell::const_new(), - OnceCell::const_new(), - ]; - - static TWONLY_TESTING_INDEX: OnceCell>> = OnceCell::const_new(); - - pub(crate) async fn initialize_twonly_for_testing(use_global: bool) -> Result<&'static Twonly> { - let default_twonly_database = PathBuf::from("tests/testing.db"); - - if !default_twonly_database.is_file() { - panic!("{} not found!", default_twonly_database.display()) - } - - let temp_file = NamedTempFile::new().unwrap().path().to_owned(); - - tracing::info!("Crated db copy: {}", temp_file.display()); - - let conn = SqlitePoolOptions::new() - .connect_with( - format!("sqlite://{}", default_twonly_database.display()) - .parse::() - .unwrap(), - ) - .await - .unwrap(); - - let path_str = temp_file.display().to_string(); - sqlx::query("VACUUM INTO $1") - .bind(path_str) - .execute(&conn) - .await - .expect("Failed to backup database"); - - let tmp_dir = TempDir::new().unwrap().path().to_owned(); - std::fs::create_dir_all(&tmp_dir).unwrap(); - let config = TwonlyConfig { - database_path: temp_file.display().to_string(), - data_directory: tmp_dir.to_str().unwrap().to_string(), - }; - - if use_global { - initialize_twonly(config).await.unwrap(); - - get_workspace() - } else { - let index = TWONLY_TESTING_INDEX - .get_or_init(|| async { Arc::default() }) - .await; - let mut index = index.lock().await; - let res: Result<&'static Twonly> = TWONLY_TESTING[*index] - .get_or_try_init(|| async { - let database = Arc::new(Database::new(&config.database_path).await?); - Ok(Twonly { - config, - database, - user_discovery: Shared::default(), - }) - }) - .await; - tracing::debug!("TWONLY_TESTING_INDEX: {index}"); - *index += 1; - res - } - } -} diff --git a/rust/src/bridge/user_discovery_utils.rs b/rust/src/bridge/user_discovery_utils.rs deleted file mode 100644 index fe83916e..00000000 --- a/rust/src/bridge/user_discovery_utils.rs +++ /dev/null @@ -1,27 +0,0 @@ -use protocols::user_discovery::error::Result; -use protocols::user_discovery::traits::UserDiscoveryUtils; - -pub(crate) struct UserDiscoveryUtilsFlutter {} - -impl UserDiscoveryUtils for UserDiscoveryUtilsFlutter { - async fn sign_data(&self, input_data: &[u8]) -> Result> { - todo!() - } - - async fn verify_signature( - &self, - input_data: &[u8], - pubkey: &[u8], - signature: &[u8], - ) -> Result { - todo!() - } - - async fn verify_stored_pubkey( - &self, - from_contact_id: protocols::user_discovery::UserID, - pubkey: &[u8], - ) -> Result { - todo!() - } -} diff --git a/rust/src/bridge/wrapper/mod.rs b/rust/src/bridge/wrapper/mod.rs new file mode 100644 index 00000000..16456710 --- /dev/null +++ b/rust/src/bridge/wrapper/mod.rs @@ -0,0 +1 @@ +pub mod user_discovery; diff --git a/rust/src/bridge/wrapper/user_discovery.rs b/rust/src/bridge/wrapper/user_discovery.rs new file mode 100644 index 00000000..6aa24137 --- /dev/null +++ b/rust/src/bridge/wrapper/user_discovery.rs @@ -0,0 +1,61 @@ +use crate::bridge::error::Result; +use crate::bridge::get_twonly_flutter; + +pub struct FlutterUserDiscovery {} + +impl FlutterUserDiscovery { + pub async fn initialize_or_update( + threshold: u8, + user_id: i64, + public_key: Vec, + ) -> Result<()> { + Ok(get_twonly_flutter()? + .user_discovery + .get() + .await + .initialize_or_update(threshold, user_id, public_key) + .await?) + } + + pub async fn get_current_version() -> Result> { + Ok(get_twonly_flutter()? + .user_discovery + .get() + .await + .get_current_version() + .await?) + } + + pub async fn get_new_messages( + contact_id: i64, + received_version: &[u8], + ) -> Result>> { + Ok(get_twonly_flutter()? + .user_discovery + .get() + .await + .get_new_messages(contact_id, received_version) + .await?) + } + + pub async fn should_request_new_messages(contact_id: i64, version: &[u8]) -> Result { + Ok(get_twonly_flutter()? + .user_discovery + .get() + .await + .should_request_new_messages(contact_id, version) + .await?) + } + + pub async fn handle_user_discovery_messages( + contact_id: i64, + messages: Vec>, + ) -> Result<()> { + Ok(get_twonly_flutter()? + .user_discovery + .get() + .await + .handle_user_discovery_messages(contact_id, messages) + .await?) + } +} diff --git a/rust/src/database/contact.rs b/rust/src/database/contact.rs deleted file mode 100644 index f6833366..00000000 --- a/rust/src/database/contact.rs +++ /dev/null @@ -1,58 +0,0 @@ -// use sqlx::types::chrono::{DateTime, Utc}; -use sqlx::FromRow; - -use super::Database; -use crate::bridge::error::Result; - -#[derive(FromRow, Clone, Debug)] -struct ContactRow { - pub(crate) user_id: i64, - pub(crate) username: String, - // pub(crate) created_at: DateTime, -} - -pub struct Contact { - pub user_id: i64, - pub username: String, - // pub created_at: DateTime, -} - -impl From for Contact { - fn from(row: ContactRow) -> Self { - Self { - user_id: row.user_id, - username: row.username, - // created_at: row.created_at, - } - } -} - -impl Contact { - pub(crate) async fn get_all_contacts(db: &Database) -> Result> { - let rows = sqlx::query_as::<_, ContactRow>("SELECT * FROM contacts") - .fetch_all(&db.pool) - .await?; - Ok(rows.into_iter().map(Into::into).collect()) - } -} - -#[cfg(test)] -mod tests { - use crate::bridge::tests::initialize_twonly_for_testing; - use crate::database::contact::Contact; - - #[tokio::test] - async fn test_get_all_contacts() { - let twonly = initialize_twonly_for_testing(true).await.unwrap(); - - let contacts = Contact::get_all_contacts(&twonly.database).await.unwrap(); - - let users = vec!["alice", "bob", "charlie", "david", "frank"]; - - assert_eq!(contacts.len(), users.len()); - - for contact in contacts { - assert_eq!(users[contact.user_id as usize], &contact.username); - } - } -} diff --git a/rust/src/database/mod.rs b/rust/src/database/mod.rs index db873560..4d9f4b71 100644 --- a/rust/src/database/mod.rs +++ b/rust/src/database/mod.rs @@ -1,4 +1,3 @@ -pub(crate) mod contact; use crate::bridge::error::{Result, TwonlyError}; use sqlx::migrate::MigrateDatabase; use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions}; @@ -10,7 +9,7 @@ pub(crate) struct Database { } impl Database { - pub(crate) async fn new(db_path: &String) -> Result { + pub(crate) async fn new(db_path: &String, read_only: bool) -> Result { let db_url = format!("sqlite://{}", db_path); match Sqlite::database_exists(&db_url).await { @@ -41,6 +40,7 @@ impl Database { let connect_options = format!("{db_url}?mode=rwc") .parse::()? .log_statements(log_statements_level) + .read_only(read_only) .journal_mode(sqlx::sqlite::SqliteJournalMode::Wal) .foreign_keys(true) .busy_timeout(Duration::from_millis(5000)) @@ -53,6 +53,13 @@ impl Database { .connect_with(connect_options) .await?; + let row: (String, String) = sqlx::query_as("SELECT sqlite_version(), sqlite_source_id()") + .fetch_one(&pool) + .await?; + + tracing::info!("Rust SQLite Version: {}", row.0); + tracing::info!("Rust SQLite Source ID: {}", row.1); + Ok(Self { pool: pool }) } } diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 6a960195..7776993e 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -38,7 +38,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 776002844; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 523281685; // Section: executor @@ -46,42 +46,115 @@ flutter_rust_bridge::frb_generated_default_handler!(); // Section: wire_funcs -fn wire__crate__bridge__get_all_contacts_impl( +fn wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_get_current_version_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, data_len_: i32, ) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "get_all_contacts", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - deserializer.end(); - move |context| async move { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || async move { - let output_ok = crate::bridge::get_all_contacts().await?; - Ok(output_ok) - })() - .await, - ) - } - }, - ) + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::(flutter_rust_bridge::for_generated::TaskInfo{ debug_name: "flutter_user_discovery_get_current_version", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal }, move || { + let message = unsafe { flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_, rust_vec_len_, data_len_) }; + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + deserializer.end(); move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>((move || async move { + let output_ok = crate::bridge::wrapper::user_discovery::FlutterUserDiscovery::get_current_version().await?; Ok(output_ok) + })().await) + } }) } -fn wire__crate__bridge__initialize_twonly_impl( +fn wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_get_new_messages_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::(flutter_rust_bridge::for_generated::TaskInfo{ debug_name: "flutter_user_discovery_get_new_messages", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal }, move || { + let message = unsafe { flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_, rust_vec_len_, data_len_) }; + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_contact_id = ::sse_decode(&mut deserializer); +let api_received_version = >::sse_decode(&mut deserializer);deserializer.end(); move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>((move || async move { + let output_ok = crate::bridge::wrapper::user_discovery::FlutterUserDiscovery::get_new_messages(api_contact_id, &api_received_version).await?; Ok(output_ok) + })().await) + } }) +} +fn wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_handle_user_discovery_messages_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::(flutter_rust_bridge::for_generated::TaskInfo{ debug_name: "flutter_user_discovery_handle_user_discovery_messages", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal }, move || { + let message = unsafe { flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_, rust_vec_len_, data_len_) }; + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_contact_id = ::sse_decode(&mut deserializer); +let api_messages = >>::sse_decode(&mut deserializer);deserializer.end(); move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>((move || async move { + let output_ok = crate::bridge::wrapper::user_discovery::FlutterUserDiscovery::handle_user_discovery_messages(api_contact_id, api_messages).await?; Ok(output_ok) + })().await) + } }) +} +fn wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_initialize_or_update_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::(flutter_rust_bridge::for_generated::TaskInfo{ debug_name: "flutter_user_discovery_initialize_or_update", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal }, move || { + let message = unsafe { flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_, rust_vec_len_, data_len_) }; + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_threshold = ::sse_decode(&mut deserializer); +let api_user_id = ::sse_decode(&mut deserializer); +let api_public_key = >::sse_decode(&mut deserializer);deserializer.end(); move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>((move || async move { + let output_ok = crate::bridge::wrapper::user_discovery::FlutterUserDiscovery::initialize_or_update(api_threshold, api_user_id, api_public_key).await?; Ok(output_ok) + })().await) + } }) +} +fn wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_should_request_new_messages_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::(flutter_rust_bridge::for_generated::TaskInfo{ debug_name: "flutter_user_discovery_should_request_new_messages", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal }, move || { + let message = unsafe { flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_, rust_vec_len_, data_len_) }; + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_contact_id = ::sse_decode(&mut deserializer); +let api_version = >::sse_decode(&mut deserializer);deserializer.end(); move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>((move || async move { + let output_ok = crate::bridge::wrapper::user_discovery::FlutterUserDiscovery::should_request_new_messages(api_contact_id, &api_version).await?; Ok(output_ok) + })().await) + } }) +} +fn wire__crate__bridge__callbacks__init_flutter_callbacks_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::(flutter_rust_bridge::for_generated::TaskInfo{ debug_name: "init_flutter_callbacks", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal }, move || { + let message = unsafe { flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_, rust_vec_len_, data_len_) }; + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_logging_get_stream_sink = decode_DartFn_Inputs__Output_StreamSink_String_Sse_AnyhowException(::sse_decode(&mut deserializer)); +let api_user_discovery_sign_data = decode_DartFn_Inputs_list_prim_u_8_strict_Output_opt_list_prim_u_8_strict_AnyhowException(::sse_decode(&mut deserializer)); +let api_user_discovery_verify_signature = decode_DartFn_Inputs_list_prim_u_8_strict_list_prim_u_8_strict_list_prim_u_8_strict_Output_bool_AnyhowException(::sse_decode(&mut deserializer)); +let api_user_discovery_verify_stored_pubkey = decode_DartFn_Inputs_i_64_list_prim_u_8_strict_Output_bool_AnyhowException(::sse_decode(&mut deserializer)); +let api_user_discovery_set_shares = decode_DartFn_Inputs_list_list_prim_u_8_strict_Output_bool_AnyhowException(::sse_decode(&mut deserializer)); +let api_user_discovery_get_share_for_contact = decode_DartFn_Inputs_i_64_Output_opt_list_prim_u_8_strict_AnyhowException(::sse_decode(&mut deserializer)); +let api_user_discovery_push_own_promotion = decode_DartFn_Inputs_i_64_i_64_list_prim_u_8_strict_Output_bool_AnyhowException(::sse_decode(&mut deserializer)); +let api_user_discovery_get_own_promotions_after_version = decode_DartFn_Inputs_i_64_Output_opt_list_list_prim_u_8_strict_AnyhowException(::sse_decode(&mut deserializer)); +let api_user_discovery_store_other_promotion = decode_DartFn_Inputs_other_promotion_Output_bool_AnyhowException(::sse_decode(&mut deserializer)); +let api_user_discovery_get_other_promotions_by_public_id = decode_DartFn_Inputs_i_64_Output_opt_list_other_promotion_AnyhowException(::sse_decode(&mut deserializer)); +let api_user_discovery_get_announced_user_by_public_id = decode_DartFn_Inputs_i_64_Output_opt_box_autoadd_announced_user_AnyhowException(::sse_decode(&mut deserializer)); +let api_user_discovery_get_contact_version = decode_DartFn_Inputs_i_64_Output_opt_list_prim_u_8_strict_AnyhowException(::sse_decode(&mut deserializer)); +let api_user_discovery_set_contact_version = decode_DartFn_Inputs_i_64_list_prim_u_8_strict_Output_bool_AnyhowException(::sse_decode(&mut deserializer)); +let api_user_discovery_push_new_user_relation = decode_DartFn_Inputs_i_64_announced_user_opt_box_autoadd_i_64_Output_bool_AnyhowException(::sse_decode(&mut deserializer));deserializer.end(); move |context| async move { + transform_result_sse::<_, ()>((move || async move { + let output_ok = Result::<_,()>::Ok({ crate::bridge::callbacks::init_flutter_callbacks(api_logging_get_stream_sink, api_user_discovery_sign_data, api_user_discovery_verify_signature, api_user_discovery_verify_stored_pubkey, api_user_discovery_set_shares, api_user_discovery_get_share_for_contact, api_user_discovery_push_own_promotion, api_user_discovery_get_own_promotions_after_version, api_user_discovery_store_other_promotion, api_user_discovery_get_other_promotions_by_public_id, api_user_discovery_get_announced_user_by_public_id, api_user_discovery_get_contact_version, api_user_discovery_set_contact_version, api_user_discovery_push_new_user_relation).await; })?; Ok(output_ok) + })().await) + } }) +} +fn wire__crate__bridge__initialize_twonly_flutter_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -89,7 +162,7 @@ fn wire__crate__bridge__initialize_twonly_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "initialize_twonly", + debug_name: "initialize_twonly_flutter", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -108,7 +181,8 @@ fn wire__crate__bridge__initialize_twonly_impl( move |context| async move { transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( (move || async move { - let output_ok = crate::bridge::initialize_twonly(api_config).await?; + let output_ok = + crate::bridge::initialize_twonly_flutter(api_config).await?; Ok(output_ok) })() .await, @@ -117,52 +191,470 @@ fn wire__crate__bridge__initialize_twonly_impl( }, ) } -fn wire__crate__bridge__load_promotions_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "load_promotions", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - deserializer.end(); - move |context| { - transform_result_sse::<_, ()>((move || { - let output_ok = Result::<_, ()>::Ok(crate::bridge::load_promotions())?; - Ok(output_ok) - })()) - } - }, - ) -} // Section: static_checks #[allow(clippy::unnecessary_literal_unwrap)] const _: fn() = || { - let OtherPromotion = None::.unwrap(); - let _: u32 = OtherPromotion.promotion_id; - let _: i64 = OtherPromotion.public_id; - let _: i64 = OtherPromotion.from_contact_id; - let _: u8 = OtherPromotion.threshold; - let _: Vec = OtherPromotion.announcement_share; - let _: Option = OtherPromotion.public_key_verified_timestamp; + { + let AnnouncedUser = None::.unwrap(); + let _: i64 = AnnouncedUser.user_id; + let _: Vec = AnnouncedUser.public_key; + let _: i64 = AnnouncedUser.public_id; + } + { + let OtherPromotion = None::.unwrap(); + let _: u32 = OtherPromotion.promotion_id; + let _: i64 = OtherPromotion.public_id; + let _: i64 = OtherPromotion.from_contact_id; + let _: u8 = OtherPromotion.threshold; + let _: Vec = OtherPromotion.announcement_share; + let _: Option = OtherPromotion.public_key_verified_timestamp; + } }; +// Section: related_funcs + +fn decode_DartFn_Inputs__Output_StreamSink_String_Sse_AnyhowException( + dart_opaque: flutter_rust_bridge::DartOpaque, +) -> impl Fn() -> flutter_rust_bridge::DartFnFuture< + StreamSink, +> { + use flutter_rust_bridge::IntoDart; + + async fn body( + dart_opaque: flutter_rust_bridge::DartOpaque, + ) -> StreamSink { + let args = vec![]; + let message = FLUTTER_RUST_BRIDGE_HANDLER + .dart_fn_invoke(dart_opaque, args) + .await; + + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let action = deserializer.cursor.read_u8().unwrap(); + let ans = match action { + 0 => std::result::Result::Ok(>::sse_decode(&mut deserializer)), + 1 => std::result::Result::Err( + ::sse_decode(&mut deserializer), + ), + _ => unreachable!(), + }; + deserializer.end(); + let ans = ans.expect("Dart throws exception but Rust side assume it is not failable"); + ans + } + + move || { + flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body(dart_opaque.clone())) + } +} +fn decode_DartFn_Inputs_i_64_Output_opt_box_autoadd_announced_user_AnyhowException( + dart_opaque: flutter_rust_bridge::DartOpaque, +) -> impl Fn(i64) -> flutter_rust_bridge::DartFnFuture> { + use flutter_rust_bridge::IntoDart; + + async fn body( + dart_opaque: flutter_rust_bridge::DartOpaque, + arg0: i64, + ) -> Option { + let args = vec![arg0.into_into_dart().into_dart()]; + let message = FLUTTER_RUST_BRIDGE_HANDLER + .dart_fn_invoke(dart_opaque, args) + .await; + + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let action = deserializer.cursor.read_u8().unwrap(); + let ans = match action { + 0 => std::result::Result::Ok(>::sse_decode( + &mut deserializer, + )), + 1 => std::result::Result::Err( + ::sse_decode(&mut deserializer), + ), + _ => unreachable!(), + }; + deserializer.end(); + let ans = ans.expect("Dart throws exception but Rust side assume it is not failable"); + ans + } + + move |arg0: i64| { + flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body( + dart_opaque.clone(), + arg0, + )) + } +} +fn decode_DartFn_Inputs_i_64_Output_opt_list_list_prim_u_8_strict_AnyhowException( + dart_opaque: flutter_rust_bridge::DartOpaque, +) -> impl Fn(i64) -> flutter_rust_bridge::DartFnFuture>>> { + use flutter_rust_bridge::IntoDart; + + async fn body(dart_opaque: flutter_rust_bridge::DartOpaque, arg0: i64) -> Option>> { + let args = vec![arg0.into_into_dart().into_dart()]; + let message = FLUTTER_RUST_BRIDGE_HANDLER + .dart_fn_invoke(dart_opaque, args) + .await; + + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let action = deserializer.cursor.read_u8().unwrap(); + let ans = match action { + 0 => std::result::Result::Ok(>>>::sse_decode(&mut deserializer)), + 1 => std::result::Result::Err( + ::sse_decode(&mut deserializer), + ), + _ => unreachable!(), + }; + deserializer.end(); + let ans = ans.expect("Dart throws exception but Rust side assume it is not failable"); + ans + } + + move |arg0: i64| { + flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body( + dart_opaque.clone(), + arg0, + )) + } +} +fn decode_DartFn_Inputs_i_64_Output_opt_list_other_promotion_AnyhowException( + dart_opaque: flutter_rust_bridge::DartOpaque, +) -> impl Fn(i64) -> flutter_rust_bridge::DartFnFuture>> { + use flutter_rust_bridge::IntoDart; + + async fn body( + dart_opaque: flutter_rust_bridge::DartOpaque, + arg0: i64, + ) -> Option> { + let args = vec![arg0.into_into_dart().into_dart()]; + let message = FLUTTER_RUST_BRIDGE_HANDLER + .dart_fn_invoke(dart_opaque, args) + .await; + + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let action = deserializer.cursor.read_u8().unwrap(); + let ans = match action { + 0 => std::result::Result::Ok(>>::sse_decode( + &mut deserializer, + )), + 1 => std::result::Result::Err( + ::sse_decode(&mut deserializer), + ), + _ => unreachable!(), + }; + deserializer.end(); + let ans = ans.expect("Dart throws exception but Rust side assume it is not failable"); + ans + } + + move |arg0: i64| { + flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body( + dart_opaque.clone(), + arg0, + )) + } +} +fn decode_DartFn_Inputs_i_64_Output_opt_list_prim_u_8_strict_AnyhowException( + dart_opaque: flutter_rust_bridge::DartOpaque, +) -> impl Fn(i64) -> flutter_rust_bridge::DartFnFuture>> { + use flutter_rust_bridge::IntoDart; + + async fn body(dart_opaque: flutter_rust_bridge::DartOpaque, arg0: i64) -> Option> { + let args = vec![arg0.into_into_dart().into_dart()]; + let message = FLUTTER_RUST_BRIDGE_HANDLER + .dart_fn_invoke(dart_opaque, args) + .await; + + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let action = deserializer.cursor.read_u8().unwrap(); + let ans = match action { + 0 => std::result::Result::Ok(>>::sse_decode(&mut deserializer)), + 1 => std::result::Result::Err( + ::sse_decode(&mut deserializer), + ), + _ => unreachable!(), + }; + deserializer.end(); + let ans = ans.expect("Dart throws exception but Rust side assume it is not failable"); + ans + } + + move |arg0: i64| { + flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body( + dart_opaque.clone(), + arg0, + )) + } +} +fn decode_DartFn_Inputs_i_64_announced_user_opt_box_autoadd_i_64_Output_bool_AnyhowException( + dart_opaque: flutter_rust_bridge::DartOpaque, +) -> impl Fn(i64, crate::bridge::AnnouncedUser, Option) -> flutter_rust_bridge::DartFnFuture +{ + use flutter_rust_bridge::IntoDart; + + async fn body( + dart_opaque: flutter_rust_bridge::DartOpaque, + arg0: i64, + arg1: crate::bridge::AnnouncedUser, + arg2: Option, + ) -> bool { + let args = vec![ + arg0.into_into_dart().into_dart(), + arg1.into_into_dart().into_dart(), + arg2.into_into_dart().into_dart(), + ]; + let message = FLUTTER_RUST_BRIDGE_HANDLER + .dart_fn_invoke(dart_opaque, args) + .await; + + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let action = deserializer.cursor.read_u8().unwrap(); + let ans = match action { + 0 => std::result::Result::Ok(::sse_decode(&mut deserializer)), + 1 => std::result::Result::Err( + ::sse_decode(&mut deserializer), + ), + _ => unreachable!(), + }; + deserializer.end(); + let ans = ans.expect("Dart throws exception but Rust side assume it is not failable"); + ans + } + + move |arg0: i64, arg1: crate::bridge::AnnouncedUser, arg2: Option| { + flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body( + dart_opaque.clone(), + arg0, + arg1, + arg2, + )) + } +} +fn decode_DartFn_Inputs_i_64_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + dart_opaque: flutter_rust_bridge::DartOpaque, +) -> impl Fn(i64, i64, Vec) -> flutter_rust_bridge::DartFnFuture { + use flutter_rust_bridge::IntoDart; + + async fn body( + dart_opaque: flutter_rust_bridge::DartOpaque, + arg0: i64, + arg1: i64, + arg2: Vec, + ) -> bool { + let args = vec![ + arg0.into_into_dart().into_dart(), + arg1.into_into_dart().into_dart(), + arg2.into_into_dart().into_dart(), + ]; + let message = FLUTTER_RUST_BRIDGE_HANDLER + .dart_fn_invoke(dart_opaque, args) + .await; + + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let action = deserializer.cursor.read_u8().unwrap(); + let ans = match action { + 0 => std::result::Result::Ok(::sse_decode(&mut deserializer)), + 1 => std::result::Result::Err( + ::sse_decode(&mut deserializer), + ), + _ => unreachable!(), + }; + deserializer.end(); + let ans = ans.expect("Dart throws exception but Rust side assume it is not failable"); + ans + } + + move |arg0: i64, arg1: i64, arg2: Vec| { + flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body( + dart_opaque.clone(), + arg0, + arg1, + arg2, + )) + } +} +fn decode_DartFn_Inputs_i_64_list_prim_u_8_strict_Output_bool_AnyhowException( + dart_opaque: flutter_rust_bridge::DartOpaque, +) -> impl Fn(i64, Vec) -> flutter_rust_bridge::DartFnFuture { + use flutter_rust_bridge::IntoDart; + + async fn body(dart_opaque: flutter_rust_bridge::DartOpaque, arg0: i64, arg1: Vec) -> bool { + let args = vec![ + arg0.into_into_dart().into_dart(), + arg1.into_into_dart().into_dart(), + ]; + let message = FLUTTER_RUST_BRIDGE_HANDLER + .dart_fn_invoke(dart_opaque, args) + .await; + + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let action = deserializer.cursor.read_u8().unwrap(); + let ans = match action { + 0 => std::result::Result::Ok(::sse_decode(&mut deserializer)), + 1 => std::result::Result::Err( + ::sse_decode(&mut deserializer), + ), + _ => unreachable!(), + }; + deserializer.end(); + let ans = ans.expect("Dart throws exception but Rust side assume it is not failable"); + ans + } + + move |arg0: i64, arg1: Vec| { + flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body( + dart_opaque.clone(), + arg0, + arg1, + )) + } +} +fn decode_DartFn_Inputs_list_list_prim_u_8_strict_Output_bool_AnyhowException( + dart_opaque: flutter_rust_bridge::DartOpaque, +) -> impl Fn(Vec>) -> flutter_rust_bridge::DartFnFuture { + use flutter_rust_bridge::IntoDart; + + async fn body(dart_opaque: flutter_rust_bridge::DartOpaque, arg0: Vec>) -> bool { + let args = vec![arg0.into_into_dart().into_dart()]; + let message = FLUTTER_RUST_BRIDGE_HANDLER + .dart_fn_invoke(dart_opaque, args) + .await; + + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let action = deserializer.cursor.read_u8().unwrap(); + let ans = match action { + 0 => std::result::Result::Ok(::sse_decode(&mut deserializer)), + 1 => std::result::Result::Err( + ::sse_decode(&mut deserializer), + ), + _ => unreachable!(), + }; + deserializer.end(); + let ans = ans.expect("Dart throws exception but Rust side assume it is not failable"); + ans + } + + move |arg0: Vec>| { + flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body( + dart_opaque.clone(), + arg0, + )) + } +} +fn decode_DartFn_Inputs_list_prim_u_8_strict_Output_opt_list_prim_u_8_strict_AnyhowException( + dart_opaque: flutter_rust_bridge::DartOpaque, +) -> impl Fn(Vec) -> flutter_rust_bridge::DartFnFuture>> { + use flutter_rust_bridge::IntoDart; + + async fn body(dart_opaque: flutter_rust_bridge::DartOpaque, arg0: Vec) -> Option> { + let args = vec![arg0.into_into_dart().into_dart()]; + let message = FLUTTER_RUST_BRIDGE_HANDLER + .dart_fn_invoke(dart_opaque, args) + .await; + + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let action = deserializer.cursor.read_u8().unwrap(); + let ans = match action { + 0 => std::result::Result::Ok(>>::sse_decode(&mut deserializer)), + 1 => std::result::Result::Err( + ::sse_decode(&mut deserializer), + ), + _ => unreachable!(), + }; + deserializer.end(); + let ans = ans.expect("Dart throws exception but Rust side assume it is not failable"); + ans + } + + move |arg0: Vec| { + flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body( + dart_opaque.clone(), + arg0, + )) + } +} +fn decode_DartFn_Inputs_list_prim_u_8_strict_list_prim_u_8_strict_list_prim_u_8_strict_Output_bool_AnyhowException( + dart_opaque: flutter_rust_bridge::DartOpaque, +) -> impl Fn(Vec, Vec, Vec) -> flutter_rust_bridge::DartFnFuture { + use flutter_rust_bridge::IntoDart; + + async fn body( + dart_opaque: flutter_rust_bridge::DartOpaque, + arg0: Vec, + arg1: Vec, + arg2: Vec, + ) -> bool { + let args = vec![ + arg0.into_into_dart().into_dart(), + arg1.into_into_dart().into_dart(), + arg2.into_into_dart().into_dart(), + ]; + let message = FLUTTER_RUST_BRIDGE_HANDLER + .dart_fn_invoke(dart_opaque, args) + .await; + + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let action = deserializer.cursor.read_u8().unwrap(); + let ans = match action { + 0 => std::result::Result::Ok(::sse_decode(&mut deserializer)), + 1 => std::result::Result::Err( + ::sse_decode(&mut deserializer), + ), + _ => unreachable!(), + }; + deserializer.end(); + let ans = ans.expect("Dart throws exception but Rust side assume it is not failable"); + ans + } + + move |arg0: Vec, arg1: Vec, arg2: Vec| { + flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body( + dart_opaque.clone(), + arg0, + arg1, + arg2, + )) + } +} +fn decode_DartFn_Inputs_other_promotion_Output_bool_AnyhowException( + dart_opaque: flutter_rust_bridge::DartOpaque, +) -> impl Fn(crate::bridge::OtherPromotion) -> flutter_rust_bridge::DartFnFuture { + use flutter_rust_bridge::IntoDart; + + async fn body( + dart_opaque: flutter_rust_bridge::DartOpaque, + arg0: crate::bridge::OtherPromotion, + ) -> bool { + let args = vec![arg0.into_into_dart().into_dart()]; + let message = FLUTTER_RUST_BRIDGE_HANDLER + .dart_fn_invoke(dart_opaque, args) + .await; + + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let action = deserializer.cursor.read_u8().unwrap(); + let ans = match action { + 0 => std::result::Result::Ok(::sse_decode(&mut deserializer)), + 1 => std::result::Result::Err( + ::sse_decode(&mut deserializer), + ), + _ => unreachable!(), + }; + deserializer.end(); + let ans = ans.expect("Dart throws exception but Rust side assume it is not failable"); + ans + } + + move |arg0: crate::bridge::OtherPromotion| { + flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body( + dart_opaque.clone(), + arg0, + )) + } +} + // Section: dart2rust impl SseDecode for flutter_rust_bridge::for_generated::anyhow::Error { @@ -173,6 +665,22 @@ impl SseDecode for flutter_rust_bridge::for_generated::anyhow::Error { } } +impl SseDecode for flutter_rust_bridge::DartOpaque { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return unsafe { flutter_rust_bridge::for_generated::sse_decode_dart_opaque(inner) }; + } +} + +impl SseDecode for StreamSink { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return StreamSink::deserialize(inner); + } +} + impl SseDecode for String { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -181,18 +689,34 @@ impl SseDecode for String { } } -impl SseDecode for crate::database::contact::Contact { +impl SseDecode for crate::bridge::AnnouncedUser { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { let mut var_userId = ::sse_decode(deserializer); - let mut var_username = ::sse_decode(deserializer); - return crate::database::contact::Contact { + let mut var_publicKey = >::sse_decode(deserializer); + let mut var_publicId = ::sse_decode(deserializer); + return crate::bridge::AnnouncedUser { user_id: var_userId, - username: var_username, + public_key: var_publicKey, + public_id: var_publicId, }; } } +impl SseDecode for bool { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_u8().unwrap() != 0 + } +} + +impl SseDecode for crate::bridge::wrapper::user_discovery::FlutterUserDiscovery { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + return crate::bridge::wrapper::user_discovery::FlutterUserDiscovery {}; + } +} + impl SseDecode for i64 { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -200,15 +724,32 @@ impl SseDecode for i64 { } } -impl SseDecode for Vec { +impl SseDecode for isize { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_i64::().unwrap() as _ + } +} + +impl SseDecode for Vec> { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { let mut len_ = ::sse_decode(deserializer); let mut ans_ = Vec::with_capacity(len_ as usize); for idx_ in 0..len_ { - ans_.push(::sse_decode( - deserializer, - )); + ans_.push(>::sse_decode(deserializer)); + } + return ans_; + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode(deserializer)); } return ans_; } @@ -226,6 +767,17 @@ impl SseDecode for Vec { } } +impl SseDecode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some(::sse_decode(deserializer)); + } else { + return None; + } + } +} + impl SseDecode for Option { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -237,6 +789,41 @@ impl SseDecode for Option { } } +impl SseDecode for Option>> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some(>>::sse_decode(deserializer)); + } else { + return None; + } + } +} + +impl SseDecode for Option> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some(>::sse_decode( + deserializer, + )); + } else { + return None; + } + } +} + +impl SseDecode for Option> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some(>::sse_decode(deserializer)); + } else { + return None; + } + } +} + impl SseDecode for crate::bridge::OtherPromotion { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -288,6 +875,13 @@ impl SseDecode for () { fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {} } +impl SseDecode for usize { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_u64::().unwrap() as _ + } +} + impl SseDecode for i32 { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -295,13 +889,6 @@ impl SseDecode for i32 { } } -impl SseDecode for bool { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - deserializer.cursor.read_u8().unwrap() != 0 - } -} - fn pde_ffi_dispatcher_primary_impl( func_id: i32, port: flutter_rust_bridge::for_generated::MessagePort, @@ -311,11 +898,15 @@ fn pde_ffi_dispatcher_primary_impl( ) { // Codec=Pde (Serialization + dispatch), see doc to use other codecs match func_id { - 1 => wire__crate__bridge__get_all_contacts_impl(port, ptr, rust_vec_len, data_len), - 2 => wire__crate__bridge__initialize_twonly_impl(port, ptr, rust_vec_len, data_len), - 3 => wire__crate__bridge__load_promotions_impl(port, ptr, rust_vec_len, data_len), - _ => unreachable!(), - } + 1 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_get_current_version_impl(port, ptr, rust_vec_len, data_len), +2 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_get_new_messages_impl(port, ptr, rust_vec_len, data_len), +3 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_handle_user_discovery_messages_impl(port, ptr, rust_vec_len, data_len), +4 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_initialize_or_update_impl(port, ptr, rust_vec_len, data_len), +5 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_should_request_new_messages_impl(port, ptr, rust_vec_len, data_len), +6 => wire__crate__bridge__callbacks__init_flutter_callbacks_impl(port, ptr, rust_vec_len, data_len), +7 => wire__crate__bridge__initialize_twonly_flutter_impl(port, ptr, rust_vec_len, data_len), + _ => unreachable!(), + } } fn pde_ffi_dispatcher_sync_impl( @@ -333,23 +924,43 @@ fn pde_ffi_dispatcher_sync_impl( // Section: rust2dart // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::database::contact::Contact { +impl flutter_rust_bridge::IntoDart for FrbWrapper { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.user_id.into_into_dart().into_dart(), - self.username.into_into_dart().into_dart(), + self.0.user_id.into_into_dart().into_dart(), + self.0.public_key.into_into_dart().into_dart(), + self.0.public_id.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::database::contact::Contact + for FrbWrapper { } -impl flutter_rust_bridge::IntoIntoDart - for crate::database::contact::Contact +impl flutter_rust_bridge::IntoIntoDart> + for crate::bridge::AnnouncedUser { - fn into_into_dart(self) -> crate::database::contact::Contact { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart + for crate::bridge::wrapper::user_discovery::FlutterUserDiscovery +{ + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + Vec::::new().into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::bridge::wrapper::user_discovery::FlutterUserDiscovery +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::bridge::wrapper::user_discovery::FlutterUserDiscovery +{ + fn into_into_dart(self) -> crate::bridge::wrapper::user_discovery::FlutterUserDiscovery { self } } @@ -407,6 +1018,20 @@ impl SseEncode for flutter_rust_bridge::for_generated::anyhow::Error { } } +impl SseEncode for flutter_rust_bridge::DartOpaque { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.encode(), serializer); + } +} + +impl SseEncode for StreamSink { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + unimplemented!("") + } +} + impl SseEncode for String { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -414,14 +1039,27 @@ impl SseEncode for String { } } -impl SseEncode for crate::database::contact::Contact { +impl SseEncode for crate::bridge::AnnouncedUser { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.user_id, serializer); - ::sse_encode(self.username, serializer); + >::sse_encode(self.public_key, serializer); + ::sse_encode(self.public_id, serializer); } } +impl SseEncode for bool { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer.cursor.write_u8(self as _).unwrap(); + } +} + +impl SseEncode for crate::bridge::wrapper::user_discovery::FlutterUserDiscovery { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {} +} + impl SseEncode for i64 { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -429,12 +1067,32 @@ impl SseEncode for i64 { } } -impl SseEncode for Vec { +impl SseEncode for isize { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer + .cursor + .write_i64::(self as _) + .unwrap(); + } +} + +impl SseEncode for Vec> { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + >::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); } } } @@ -449,6 +1107,16 @@ impl SseEncode for Vec { } } +impl SseEncode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + ::sse_encode(value, serializer); + } + } +} + impl SseEncode for Option { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -459,6 +1127,36 @@ impl SseEncode for Option { } } +impl SseEncode for Option>> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + >>::sse_encode(value, serializer); + } + } +} + +impl SseEncode for Option> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + >::sse_encode(value, serializer); + } + } +} + +impl SseEncode for Option> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + >::sse_encode(value, serializer); + } + } +} + impl SseEncode for crate::bridge::OtherPromotion { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -498,6 +1196,16 @@ impl SseEncode for () { fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {} } +impl SseEncode for usize { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer + .cursor + .write_u64::(self as _) + .unwrap(); + } +} + impl SseEncode for i32 { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -505,13 +1213,6 @@ impl SseEncode for i32 { } } -impl SseEncode for bool { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - serializer.cursor.write_u8(self as _).unwrap(); - } -} - #[cfg(not(target_family = "wasm"))] mod io { // This file is automatically generated, so please do not edit it. diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 519a5714..39c49fb0 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -1,5 +1,5 @@ pub mod bridge; mod database; mod frb_generated; -mod user_discovery_store; +mod standalone; mod utils; diff --git a/rust/src/standalone/mod.rs b/rust/src/standalone/mod.rs new file mode 100644 index 00000000..09822bc7 --- /dev/null +++ b/rust/src/standalone/mod.rs @@ -0,0 +1,9 @@ +use crate::{bridge::TwonlyConfig, database::Database}; +use std::sync::Arc; + +pub(crate) struct TwonlyStandalone { + #[allow(dead_code)] + pub(crate) config: TwonlyConfig, + /// Because Rust is called from a different process it is safe to write to the twonly_db. + pub(crate) twonly_db: Arc, +} diff --git a/rust/src/user_discovery_store.rs b/rust/src/user_discovery_store.rs deleted file mode 100644 index 1cee04e1..00000000 --- a/rust/src/user_discovery_store.rs +++ /dev/null @@ -1,349 +0,0 @@ -#[allow(async_fn_in_trait)] -use protocols::user_discovery::error::{Result, UserDiscoveryError}; -use protocols::user_discovery::traits::{AnnouncedUser, OtherPromotion, UserDiscoveryStore}; -use protocols::user_discovery::UserID; -use sqlx::{QueryBuilder, Row, Sqlite, Transaction}; -use std::collections::HashMap; -use std::path::PathBuf; -use std::sync::Arc; - -use crate::bridge::error::TwonlyError; -use crate::bridge::{get_workspace, Twonly}; - -#[derive(Clone)] -pub(crate) struct UserDiscoveryDatabaseStore { - ws: Arc<&'static Twonly>, -} - -impl UserDiscoveryStore for UserDiscoveryDatabaseStore { - async fn new() -> Self { - #[cfg(test)] - return Self { - ws: Arc::new( - crate::bridge::tests::initialize_twonly_for_testing(false) - .await - .unwrap(), - ), - }; - #[allow(unreachable_code)] - Self { - ws: Arc::new(get_workspace().unwrap()), - } - } - async fn get_config(&self) -> Result { - let config_path = - PathBuf::from(&self.ws.config.data_directory).join("user_discovery_config.json"); - - if !config_path.is_file() { - return Err(UserDiscoveryError::NotInitialized); - } - - tracing::debug!("Loading Config from {}", config_path.display()); - Ok(std::fs::read_to_string(&config_path)?) - } - - async fn update_config(&self, update: String) -> Result<()> { - tracing::debug!("Updating configuration file."); - let config_path = - PathBuf::from(&self.ws.config.data_directory).join("user_discovery_config.json"); - std::fs::write(config_path, &update)?; - Ok(()) - } - - async fn set_shares(&self, shares: Vec>) -> Result<()> { - let mut query_builder: QueryBuilder = - QueryBuilder::new("INSERT INTO user_discovery_shares (share) "); - - query_builder.push_values(shares, |mut b, share| { - b.push_bind(share); - }); - - query_builder - .build() - .execute(&self.ws.database.pool) - .await - .map_err(TwonlyError::from)?; - - Ok(()) - } - - async fn get_share_for_contact(&self, contact_id: UserID) -> Result> { - let mut tx: Transaction<'_, Sqlite> = self - .ws - .database - .pool - .begin() - .await - .map_err(TwonlyError::from)?; - - // 1. Check if the user already has a share assigned - let existing: Option> = - sqlx::query_scalar("SELECT share FROM user_discovery_shares WHERE contact_id = ?") - .bind(contact_id) - .fetch_optional(&mut *tx) - .await - .map_err(TwonlyError::from)?; - - if let Some(share) = existing { - tx.commit().await.map_err(TwonlyError::from)?; - return Ok(share); - } - - // 2. No share found. Try to assign an available one (where contact_id is NULL) - let rows_affected = sqlx::query( - "UPDATE user_discovery_shares - SET contact_id = ? - WHERE share_id = ( - SELECT share_id FROM user_discovery_shares - WHERE contact_id IS NULL - LIMIT 1 - )", - ) - .bind(contact_id) - .execute(&mut *tx) - .await - .map_err(TwonlyError::from)? - .rows_affected(); - - if rows_affected == 0 { - return Err(UserDiscoveryError::NoSharesLeft); - } - - // 3. Retrieve the newly assigned share - let assigned_share: Vec = - sqlx::query_scalar("SELECT share FROM user_discovery_shares WHERE contact_id = ?") - .bind(contact_id) - .fetch_one(&mut *tx) - .await - .map_err(TwonlyError::from)?; - - tx.commit().await.map_err(TwonlyError::from)?; - Ok(assigned_share) - } - - async fn push_own_promotion( - &self, - contact_id: UserID, - version: u32, - promotion: Vec, - ) -> Result<()> { - sqlx::query( - r#" - INSERT INTO user_discovery_own_promotions (contact_id, promotion, version_id) - VALUES (?1, ?2, ?3) - "#, - ) - .bind(contact_id) - .bind(promotion) - .bind(version as i64) // SQLite integers are usually i32/i64 - .execute(&self.ws.database.pool) - .await - .map_err(TwonlyError::from)?; - Ok(()) - } - - async fn get_own_promotions_after_version(&self, version: u32) -> Result>> { - let promotions: Vec> = sqlx::query_scalar( - "SELECT promotion FROM user_discovery_own_promotions - WHERE version_id > ? - ORDER BY version_id ASC", - ) - .bind(version as i64) - .fetch_all(&self.ws.database.pool) - .await - .map_err(TwonlyError::from)?; - Ok(promotions) - } - - async fn store_other_promotion(&self, promotion: OtherPromotion) -> Result<()> { - sqlx::query( - r" - INSERT INTO user_discovery_other_promotions ( - from_contact_id, - promotion_id, - public_id, - threshold, - announcement_share, - public_key_verified_timestamp - ) - VALUES (?1, ?2, ?3, ?4, ?5, ?6) - ", - ) - .bind(promotion.from_contact_id) - .bind(promotion.promotion_id as i64) - .bind(promotion.public_id) - .bind(promotion.threshold as i64) - .bind(promotion.announcement_share) - .bind(promotion.public_key_verified_timestamp) // Option maps to NULLable - .execute(&self.ws.database.pool) - .await - .map_err(TwonlyError::from)?; - - Ok(()) - } - - async fn get_other_promotions_by_public_id( - &self, - public_id: i64, - ) -> Result> { - let promotions = sqlx::query_as::<_, OtherPromotion>( - "SELECT * FROM user_discovery_other_promotions WHERE public_id = ?", - ) - .bind(public_id) - .fetch_all(&self.ws.database.pool) - .await - .map_err(TwonlyError::from)?; - Ok(promotions) - } - - async fn get_announced_user_by_public_id( - &self, - public_id: i64, - ) -> Result> { - let row = sqlx::query("SELECT * FROM user_discovery_announced_users WHERE public_id = ?") - .bind(public_id) - .fetch_optional(&self.ws.database.pool) - .await - .map_err(TwonlyError::from)?; - match row { - Some(r) => Ok(Some(AnnouncedUser { - user_id: r.get::("announced_user_id"), - public_key: r.get::, _>("announced_public_key"), - public_id: r.get::("public_id"), - })), - None => Ok(None), - } - } - - async fn push_new_user_relation( - &self, - from_contact_id: UserID, - announced_user: AnnouncedUser, - public_key_verified_timestamp: Option, - ) -> Result<()> { - let mut tx = self - .ws - .database - .pool - .begin() - .await - .map_err(TwonlyError::from)?; - - sqlx::query( - r" - INSERT INTO user_discovery_announced_users (announced_user_id, announced_public_key, public_id) - VALUES (?1, ?2, ?3) - ON CONFLICT(announced_user_id) DO NOTHING - ") - .bind(announced_user.user_id) - .bind(announced_user.public_key) - .bind(announced_user.public_id) - .execute(&mut *tx) - .await.map_err(TwonlyError::from)?; - - if from_contact_id != announced_user.user_id { - tracing::debug!( - "INSERTING THAT {} KNOWS {}", - from_contact_id, - announced_user.user_id - ); - sqlx::query( - r"INSERT INTO user_discovery_user_relations ( - announced_user_id, - from_contact_id, - public_key_verified_timestamp - ) - VALUES (?1, ?2, ?3) - ON CONFLICT(announced_user_id, from_contact_id) DO UPDATE SET - public_key_verified_timestamp = excluded.public_key_verified_timestamp - ", - ) - .bind(announced_user.user_id) - .bind(from_contact_id) - .bind(public_key_verified_timestamp) - .execute(&mut *tx) - .await - .map_err(TwonlyError::from)?; - } - - tx.commit().await.map_err(TwonlyError::from)?; - - Ok(()) - } - - async fn get_all_announced_users( - &self, - ) -> Result)>>> { - let rows = sqlx::query( - r#" - SELECT - u.announced_user_id, - u.announced_public_key, - u.public_id, - r.from_contact_id, - r.public_key_verified_timestamp - FROM user_discovery_announced_users u - LEFT JOIN user_discovery_user_relations r - ON u.announced_user_id = r.announced_user_id - ORDER BY u.announced_user_id - "#, - ) - .fetch_all(&self.ws.database.pool) - .await - .map_err(TwonlyError::from)?; - - let mut map: HashMap)>> = HashMap::new(); - - for row in rows { - let announced_user = AnnouncedUser { - user_id: row.get::("announced_user_id"), - public_key: row.get::, _>("announced_public_key"), - public_id: row.get::("public_id"), - }; - - let relations_list = map.entry(announced_user).or_insert_with(Vec::new); - - // SQLX returns NULL for columns in a LEFT JOIN where no match is found. - if let Ok(Some(contact_id)) = row.try_get::, _>("from_contact_id") { - let timestamp = row.get::, _>("public_key_verified_timestamp"); - relations_list.push((contact_id, timestamp)); - } - } - - Ok(map) - } - - async fn get_contact_version(&self, contact_id: UserID) -> Result>> { - let version: Option> = - sqlx::query_scalar("SELECT user_discovery_version FROM contacts WHERE user_id = ?") - .bind(contact_id) - .fetch_optional(&self.ws.database.pool) - .await - .map_err(TwonlyError::from)?; - - Ok(version) - } - - async fn set_contact_version(&self, contact_id: UserID, update: Vec) -> Result<()> { - sqlx::query("UPDATE contacts SET user_discovery_version = ? WHERE user_id = ?") - .bind(update) - .bind(contact_id) - .execute(&self.ws.database.pool) - .await - .map_err(TwonlyError::from)?; - - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use crate::user_discovery_store::UserDiscoveryDatabaseStore; - use protocols::user_discovery::tests::test_initialize_user_discovery; - - #[tokio::test] - async fn test_initialize_user_discovery_database_store() { - let _ = pretty_env_logger::try_init(); - test_initialize_user_discovery::().await; - } -} diff --git a/rust/src/utils.rs b/rust/src/utils.rs index 7ec8da6d..c4bba078 100644 --- a/rust/src/utils.rs +++ b/rust/src/utils.rs @@ -1,22 +1,16 @@ -use parking_lot::{RwLock, RwLockReadGuard}; use std::sync::Arc; +use tokio::sync::{RwLock, RwLockReadGuard}; #[derive(Default, Clone)] pub(crate) struct Shared(Arc>); -impl Shared -where - T: Clone, -{ +impl Shared { pub(crate) fn new(value: T) -> Self { Self(Arc::new(RwLock::new(value))) } - pub(crate) fn get(&self) -> RwLockReadGuard<'_, T> { - self.0.read() - } - pub(crate) fn cloned(&self) -> T { - self.0.read().clone() - } - pub(crate) fn set(&self, value: T) { - *self.0.write() = value; + pub(crate) async fn get(&self) -> RwLockReadGuard<'_, T> { + self.0.read().await } + // pub(crate) async fn set(&self, value: T) { + // *self.0.write().await = value; + // } } diff --git a/rust_dependencies/protocols/src/user_discovery/stores/in_memory_store.rs b/rust_dependencies/protocols/src/user_discovery/stores/in_memory_store.rs index e1befe8e..3d3b8450 100644 --- a/rust_dependencies/protocols/src/user_discovery/stores/in_memory_store.rs +++ b/rust_dependencies/protocols/src/user_discovery/stores/in_memory_store.rs @@ -27,9 +27,6 @@ impl InMemoryStore { } impl UserDiscoveryStore for InMemoryStore { - async fn new() -> Self { - Self::default() - } async fn get_config(&self) -> Result { if let Some(storage) = self.storage().config.clone() { return Ok(storage); diff --git a/rust_dependencies/protocols/src/user_discovery/tests.rs b/rust_dependencies/protocols/src/user_discovery/tests.rs index 58b957af..43b7db1f 100644 --- a/rust_dependencies/protocols/src/user_discovery/tests.rs +++ b/rust_dependencies/protocols/src/user_discovery/tests.rs @@ -12,8 +12,10 @@ fn get_version_bytes(announcement: u32, promotion: u32) -> Vec { .encode_to_vec() } -async fn get_ud(user_id: usize) -> UserDiscovery { - let store = S::new().await; +async fn get_ud( + user_id: usize, +) -> UserDiscovery { + let store = S::default(); let ud = UserDiscovery::new(store.to_owned(), TestingUtils::default()).unwrap(); ud.initialize_or_update(2, user_id as UserID, vec![user_id as u8; 32]) @@ -97,7 +99,7 @@ struct TestUsers { uds: Vec>, } -impl TestUsers { +impl TestUsers { async fn get() -> Self { let names = ["ALICE", "BOB", "CHARLIE", "DAVID", "FRANK"]; let mut uds = vec![]; @@ -119,7 +121,7 @@ impl TestUsers { } } -pub async fn test_initialize_user_discovery() { +pub async fn test_initialize_user_discovery() { #[cfg(test)] let _ = pretty_env_logger::try_init(); diff --git a/rust_dependencies/protocols/src/user_discovery/traits.rs b/rust_dependencies/protocols/src/user_discovery/traits.rs index 8e88573a..8c4c51d3 100644 --- a/rust_dependencies/protocols/src/user_discovery/traits.rs +++ b/rust_dependencies/protocols/src/user_discovery/traits.rs @@ -22,7 +22,6 @@ pub struct AnnouncedUser { } pub trait UserDiscoveryStore { - fn new() -> impl std::future::Future + Send; fn get_config(&self) -> impl Future> + Send; fn update_config(&self, update: String) -> impl Future> + Send; fn set_shares(&self, shares: Vec>) -> impl Future> + Send; @@ -88,6 +87,9 @@ pub trait UserDiscoveryUtils { pubkey: &[u8], signature: &[u8], ) -> impl Future> + Send; + /// In case the the user does not exists yet return false. + /// If this happens this should trigger an error, as this functions is only when a message was received from this user... + /// This is used to verify that the share of the promotions contains the same public key and the user is not secretly announcing a different one fn verify_stored_pubkey( &self, from_contact_id: UserID,