From 90de693a9b1b04b48a8382a89e609bad433255bd Mon Sep 17 00:00:00 2001 From: Tien Do Nam Date: Tue, 3 Mar 2026 02:34:20 +0100 Subject: [PATCH] feat: integrate rust http client --- app/lib/provider/http_provider.dart | 43 +- app/lib/provider/network/send_provider.dart | 110 ++-- .../server/controller/receive_controller.dart | 14 +- .../server/controller/send_controller.dart | 1 - .../network/webrtc/webrtc_receiver.dart | 1 - app/lib/rust/api/http.dart | 36 +- app/lib/rust/api/http.freezed.dart | 524 ++++++++++++++++++ app/lib/rust/frb_generated.dart | 275 +++++---- app/lib/rust/frb_generated.io.dart | 111 ++-- app/lib/rust/frb_generated.web.dart | 99 ++-- app/lib/util/rust.dart | 54 ++ app/rust/Cargo.lock | 18 +- app/rust/src/api/http.rs | 69 ++- app/rust/src/frb_generated.rs | 254 +++++---- .../dto/prepare_upload_request_dto_test.dart | 35 -- common/lib/constants.dart | 3 +- common/lib/model/dto/file_dto.dart | 13 +- core/src/http/client/v2.rs | 14 +- core/src/http/client/v3.rs | 11 +- core/src/http/dto.rs | 4 +- core/src/http/dto_v2.rs | 2 +- core/src/http/mod.rs | 4 +- core/src/lib.rs | 4 + 23 files changed, 1181 insertions(+), 518 deletions(-) create mode 100644 app/lib/rust/api/http.freezed.dart create mode 100644 app/lib/util/rust.dart diff --git a/app/lib/provider/http_provider.dart b/app/lib/provider/http_provider.dart index d1dfe9fa..4aefef07 100644 --- a/app/lib/provider/http_provider.dart +++ b/app/lib/provider/http_provider.dart @@ -1,52 +1,19 @@ -import 'package:localsend_app/provider/logging/http_logs_provider.dart'; import 'package:localsend_app/provider/security_provider.dart'; -import 'package:localsend_app/provider/settings_provider.dart'; -import 'package:localsend_app/util/rhttp.dart'; +import 'package:localsend_app/rust/api/http.dart'; import 'package:refena_flutter/refena_flutter.dart'; -import 'package:rhttp/rhttp.dart'; class HttpClientCollection { - final RhttpClient discovery; - final RhttpClient longLiving; + final RsHttpClient v2; HttpClientCollection({ - required this.discovery, - required this.longLiving, + required this.v2, }); } -/// Provides a dio having a specific timeout. -/// Changes must be made in common/lib/src/isolate/child/dio_provider.dart also +/// Provides an HTTP client for each protocol version. final httpProvider = ViewProvider((ref) { final securityContext = ref.watch(securityProvider); - final discoveryTimeout = ref.watch(settingsProvider.select((state) => state.discoveryTimeout)); return HttpClientCollection( - discovery: createRhttpClient(Duration(milliseconds: discoveryTimeout), securityContext), - longLiving: createRhttpClient( - const Duration(days: 30), - securityContext, - interceptor: SimpleInterceptor( - beforeRequest: (request) async { - ref.notifier(httpLogsProvider).addLog('HTTP Request: ${request.method} ${request.url}'); - return Interceptor.next(); - }, - afterResponse: (response) async { - final body = switch (response) { - HttpTextResponse() => response.body, - HttpBytesResponse() => '<${response.body.length} bytes>', - HttpStreamResponse() => '', - }; - - ref - .notifier(httpLogsProvider) - .addLog('HTTP Response: ${response.request.method} ${response.request.url} returned ${response.statusCode} with body: $body'); - return Interceptor.next(); - }, - onError: (exception) async { - ref.notifier(httpLogsProvider).addLog(exception.toString()); - return Interceptor.next(); - }, - ), - ), + v2: createClient(privateKey: securityContext.privateKey, cert: securityContext.certificate, version: LsHttpClientVersion.v2), ); }); diff --git a/app/lib/provider/network/send_provider.dart b/app/lib/provider/network/send_provider.dart index 1a0f6ee9..0a1bbd6c 100644 --- a/app/lib/provider/network/send_provider.dart +++ b/app/lib/provider/network/send_provider.dart @@ -2,14 +2,9 @@ import 'dart:async'; import 'dart:collection'; import 'dart:convert'; -import 'package:common/api_route_builder.dart'; import 'package:common/isolate.dart'; import 'package:common/model/device.dart'; import 'package:common/model/dto/file_dto.dart'; -import 'package:common/model/dto/info_register_dto.dart'; -import 'package:common/model/dto/multicast_dto.dart'; -import 'package:common/model/dto/prepare_upload_request_dto.dart'; -import 'package:common/model/dto/prepare_upload_response_dto.dart'; import 'package:common/model/file_status.dart'; import 'package:common/model/file_type.dart'; import 'package:common/model/session_status.dart'; @@ -27,6 +22,9 @@ import 'package:localsend_app/provider/http_provider.dart'; import 'package:localsend_app/provider/progress_provider.dart'; import 'package:localsend_app/provider/selection/selected_sending_files_provider.dart'; import 'package:localsend_app/provider/settings_provider.dart'; +import 'package:localsend_app/rust/api/http.dart' as rust_http; +import 'package:localsend_app/rust/api/model.dart' as rust_model; +import 'package:localsend_app/util/rust.dart'; import 'package:localsend_app/widget/dialogs/pin_dialog.dart'; import 'package:logging/logging.dart'; import 'package:refena_flutter/refena_flutter.dart'; @@ -62,8 +60,7 @@ class SendNotifier extends Notifier> { required List files, required bool background, }) async { - final client = ref.read(httpProvider).longLiving; - final cancelToken = CancelToken(); + final client = ref.read(httpProvider).v2; final sessionId = _uuid.v4(); final requestState = SendSessionState( @@ -94,7 +91,6 @@ class SendNotifier extends Notifier> { lastAccessed: file.lastAccessed, ) : null, - legacy: target.version == '1.0', ), status: FileStatus.queue, token: null, @@ -115,19 +111,19 @@ class SendNotifier extends Notifier> { ); final originDevice = ref.read(deviceFullInfoProvider); - final requestDto = PrepareUploadRequestDto( - info: InfoRegisterDto( + final requestDto = rust_model.PrepareUploadRequestDto( + info: rust_model.RegisterDto( alias: originDevice.alias, version: originDevice.version, deviceModel: originDevice.deviceModel, - deviceType: originDevice.deviceType, - fingerprint: originDevice.fingerprint, + deviceType: originDevice.deviceType.toRust(), + token: originDevice.fingerprint, port: originDevice.port, - protocol: originDevice.https ? ProtocolType.https : ProtocolType.http, - download: originDevice.download, + protocol: originDevice.https ? rust_model.ProtocolType.https : rust_model.ProtocolType.http, + hasWebInterface: originDevice.download, ), files: { - for (final entry in requestState.files.entries) entry.key: entry.value.file, + for (final entry in requestState.files.entries) entry.key: entry.value.file.toRust(), }, ); @@ -144,23 +140,24 @@ class SendNotifier extends Notifier> { ); } - HttpTextResponse? response; + rust_http.PrepareUploadResult? response; bool invalidPin; bool pinFirstAttempt = true; String? pin; do { invalidPin = false; try { - response = await client.post( - ApiRoute.prepareUpload.target(target), - query: { - if (pin != null) 'pin': pin, - }, - body: HttpBody.json(requestDto.toJson()), - cancelToken: cancelToken, + response = await client.prepareUpload( + protocol: target.getProtocolType(), + ip: target.ip!, + port: target.port, + payload: requestDto, + // TODO + publicKey: null, + pin: pin, ); - } on RhttpStatusCodeException catch (e) { - switch (e.statusCode) { + } on rust_http.RsHttpClientError_StatusCode catch (e) { + switch (e.status) { case 401: invalidPin = true; @@ -238,33 +235,29 @@ class SendNotifier extends Notifier> { } final Map fileMap; - if (target.version == '1.0') { - fileMap = (response.bodyToJson as Map).cast(); + if (response.statusCode == 204) { + // Nothing selected + // Interpret this as "Read and close" + fileMap = {}; } else { - if (response.statusCode == 204) { - // Nothing selected - // Interpret this as "Read and close" - fileMap = {}; - } else { - try { - final responseDto = PrepareUploadResponseDto.fromJson(response.bodyToJson); - fileMap = responseDto.files; - state = state.updateSession( - sessionId: sessionId, - state: (s) => s?.copyWith( - remoteSessionId: responseDto.sessionId, - ), - ); - } catch (e) { - state = state.updateSession( - sessionId: sessionId, - state: (s) => s?.copyWith( - status: SessionStatus.finishedWithErrors, - errorMessage: e.humanErrorMessage, - ), - ); - return; - } + try { + fileMap = response.response!.files; + final sessionId = response.response!.sessionId; + state = state.updateSession( + sessionId: sessionId, + state: (s) => s?.copyWith( + remoteSessionId: sessionId, + ), + ); + } catch (e) { + state = state.updateSession( + sessionId: sessionId, + state: (s) => s?.copyWith( + status: SessionStatus.finishedWithErrors, + errorMessage: e.humanErrorMessage, + ), + ); + return; } } @@ -521,13 +514,24 @@ class SendNotifier extends Notifier> { _cancelRunningRequests(sessionState); + if (remoteSessionId == null) { + closeSession(sessionId); + return; + } + // notify the receiver + final target = sessionState.target; try { ref .read(httpProvider) - .discovery + .v2 // ignore: discarded_futures - .post(ApiRoute.cancel.target(sessionState.target, query: remoteSessionId != null ? {'sessionId': remoteSessionId} : null)); + .cancel( + protocol: target.getProtocolType(), + ip: target.ip!, + port: target.port, + sessionId: remoteSessionId, + ); } catch (e) { _logger.warning('Error while canceling session', e); } diff --git a/app/lib/provider/network/server/controller/receive_controller.dart b/app/lib/provider/network/server/controller/receive_controller.dart index da66eae3..149aa2fd 100644 --- a/app/lib/provider/network/server/controller/receive_controller.dart +++ b/app/lib/provider/network/server/controller/receive_controller.dart @@ -42,6 +42,7 @@ import 'package:localsend_app/util/native/directories.dart'; import 'package:localsend_app/util/native/file_saver.dart'; import 'package:localsend_app/util/native/platform_check.dart'; import 'package:localsend_app/util/native/tray_helper.dart'; +import 'package:localsend_app/util/rust.dart'; import 'package:localsend_app/util/simple_server.dart'; import 'package:localsend_app/widget/dialogs/open_file_dialog.dart'; import 'package:logging/logging.dart'; @@ -798,9 +799,18 @@ class ReceiveController { } // notify sender + final target = session.sender; try { - // ignore: unawaited_futures - server.ref.read(httpProvider).discovery.post(ApiRoute.cancel.target(session.sender, query: {'sessionId': session.sessionId})); + server.ref + .read(httpProvider) + .v2 + // ignore: unawaited_futures + .cancel( + protocol: target.getProtocolType(), + ip: target.ip!, + port: target.port, + sessionId: session.sessionId, + ); } catch (e) { _logger.warning('Failed to notify sender', e); } diff --git a/app/lib/provider/network/server/controller/send_controller.dart b/app/lib/provider/network/server/controller/send_controller.dart index 0b80485a..470fdf95 100644 --- a/app/lib/provider/network/server/controller/send_controller.dart +++ b/app/lib/provider/network/server/controller/send_controller.dart @@ -273,7 +273,6 @@ class SendController { lastAccessed: file.lastAccessed, ) : null, - legacy: false, ), asset: file.asset, path: file.path, diff --git a/app/lib/provider/network/webrtc/webrtc_receiver.dart b/app/lib/provider/network/webrtc/webrtc_receiver.dart index 64136c95..18efad3b 100644 --- a/app/lib/provider/network/webrtc/webrtc_receiver.dart +++ b/app/lib/provider/network/webrtc/webrtc_receiver.dart @@ -195,7 +195,6 @@ extension on FileDto { fileType: dart_model.decodeFromMime(fileType), hash: null, preview: preview, - legacy: false, metadata: metadata?.toFileMetadata(), ); } diff --git a/app/lib/rust/api/http.dart b/app/lib/rust/api/http.dart index 470c3684..02e63ccc 100644 --- a/app/lib/rust/api/http.dart +++ b/app/lib/rust/api/http.dart @@ -4,11 +4,16 @@ // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; +import 'package:freezed_annotation/freezed_annotation.dart' hide protected; import 'package:localsend_app/rust/api/model.dart'; import 'package:localsend_app/rust/api/stream.dart'; import 'package:localsend_app/rust/frb_generated.dart'; -Future createClient({ +part 'http.freezed.dart'; + +// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `from` + +RsHttpClient createClient({ required String privateKey, required String cert, required LsHttpClientVersion version, @@ -18,9 +23,6 @@ Future createClient({ version: version, ); -// Rust type: RustOpaqueMoi> -abstract class ClientError implements RustOpaqueInterface {} - // Rust type: RustOpaqueMoi> abstract class RsHttpClient implements RustOpaqueInterface { Future cancel({ @@ -65,11 +67,11 @@ enum LsHttpClientVersion { class PrepareUploadResult { final int statusCode; - final PrepareUploadResponseDto response; + final PrepareUploadResponseDto? response; const PrepareUploadResult({ required this.statusCode, - required this.response, + this.response, }); @override @@ -98,3 +100,25 @@ class ResultWithPublicKeyRegisterResponseDto { identical(this, other) || other is ResultWithPublicKeyRegisterResponseDto && runtimeType == other.runtimeType && publicKey == other.publicKey && body == other.body; } + +@freezed +sealed class RsHttpClientError with _$RsHttpClientError implements FrbException { + const RsHttpClientError._(); + + const factory RsHttpClientError.statusCode({ + required int status, + String? message, + }) = RsHttpClientError_StatusCode; + const factory RsHttpClientError.reqwest( + String field0, + ) = RsHttpClientError_Reqwest; + const factory RsHttpClientError.json( + String field0, + ) = RsHttpClientError_Json; + const factory RsHttpClientError.io( + String field0, + ) = RsHttpClientError_Io; + const factory RsHttpClientError.other( + String field0, + ) = RsHttpClientError_Other; +} diff --git a/app/lib/rust/api/http.freezed.dart b/app/lib/rust/api/http.freezed.dart new file mode 100644 index 00000000..b1da4f1f --- /dev/null +++ b/app/lib/rust/api/http.freezed.dart @@ -0,0 +1,524 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'http.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$RsHttpClientError { + + + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is RsHttpClientError); +} + + +@override +int get hashCode => runtimeType.hashCode; + +@override +String toString() { + return 'RsHttpClientError()'; +} + + +} + +/// @nodoc +class $RsHttpClientErrorCopyWith<$Res> { +$RsHttpClientErrorCopyWith(RsHttpClientError _, $Res Function(RsHttpClientError) __); +} + + +/// Adds pattern-matching-related methods to [RsHttpClientError]. +extension RsHttpClientErrorPatterns on RsHttpClientError { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap({TResult Function( RsHttpClientError_StatusCode value)? statusCode,TResult Function( RsHttpClientError_Reqwest value)? reqwest,TResult Function( RsHttpClientError_Json value)? json,TResult Function( RsHttpClientError_Io value)? io,TResult Function( RsHttpClientError_Other value)? other,required TResult orElse(),}){ +final _that = this; +switch (_that) { +case RsHttpClientError_StatusCode() when statusCode != null: +return statusCode(_that);case RsHttpClientError_Reqwest() when reqwest != null: +return reqwest(_that);case RsHttpClientError_Json() when json != null: +return json(_that);case RsHttpClientError_Io() when io != null: +return io(_that);case RsHttpClientError_Other() when other != null: +return other(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map({required TResult Function( RsHttpClientError_StatusCode value) statusCode,required TResult Function( RsHttpClientError_Reqwest value) reqwest,required TResult Function( RsHttpClientError_Json value) json,required TResult Function( RsHttpClientError_Io value) io,required TResult Function( RsHttpClientError_Other value) other,}){ +final _that = this; +switch (_that) { +case RsHttpClientError_StatusCode(): +return statusCode(_that);case RsHttpClientError_Reqwest(): +return reqwest(_that);case RsHttpClientError_Json(): +return json(_that);case RsHttpClientError_Io(): +return io(_that);case RsHttpClientError_Other(): +return other(_that);} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull({TResult? Function( RsHttpClientError_StatusCode value)? statusCode,TResult? Function( RsHttpClientError_Reqwest value)? reqwest,TResult? Function( RsHttpClientError_Json value)? json,TResult? Function( RsHttpClientError_Io value)? io,TResult? Function( RsHttpClientError_Other value)? other,}){ +final _that = this; +switch (_that) { +case RsHttpClientError_StatusCode() when statusCode != null: +return statusCode(_that);case RsHttpClientError_Reqwest() when reqwest != null: +return reqwest(_that);case RsHttpClientError_Json() when json != null: +return json(_that);case RsHttpClientError_Io() when io != null: +return io(_that);case RsHttpClientError_Other() when other != null: +return other(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen({TResult Function( int status, String? message)? statusCode,TResult Function( String field0)? reqwest,TResult Function( String field0)? json,TResult Function( String field0)? io,TResult Function( String field0)? other,required TResult orElse(),}) {final _that = this; +switch (_that) { +case RsHttpClientError_StatusCode() when statusCode != null: +return statusCode(_that.status,_that.message);case RsHttpClientError_Reqwest() when reqwest != null: +return reqwest(_that.field0);case RsHttpClientError_Json() when json != null: +return json(_that.field0);case RsHttpClientError_Io() when io != null: +return io(_that.field0);case RsHttpClientError_Other() when other != null: +return other(_that.field0);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when({required TResult Function( int status, String? message) statusCode,required TResult Function( String field0) reqwest,required TResult Function( String field0) json,required TResult Function( String field0) io,required TResult Function( String field0) other,}) {final _that = this; +switch (_that) { +case RsHttpClientError_StatusCode(): +return statusCode(_that.status,_that.message);case RsHttpClientError_Reqwest(): +return reqwest(_that.field0);case RsHttpClientError_Json(): +return json(_that.field0);case RsHttpClientError_Io(): +return io(_that.field0);case RsHttpClientError_Other(): +return other(_that.field0);} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull({TResult? Function( int status, String? message)? statusCode,TResult? Function( String field0)? reqwest,TResult? Function( String field0)? json,TResult? Function( String field0)? io,TResult? Function( String field0)? other,}) {final _that = this; +switch (_that) { +case RsHttpClientError_StatusCode() when statusCode != null: +return statusCode(_that.status,_that.message);case RsHttpClientError_Reqwest() when reqwest != null: +return reqwest(_that.field0);case RsHttpClientError_Json() when json != null: +return json(_that.field0);case RsHttpClientError_Io() when io != null: +return io(_that.field0);case RsHttpClientError_Other() when other != null: +return other(_that.field0);case _: + return null; + +} +} + +} + +/// @nodoc + + +class RsHttpClientError_StatusCode extends RsHttpClientError { + const RsHttpClientError_StatusCode({required this.status, this.message}): super._(); + + + final int status; + final String? message; + +/// Create a copy of RsHttpClientError +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$RsHttpClientError_StatusCodeCopyWith get copyWith => _$RsHttpClientError_StatusCodeCopyWithImpl(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is RsHttpClientError_StatusCode&&(identical(other.status, status) || other.status == status)&&(identical(other.message, message) || other.message == message)); +} + + +@override +int get hashCode => Object.hash(runtimeType,status,message); + +@override +String toString() { + return 'RsHttpClientError.statusCode(status: $status, message: $message)'; +} + + +} + +/// @nodoc +abstract mixin class $RsHttpClientError_StatusCodeCopyWith<$Res> implements $RsHttpClientErrorCopyWith<$Res> { + factory $RsHttpClientError_StatusCodeCopyWith(RsHttpClientError_StatusCode value, $Res Function(RsHttpClientError_StatusCode) _then) = _$RsHttpClientError_StatusCodeCopyWithImpl; +@useResult +$Res call({ + int status, String? message +}); + + + + +} +/// @nodoc +class _$RsHttpClientError_StatusCodeCopyWithImpl<$Res> + implements $RsHttpClientError_StatusCodeCopyWith<$Res> { + _$RsHttpClientError_StatusCodeCopyWithImpl(this._self, this._then); + + final RsHttpClientError_StatusCode _self; + final $Res Function(RsHttpClientError_StatusCode) _then; + +/// Create a copy of RsHttpClientError +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? status = null,Object? message = freezed,}) { + return _then(RsHttpClientError_StatusCode( +status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as int,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + + +} + +/// @nodoc + + +class RsHttpClientError_Reqwest extends RsHttpClientError { + const RsHttpClientError_Reqwest(this.field0): super._(); + + + final String field0; + +/// Create a copy of RsHttpClientError +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$RsHttpClientError_ReqwestCopyWith get copyWith => _$RsHttpClientError_ReqwestCopyWithImpl(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is RsHttpClientError_Reqwest&&(identical(other.field0, field0) || other.field0 == field0)); +} + + +@override +int get hashCode => Object.hash(runtimeType,field0); + +@override +String toString() { + return 'RsHttpClientError.reqwest(field0: $field0)'; +} + + +} + +/// @nodoc +abstract mixin class $RsHttpClientError_ReqwestCopyWith<$Res> implements $RsHttpClientErrorCopyWith<$Res> { + factory $RsHttpClientError_ReqwestCopyWith(RsHttpClientError_Reqwest value, $Res Function(RsHttpClientError_Reqwest) _then) = _$RsHttpClientError_ReqwestCopyWithImpl; +@useResult +$Res call({ + String field0 +}); + + + + +} +/// @nodoc +class _$RsHttpClientError_ReqwestCopyWithImpl<$Res> + implements $RsHttpClientError_ReqwestCopyWith<$Res> { + _$RsHttpClientError_ReqwestCopyWithImpl(this._self, this._then); + + final RsHttpClientError_Reqwest _self; + final $Res Function(RsHttpClientError_Reqwest) _then; + +/// Create a copy of RsHttpClientError +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? field0 = null,}) { + return _then(RsHttpClientError_Reqwest( +null == field0 ? _self.field0 : field0 // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +/// @nodoc + + +class RsHttpClientError_Json extends RsHttpClientError { + const RsHttpClientError_Json(this.field0): super._(); + + + final String field0; + +/// Create a copy of RsHttpClientError +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$RsHttpClientError_JsonCopyWith get copyWith => _$RsHttpClientError_JsonCopyWithImpl(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is RsHttpClientError_Json&&(identical(other.field0, field0) || other.field0 == field0)); +} + + +@override +int get hashCode => Object.hash(runtimeType,field0); + +@override +String toString() { + return 'RsHttpClientError.json(field0: $field0)'; +} + + +} + +/// @nodoc +abstract mixin class $RsHttpClientError_JsonCopyWith<$Res> implements $RsHttpClientErrorCopyWith<$Res> { + factory $RsHttpClientError_JsonCopyWith(RsHttpClientError_Json value, $Res Function(RsHttpClientError_Json) _then) = _$RsHttpClientError_JsonCopyWithImpl; +@useResult +$Res call({ + String field0 +}); + + + + +} +/// @nodoc +class _$RsHttpClientError_JsonCopyWithImpl<$Res> + implements $RsHttpClientError_JsonCopyWith<$Res> { + _$RsHttpClientError_JsonCopyWithImpl(this._self, this._then); + + final RsHttpClientError_Json _self; + final $Res Function(RsHttpClientError_Json) _then; + +/// Create a copy of RsHttpClientError +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? field0 = null,}) { + return _then(RsHttpClientError_Json( +null == field0 ? _self.field0 : field0 // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +/// @nodoc + + +class RsHttpClientError_Io extends RsHttpClientError { + const RsHttpClientError_Io(this.field0): super._(); + + + final String field0; + +/// Create a copy of RsHttpClientError +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$RsHttpClientError_IoCopyWith get copyWith => _$RsHttpClientError_IoCopyWithImpl(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is RsHttpClientError_Io&&(identical(other.field0, field0) || other.field0 == field0)); +} + + +@override +int get hashCode => Object.hash(runtimeType,field0); + +@override +String toString() { + return 'RsHttpClientError.io(field0: $field0)'; +} + + +} + +/// @nodoc +abstract mixin class $RsHttpClientError_IoCopyWith<$Res> implements $RsHttpClientErrorCopyWith<$Res> { + factory $RsHttpClientError_IoCopyWith(RsHttpClientError_Io value, $Res Function(RsHttpClientError_Io) _then) = _$RsHttpClientError_IoCopyWithImpl; +@useResult +$Res call({ + String field0 +}); + + + + +} +/// @nodoc +class _$RsHttpClientError_IoCopyWithImpl<$Res> + implements $RsHttpClientError_IoCopyWith<$Res> { + _$RsHttpClientError_IoCopyWithImpl(this._self, this._then); + + final RsHttpClientError_Io _self; + final $Res Function(RsHttpClientError_Io) _then; + +/// Create a copy of RsHttpClientError +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? field0 = null,}) { + return _then(RsHttpClientError_Io( +null == field0 ? _self.field0 : field0 // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +/// @nodoc + + +class RsHttpClientError_Other extends RsHttpClientError { + const RsHttpClientError_Other(this.field0): super._(); + + + final String field0; + +/// Create a copy of RsHttpClientError +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$RsHttpClientError_OtherCopyWith get copyWith => _$RsHttpClientError_OtherCopyWithImpl(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is RsHttpClientError_Other&&(identical(other.field0, field0) || other.field0 == field0)); +} + + +@override +int get hashCode => Object.hash(runtimeType,field0); + +@override +String toString() { + return 'RsHttpClientError.other(field0: $field0)'; +} + + +} + +/// @nodoc +abstract mixin class $RsHttpClientError_OtherCopyWith<$Res> implements $RsHttpClientErrorCopyWith<$Res> { + factory $RsHttpClientError_OtherCopyWith(RsHttpClientError_Other value, $Res Function(RsHttpClientError_Other) _then) = _$RsHttpClientError_OtherCopyWithImpl; +@useResult +$Res call({ + String field0 +}); + + + + +} +/// @nodoc +class _$RsHttpClientError_OtherCopyWithImpl<$Res> + implements $RsHttpClientError_OtherCopyWith<$Res> { + _$RsHttpClientError_OtherCopyWithImpl(this._self, this._then); + + final RsHttpClientError_Other _self; + final $Res Function(RsHttpClientError_Other) _then; + +/// Create a copy of RsHttpClientError +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? field0 = null,}) { + return _then(RsHttpClientError_Other( +null == field0 ? _self.field0 : field0 // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/app/lib/rust/frb_generated.dart b/app/lib/rust/frb_generated.dart index dbf67be4..3e881561 100644 --- a/app/lib/rust/frb_generated.dart +++ b/app/lib/rust/frb_generated.dart @@ -225,7 +225,7 @@ abstract class RustLibApi extends BaseApi { required FutureOr Function(LsSignalingConnection) onConnection, }); - Future crateApiHttpCreateClient({ + RsHttpClient crateApiHttpCreateClient({ required String privateKey, required String cert, required LsHttpClientVersion version, @@ -242,12 +242,6 @@ abstract class RustLibApi extends BaseApi { required String publicKey, }); - RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_ClientError; - - RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_ClientError; - - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_ClientErrorPtr; - RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_Dart2RustStreamReceiver; RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_Dart2RustStreamReceiver; @@ -536,7 +530,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { }, codec: SseCodec( decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError, + decodeErrorData: sse_decode_rs_http_client_error, ), constMeta: kCrateApiHttpRsHttpClientCancelConstMeta, argValues: [that, protocol, ip, port, sessionId], @@ -586,7 +580,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { }, codec: SseCodec( decodeSuccessData: sse_decode_prepare_upload_result, - decodeErrorData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError, + decodeErrorData: sse_decode_rs_http_client_error, ), constMeta: kCrateApiHttpRsHttpClientPrepareUploadConstMeta, argValues: [that, protocol, ip, port, payload, publicKey, pin], @@ -637,7 +631,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { }, codec: SseCodec( decodeSuccessData: sse_decode_result_with_public_key_register_response_dto, - decodeErrorData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError, + decodeErrorData: sse_decode_rs_http_client_error, ), constMeta: kCrateApiHttpRsHttpClientRegisterConstMeta, argValues: [that, protocol, ip, port, payload], @@ -691,7 +685,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { }, codec: SseCodec( decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError, + decodeErrorData: sse_decode_rs_http_client_error, ), constMeta: kCrateApiHttpRsHttpClientUploadConstMeta, argValues: [ @@ -1377,28 +1371,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiHttpCreateClient({ + RsHttpClient crateApiHttpCreateClient({ required String privateKey, required String cert, required LsHttpClientVersion version, }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { + return handler.executeSync( + SyncTask( + callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(privateKey, serializer); sse_encode_String(cert, serializer); sse_encode_ls_http_client_version(version, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 26, - port: port_, - ); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 26)!; }, codec: SseCodec( decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient, - decodeErrorData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError, + decodeErrorData: sse_decode_rs_http_client_error, ), constMeta: kCrateApiHttpCreateClientConstMeta, argValues: [privateKey, cert, version], @@ -1571,12 +1560,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { }; } - RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_ClientError => - wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError; - - RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_ClientError => - wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError; - RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_Dart2RustStreamReceiver => wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver; @@ -1631,14 +1614,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return AnyhowException(raw as String); } - @protected - ClientError dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - dynamic raw, - ) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return ClientErrorImpl.frbInternalDcoDecode(raw as List); - } - @protected Dart2RustStreamReceiver dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( dynamic raw, @@ -1804,14 +1779,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - @protected - ClientError dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - dynamic raw, - ) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return ClientErrorImpl.frbInternalDcoDecode(raw as List); - } - @protected Dart2RustStreamReceiver dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( dynamic raw, @@ -1986,6 +1953,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return dco_decode_prepare_upload_request_dto(raw); } + @protected + PrepareUploadResponseDto dco_decode_box_autoadd_prepare_upload_response_dto( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return dco_decode_prepare_upload_response_dto(raw); + } + @protected ProposingClientInfo dco_decode_box_autoadd_proposing_client_info( dynamic raw, @@ -2190,6 +2165,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return raw == null ? null : dco_decode_box_autoadd_pin_config(raw); } + @protected + PrepareUploadResponseDto? dco_decode_opt_box_autoadd_prepare_upload_response_dto(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_box_autoadd_prepare_upload_response_dto(raw); + } + @protected PinConfig dco_decode_pin_config(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2230,7 +2211,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return PrepareUploadResult( statusCode: dco_decode_u_16(arr[0]), - response: dco_decode_prepare_upload_response_dto(arr[1]), + response: dco_decode_opt_box_autoadd_prepare_upload_response_dto(arr[1]), ); } @@ -2342,6 +2323,36 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + RsHttpClientError dco_decode_rs_http_client_error(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + switch (raw[0]) { + case 0: + return RsHttpClientError_StatusCode( + status: dco_decode_u_16(raw[1]), + message: dco_decode_opt_String(raw[2]), + ); + case 1: + return RsHttpClientError_Reqwest( + dco_decode_String(raw[1]), + ); + case 2: + return RsHttpClientError_Json( + dco_decode_String(raw[1]), + ); + case 3: + return RsHttpClientError_Io( + dco_decode_String(raw[1]), + ); + case 4: + return RsHttpClientError_Other( + dco_decode_String(raw[1]), + ); + default: + throw Exception('unreachable'); + } + } + @protected RTCFileError dco_decode_rtc_file_error(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2479,17 +2490,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return AnyhowException(inner); } - @protected - ClientError sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - SseDeserializer deserializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - return ClientErrorImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), - sse_decode_i_32(deserializer), - ); - } - @protected Dart2RustStreamReceiver sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( SseDeserializer deserializer, @@ -2691,17 +2691,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return Map.fromEntries(inner.map((e) => MapEntry(e.$1, e.$2))); } - @protected - ClientError sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - SseDeserializer deserializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - return ClientErrorImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), - sse_decode_i_32(deserializer), - ); - } - @protected Dart2RustStreamReceiver sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( SseDeserializer deserializer, @@ -2907,6 +2896,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return (sse_decode_prepare_upload_request_dto(deserializer)); } + @protected + PrepareUploadResponseDto sse_decode_box_autoadd_prepare_upload_response_dto( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + return (sse_decode_prepare_upload_response_dto(deserializer)); + } + @protected ProposingClientInfo sse_decode_box_autoadd_proposing_client_info( SseDeserializer deserializer, @@ -3193,6 +3190,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + PrepareUploadResponseDto? sse_decode_opt_box_autoadd_prepare_upload_response_dto( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return (sse_decode_box_autoadd_prepare_upload_response_dto(deserializer)); + } else { + return null; + } + } + @protected PinConfig sse_decode_pin_config(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -3227,7 +3237,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_statusCode = sse_decode_u_16(deserializer); - var var_response = sse_decode_prepare_upload_response_dto(deserializer); + var var_response = sse_decode_opt_box_autoadd_prepare_upload_response_dto( + deserializer, + ); return PrepareUploadResult( statusCode: var_statusCode, response: var_response, @@ -3350,6 +3362,38 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + RsHttpClientError sse_decode_rs_http_client_error( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var tag_ = sse_decode_i_32(deserializer); + switch (tag_) { + case 0: + var var_status = sse_decode_u_16(deserializer); + var var_message = sse_decode_opt_String(deserializer); + return RsHttpClientError_StatusCode( + status: var_status, + message: var_message, + ); + case 1: + var var_field0 = sse_decode_String(deserializer); + return RsHttpClientError_Reqwest(var_field0); + case 2: + var var_field0 = sse_decode_String(deserializer); + return RsHttpClientError_Json(var_field0); + case 3: + var var_field0 = sse_decode_String(deserializer); + return RsHttpClientError_Io(var_field0); + case 4: + var var_field0 = sse_decode_String(deserializer); + return RsHttpClientError_Other(var_field0); + default: + throw UnimplementedError(''); + } + } + @protected RTCFileError sse_decode_rtc_file_error(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -3491,18 +3535,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(self.message, serializer); } - @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ClientError self, - SseSerializer serializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as ClientErrorImpl).frbInternalSseEncode(move: true), - serializer, - ); - } - @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( Dart2RustStreamReceiver self, @@ -3749,18 +3781,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ClientError self, - SseSerializer serializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as ClientErrorImpl).frbInternalSseEncode(move: null), - serializer, - ); - } - @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( Dart2RustStreamReceiver self, @@ -4029,6 +4049,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_prepare_upload_request_dto(self, serializer); } + @protected + void sse_encode_box_autoadd_prepare_upload_response_dto( + PrepareUploadResponseDto self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_prepare_upload_response_dto(self, serializer); + } + @protected void sse_encode_box_autoadd_proposing_client_info( ProposingClientInfo self, @@ -4290,6 +4319,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_opt_box_autoadd_prepare_upload_response_dto( + PrepareUploadResponseDto? 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_prepare_upload_response_dto(self, serializer); + } + } + @protected void sse_encode_pin_config(PinConfig self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4324,7 +4366,10 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_16(self.statusCode, serializer); - sse_encode_prepare_upload_response_dto(self.response, serializer); + sse_encode_opt_box_autoadd_prepare_upload_response_dto( + self.response, + serializer, + ); } @protected @@ -4419,6 +4464,35 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_register_response_dto(self.body, serializer); } + @protected + void sse_encode_rs_http_client_error( + RsHttpClientError self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + switch (self) { + case RsHttpClientError_StatusCode( + status: final status, + message: final message, + ): + sse_encode_i_32(0, serializer); + sse_encode_u_16(status, serializer); + sse_encode_opt_String(message, serializer); + case RsHttpClientError_Reqwest(field0: final field0): + sse_encode_i_32(1, serializer); + sse_encode_String(field0, serializer); + case RsHttpClientError_Json(field0: final field0): + sse_encode_i_32(2, serializer); + sse_encode_String(field0, serializer); + case RsHttpClientError_Io(field0: final field0): + sse_encode_i_32(3, serializer); + sse_encode_String(field0, serializer); + case RsHttpClientError_Other(field0: final field0): + sse_encode_i_32(4, serializer); + sse_encode_String(field0, serializer); + } + } + @protected void sse_encode_rtc_file_error(RTCFileError self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4534,21 +4608,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } -@sealed -class ClientErrorImpl extends RustOpaque implements ClientError { - // Not to be used by end users - ClientErrorImpl.frbInternalDcoDecode(List wire) : super.frbInternalDcoDecode(wire, _kStaticData); - - // Not to be used by end users - ClientErrorImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); - - static final _kStaticData = RustArcStaticData( - rustArcIncrementStrongCount: RustLib.instance.api.rust_arc_increment_strong_count_ClientError, - rustArcDecrementStrongCount: RustLib.instance.api.rust_arc_decrement_strong_count_ClientError, - rustArcDecrementStrongCountPtr: RustLib.instance.api.rust_arc_decrement_strong_count_ClientErrorPtr, - ); -} - @sealed class Dart2RustStreamReceiverImpl extends RustOpaque implements Dart2RustStreamReceiver { // Not to be used by end users diff --git a/app/lib/rust/frb_generated.io.dart b/app/lib/rust/frb_generated.io.dart index b50ecaec..9234505f 100644 --- a/app/lib/rust/frb_generated.io.dart +++ b/app/lib/rust/frb_generated.io.dart @@ -25,9 +25,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { required super.portManager, }); - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_ClientErrorPtr => - wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientErrorPtr; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_Dart2RustStreamReceiverPtr => wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiverPtr; @@ -55,11 +52,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected AnyhowException dco_decode_AnyhowException(dynamic raw); - @protected - ClientError dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - dynamic raw, - ); - @protected Dart2RustStreamReceiver dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( dynamic raw, @@ -155,11 +147,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected Map dco_decode_Map_String_file_dto_None(dynamic raw); - @protected - ClientError dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - dynamic raw, - ); - @protected Dart2RustStreamReceiver dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( dynamic raw, @@ -260,6 +247,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dynamic raw, ); + @protected + PrepareUploadResponseDto dco_decode_box_autoadd_prepare_upload_response_dto( + dynamic raw, + ); + @protected ProposingClientInfo dco_decode_box_autoadd_proposing_client_info(dynamic raw); @@ -342,6 +334,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected PinConfig? dco_decode_opt_box_autoadd_pin_config(dynamic raw); + @protected + PrepareUploadResponseDto? dco_decode_opt_box_autoadd_prepare_upload_response_dto(dynamic raw); + @protected PinConfig dco_decode_pin_config(dynamic raw); @@ -381,6 +376,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected ResultWithPublicKeyRegisterResponseDto dco_decode_result_with_public_key_register_response_dto(dynamic raw); + @protected + RsHttpClientError dco_decode_rs_http_client_error(dynamic raw); + @protected RTCFileError dco_decode_rtc_file_error(dynamic raw); @@ -414,11 +412,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); - @protected - ClientError sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - SseDeserializer deserializer, - ); - @protected Dart2RustStreamReceiver sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( SseDeserializer deserializer, @@ -512,11 +505,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); - @protected - ClientError sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - SseDeserializer deserializer, - ); - @protected Dart2RustStreamReceiver sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( SseDeserializer deserializer, @@ -623,6 +611,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + PrepareUploadResponseDto sse_decode_box_autoadd_prepare_upload_response_dto( + SseDeserializer deserializer, + ); + @protected ProposingClientInfo sse_decode_box_autoadd_proposing_client_info( SseDeserializer deserializer, @@ -725,6 +718,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + PrepareUploadResponseDto? sse_decode_opt_box_autoadd_prepare_upload_response_dto( + SseDeserializer deserializer, + ); + @protected PinConfig sse_decode_pin_config(SseDeserializer deserializer); @@ -780,6 +778,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + RsHttpClientError sse_decode_rs_http_client_error( + SseDeserializer deserializer, + ); + @protected RTCFileError sse_decode_rtc_file_error(SseDeserializer deserializer); @@ -820,12 +823,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); - @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ClientError self, - SseSerializer serializer, - ); - @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( Dart2RustStreamReceiver self, @@ -944,12 +941,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); - @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ClientError self, - SseSerializer serializer, - ); - @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( Dart2RustStreamReceiver self, @@ -1082,6 +1073,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_box_autoadd_prepare_upload_response_dto( + PrepareUploadResponseDto self, + SseSerializer serializer, + ); + @protected void sse_encode_box_autoadd_proposing_client_info( ProposingClientInfo self, @@ -1205,6 +1202,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_opt_box_autoadd_prepare_upload_response_dto( + PrepareUploadResponseDto? self, + SseSerializer serializer, + ); + @protected void sse_encode_pin_config(PinConfig self, SseSerializer serializer); @@ -1269,6 +1272,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_rs_http_client_error( + RsHttpClientError self, + SseSerializer serializer, + ); + @protected void sse_encode_rtc_file_error(RTCFileError self, SseSerializer serializer); @@ -1320,38 +1329,6 @@ class RustLibWire implements BaseWire { /// The symbols are looked up in [dynamicLibrary]. RustLibWire(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup; - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ffi.Pointer ptr, - ) { - return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ptr, - ); - } - - late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientErrorPtr = - _lookup)>>( - 'frbgen_localsend_app_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError', - ); - late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError = - _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientErrorPtr - .asFunction)>(); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ffi.Pointer ptr, - ) { - return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ptr, - ); - } - - late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientErrorPtr = - _lookup)>>( - 'frbgen_localsend_app_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError', - ); - late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError = - _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientErrorPtr - .asFunction)>(); - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( ffi.Pointer ptr, ) { diff --git a/app/lib/rust/frb_generated.web.dart b/app/lib/rust/frb_generated.web.dart index f4e38724..3b9a78ba 100644 --- a/app/lib/rust/frb_generated.web.dart +++ b/app/lib/rust/frb_generated.web.dart @@ -27,9 +27,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { required super.portManager, }); - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_ClientErrorPtr => - wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_Dart2RustStreamReceiverPtr => wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver; @@ -57,11 +54,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected AnyhowException dco_decode_AnyhowException(dynamic raw); - @protected - ClientError dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - dynamic raw, - ); - @protected Dart2RustStreamReceiver dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( dynamic raw, @@ -157,11 +149,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected Map dco_decode_Map_String_file_dto_None(dynamic raw); - @protected - ClientError dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - dynamic raw, - ); - @protected Dart2RustStreamReceiver dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( dynamic raw, @@ -262,6 +249,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dynamic raw, ); + @protected + PrepareUploadResponseDto dco_decode_box_autoadd_prepare_upload_response_dto( + dynamic raw, + ); + @protected ProposingClientInfo dco_decode_box_autoadd_proposing_client_info(dynamic raw); @@ -344,6 +336,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected PinConfig? dco_decode_opt_box_autoadd_pin_config(dynamic raw); + @protected + PrepareUploadResponseDto? dco_decode_opt_box_autoadd_prepare_upload_response_dto(dynamic raw); + @protected PinConfig dco_decode_pin_config(dynamic raw); @@ -383,6 +378,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected ResultWithPublicKeyRegisterResponseDto dco_decode_result_with_public_key_register_response_dto(dynamic raw); + @protected + RsHttpClientError dco_decode_rs_http_client_error(dynamic raw); + @protected RTCFileError dco_decode_rtc_file_error(dynamic raw); @@ -416,11 +414,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); - @protected - ClientError sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - SseDeserializer deserializer, - ); - @protected Dart2RustStreamReceiver sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( SseDeserializer deserializer, @@ -514,11 +507,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); - @protected - ClientError sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - SseDeserializer deserializer, - ); - @protected Dart2RustStreamReceiver sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( SseDeserializer deserializer, @@ -625,6 +613,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + PrepareUploadResponseDto sse_decode_box_autoadd_prepare_upload_response_dto( + SseDeserializer deserializer, + ); + @protected ProposingClientInfo sse_decode_box_autoadd_proposing_client_info( SseDeserializer deserializer, @@ -727,6 +720,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + PrepareUploadResponseDto? sse_decode_opt_box_autoadd_prepare_upload_response_dto( + SseDeserializer deserializer, + ); + @protected PinConfig sse_decode_pin_config(SseDeserializer deserializer); @@ -782,6 +780,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + RsHttpClientError sse_decode_rs_http_client_error( + SseDeserializer deserializer, + ); + @protected RTCFileError sse_decode_rtc_file_error(SseDeserializer deserializer); @@ -822,12 +825,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); - @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ClientError self, - SseSerializer serializer, - ); - @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( Dart2RustStreamReceiver self, @@ -946,12 +943,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); - @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ClientError self, - SseSerializer serializer, - ); - @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( Dart2RustStreamReceiver self, @@ -1084,6 +1075,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_box_autoadd_prepare_upload_response_dto( + PrepareUploadResponseDto self, + SseSerializer serializer, + ); + @protected void sse_encode_box_autoadd_proposing_client_info( ProposingClientInfo self, @@ -1207,6 +1204,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_opt_box_autoadd_prepare_upload_response_dto( + PrepareUploadResponseDto? self, + SseSerializer serializer, + ); + @protected void sse_encode_pin_config(PinConfig self, SseSerializer serializer); @@ -1271,6 +1274,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_rs_http_client_error( + RsHttpClientError self, + SseSerializer serializer, + ); + @protected void sse_encode_rtc_file_error(RTCFileError self, SseSerializer serializer); @@ -1316,18 +1325,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { class RustLibWire implements BaseWire { RustLibWire.fromExternalLibrary(ExternalLibrary lib); - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - int ptr, - ) => wasmModule.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ptr, - ); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - int ptr, - ) => wasmModule.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ptr, - ); - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( int ptr, ) => wasmModule.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( @@ -1431,14 +1428,6 @@ external RustLibWasmModule get wasmModule; @JS() @anonymous extension type RustLibWasmModule._(JSObject _) implements JSObject { - external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - int ptr, - ); - - external void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - int ptr, - ); - external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( int ptr, ); diff --git a/app/lib/util/rust.dart b/app/lib/util/rust.dart new file mode 100644 index 00000000..e51d32ad --- /dev/null +++ b/app/lib/util/rust.dart @@ -0,0 +1,54 @@ +import 'package:common/model/device.dart'; +import 'package:common/model/dto/file_dto.dart'; +import 'package:common/model/dto/multicast_dto.dart'; +import 'package:localsend_app/rust/api/model.dart' as rust_model; +import 'package:mime/mime.dart'; + +extension ProtocolTypeExt on ProtocolType { + rust_model.ProtocolType toRust() { + return switch (this) { + ProtocolType.http => rust_model.ProtocolType.http, + ProtocolType.https => rust_model.ProtocolType.https, + }; + } +} + +extension DeviceExt on Device { + rust_model.ProtocolType getProtocolType() { + return switch (https) { + false => rust_model.ProtocolType.http, + true => rust_model.ProtocolType.https, + }; + } +} + +extension DeviceTypeExt on DeviceType { + rust_model.DeviceType toRust() { + return switch (this) { + DeviceType.mobile => rust_model.DeviceType.mobile, + DeviceType.desktop => rust_model.DeviceType.desktop, + DeviceType.web => rust_model.DeviceType.web, + DeviceType.headless => rust_model.DeviceType.headless, + DeviceType.server => rust_model.DeviceType.server, + }; + } +} + +extension FileDtoExt on FileDto { + rust_model.FileDto toRust() { + return rust_model.FileDto( + id: id, + fileName: fileName, + size: BigInt.from(size), + fileType: lookupMimeType(fileName) ?? 'application/octet-stream', + sha256: hash, + preview: preview, + metadata: metadata != null + ? rust_model.FileMetadata( + modified: metadata!.lastModified?.toUtc().toIso8601String(), + accessed: metadata!.lastAccessed?.toUtc().toIso8601String(), + ) + : null, + ); + } +} diff --git a/app/rust/Cargo.lock b/app/rust/Cargo.lock index adce9572..4b2b1d02 100644 --- a/app/rust/Cargo.lock +++ b/app/rust/Cargo.lock @@ -2307,12 +2307,6 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - [[package]] name = "same-file" version = "1.0.6" @@ -2424,15 +2418,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -3954,3 +3948,9 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/app/rust/src/api/http.rs b/app/rust/src/api/http.rs index 40fccf52..3605f000 100644 --- a/app/rust/src/api/http.rs +++ b/app/rust/src/api/http.rs @@ -1,23 +1,23 @@ use crate::api::stream; use flutter_rust_bridge::frb; -use localsend::http::{ - client::{ClientError, LsHttpClientVersion}, - dto::{ - PrepareUploadRequestDto, PrepareUploadResponseDto, PrepareUploadResult, ProtocolType, - RegisterDto, RegisterResponseDto, - }, +pub use localsend::http::client::{ClientError, LsHttpClientVersion}; +pub use localsend::http::dto::{ + PrepareUploadRequestDto, PrepareUploadResponseDto, PrepareUploadResult, ProtocolType, + RegisterDto, RegisterResponseDto, }; pub struct RsHttpClient { inner: localsend::http::client::LsHttpClient, } +#[frb(sync)] pub fn create_client( private_key: String, cert: String, version: LsHttpClientVersion, -) -> Result { - let inner = localsend::http::client::LsHttpClient::new(&private_key, &cert, version)?; +) -> Result { + let inner = localsend::http::client::LsHttpClient::new(&private_key, &cert, version) + .map_err(RsHttpClientError::from)?; Ok(RsHttpClient { inner }) } @@ -29,8 +29,12 @@ impl RsHttpClient { ip: &str, port: u16, payload: RegisterDto, - ) -> Result { - let response = self.inner.register(protocol, ip, port, payload).await?; + ) -> Result { + let response = self + .inner + .register(protocol, ip, port, payload) + .await + .map_err(RsHttpClientError::from)?; Ok(ResultWithPublicKeyRegisterResponseDto { public_key: response.public_key, @@ -46,11 +50,12 @@ impl RsHttpClient { payload: PrepareUploadRequestDto, public_key: Option, pin: Option, - ) -> Result { + ) -> Result { let response = self .inner .prepare_upload(protocol, ip, port, public_key, payload, pin.as_deref()) - .await?; + .await + .map_err(RsHttpClientError::from)?; Ok(response) } @@ -65,7 +70,7 @@ impl RsHttpClient { file_id: &str, token: &str, binary: stream::Dart2RustStreamReceiver, - ) -> Result<(), ClientError> { + ) -> Result<(), RsHttpClientError> { self.inner .upload( protocol, @@ -77,7 +82,8 @@ impl RsHttpClient { token, binary.receiver, ) - .await?; + .await + .map_err(RsHttpClientError::from)?; Ok(()) } @@ -88,13 +94,42 @@ impl RsHttpClient { ip: &str, port: u16, session_id: &str, - ) -> Result<(), ClientError> { - self.inner.cancel(protocol, ip, port, session_id).await?; + ) -> Result<(), RsHttpClientError> { + self.inner + .cancel(protocol, ip, port, session_id) + .await + .map_err(RsHttpClientError::from)?; Ok(()) } } +pub enum RsHttpClientError { + StatusCode { + status: u16, + message: Option, + }, + Reqwest(String), + Json(String), + Io(String), + Other(String), +} + +impl From for RsHttpClientError { + fn from(e: ClientError) -> Self { + match e { + ClientError::StatusCode(e) => RsHttpClientError::StatusCode { + status: e.status, + message: e.message, + }, + ClientError::Reqwest(e) => RsHttpClientError::Reqwest(e.to_string()), + ClientError::Json(e) => RsHttpClientError::Json(e.to_string()), + ClientError::Io(e) => RsHttpClientError::Io(e.to_string()), + ClientError::Other(e) => RsHttpClientError::Other(e.to_string()), + } + } +} + #[frb(mirror(LsHttpClientVersion))] pub enum _LsHttpClientVersion { V2, @@ -104,7 +139,7 @@ pub enum _LsHttpClientVersion { #[frb(mirror(PrepareUploadResult))] pub struct _PrepareUploadResult { pub status_code: u16, - pub response: PrepareUploadResponseDto, + pub response: Option, } pub struct ResultWithPublicKeyRegisterResponseDto { diff --git a/app/rust/src/frb_generated.rs b/app/rust/src/frb_generated.rs index c2c57237..72c8814b 100644 --- a/app/rust/src/frb_generated.rs +++ b/app/rust/src/frb_generated.rs @@ -339,7 +339,7 @@ fn wire__crate__api__http__RsHttpClient_cancel_impl( let api_session_id = ::sse_decode(&mut deserializer); deserializer.end(); move |context| async move { - transform_result_sse::<_, ClientError>( + transform_result_sse::<_, crate::api::http::RsHttpClientError>( (move || async move { let mut api_that_guard = None; let decode_indices_ = @@ -408,7 +408,7 @@ fn wire__crate__api__http__RsHttpClient_prepare_upload_impl( let api_pin = >::sse_decode(&mut deserializer); deserializer.end(); move |context| async move { - transform_result_sse::<_, ClientError>( + transform_result_sse::<_, crate::api::http::RsHttpClientError>( (move || async move { let mut api_that_guard = None; let decode_indices_ = @@ -476,7 +476,7 @@ fn wire__crate__api__http__RsHttpClient_register_impl( let api_payload = ::sse_decode(&mut deserializer); deserializer.end(); move |context| async move { - transform_result_sse::<_, ClientError>( + transform_result_sse::<_, crate::api::http::RsHttpClientError>( (move || async move { let mut api_that_guard = None; let decode_indices_ = @@ -546,7 +546,7 @@ fn wire__crate__api__http__RsHttpClient_upload_impl( let api_binary = ::sse_decode(&mut deserializer); deserializer.end(); move |context| async move { - transform_result_sse::<_, ClientError>( + transform_result_sse::<_, crate::api::http::RsHttpClientError>( (move || async move { let mut api_that_guard = None; let decode_indices_ = @@ -1577,16 +1577,15 @@ let api_on_connection = decode_DartFn_Inputs_Auto_Owned_RustOpaque_flutter_rust_ } }) } fn wire__crate__api__http__create_client_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::WireSyncRust2DartSse { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( flutter_rust_bridge::for_generated::TaskInfo { debug_name: "create_client", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + port: None, + mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, }, move || { let message = unsafe { @@ -1603,13 +1602,11 @@ fn wire__crate__api__http__create_client_impl( let api_version = ::sse_decode(&mut deserializer); deserializer.end(); - move |context| { - transform_result_sse::<_, ClientError>((move || { - let output_ok = - crate::api::http::create_client(api_private_key, api_cert, api_version)?; - Ok(output_ok) - })()) - } + transform_result_sse::<_, crate::api::http::RsHttpClientError>((move || { + let output_ok = + crate::api::http::create_client(api_private_key, api_cert, api_version)?; + Ok(output_ok) + })()) }, ) } @@ -1805,7 +1802,7 @@ const _: fn() = || { { let PrepareUploadResult = None::.unwrap(); let _: u16 = PrepareUploadResult.status_code; - let _: crate::api::model::PrepareUploadResponseDto = PrepareUploadResult.response; + let _: Option = PrepareUploadResult.response; } { let RegisterDto = None::.unwrap(); @@ -1916,9 +1913,6 @@ fn decode_DartFn_Inputs_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRu )) } } -flutter_rust_bridge::frb_generated_moi_arc_impl_value!( - flutter_rust_bridge::for_generated::RustAutoOpaqueInner -); flutter_rust_bridge::frb_generated_moi_arc_impl_value!( flutter_rust_bridge::for_generated::RustAutoOpaqueInner ); @@ -1954,16 +1948,6 @@ impl SseDecode for flutter_rust_bridge::for_generated::anyhow::Error { } } -impl SseDecode for ClientError { - // 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 flutter_rust_bridge::for_generated::rust_auto_opaque_decode_owned(inner); - } -} - impl SseDecode for Dart2RustStreamReceiver { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -2068,16 +2052,6 @@ impl SseDecode for std::collections::HashMap } } -impl SseDecode - for RustOpaqueMoi> -{ - // 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 decode_rust_opaque_moi(inner); - } -} - impl SseDecode for RustOpaqueMoi< flutter_rust_bridge::for_generated::RustAutoOpaqueInner, @@ -2510,6 +2484,19 @@ 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 crate::api::webrtc::PinConfig { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -2554,7 +2541,7 @@ impl SseDecode for crate::api::http::PrepareUploadResult { fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { let mut var_statusCode = ::sse_decode(deserializer); let mut var_response = - ::sse_decode(deserializer); + >::sse_decode(deserializer); return crate::api::http::PrepareUploadResult { status_code: var_statusCode, response: var_response, @@ -2673,6 +2660,42 @@ impl SseDecode for crate::api::http::ResultWithPublicKeyRegisterResponseDto { } } +impl SseDecode for crate::api::http::RsHttpClientError { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut tag_ = ::sse_decode(deserializer); + match tag_ { + 0 => { + let mut var_status = ::sse_decode(deserializer); + let mut var_message = >::sse_decode(deserializer); + return crate::api::http::RsHttpClientError::StatusCode { + status: var_status, + message: var_message, + }; + } + 1 => { + let mut var_field0 = ::sse_decode(deserializer); + return crate::api::http::RsHttpClientError::Reqwest(var_field0); + } + 2 => { + let mut var_field0 = ::sse_decode(deserializer); + return crate::api::http::RsHttpClientError::Json(var_field0); + } + 3 => { + let mut var_field0 = ::sse_decode(deserializer); + return crate::api::http::RsHttpClientError::Io(var_field0); + } + 4 => { + let mut var_field0 = ::sse_decode(deserializer); + return crate::api::http::RsHttpClientError::Other(var_field0); + } + _ => { + unimplemented!(""); + } + } + } +} + impl SseDecode for crate::api::webrtc::RTCFileError { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -2965,7 +2988,6 @@ fn pde_ffi_dispatcher_primary_impl( data_len, ), 25 => wire__crate__api__webrtc__connect_impl(port, ptr, rust_vec_len, data_len), - 26 => wire__crate__api__http__create_client_impl(port, ptr, rust_vec_len, data_len), 27 => wire__crate__api__stream__create_stream_impl(port, ptr, rust_vec_len, data_len), 28 => { wire__crate__api__logging__enable_debug_logging_impl(port, ptr, rust_vec_len, data_len) @@ -2984,27 +3006,13 @@ fn pde_ffi_dispatcher_sync_impl( ) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { // Codec=Pde (Serialization + dispatch), see doc to use other codecs match func_id { + 26 => wire__crate__api__http__create_client_impl(ptr, rust_vec_len, data_len), _ => unreachable!(), } } // Section: rust2dart -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for FrbWrapper { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} - -impl flutter_rust_bridge::IntoIntoDart> for ClientError { - fn into_into_dart(self) -> FrbWrapper { - self.into() - } -} - // Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for FrbWrapper { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { @@ -3523,6 +3531,45 @@ impl flutter_rust_bridge::IntoIntoDart flutter_rust_bridge::for_generated::DartAbi { + match self { + crate::api::http::RsHttpClientError::StatusCode { status, message } => [ + 0.into_dart(), + status.into_into_dart().into_dart(), + message.into_into_dart().into_dart(), + ] + .into_dart(), + crate::api::http::RsHttpClientError::Reqwest(field0) => { + [1.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + crate::api::http::RsHttpClientError::Json(field0) => { + [2.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + crate::api::http::RsHttpClientError::Io(field0) => { + [3.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + crate::api::http::RsHttpClientError::Other(field0) => { + [4.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + _ => { + unimplemented!(""); + } + } + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::http::RsHttpClientError +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::http::RsHttpClientError +{ + fn into_into_dart(self) -> crate::api::http::RsHttpClientError { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for FrbWrapper { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ @@ -3671,13 +3718,6 @@ impl SseEncode for flutter_rust_bridge::for_generated::anyhow::Error { } } -impl SseEncode for ClientError { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - >>::sse_encode(flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self), serializer); - } -} - impl SseEncode for Dart2RustStreamReceiver { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -3773,17 +3813,6 @@ impl SseEncode for std::collections::HashMap } } -impl SseEncode - for RustOpaqueMoi> -{ - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - let (ptr, size) = self.sse_encode_raw(); - ::sse_encode(ptr, serializer); - ::sse_encode(size, serializer); - } -} - impl SseEncode for RustOpaqueMoi< flutter_rust_bridge::for_generated::RustAutoOpaqueInner, @@ -4170,6 +4199,16 @@ 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 crate::api::webrtc::PinConfig { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -4200,7 +4239,10 @@ impl SseEncode for crate::api::http::PrepareUploadResult { // 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.status_code, serializer); - ::sse_encode(self.response, serializer); + >::sse_encode( + self.response, + serializer, + ); } } @@ -4288,6 +4330,38 @@ impl SseEncode for crate::api::http::ResultWithPublicKeyRegisterResponseDto { } } +impl SseEncode for crate::api::http::RsHttpClientError { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + match self { + crate::api::http::RsHttpClientError::StatusCode { status, message } => { + ::sse_encode(0, serializer); + ::sse_encode(status, serializer); + >::sse_encode(message, serializer); + } + crate::api::http::RsHttpClientError::Reqwest(field0) => { + ::sse_encode(1, serializer); + ::sse_encode(field0, serializer); + } + crate::api::http::RsHttpClientError::Json(field0) => { + ::sse_encode(2, serializer); + ::sse_encode(field0, serializer); + } + crate::api::http::RsHttpClientError::Io(field0) => { + ::sse_encode(3, serializer); + ::sse_encode(field0, serializer); + } + crate::api::http::RsHttpClientError::Other(field0) => { + ::sse_encode(4, serializer); + ::sse_encode(field0, serializer); + } + _ => { + unimplemented!(""); + } + } + } +} + impl SseEncode for crate::api::webrtc::RTCFileError { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -4447,20 +4521,6 @@ mod io { flutter_rust_bridge::frb_generated_boilerplate_io!(); - #[unsafe(no_mangle)] - pub extern "C" fn frbgen_localsend_app_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ptr: *const std::ffi::c_void, - ) { - MoiArc::>::increment_strong_count(ptr as _); - } - - #[unsafe(no_mangle)] - pub extern "C" fn frbgen_localsend_app_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ptr: *const std::ffi::c_void, - ) { - MoiArc::>::decrement_strong_count(ptr as _); - } - #[unsafe(no_mangle)] pub extern "C" fn frbgen_localsend_app_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( ptr: *const std::ffi::c_void, @@ -4600,20 +4660,6 @@ mod web { flutter_rust_bridge::frb_generated_boilerplate_web!(); - #[wasm_bindgen] - pub fn rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ptr: *const std::ffi::c_void, - ) { - MoiArc::>::increment_strong_count(ptr as _); - } - - #[wasm_bindgen] - pub fn rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerClientError( - ptr: *const std::ffi::c_void, - ) { - MoiArc::>::decrement_strong_count(ptr as _); - } - #[wasm_bindgen] pub fn rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamReceiver( ptr: *const std::ffi::c_void, diff --git a/app/test/unit/model/dto/prepare_upload_request_dto_test.dart b/app/test/unit/model/dto/prepare_upload_request_dto_test.dart index a3cace7d..5f7ec717 100644 --- a/app/test/unit/model/dto/prepare_upload_request_dto_test.dart +++ b/app/test/unit/model/dto/prepare_upload_request_dto_test.dart @@ -150,39 +150,6 @@ void main() { download: false, ); - test('should serialize in legacy mode', () { - const dto = PrepareUploadRequestDto( - info: info, - files: { - 'some id': FileDto( - id: 'some id', - fileName: 'another image.jpg', - size: 1234, - fileType: FileType.image, - hash: '*hash*', - preview: '*preview data*', - legacy: true, - metadata: null, - ), - 'some id 2': FileDto( - id: 'some id 2', - fileName: 'my apk.apk', - size: 1234, - fileType: FileType.apk, - hash: '*hash*', - preview: '*preview data*', - legacy: true, - metadata: null, - ), - }, - ); - final serialized = dto.toJson(); - expect(serialized['info']['deviceType'], 'mobile'); - expect(serialized['files'].length, 2); - expect(serialized['files']['some id']['fileType'], 'image'); - expect(serialized['files']['some id 2']['fileType'], 'apk'); - }); - test('should serialize in mime mode', () { final dto = PrepareUploadRequestDto( info: info, @@ -194,7 +161,6 @@ void main() { fileType: FileType.image, hash: '*hash*', preview: '*preview data*', - legacy: false, metadata: null, ), 'some id 2': FileDto( @@ -204,7 +170,6 @@ void main() { fileType: FileType.apk, hash: '*hash*', preview: '*preview data*', - legacy: false, metadata: FileMetadata( lastModified: DateTime.utc(2020), lastAccessed: DateTime.utc(2021), diff --git a/common/lib/constants.dart b/common/lib/constants.dart index 7b7ebadc..1bc13e3b 100644 --- a/common/lib/constants.dart +++ b/common/lib/constants.dart @@ -5,7 +5,8 @@ /// ----------|------------------------------ /// 1.0 | 1.0.0 - 1.8.0 /// 1.0, 2.0 | 1.9.0 - 1.14.0 -/// 1.0, 2.1 | 1.15.0 +/// 1.0, 2.1 | 1.15.0 - 1.17.0 +/// 2.1 | 1.18.0 const protocolVersion = '2.1'; /// Assumed protocol version of peers for first handshake. diff --git a/common/lib/model/dto/file_dto.dart b/common/lib/model/dto/file_dto.dart index 68edbb28..5de955e8 100644 --- a/common/lib/model/dto/file_dto.dart +++ b/common/lib/model/dto/file_dto.dart @@ -29,10 +29,6 @@ class FileDto { final String? preview; final FileMetadata? metadata; - /// This is only used internally to determine if fileType is a mime type or a legacy enum. - /// It is not serialized. - final bool legacy; - const FileDto({ required this.id, required this.fileName, @@ -40,7 +36,6 @@ class FileDto { required this.fileType, required this.hash, required this.preview, - required this.legacy, required this.metadata, }); @@ -56,11 +51,10 @@ class FileDto { size == other.size && fileType == other.fileType && hash == other.hash && - preview == other.preview && - legacy == other.legacy; + preview == other.preview; @override - int get hashCode => Object.hash(id, fileName, size, fileType, hash, preview, legacy); + int get hashCode => Object.hash(id, fileName, size, fileType, hash, preview); } class FileDtoMapper extends SimpleMapper { @@ -86,7 +80,6 @@ class FileDtoMapper extends SimpleMapper { fileType: fileType, hash: map['hash'] as String?, preview: map['preview'] as String?, - legacy: false, metadata: switch (map['metadata']) { Map metadata => FileMetadataMapper.fromJson(metadata), _ => null, @@ -100,7 +93,7 @@ class FileDtoMapper extends SimpleMapper { 'id': self.id, 'fileName': self.fileName, 'size': self.size, - 'fileType': self.legacy ? self.fileType.name : self.lookupMime(), + 'fileType': self.lookupMime(), if (self.hash != null) 'hash': self.hash, if (self.preview != null) 'preview': self.preview, if (self.metadata != null) 'metadata': self.metadata!.toJson(), diff --git a/core/src/http/client/v2.rs b/core/src/http/client/v2.rs index 528211df..c687df9e 100644 --- a/core/src/http/client/v2.rs +++ b/core/src/http/client/v2.rs @@ -1,16 +1,15 @@ use super::{ClientError, ResponseExt, ResultWithPublicKey}; use crate::http::client::url::{ApiVersion, TargetUrl}; +use crate::http::dto::ProtocolType; use crate::http::dto_v2::{ InfoResponseDtoV2, PrepareDownloadResponseDtoV2, PrepareUploadRequestDtoV2, - PrepareUploadResponseDtoV2, PrepareUploadResultV2, RegisterDtoV2, - RegisterResponseDtoV2, + PrepareUploadResponseDtoV2, PrepareUploadResultV2, RegisterDtoV2, RegisterResponseDtoV2, }; use futures_util::StreamExt; use reqwest::{Response, StatusCode}; use tokio::io::AsyncWriteExt; use tokio::sync::mpsc; use tokio_stream::wrappers::ReceiverStream; -use crate::http::dto::ProtocolType; /// HTTP client for LocalSend Protocol v2.1. pub struct LsHttpClientV2 { @@ -164,11 +163,18 @@ impl LsHttpClientV2 { return res.into_error().await; } + if status == StatusCode::NO_CONTENT { + return Ok(PrepareUploadResultV2 { + status_code: status.as_u16(), + response: None, + }); + } + let body = res.json::().await?; Ok(PrepareUploadResultV2 { status_code: status.as_u16(), - response: body, + response: Some(body), }) } diff --git a/core/src/http/client/v3.rs b/core/src/http/client/v3.rs index d9531bfd..d79b3c59 100644 --- a/core/src/http/client/v3.rs +++ b/core/src/http/client/v3.rs @@ -164,11 +164,18 @@ impl LsHttpClientV3 { return res.into_error().await; } - let response = res.json::().await?; + if status == StatusCode::NO_CONTENT { + return Ok(http::dto::PrepareUploadResult { + status_code: status.as_u16(), + response: None, + }); + } + + let body = res.json::().await?; Ok(http::dto::PrepareUploadResult { status_code: status.as_u16(), - response, + response: Some(body), }) } diff --git a/core/src/http/dto.rs b/core/src/http/dto.rs index 7937b440..70144080 100644 --- a/core/src/http/dto.rs +++ b/core/src/http/dto.rs @@ -133,7 +133,7 @@ impl From for PrepareUploadRequestDtoV2 { pub struct PrepareUploadResult { pub status_code: u16, - pub response: PrepareUploadResponseDto, + pub response: Option, } impl From for PrepareUploadResponseDto { @@ -149,7 +149,7 @@ impl From for PrepareUploadResult { fn from(v2: crate::http::dto_v2::PrepareUploadResultV2) -> Self { PrepareUploadResult { status_code: v2.status_code, - response: v2.response.into(), + response: v2.response.map(|r| r.into()), } } } diff --git a/core/src/http/dto_v2.rs b/core/src/http/dto_v2.rs index 835a5e98..faba4fe6 100644 --- a/core/src/http/dto_v2.rs +++ b/core/src/http/dto_v2.rs @@ -156,7 +156,7 @@ pub struct PrepareUploadResponseDtoV2 { pub struct PrepareUploadResultV2 { pub status_code: u16, - pub response: PrepareUploadResponseDtoV2, + pub response: Option, } /// Prepare download response DTO for v2.1 protocol (Download API). diff --git a/core/src/http/mod.rs b/core/src/http/mod.rs index 854a62fc..2af0c5a8 100644 --- a/core/src/http/mod.rs +++ b/core/src/http/mod.rs @@ -9,6 +9,6 @@ pub mod state; #[derive(Debug, Error)] #[error("{status};{message:?}")] pub struct StatusCodeError { - status: u16, - message: Option, + pub status: u16, + pub message: Option, } diff --git a/core/src/lib.rs b/core/src/lib.rs index 8a3ad592..540128b8 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -5,3 +5,7 @@ pub mod http; pub mod model; pub(crate) mod util; pub mod webrtc; + +#[cfg(feature = "http")] +pub use reqwest; +pub use serde_json;