- adding modify codes from the rhttp package
This commit is contained in:
kodjomoustapha 2024-09-11 12:04:01 +01:00
parent 8ed6b21125
commit aa2b408144
41 changed files with 10618 additions and 134 deletions

View file

@ -1,3 +1,4 @@
rust_root: rust/
rust_input: crate::api
dart_output: lib/src/rust
dart_output: lib/src/rust
enable_lifetime: true

View file

@ -20,7 +20,6 @@ import 'package:mangayomi/modules/more/settings/appearance/providers/theme_mode_
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:mangayomi/src/rust/frb_generated.dart';
import 'package:media_kit/media_kit.dart';
import 'package:rhttp/rhttp.dart';
import 'package:window_manager/window_manager.dart';
late Isar isar;
@ -34,7 +33,6 @@ void main(List<String> args) async {
}
MediaKit.ensureInitialized();
await RustLib.init();
await Rhttp.init();
if (!(Platform.isAndroid || Platform.isIOS)) {
await windowManager.ensureInitialized();
}

View file

@ -51,6 +51,7 @@ Future<List<PageUrl>> downloadChapter(
bool hasM3U8File = false;
bool nonM3U8File = false;
M3u8Downloader? m3u8Downloader;
String? tsKey;
void savePageUrls() {
final settings = isar.settings.getSync(227)!;
List<ChapterPageurls>? chapterPageUrls = [];
@ -96,13 +97,9 @@ Future<List<PageUrl>> downloadChapter(
final nonM3u8Urls = value.$1
.where((element) => element.originalUrl.isMediaVideo())
.toList();
nonM3U8File = nonM3u8Urls.isNotEmpty && !Platform.isIOS;
nonM3U8File = nonM3u8Urls.isNotEmpty;
hasM3U8File = nonM3U8File ? false : m3u8Urls.isNotEmpty;
final videosUrls = nonM3U8File
? nonM3u8Urls
: (hasM3U8File || Platform.isIOS)
? m3u8Urls
: nonM3u8Urls;
final videosUrls = nonM3U8File ? nonM3u8Urls : m3u8Urls;
if (videosUrls.isNotEmpty) {
List<TsInfo> tsList = [];
if (hasM3U8File) {
@ -110,7 +107,7 @@ Future<List<PageUrl>> downloadChapter(
m3u8Url: videosUrls.first.url,
downloadDir: "${path!.path}$chapterName",
headers: videosUrls.first.headers ?? {});
tsList = await m3u8Downloader!.getTsList();
(tsList, tsKey) = await m3u8Downloader!.getTsList();
}
pageUrls = hasM3U8File
? [...tsList.map((e) => PageUrl(e.url))]
@ -302,6 +299,7 @@ Future<List<PageUrl>> downloadChapter(
isar.downloads.putSync(download..chapter.value = chapter);
});
} else {
savePageUrls();
await FileDownloader().downloadBatch(
tasks,
batchProgressCallback: (succeeded, failed) async {
@ -309,7 +307,6 @@ Future<List<PageUrl>> downloadChapter(
if (succeeded == tasks.length) {
if (hasM3U8File) {
} else {
savePageUrls();
if (ref.watch(saveAsCBZArchiveStateProvider)) {
await ref.watch(convertToCBZProvider(
path!.path,

View file

@ -6,7 +6,7 @@ part of 'download_provider.dart';
// RiverpodGenerator
// **************************************************************************
String _$downloadChapterHash() => r'ceb6f5d311f5da585b0272a0af598532ab511adc';
String _$downloadChapterHash() => r'c5e5cf07f28a558d6dc827a1e08933125ef52261';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -9,9 +9,10 @@ import 'package:collection/collection.dart';
import 'package:flutter/services.dart';
import 'package:logging/logging.dart';
import 'package:mangayomi/services/http/m_client.dart';
import 'package:mangayomi/src/rust/frb_generated.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
import 'package:rhttp/rhttp.dart';
import 'package:mangayomi/services/http/rhttp/rhttp.dart';
import '../base_downloader.dart';
import '../chunk.dart';
import '../exceptions.dart';
@ -571,9 +572,7 @@ final class DownloaderHttpClient extends BaseDownloader {
/// Recreates the [httpClient] used for Requests and isolate downloads/uploads
static _recreateClient() async {
if (!Platform.isIOS) {
await Rhttp.init();
}
await RustLib.init();
httpClient = MClient.httpClient(
settings: const ClientSettings(
throwOnStatusCode: false,

View file

@ -1,4 +1,3 @@
import 'package:cupertino_http/cupertino_http.dart';
import 'package:http_interceptor/http_interceptor.dart';
import 'package:mangayomi/eval/dart/model/m_bridge.dart';
import 'dart:async';
@ -10,18 +9,13 @@ import 'package:flutter_inappwebview/flutter_inappwebview.dart'
import 'package:mangayomi/models/settings.dart';
import 'package:http/io_client.dart';
import 'package:mangayomi/utils/log/log.dart';
import 'package:rhttp/rhttp.dart' as rhttp;
import 'package:mangayomi/services/http/rhttp/rhttp.dart' as rhttp;
class MClient {
MClient();
static Client httpClient(
{Map<String, dynamic>? reqcopyWith, rhttp.ClientSettings? settings}) {
if (!(reqcopyWith?["useDartHttpClient"] ?? false)) {
if (Platform.isIOS) {
final config = URLSessionConfiguration.ephemeralSessionConfiguration()
..cache = URLCache.withCapacity(memoryCapacity: 5 * 1024 * 1024);
return CupertinoClient.fromSessionConfiguration(config);
}
try {
settings ??= rhttp.ClientSettings(
throwOnStatusCode: false,
@ -44,9 +38,11 @@ class MClient {
}
static InterceptedClient init(
{MSource? source, Map<String, dynamic>? reqcopyWith}) {
{MSource? source,
Map<String, dynamic>? reqcopyWith,
rhttp.ClientSettings? settings}) {
return InterceptedClient.build(
client: httpClient(reqcopyWith: reqcopyWith),
client: httpClient(settings: settings),
interceptors: [MCookieManager(reqcopyWith), LoggerInterceptor()]);
}

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Tien Do Nam
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,29 @@
library rhttp;
export 'src/client/compatible_client.dart'
show RhttpCompatibleClient, RhttpWrappedClientException;
export 'src/client/rhttp_client.dart' show RhttpClient;
export 'src/model/cancel_token.dart' show CancelToken;
export 'src/model/exception.dart'
show
RhttpException,
RhttpCancelException,
RhttpTimeoutException,
RhttpRedirectException,
RhttpStatusCodeException,
RhttpInvalidCertificateException,
RhttpConnectionException,
RhttpClientDisposedException,
RhttpInterceptorException,
RhttpUnknownException;
export 'src/model/header.dart';
export 'src/model/request.dart' show BaseHttpRequest, HttpRequest;
export 'src/model/settings.dart'
show
ClientSettings,
ProxySettings,
RedirectSettings,
TlsSettings,
ClientCertificate;
export 'src/model/response.dart'
show HttpResponse, HttpBytesResponse, HttpStreamResponse, HttpVersion;

View file

@ -0,0 +1,118 @@
import 'package:http/http.dart';
import 'package:mangayomi/services/http/rhttp/src/client/rhttp_client.dart';
import 'package:mangayomi/services/http/rhttp/src/model/exception.dart';
import 'package:mangayomi/services/http/rhttp/src/model/settings.dart';
import 'package:mangayomi/src/rust/api/rhttp/http.dart' as rust;
/// An HTTP client that is compatible with the `http` package.
/// This minimizes the changes needed to switch from `http` to `rhttp`
/// and also avoids vendor lock-in.
///
/// This comes with some downsides, such as:
/// - inferior type safety due to the flaw that `body` is of type `Object?`
/// instead of a sane supertype.
/// - body of type [Map] is implicitly interpreted as `x-www-form-urlencoded`
/// that is only documented in StackOverflow (as of writing this).
/// - no support for cancellation
/// - no out-of-the-box support for multipart requests
class RhttpCompatibleClient with BaseClient {
/// The actual client that is used to make requests.
final RhttpClient client;
RhttpCompatibleClient._(this.client);
/// Use this method if your app is starting up to simplify the code
/// that might arise by using async/await.
///
/// Note:
/// This method crashes when configured to use HTTP/3.
/// See: https://github.com/Tienisto/rhttp/issues/10
factory RhttpCompatibleClient.createSync({
ClientSettings? settings,
}) {
final client = RhttpClient.createSync(
settings: (settings ?? const ClientSettings()).digest(),
);
return RhttpCompatibleClient._(client);
}
@override
Future<StreamedResponse> send(BaseRequest request) async {
try {
final response = await client.requestStream(
method: switch (request.method) {
'GET' => rust.HttpMethod.get_,
'POST' => rust.HttpMethod.post,
'PUT' => rust.HttpMethod.put,
'PATCH' => rust.HttpMethod.patch,
'DELETE' => rust.HttpMethod.delete,
'HEAD' => rust.HttpMethod.head,
'OPTIONS' => rust.HttpMethod.options,
'TRACE' => rust.HttpMethod.trace,
'CONNECT' => rust.HttpMethod.connect,
_ => throw ArgumentError('Unsupported method: ${request.method}'),
},
url: request.url.toString(),
headers: rust.HttpHeaders.map(request.headers),
body: await request.finalize().toBytes(),
);
final responseHeaderMap = response.headerMap;
return StreamedResponse(
response.body,
response.statusCode,
contentLength: switch (responseHeaderMap['content-length']) {
String s => int.parse(s),
null => null,
},
request: request,
headers: responseHeaderMap,
isRedirect: false,
persistentConnection: true,
reasonPhrase: null,
);
} on RhttpException catch (e, st) {
Error.throwWithStackTrace(
RhttpWrappedClientException(e.toString(), request.url, e),
st,
);
} catch (e, st) {
Error.throwWithStackTrace(
ClientException(e.toString(), request.url),
st,
);
}
}
@override
void close() {
client.dispose(cancelRunningRequests: true);
}
}
/// Every exception must be a subclass of [ClientException]
/// as per contract of [BaseClient].
class RhttpWrappedClientException extends ClientException {
/// The original exception that was thrown by rhttp.
final RhttpException rhttpException;
RhttpWrappedClientException(super.message, super.uri, this.rhttpException);
@override
String toString() => rhttpException.toString();
}
extension on ClientSettings {
/// Makes sure that the settings conform to the requirements of [BaseClient].
ClientSettings digest() {
ClientSettings settings = this;
if (throwOnStatusCode) {
settings = settings.copyWith(
throwOnStatusCode: false,
);
}
return settings;
}
}

View file

@ -0,0 +1,102 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:mangayomi/services/http/rhttp/src/model/cancel_token.dart';
import 'package:mangayomi/services/http/rhttp/src/model/request.dart';
import 'package:mangayomi/services/http/rhttp/src/model/response.dart';
import 'package:mangayomi/services/http/rhttp/src/model/settings.dart';
import 'package:mangayomi/services/http/rhttp/src/request.dart';
import 'package:mangayomi/src/rust/api/rhttp/client.dart' as rust_client;
import 'package:mangayomi/src/rust/api/rhttp/http.dart' as rust;
/// An HTTP client that is used to make requests.
/// Creating this is an expensive operation, so it is recommended to reuse it.
/// Internally, it holds a connection pool and other resources on the Rust side.
class RhttpClient {
/// Settings for the client.
final ClientSettings settings;
/// Internal reference to the Rust client.
final rust_client.RequestClient ref;
const RhttpClient._({
required this.settings,
required this.ref,
});
/// Creates a new HTTP client synchronously.
/// Use this method if your app is starting up to simplify the code
/// that might arise by using async/await.
///
/// Note:
/// This method crashes when configured to use HTTP/3.
/// See: https://github.com/Tienisto/rhttp/issues/10
factory RhttpClient.createSync({
ClientSettings? settings,
}) {
settings ??= const ClientSettings();
final ref = rust.registerClientSync(
settings: settings.toRustType(),
);
return RhttpClient._(
settings: settings,
ref: ref,
);
}
/// Disposes the client.
/// This frees the resources associated with the client.
/// After calling this method, the client should not be used anymore.
///
/// Note:
/// This might improve performance but it is not necessary because the client
/// is automatically disposed when the Dart object is garbage collected.
void dispose({bool cancelRunningRequests = false}) async {
if (ref.isDisposed) {
return;
}
if (cancelRunningRequests) {
await rust.cancelRunningRequests(client: ref);
}
ref.dispose();
}
/// Makes an HTTP request.
/// Use [send] if you already have a [BaseHttpRequest] object.
Future<HttpResponse> request(
{required rust.HttpMethod method,
required String url,
Map<String, String>? query,
required rust.HttpHeaders headers,
Uint8List? body,
CancelToken? cancelToken}) =>
requestInternalGeneric(HttpRequest(
client: this,
settings: settings,
method: method,
url: url,
query: query,
headers: headers,
body: body,
cancelToken: cancelToken));
/// Makes an HTTP request and returns the response as a stream.
Future<HttpStreamResponse> requestStream(
{required rust.HttpMethod method,
required String url,
Map<String, String>? query,
required rust.HttpHeaders headers,
Uint8List? body,
CancelToken? cancelToken}) async {
final response = await request(
method: method,
url: url,
query: query,
headers: headers,
body: body,
cancelToken: cancelToken);
return response as HttpStreamResponse;
}
}

View file

@ -0,0 +1,48 @@
import 'dart:async';
import 'package:mangayomi/src/rust/api/rhttp/http.dart' as rust;
import 'package:mangayomi/src/rust/lib.dart' as rust_lib;
/// A token that can be used to cancel an HTTP request.
/// This token must be passed to the request method.
class CancelToken {
final _ref = Completer<rust_lib.CancellationToken>();
bool _isCancelled = false;
/// Whether the request has been cancelled.
bool get isCancelled => _isCancelled;
CancelToken? _delegated;
CancelToken();
void setRef(rust_lib.CancellationToken ref) {
_ref.complete(ref);
}
/// Cancels the HTTP request.
/// If the [CancelToken] is not passed to the request method,
/// this method never finishes.
Future<void> cancel() async {
if (_delegated != null) {
await _delegated!.cancel();
} else {
// We need to wait for the ref to be set.
final ref = await _ref.future;
await rust.cancelRequest(token: ref);
_isCancelled = true;
}
}
/// When a request is retried, a new [CancelToken] is created.
/// To ensure that [cancel] is still working on the old token,
/// a new token is created that gets cancelled
/// when the old token is cancelled.
CancelToken createDelegatedToken() {
final delegated = CancelToken();
_delegated = delegated;
return delegated;
}
}

View file

@ -0,0 +1,151 @@
import 'dart:typed_data';
import 'package:mangayomi/services/http/rhttp/src/model/request.dart';
import 'package:mangayomi/src/rust/api/rhttp/error.dart' as rust;
import 'package:mangayomi/src/rust/api/rhttp/http.dart' as rust_http;
/// The base class for all exceptions thrown by the `rhttp` library
/// or by interceptors.
///
/// This class is not sealed to allow for custom exceptions.
class RhttpException {
/// The associated request when the exception was thrown.
final HttpRequest request;
const RhttpException(this.request);
}
/// An exception thrown when a request is canceled.
class RhttpCancelException extends RhttpException {
const RhttpCancelException(super.request);
@override
String toString() =>
'[$runtimeType] Request was canceled. URL: ${request.url}';
}
/// An exception thrown when a request times out.
class RhttpTimeoutException extends RhttpException {
const RhttpTimeoutException(super.request);
@override
String toString() => '[$runtimeType] Request timed out. URL: ${request.url}';
}
/// An exception thrown when there are issues related to redirects.
class RhttpRedirectException extends RhttpException {
const RhttpRedirectException(super.request);
@override
String toString() => '[$runtimeType] Redirect error. URL: ${request.url}';
}
/// An exception thrown on a 4xx or 5xx status code.
class RhttpStatusCodeException extends RhttpException {
/// The status code of the response.
final int statusCode;
/// Response headers.
final List<(String, String)> headers;
Map<String, String> get headerMap => {
for (final entry in headers) entry.$1: entry.$2,
};
/// The response body. For simplicity, we don't differentiate between
/// text or bytes. Streams are always null.
/// Can be [String], [Uint8List], or null.
final Object? body;
const RhttpStatusCodeException({
required HttpRequest request,
required this.statusCode,
required this.headers,
required this.body,
}) : super(request);
@override
String toString() =>
'[$runtimeType] Status code: $statusCode. URL: ${request.url}';
}
/// An exception thrown when the server's certificate is invalid.
class RhttpInvalidCertificateException extends RhttpException {
/// The more detailed error message.
final String message;
const RhttpInvalidCertificateException({
required HttpRequest request,
required this.message,
}) : super(request);
@override
String toString() =>
'[$runtimeType] Invalid certificate. $message URL: ${request.url}';
}
/// An exception thrown when a connection error occurs.
/// For example, when the server is unreachable or internet is not available.
class RhttpConnectionException extends RhttpException {
final String message;
const RhttpConnectionException(super.request, this.message);
@override
String toString() =>
'[$runtimeType] Connection error. URL: ${request.url} ($message)';
}
/// An exception thrown a request is made with an invalid client.
class RhttpClientDisposedException extends RhttpException {
const RhttpClientDisposedException(super.request);
@override
String toString() =>
'[$runtimeType] Client is already disposed. URL: ${request.url}';
}
/// An exception thrown by an interceptor.
/// Interceptors should only throw exceptions of type [RhttpException].
class RhttpInterceptorException extends RhttpException {
final Object error;
RhttpInterceptorException(super.request, this.error);
@override
String toString() => '[$runtimeType] $error. URL: ${request.url}';
}
/// An exception thrown when an unknown error occurs.
class RhttpUnknownException extends RhttpException {
/// The error message
final String message;
const RhttpUnknownException(super.request, this.message);
@override
String toString() => '[$runtimeType] $message';
}
RhttpException parseError(HttpRequest request, rust.RhttpError error) {
return error.when(
rhttpCancelError: () => RhttpCancelException(request),
rhttpTimeoutError: () => RhttpTimeoutException(request),
rhttpRedirectError: () => RhttpRedirectException(request),
rhttpStatusCodeError: (code, headers, body) => RhttpStatusCodeException(
request: request,
statusCode: code,
headers: headers,
body: switch (body) {
rust_http.HttpResponseBody_Text() => body.field0,
rust_http.HttpResponseBody_Bytes() => body.field0,
rust_http.HttpResponseBody_Stream() => null,
},
),
rhttpInvalidCertificateError: (message) =>
RhttpInvalidCertificateException(request: request, message: message),
rhttpConnectionError: (message) =>
RhttpConnectionException(request, message),
rhttpUnknownError: (message) => RhttpUnknownException(request, message),
);
}

View file

@ -0,0 +1,88 @@
/// Type safe representation of HTTP headers.
enum HttpHeaderName {
accept('accept'),
acceptCharset('accept-charset'),
acceptEncoding('accept-encoding'),
acceptLanguage('accept-language'),
acceptRanges('accept-ranges'),
accessControlAllowCredentials('access-control-allow-credentials'),
accessControlAllowHeaders('access-control-allow-headers'),
accessControlAllowMethods('access-control-allow-methods'),
accessControlAllowOrigin('access-control-allow-origin'),
accessControlExposeHeaders('access-control-expose-headers'),
accessControlMaxAge('access-control-max-age'),
accessControlRequestHeaders('access-control-request-headers'),
accessControlRequestMethod('access-control-request-method'),
age('age'),
allow('allow'),
altSvc('alt-svc'),
authorization('authorization'),
cacheControl('cache-control'),
cacheStatus('cache-status'),
cdnCacheControl('cdn-cache-control'),
connection('connection'),
contentDisposition('content-disposition'),
contentEncoding('content-encoding'),
contentLanguage('content-language'),
contentLength('content-length'),
contentLocation('content-location'),
contentRange('content-range'),
contentSecurityPolicy('content-security-policy'),
contentSecurityPolicyReportOnly('content-security-policy-report-only'),
contentType('content-type'),
cookie('cookie'),
dnt('dnt'),
date('date'),
etag('etag'),
expect('expect'),
expires('expires'),
forwarded('forwarded'),
from('from'),
host('host'),
ifMatch('if-match'),
ifModifiedSince('if-modified-since'),
ifNoneMatch('if-none-match'),
ifRange('if-range'),
ifUnmodifiedSince('if-unmodified-since'),
lastModified('last-modified'),
link('link'),
location('location'),
maxForwards('max-forwards'),
origin('origin'),
pragma('pragma'),
proxyAuthenticate('proxy-authenticate'),
proxyAuthorization('proxy-authorization'),
publicKeyPins('public-key-pins'),
publicKeyPinsReportOnly('public-key-pins-report-only'),
range('range'),
referer('referer'),
referrerPolicy('referrer-policy'),
refresh('refresh'),
retryAfter('retry-after'),
secWebSocketAccept('sec-websocket-accept'),
secWebSocketExtensions('sec-websocket-extensions'),
secWebSocketKey('sec-websocket-key'),
secWebSocketProtocol('sec-websocket-protocol'),
secWebSocketVersion('sec-websocket-version'),
server('server'),
setCookie('set-cookie'),
strictTransportSecurity('strict-transport-security'),
te('te'),
trailer('trailer'),
transferEncoding('transfer-encoding'),
userAgent('user-agent'),
upgrade('upgrade'),
upgradeInsecureRequests('upgrade-insecure-requests'),
vary('vary'),
via('via'),
warning('warning'),
wwwAuthenticate('www-authenticate'),
xContentTypeOptions('x-content-type-options'),
xDnsPrefetchControl('x-dns-prefetch-control'),
xFrameOptions('x-frame-options'),
xXssProtection('x-xss-protection');
final String httpName;
const HttpHeaderName(this.httpName);
}

View file

@ -0,0 +1,62 @@
import 'dart:typed_data';
import 'package:mangayomi/services/http/rhttp/src/client/rhttp_client.dart';
import 'package:mangayomi/services/http/rhttp/src/model/cancel_token.dart';
import 'package:mangayomi/services/http/rhttp/src/model/settings.dart';
import 'package:mangayomi/src/rust/api/rhttp/http.dart' as rust;
/// An HTTP request that can be used
/// on a client or statically.
class BaseHttpRequest {
/// The HTTP method to use.
final rust.HttpMethod method;
/// The URL to request.
final String url;
/// Query parameters.
/// This can be null, if there are no query parameters
/// or if they are already part of the URL.
final Map<String, String>? query;
/// Headers to send with the request.
final rust.HttpHeaders? headers;
/// The body of the request.
final Uint8List? body;
/// The cancel token to use for the request.
final CancelToken? cancelToken;
/// Map that can be used to store additional information.
/// Primarily used by interceptors.
/// This is not const to allow for modifications.
final Map<String, dynamic> additionalData = {};
BaseHttpRequest(
{required this.method,
required this.url,
required this.query,
required this.headers,
required this.body,
required this.cancelToken});
}
/// An HTTP request with the information which client to use.
class HttpRequest extends BaseHttpRequest {
/// The client to use for the request.
final RhttpClient? client;
/// The settings to use for the request.
/// This is **only** used if [client] is `null`.
final ClientSettings? settings;
HttpRequest(
{required this.client,
required this.settings,
required super.method,
required super.url,
required super.query,
required super.headers,
required super.body,
required super.cancelToken});
}

View file

@ -0,0 +1,90 @@
import 'dart:typed_data';
import 'package:mangayomi/services/http/rhttp/src/model/request.dart';
import 'package:mangayomi/src/rust/api/rhttp/http.dart' as rust;
sealed class HttpResponse {
final HttpRequest request;
final HttpVersion version;
final int statusCode;
final List<(String, String)> headers;
Map<String, String> get headerMap => {
for (final entry in headers) entry.$1: entry.$2,
};
const HttpResponse({
required this.request,
required this.version,
required this.statusCode,
required this.headers,
});
}
class HttpBytesResponse extends HttpResponse {
final Uint8List body;
const HttpBytesResponse({
required super.request,
required super.version,
required super.statusCode,
required super.headers,
required this.body,
});
@override
String toString() {
return 'HttpBytesResponse(${version.name}, status: $statusCode)';
}
}
class HttpStreamResponse extends HttpResponse {
final Stream<Uint8List> body;
const HttpStreamResponse({
required super.request,
required super.version,
required super.statusCode,
required super.headers,
required this.body,
});
@override
String toString() {
return 'HttpStreamResponse(${version.name}, status: $statusCode)';
}
}
enum HttpVersion {
http09,
http1_0,
http1_1,
other,
;
}
HttpResponse parseHttpResponse(
HttpRequest request,
rust.HttpResponse response, {
Stream<Uint8List>? bodyStream,
}) {
assert((response.body is rust.HttpResponseBody_Stream &&
bodyStream != null) ||
(response.body is! rust.HttpResponseBody_Stream && bodyStream == null));
return HttpStreamResponse(
request: request,
version: parseHttpVersion(response.version),
statusCode: response.statusCode,
headers: response.headers,
body: bodyStream!,
);
}
HttpVersion parseHttpVersion(rust.HttpVersion version) {
return switch (version) {
rust.HttpVersion.http09 => HttpVersion.http09,
rust.HttpVersion.http10 => HttpVersion.http1_0,
rust.HttpVersion.http11 => HttpVersion.http1_1,
rust.HttpVersion.other => HttpVersion.other,
};
}

View file

@ -0,0 +1,214 @@
import 'dart:typed_data';
import 'package:mangayomi/src/rust/api/rhttp/client.dart' as rust_client;
export 'package:mangayomi/src/rust/api/rhttp/client.dart' show TlsVersion;
const _keepBaseUrl = '__rhttp_keep__';
const _keepDuration = Duration(microseconds: -9999);
const _keepProxySettings = ProxySettings.noProxy();
const _keepRedirectSettings = RedirectSettings.limited(-9999);
const _keepTlsSettings = TlsSettings();
class ClientSettings {
/// Base URL to be prefixed to all requests.
final String? baseUrl;
/// The timeout for the request including time to establish a connection.
final Duration? timeout;
/// The timeout for establishing a connection.
/// See [timeout] for the total timeout.
final Duration? connectTimeout;
/// Throws an exception if the status code is 4xx or 5xx.
final bool throwOnStatusCode;
/// Proxy settings.
final ProxySettings? proxySettings;
/// Redirect settings.
/// By default, the client will follow maximum 10 redirects.
/// See: https://docs.rs/reqwest/latest/reqwest/redirect/struct.Policy.html
final RedirectSettings? redirectSettings;
/// TLS settings.
final TlsSettings? tlsSettings;
const ClientSettings({
this.baseUrl,
this.timeout,
this.connectTimeout,
this.throwOnStatusCode = true,
this.proxySettings,
this.redirectSettings,
this.tlsSettings,
});
ClientSettings copyWith({
String? baseUrl = _keepBaseUrl,
Duration? timeout = _keepDuration,
Duration? connectTimeout = _keepDuration,
bool? throwOnStatusCode,
ProxySettings? proxySettings = _keepProxySettings,
RedirectSettings? redirectSettings = _keepRedirectSettings,
TlsSettings? tlsSettings = _keepTlsSettings,
}) {
return ClientSettings(
baseUrl: identical(baseUrl, _keepBaseUrl) ? this.baseUrl : baseUrl,
timeout: identical(timeout, _keepDuration) ? this.timeout : timeout,
connectTimeout: identical(connectTimeout, _keepDuration)
? this.connectTimeout
: connectTimeout,
throwOnStatusCode: throwOnStatusCode ?? this.throwOnStatusCode,
proxySettings: identical(proxySettings, _keepProxySettings)
? this.proxySettings
: proxySettings,
redirectSettings: identical(redirectSettings, _keepRedirectSettings)
? this.redirectSettings
: redirectSettings,
tlsSettings: identical(tlsSettings, _keepTlsSettings)
? this.tlsSettings
: tlsSettings,
);
}
}
sealed class ProxySettings {
const ProxySettings();
/// Disables any proxy settings including system settings.
const factory ProxySettings.noProxy() = NoProxy._;
}
class NoProxy extends ProxySettings {
const NoProxy._();
}
sealed class RedirectSettings {
const RedirectSettings();
/// Disables any redirects and exceptions related to redirects.
const factory RedirectSettings.none() = NoRedirectSetting._;
/// Limits the number of redirects.
const factory RedirectSettings.limited(int maxRedirects) = LimitedRedirects._;
}
/// Disables any redirects.
class NoRedirectSetting extends RedirectSettings {
const NoRedirectSetting._();
}
/// Limits the number of redirects.
class LimitedRedirects extends RedirectSettings {
final int maxRedirects;
const LimitedRedirects._(this.maxRedirects);
}
/// TLS settings for the client.
/// Used to configure HTTPS connections.
class TlsSettings {
/// Trust the root certificates that are pre-installed on the system.
final bool trustRootCertificates;
/// The trusted root certificates in PEM format.
/// Either specify the root certificate or the full
/// certificate chain.
/// The Rust API currently doesn't support trusting a single leaf certificate.
/// Hint: PEM format starts with `-----BEGIN CERTIFICATE-----`.
final List<String> trustedRootCertificates;
/// Verify the server's certificate.
/// If set to `false`, the client will accept any certificate.
/// This is insecure and should only be used for testing.
final bool verifyCertificates;
/// The client certificate to use.
/// This is used for client authentication / mutual TLS.
final ClientCertificate? clientCertificate;
/// The minimum TLS version to use.
final rust_client.TlsVersion? minTlsVersion;
/// The maximum TLS version to use.
final rust_client.TlsVersion? maxTlsVersion;
const TlsSettings({
this.trustRootCertificates = true,
this.trustedRootCertificates = const [],
this.verifyCertificates = true,
this.clientCertificate,
this.minTlsVersion,
this.maxTlsVersion,
});
}
/// A client certificate for client authentication / mutual TLS.
class ClientCertificate {
/// The certificate in PEM format.
final String certificate;
/// The private key in PEM format.
final String privateKey;
const ClientCertificate({
required this.certificate,
required this.privateKey,
});
}
extension ClientSettingsExt on ClientSettings {
rust_client.ClientSettings toRustType() {
return rust_client.ClientSettings(
timeout: timeout,
connectTimeout: connectTimeout,
throwOnStatusCode: throwOnStatusCode,
proxySettings: proxySettings?._toRustType(),
redirectSettings: redirectSettings?._toRustType(),
tlsSettings: tlsSettings?._toRustType(),
);
}
}
extension on ProxySettings {
rust_client.ProxySettings _toRustType() {
return switch (this) {
NoProxy() => rust_client.ProxySettings.noProxy,
};
}
}
extension on RedirectSettings {
rust_client.RedirectSettings _toRustType() {
return switch (this) {
NoRedirectSetting() => const rust_client.RedirectSettings.noRedirect(),
LimitedRedirects r =>
rust_client.RedirectSettings.limitedRedirects(r.maxRedirects),
};
}
}
extension on TlsSettings {
rust_client.TlsSettings _toRustType() {
return rust_client.TlsSettings(
trustRootCertificates: trustRootCertificates,
trustedRootCertificates: trustedRootCertificates
.map((e) => Uint8List.fromList(e.codeUnits))
.toList(),
verifyCertificates: verifyCertificates,
clientCertificate: clientCertificate?._toRustType(),
minTlsVersion: minTlsVersion,
maxTlsVersion: maxTlsVersion,
);
}
}
extension on ClientCertificate {
rust_client.ClientCertificate _toRustType() {
return rust_client.ClientCertificate(
certificate: Uint8List.fromList(certificate.codeUnits),
privateKey: Uint8List.fromList(privateKey.codeUnits),
);
}
}

View file

@ -0,0 +1,64 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:mangayomi/services/http/rhttp/src/model/exception.dart';
import 'package:mangayomi/services/http/rhttp/src/model/request.dart';
import 'package:mangayomi/services/http/rhttp/src/model/response.dart';
import 'package:mangayomi/services/http/rhttp/src/model/settings.dart';
import 'package:mangayomi/src/rust/api/rhttp/error.dart' as rust_error;
import 'package:mangayomi/src/rust/api/rhttp/http.dart' as rust;
import 'package:mangayomi/src/rust/lib.dart' as rust_lib;
/// Non-Generated helper function that is used by
/// the client and also by the static class.
Future<HttpResponse> requestInternalGeneric(HttpRequest request) async {
if (request.client?.ref.isDisposed ?? false) {
throw RhttpClientDisposedException(request);
}
final url = switch (request.settings?.baseUrl) {
String baseUrl => baseUrl + request.url,
null => request.url,
};
try {
final cancelRefCompleter = Completer<rust_lib.CancellationToken>();
final responseCompleter = Completer<rust.HttpResponse>();
Stream<Uint8List> stream = rust.makeHttpRequestReceiveStream(
client: request.client?.ref,
settings: request.settings?.toRustType(),
method: request.method,
url: url,
query: request.query?.entries.map((e) => (e.key, e.value)).toList(),
headers: request.headers,
body: request.body,
onResponse: (r) => responseCompleter.complete(r),
onError: (e) => responseCompleter.completeError(e),
onCancelToken: (cancelRef) => cancelRefCompleter.complete(cancelRef),
cancelable: request.cancelToken != null,
);
final cancelToken = request.cancelToken;
if (cancelToken != null) {
final cancelRef = await cancelRefCompleter.future;
cancelToken.setRef(cancelRef);
}
final rustResponse = await responseCompleter.future;
HttpResponse response = parseHttpResponse(
request,
rustResponse,
bodyStream: stream,
);
return response;
} catch (e, st) {
if (e is rust_error.RhttpError) {
RhttpException exception = parseError(request, e);
Error.throwWithStackTrace(exception, st);
} else {
rethrow;
}
}
}

View file

@ -19,18 +19,28 @@ class M3u8Downloader {
required this.downloadDir,
required this.headers});
Future<List<TsInfo>> getTsList() async {
Future<(List<TsInfo>, String?)> getTsList() async {
String? key;
final uri = Uri.parse(m3u8Url);
final m3u8Host = "${uri.scheme}://${uri.host}${path.dirname(uri.path)}";
final m3u8Body = await _getM3u8Body(m3u8Url, headers);
final m3u8Body = await _getM3u8Body(m3u8Url);
final tsList = _parseTsList(m3u8Host, m3u8Body);
if (kDebugMode) {
print("Total TS files to download: ${tsList.length}");
}
return tsList;
String? tsKey = await getM3u8Key(m3u8Body);
if (tsKey?.isNotEmpty ?? false) {
if (kDebugMode) {
print("TS Key: $tsKey");
}
key = tsKey;
}
return (tsList, key);
}
Future<String> _getM3u8Body(String url, Map<String, String>? headers) async {
Future<String> _getM3u8Body(
String url,
) async {
final response =
await MClient.httpClient().get(Uri.parse(url), headers: headers);
if (response.statusCode == 200) {
@ -61,4 +71,31 @@ class M3u8Downloader {
File("$downloadDir/index.m3u8").writeAsStringSync(allText);
return tsList;
}
Future<String?> getM3u8Key(String m3u8Body) async {
final uri = Uri.parse(m3u8Url);
final m3u8Host = "${uri.scheme}://${uri.host}${path.dirname(uri.path)}";
final lines = m3u8Body.split("\n");
for (final line in lines) {
if (line.contains("#EXT-X-KEY")) {
final keyUrl = _extractKeyUrl(m3u8Host, line);
final response =
await MClient.httpClient().get(Uri.parse(keyUrl), headers: headers);
if (response.statusCode == 200) {
return response.body;
}
}
}
return null;
}
String _extractKeyUrl(String host, String line) {
final uriPos = line.indexOf("URI");
final quotationMarkPos = line.lastIndexOf("\"");
var keyUrl = line.substring(uriPos, quotationMarkPos).split("\"")[1];
if (!line.contains("http")) {
keyUrl = "$host/$keyUrl";
}
return keyUrl;
}
}

View file

@ -0,0 +1,138 @@
// This file is automatically generated, so please do not edit it.
// Generated by `flutter_rust_bridge`@ 2.3.0.
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
import '../../frb_generated.dart';
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
part 'client.freezed.dart';
// These functions are ignored because they are not marked as `pub`: `create_client`, `new_default`, `new`
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`
// Rust type: RustOpaqueMoi<flutter_rust_bridge::for_generated::RustAutoOpaqueInner<RequestClient>>
abstract class RequestClient implements RustOpaqueInterface {}
class ClientCertificate {
final Uint8List certificate;
final Uint8List privateKey;
const ClientCertificate({
required this.certificate,
required this.privateKey,
});
@override
int get hashCode => certificate.hashCode ^ privateKey.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ClientCertificate &&
runtimeType == other.runtimeType &&
certificate == other.certificate &&
privateKey == other.privateKey;
}
class ClientSettings {
final Duration? timeout;
final Duration? connectTimeout;
final bool throwOnStatusCode;
final ProxySettings? proxySettings;
final RedirectSettings? redirectSettings;
final TlsSettings? tlsSettings;
const ClientSettings({
this.timeout,
this.connectTimeout,
required this.throwOnStatusCode,
this.proxySettings,
this.redirectSettings,
this.tlsSettings,
});
static Future<ClientSettings> default_() =>
RustLib.instance.api.crateApiRhttpClientClientSettingsDefault();
@override
int get hashCode =>
timeout.hashCode ^
connectTimeout.hashCode ^
throwOnStatusCode.hashCode ^
proxySettings.hashCode ^
redirectSettings.hashCode ^
tlsSettings.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ClientSettings &&
runtimeType == other.runtimeType &&
timeout == other.timeout &&
connectTimeout == other.connectTimeout &&
throwOnStatusCode == other.throwOnStatusCode &&
proxySettings == other.proxySettings &&
redirectSettings == other.redirectSettings &&
tlsSettings == other.tlsSettings;
}
enum ProxySettings {
noProxy,
;
}
@freezed
sealed class RedirectSettings with _$RedirectSettings {
const RedirectSettings._();
const factory RedirectSettings.noRedirect() = RedirectSettings_NoRedirect;
const factory RedirectSettings.limitedRedirects(
int field0,
) = RedirectSettings_LimitedRedirects;
}
class TlsSettings {
final bool trustRootCertificates;
final List<Uint8List> trustedRootCertificates;
final bool verifyCertificates;
final ClientCertificate? clientCertificate;
final TlsVersion? minTlsVersion;
final TlsVersion? maxTlsVersion;
const TlsSettings({
required this.trustRootCertificates,
required this.trustedRootCertificates,
required this.verifyCertificates,
this.clientCertificate,
this.minTlsVersion,
this.maxTlsVersion,
});
@override
int get hashCode =>
trustRootCertificates.hashCode ^
trustedRootCertificates.hashCode ^
verifyCertificates.hashCode ^
clientCertificate.hashCode ^
minTlsVersion.hashCode ^
maxTlsVersion.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is TlsSettings &&
runtimeType == other.runtimeType &&
trustRootCertificates == other.trustRootCertificates &&
trustedRootCertificates == other.trustedRootCertificates &&
verifyCertificates == other.verifyCertificates &&
clientCertificate == other.clientCertificate &&
minTlsVersion == other.minTlsVersion &&
maxTlsVersion == other.maxTlsVersion;
}
enum TlsVersion {
tls12,
tls13,
;
}

View file

@ -0,0 +1,344 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// 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 'client.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$RedirectSettings {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() noRedirect,
required TResult Function(int field0) limitedRedirects,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? noRedirect,
TResult? Function(int field0)? limitedRedirects,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? noRedirect,
TResult Function(int field0)? limitedRedirects,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(RedirectSettings_NoRedirect value) noRedirect,
required TResult Function(RedirectSettings_LimitedRedirects value)
limitedRedirects,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(RedirectSettings_NoRedirect value)? noRedirect,
TResult? Function(RedirectSettings_LimitedRedirects value)?
limitedRedirects,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(RedirectSettings_NoRedirect value)? noRedirect,
TResult Function(RedirectSettings_LimitedRedirects value)? limitedRedirects,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $RedirectSettingsCopyWith<$Res> {
factory $RedirectSettingsCopyWith(
RedirectSettings value, $Res Function(RedirectSettings) then) =
_$RedirectSettingsCopyWithImpl<$Res, RedirectSettings>;
}
/// @nodoc
class _$RedirectSettingsCopyWithImpl<$Res, $Val extends RedirectSettings>
implements $RedirectSettingsCopyWith<$Res> {
_$RedirectSettingsCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of RedirectSettings
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
abstract class _$$RedirectSettings_NoRedirectImplCopyWith<$Res> {
factory _$$RedirectSettings_NoRedirectImplCopyWith(
_$RedirectSettings_NoRedirectImpl value,
$Res Function(_$RedirectSettings_NoRedirectImpl) then) =
__$$RedirectSettings_NoRedirectImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$RedirectSettings_NoRedirectImplCopyWithImpl<$Res>
extends _$RedirectSettingsCopyWithImpl<$Res,
_$RedirectSettings_NoRedirectImpl>
implements _$$RedirectSettings_NoRedirectImplCopyWith<$Res> {
__$$RedirectSettings_NoRedirectImplCopyWithImpl(
_$RedirectSettings_NoRedirectImpl _value,
$Res Function(_$RedirectSettings_NoRedirectImpl) _then)
: super(_value, _then);
/// Create a copy of RedirectSettings
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
class _$RedirectSettings_NoRedirectImpl extends RedirectSettings_NoRedirect {
const _$RedirectSettings_NoRedirectImpl() : super._();
@override
String toString() {
return 'RedirectSettings.noRedirect()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$RedirectSettings_NoRedirectImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() noRedirect,
required TResult Function(int field0) limitedRedirects,
}) {
return noRedirect();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? noRedirect,
TResult? Function(int field0)? limitedRedirects,
}) {
return noRedirect?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? noRedirect,
TResult Function(int field0)? limitedRedirects,
required TResult orElse(),
}) {
if (noRedirect != null) {
return noRedirect();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(RedirectSettings_NoRedirect value) noRedirect,
required TResult Function(RedirectSettings_LimitedRedirects value)
limitedRedirects,
}) {
return noRedirect(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(RedirectSettings_NoRedirect value)? noRedirect,
TResult? Function(RedirectSettings_LimitedRedirects value)?
limitedRedirects,
}) {
return noRedirect?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(RedirectSettings_NoRedirect value)? noRedirect,
TResult Function(RedirectSettings_LimitedRedirects value)? limitedRedirects,
required TResult orElse(),
}) {
if (noRedirect != null) {
return noRedirect(this);
}
return orElse();
}
}
abstract class RedirectSettings_NoRedirect extends RedirectSettings {
const factory RedirectSettings_NoRedirect() =
_$RedirectSettings_NoRedirectImpl;
const RedirectSettings_NoRedirect._() : super._();
}
/// @nodoc
abstract class _$$RedirectSettings_LimitedRedirectsImplCopyWith<$Res> {
factory _$$RedirectSettings_LimitedRedirectsImplCopyWith(
_$RedirectSettings_LimitedRedirectsImpl value,
$Res Function(_$RedirectSettings_LimitedRedirectsImpl) then) =
__$$RedirectSettings_LimitedRedirectsImplCopyWithImpl<$Res>;
@useResult
$Res call({int field0});
}
/// @nodoc
class __$$RedirectSettings_LimitedRedirectsImplCopyWithImpl<$Res>
extends _$RedirectSettingsCopyWithImpl<$Res,
_$RedirectSettings_LimitedRedirectsImpl>
implements _$$RedirectSettings_LimitedRedirectsImplCopyWith<$Res> {
__$$RedirectSettings_LimitedRedirectsImplCopyWithImpl(
_$RedirectSettings_LimitedRedirectsImpl _value,
$Res Function(_$RedirectSettings_LimitedRedirectsImpl) _then)
: super(_value, _then);
/// Create a copy of RedirectSettings
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? field0 = null,
}) {
return _then(_$RedirectSettings_LimitedRedirectsImpl(
null == field0
? _value.field0
: field0 // ignore: cast_nullable_to_non_nullable
as int,
));
}
}
/// @nodoc
class _$RedirectSettings_LimitedRedirectsImpl
extends RedirectSettings_LimitedRedirects {
const _$RedirectSettings_LimitedRedirectsImpl(this.field0) : super._();
@override
final int field0;
@override
String toString() {
return 'RedirectSettings.limitedRedirects(field0: $field0)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$RedirectSettings_LimitedRedirectsImpl &&
(identical(other.field0, field0) || other.field0 == field0));
}
@override
int get hashCode => Object.hash(runtimeType, field0);
/// Create a copy of RedirectSettings
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$RedirectSettings_LimitedRedirectsImplCopyWith<
_$RedirectSettings_LimitedRedirectsImpl>
get copyWith => __$$RedirectSettings_LimitedRedirectsImplCopyWithImpl<
_$RedirectSettings_LimitedRedirectsImpl>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() noRedirect,
required TResult Function(int field0) limitedRedirects,
}) {
return limitedRedirects(field0);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? noRedirect,
TResult? Function(int field0)? limitedRedirects,
}) {
return limitedRedirects?.call(field0);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? noRedirect,
TResult Function(int field0)? limitedRedirects,
required TResult orElse(),
}) {
if (limitedRedirects != null) {
return limitedRedirects(field0);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(RedirectSettings_NoRedirect value) noRedirect,
required TResult Function(RedirectSettings_LimitedRedirects value)
limitedRedirects,
}) {
return limitedRedirects(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(RedirectSettings_NoRedirect value)? noRedirect,
TResult? Function(RedirectSettings_LimitedRedirects value)?
limitedRedirects,
}) {
return limitedRedirects?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(RedirectSettings_NoRedirect value)? noRedirect,
TResult Function(RedirectSettings_LimitedRedirects value)? limitedRedirects,
required TResult orElse(),
}) {
if (limitedRedirects != null) {
return limitedRedirects(this);
}
return orElse();
}
}
abstract class RedirectSettings_LimitedRedirects extends RedirectSettings {
const factory RedirectSettings_LimitedRedirects(final int field0) =
_$RedirectSettings_LimitedRedirectsImpl;
const RedirectSettings_LimitedRedirects._() : super._();
int get field0;
/// Create a copy of RedirectSettings
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$RedirectSettings_LimitedRedirectsImplCopyWith<
_$RedirectSettings_LimitedRedirectsImpl>
get copyWith => throw _privateConstructorUsedError;
}

View file

@ -0,0 +1,35 @@
// This file is automatically generated, so please do not edit it.
// Generated by `flutter_rust_bridge`@ 2.3.0.
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
import '../../frb_generated.dart';
import 'http.dart';
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
part 'error.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): `clone`, `fmt`, `fmt`
@freezed
sealed class RhttpError with _$RhttpError {
const RhttpError._();
const factory RhttpError.rhttpCancelError() = RhttpError_RhttpCancelError;
const factory RhttpError.rhttpTimeoutError() = RhttpError_RhttpTimeoutError;
const factory RhttpError.rhttpRedirectError() = RhttpError_RhttpRedirectError;
const factory RhttpError.rhttpStatusCodeError(
int field0,
List<(String, String)> field1,
HttpResponseBody field2,
) = RhttpError_RhttpStatusCodeError;
const factory RhttpError.rhttpInvalidCertificateError(
String field0,
) = RhttpError_RhttpInvalidCertificateError;
const factory RhttpError.rhttpConnectionError(
String field0,
) = RhttpError_RhttpConnectionError;
const factory RhttpError.rhttpUnknownError(
String field0,
) = RhttpError_RhttpUnknownError;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,128 @@
// This file is automatically generated, so please do not edit it.
// Generated by `flutter_rust_bridge`@ 2.3.0.
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
import '../../frb_generated.dart';
import '../../lib.dart';
import 'client.dart';
import 'error.dart';
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
part 'http.freezed.dart';
// These functions are ignored because they are not marked as `pub`: `build_cancel_tokens`, `from_version`, `header_to_vec`, `make_http_request_helper`, `make_http_request_receive_stream_inner`, `register_client_internal`, `to_method`
// These types are ignored because they are not used by any `pub` functions: `HttpExpectBody`, `RequestCancelTokens`
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `fmt`
Future<RequestClient> registerClient({required ClientSettings settings}) =>
RustLib.instance.api.crateApiRhttpHttpRegisterClient(settings: settings);
RequestClient registerClientSync({required ClientSettings settings}) =>
RustLib.instance.api
.crateApiRhttpHttpRegisterClientSync(settings: settings);
Future<void> cancelRunningRequests({required RequestClient client}) =>
RustLib.instance.api.crateApiRhttpHttpCancelRunningRequests(client: client);
Stream<Uint8List> makeHttpRequestReceiveStream(
{RequestClient? client,
ClientSettings? settings,
required HttpMethod method,
required String url,
List<(String, String)>? query,
HttpHeaders? headers,
Uint8List? body,
required FutureOr<void> Function(HttpResponse) onResponse,
required FutureOr<void> Function(RhttpError) onError,
required FutureOr<void> Function(CancellationToken) onCancelToken,
required bool cancelable}) =>
RustLib.instance.api.crateApiRhttpHttpMakeHttpRequestReceiveStream(
client: client,
settings: settings,
method: method,
url: url,
query: query,
headers: headers,
body: body,
onResponse: onResponse,
onError: onError,
onCancelToken: onCancelToken,
cancelable: cancelable);
Future<void> cancelRequest({required CancellationToken token}) =>
RustLib.instance.api.crateApiRhttpHttpCancelRequest(token: token);
@freezed
sealed class HttpHeaders with _$HttpHeaders {
const HttpHeaders._();
const factory HttpHeaders.map(
Map<String, String> field0,
) = HttpHeaders_Map;
const factory HttpHeaders.list(
List<(String, String)> field0,
) = HttpHeaders_List;
}
enum HttpMethod {
options,
get_,
post,
put,
delete,
head,
trace,
connect,
patch,
;
}
class HttpResponse {
final List<(String, String)> headers;
final HttpVersion version;
final int statusCode;
final HttpResponseBody body;
const HttpResponse({
required this.headers,
required this.version,
required this.statusCode,
required this.body,
});
@override
int get hashCode =>
headers.hashCode ^ version.hashCode ^ statusCode.hashCode ^ body.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is HttpResponse &&
runtimeType == other.runtimeType &&
headers == other.headers &&
version == other.version &&
statusCode == other.statusCode &&
body == other.body;
}
@freezed
sealed class HttpResponseBody with _$HttpResponseBody {
const HttpResponseBody._();
const factory HttpResponseBody.text(
String field0,
) = HttpResponseBody_Text;
const factory HttpResponseBody.bytes(
Uint8List field0,
) = HttpResponseBody_Bytes;
const factory HttpResponseBody.stream() = HttpResponseBody_Stream;
}
enum HttpVersion {
http09,
http10,
http11,
other,
;
}

View file

@ -0,0 +1,869 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// 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
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$HttpHeaders {
Object get field0 => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(Map<String, String> field0) map,
required TResult Function(List<(String, String)> field0) list,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(Map<String, String> field0)? map,
TResult? Function(List<(String, String)> field0)? list,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(Map<String, String> field0)? map,
TResult Function(List<(String, String)> field0)? list,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(HttpHeaders_Map value) map,
required TResult Function(HttpHeaders_List value) list,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(HttpHeaders_Map value)? map,
TResult? Function(HttpHeaders_List value)? list,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(HttpHeaders_Map value)? map,
TResult Function(HttpHeaders_List value)? list,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $HttpHeadersCopyWith<$Res> {
factory $HttpHeadersCopyWith(
HttpHeaders value, $Res Function(HttpHeaders) then) =
_$HttpHeadersCopyWithImpl<$Res, HttpHeaders>;
}
/// @nodoc
class _$HttpHeadersCopyWithImpl<$Res, $Val extends HttpHeaders>
implements $HttpHeadersCopyWith<$Res> {
_$HttpHeadersCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of HttpHeaders
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
abstract class _$$HttpHeaders_MapImplCopyWith<$Res> {
factory _$$HttpHeaders_MapImplCopyWith(_$HttpHeaders_MapImpl value,
$Res Function(_$HttpHeaders_MapImpl) then) =
__$$HttpHeaders_MapImplCopyWithImpl<$Res>;
@useResult
$Res call({Map<String, String> field0});
}
/// @nodoc
class __$$HttpHeaders_MapImplCopyWithImpl<$Res>
extends _$HttpHeadersCopyWithImpl<$Res, _$HttpHeaders_MapImpl>
implements _$$HttpHeaders_MapImplCopyWith<$Res> {
__$$HttpHeaders_MapImplCopyWithImpl(
_$HttpHeaders_MapImpl _value, $Res Function(_$HttpHeaders_MapImpl) _then)
: super(_value, _then);
/// Create a copy of HttpHeaders
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? field0 = null,
}) {
return _then(_$HttpHeaders_MapImpl(
null == field0
? _value._field0
: field0 // ignore: cast_nullable_to_non_nullable
as Map<String, String>,
));
}
}
/// @nodoc
class _$HttpHeaders_MapImpl extends HttpHeaders_Map {
const _$HttpHeaders_MapImpl(final Map<String, String> field0)
: _field0 = field0,
super._();
final Map<String, String> _field0;
@override
Map<String, String> get field0 {
if (_field0 is EqualUnmodifiableMapView) return _field0;
// ignore: implicit_dynamic_type
return EqualUnmodifiableMapView(_field0);
}
@override
String toString() {
return 'HttpHeaders.map(field0: $field0)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$HttpHeaders_MapImpl &&
const DeepCollectionEquality().equals(other._field0, _field0));
}
@override
int get hashCode =>
Object.hash(runtimeType, const DeepCollectionEquality().hash(_field0));
/// Create a copy of HttpHeaders
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$HttpHeaders_MapImplCopyWith<_$HttpHeaders_MapImpl> get copyWith =>
__$$HttpHeaders_MapImplCopyWithImpl<_$HttpHeaders_MapImpl>(
this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(Map<String, String> field0) map,
required TResult Function(List<(String, String)> field0) list,
}) {
return map(field0);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(Map<String, String> field0)? map,
TResult? Function(List<(String, String)> field0)? list,
}) {
return map?.call(field0);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(Map<String, String> field0)? map,
TResult Function(List<(String, String)> field0)? list,
required TResult orElse(),
}) {
if (map != null) {
return map(field0);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(HttpHeaders_Map value) map,
required TResult Function(HttpHeaders_List value) list,
}) {
return map(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(HttpHeaders_Map value)? map,
TResult? Function(HttpHeaders_List value)? list,
}) {
return map?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(HttpHeaders_Map value)? map,
TResult Function(HttpHeaders_List value)? list,
required TResult orElse(),
}) {
if (map != null) {
return map(this);
}
return orElse();
}
}
abstract class HttpHeaders_Map extends HttpHeaders {
const factory HttpHeaders_Map(final Map<String, String> field0) =
_$HttpHeaders_MapImpl;
const HttpHeaders_Map._() : super._();
@override
Map<String, String> get field0;
/// Create a copy of HttpHeaders
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$HttpHeaders_MapImplCopyWith<_$HttpHeaders_MapImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class _$$HttpHeaders_ListImplCopyWith<$Res> {
factory _$$HttpHeaders_ListImplCopyWith(_$HttpHeaders_ListImpl value,
$Res Function(_$HttpHeaders_ListImpl) then) =
__$$HttpHeaders_ListImplCopyWithImpl<$Res>;
@useResult
$Res call({List<(String, String)> field0});
}
/// @nodoc
class __$$HttpHeaders_ListImplCopyWithImpl<$Res>
extends _$HttpHeadersCopyWithImpl<$Res, _$HttpHeaders_ListImpl>
implements _$$HttpHeaders_ListImplCopyWith<$Res> {
__$$HttpHeaders_ListImplCopyWithImpl(_$HttpHeaders_ListImpl _value,
$Res Function(_$HttpHeaders_ListImpl) _then)
: super(_value, _then);
/// Create a copy of HttpHeaders
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? field0 = null,
}) {
return _then(_$HttpHeaders_ListImpl(
null == field0
? _value._field0
: field0 // ignore: cast_nullable_to_non_nullable
as List<(String, String)>,
));
}
}
/// @nodoc
class _$HttpHeaders_ListImpl extends HttpHeaders_List {
const _$HttpHeaders_ListImpl(final List<(String, String)> field0)
: _field0 = field0,
super._();
final List<(String, String)> _field0;
@override
List<(String, String)> get field0 {
if (_field0 is EqualUnmodifiableListView) return _field0;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_field0);
}
@override
String toString() {
return 'HttpHeaders.list(field0: $field0)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$HttpHeaders_ListImpl &&
const DeepCollectionEquality().equals(other._field0, _field0));
}
@override
int get hashCode =>
Object.hash(runtimeType, const DeepCollectionEquality().hash(_field0));
/// Create a copy of HttpHeaders
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$HttpHeaders_ListImplCopyWith<_$HttpHeaders_ListImpl> get copyWith =>
__$$HttpHeaders_ListImplCopyWithImpl<_$HttpHeaders_ListImpl>(
this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(Map<String, String> field0) map,
required TResult Function(List<(String, String)> field0) list,
}) {
return list(field0);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(Map<String, String> field0)? map,
TResult? Function(List<(String, String)> field0)? list,
}) {
return list?.call(field0);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(Map<String, String> field0)? map,
TResult Function(List<(String, String)> field0)? list,
required TResult orElse(),
}) {
if (list != null) {
return list(field0);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(HttpHeaders_Map value) map,
required TResult Function(HttpHeaders_List value) list,
}) {
return list(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(HttpHeaders_Map value)? map,
TResult? Function(HttpHeaders_List value)? list,
}) {
return list?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(HttpHeaders_Map value)? map,
TResult Function(HttpHeaders_List value)? list,
required TResult orElse(),
}) {
if (list != null) {
return list(this);
}
return orElse();
}
}
abstract class HttpHeaders_List extends HttpHeaders {
const factory HttpHeaders_List(final List<(String, String)> field0) =
_$HttpHeaders_ListImpl;
const HttpHeaders_List._() : super._();
@override
List<(String, String)> get field0;
/// Create a copy of HttpHeaders
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$HttpHeaders_ListImplCopyWith<_$HttpHeaders_ListImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
mixin _$HttpResponseBody {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(String field0) text,
required TResult Function(Uint8List field0) bytes,
required TResult Function() stream,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(String field0)? text,
TResult? Function(Uint8List field0)? bytes,
TResult? Function()? stream,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(String field0)? text,
TResult Function(Uint8List field0)? bytes,
TResult Function()? stream,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(HttpResponseBody_Text value) text,
required TResult Function(HttpResponseBody_Bytes value) bytes,
required TResult Function(HttpResponseBody_Stream value) stream,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(HttpResponseBody_Text value)? text,
TResult? Function(HttpResponseBody_Bytes value)? bytes,
TResult? Function(HttpResponseBody_Stream value)? stream,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(HttpResponseBody_Text value)? text,
TResult Function(HttpResponseBody_Bytes value)? bytes,
TResult Function(HttpResponseBody_Stream value)? stream,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $HttpResponseBodyCopyWith<$Res> {
factory $HttpResponseBodyCopyWith(
HttpResponseBody value, $Res Function(HttpResponseBody) then) =
_$HttpResponseBodyCopyWithImpl<$Res, HttpResponseBody>;
}
/// @nodoc
class _$HttpResponseBodyCopyWithImpl<$Res, $Val extends HttpResponseBody>
implements $HttpResponseBodyCopyWith<$Res> {
_$HttpResponseBodyCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of HttpResponseBody
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
abstract class _$$HttpResponseBody_TextImplCopyWith<$Res> {
factory _$$HttpResponseBody_TextImplCopyWith(
_$HttpResponseBody_TextImpl value,
$Res Function(_$HttpResponseBody_TextImpl) then) =
__$$HttpResponseBody_TextImplCopyWithImpl<$Res>;
@useResult
$Res call({String field0});
}
/// @nodoc
class __$$HttpResponseBody_TextImplCopyWithImpl<$Res>
extends _$HttpResponseBodyCopyWithImpl<$Res, _$HttpResponseBody_TextImpl>
implements _$$HttpResponseBody_TextImplCopyWith<$Res> {
__$$HttpResponseBody_TextImplCopyWithImpl(_$HttpResponseBody_TextImpl _value,
$Res Function(_$HttpResponseBody_TextImpl) _then)
: super(_value, _then);
/// Create a copy of HttpResponseBody
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? field0 = null,
}) {
return _then(_$HttpResponseBody_TextImpl(
null == field0
? _value.field0
: field0 // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _$HttpResponseBody_TextImpl extends HttpResponseBody_Text {
const _$HttpResponseBody_TextImpl(this.field0) : super._();
@override
final String field0;
@override
String toString() {
return 'HttpResponseBody.text(field0: $field0)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$HttpResponseBody_TextImpl &&
(identical(other.field0, field0) || other.field0 == field0));
}
@override
int get hashCode => Object.hash(runtimeType, field0);
/// Create a copy of HttpResponseBody
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$HttpResponseBody_TextImplCopyWith<_$HttpResponseBody_TextImpl>
get copyWith => __$$HttpResponseBody_TextImplCopyWithImpl<
_$HttpResponseBody_TextImpl>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(String field0) text,
required TResult Function(Uint8List field0) bytes,
required TResult Function() stream,
}) {
return text(field0);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(String field0)? text,
TResult? Function(Uint8List field0)? bytes,
TResult? Function()? stream,
}) {
return text?.call(field0);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(String field0)? text,
TResult Function(Uint8List field0)? bytes,
TResult Function()? stream,
required TResult orElse(),
}) {
if (text != null) {
return text(field0);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(HttpResponseBody_Text value) text,
required TResult Function(HttpResponseBody_Bytes value) bytes,
required TResult Function(HttpResponseBody_Stream value) stream,
}) {
return text(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(HttpResponseBody_Text value)? text,
TResult? Function(HttpResponseBody_Bytes value)? bytes,
TResult? Function(HttpResponseBody_Stream value)? stream,
}) {
return text?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(HttpResponseBody_Text value)? text,
TResult Function(HttpResponseBody_Bytes value)? bytes,
TResult Function(HttpResponseBody_Stream value)? stream,
required TResult orElse(),
}) {
if (text != null) {
return text(this);
}
return orElse();
}
}
abstract class HttpResponseBody_Text extends HttpResponseBody {
const factory HttpResponseBody_Text(final String field0) =
_$HttpResponseBody_TextImpl;
const HttpResponseBody_Text._() : super._();
String get field0;
/// Create a copy of HttpResponseBody
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$HttpResponseBody_TextImplCopyWith<_$HttpResponseBody_TextImpl>
get copyWith => throw _privateConstructorUsedError;
}
/// @nodoc
abstract class _$$HttpResponseBody_BytesImplCopyWith<$Res> {
factory _$$HttpResponseBody_BytesImplCopyWith(
_$HttpResponseBody_BytesImpl value,
$Res Function(_$HttpResponseBody_BytesImpl) then) =
__$$HttpResponseBody_BytesImplCopyWithImpl<$Res>;
@useResult
$Res call({Uint8List field0});
}
/// @nodoc
class __$$HttpResponseBody_BytesImplCopyWithImpl<$Res>
extends _$HttpResponseBodyCopyWithImpl<$Res, _$HttpResponseBody_BytesImpl>
implements _$$HttpResponseBody_BytesImplCopyWith<$Res> {
__$$HttpResponseBody_BytesImplCopyWithImpl(
_$HttpResponseBody_BytesImpl _value,
$Res Function(_$HttpResponseBody_BytesImpl) _then)
: super(_value, _then);
/// Create a copy of HttpResponseBody
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? field0 = null,
}) {
return _then(_$HttpResponseBody_BytesImpl(
null == field0
? _value.field0
: field0 // ignore: cast_nullable_to_non_nullable
as Uint8List,
));
}
}
/// @nodoc
class _$HttpResponseBody_BytesImpl extends HttpResponseBody_Bytes {
const _$HttpResponseBody_BytesImpl(this.field0) : super._();
@override
final Uint8List field0;
@override
String toString() {
return 'HttpResponseBody.bytes(field0: $field0)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$HttpResponseBody_BytesImpl &&
const DeepCollectionEquality().equals(other.field0, field0));
}
@override
int get hashCode =>
Object.hash(runtimeType, const DeepCollectionEquality().hash(field0));
/// Create a copy of HttpResponseBody
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$HttpResponseBody_BytesImplCopyWith<_$HttpResponseBody_BytesImpl>
get copyWith => __$$HttpResponseBody_BytesImplCopyWithImpl<
_$HttpResponseBody_BytesImpl>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(String field0) text,
required TResult Function(Uint8List field0) bytes,
required TResult Function() stream,
}) {
return bytes(field0);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(String field0)? text,
TResult? Function(Uint8List field0)? bytes,
TResult? Function()? stream,
}) {
return bytes?.call(field0);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(String field0)? text,
TResult Function(Uint8List field0)? bytes,
TResult Function()? stream,
required TResult orElse(),
}) {
if (bytes != null) {
return bytes(field0);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(HttpResponseBody_Text value) text,
required TResult Function(HttpResponseBody_Bytes value) bytes,
required TResult Function(HttpResponseBody_Stream value) stream,
}) {
return bytes(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(HttpResponseBody_Text value)? text,
TResult? Function(HttpResponseBody_Bytes value)? bytes,
TResult? Function(HttpResponseBody_Stream value)? stream,
}) {
return bytes?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(HttpResponseBody_Text value)? text,
TResult Function(HttpResponseBody_Bytes value)? bytes,
TResult Function(HttpResponseBody_Stream value)? stream,
required TResult orElse(),
}) {
if (bytes != null) {
return bytes(this);
}
return orElse();
}
}
abstract class HttpResponseBody_Bytes extends HttpResponseBody {
const factory HttpResponseBody_Bytes(final Uint8List field0) =
_$HttpResponseBody_BytesImpl;
const HttpResponseBody_Bytes._() : super._();
Uint8List get field0;
/// Create a copy of HttpResponseBody
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$HttpResponseBody_BytesImplCopyWith<_$HttpResponseBody_BytesImpl>
get copyWith => throw _privateConstructorUsedError;
}
/// @nodoc
abstract class _$$HttpResponseBody_StreamImplCopyWith<$Res> {
factory _$$HttpResponseBody_StreamImplCopyWith(
_$HttpResponseBody_StreamImpl value,
$Res Function(_$HttpResponseBody_StreamImpl) then) =
__$$HttpResponseBody_StreamImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$HttpResponseBody_StreamImplCopyWithImpl<$Res>
extends _$HttpResponseBodyCopyWithImpl<$Res, _$HttpResponseBody_StreamImpl>
implements _$$HttpResponseBody_StreamImplCopyWith<$Res> {
__$$HttpResponseBody_StreamImplCopyWithImpl(
_$HttpResponseBody_StreamImpl _value,
$Res Function(_$HttpResponseBody_StreamImpl) _then)
: super(_value, _then);
/// Create a copy of HttpResponseBody
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
class _$HttpResponseBody_StreamImpl extends HttpResponseBody_Stream {
const _$HttpResponseBody_StreamImpl() : super._();
@override
String toString() {
return 'HttpResponseBody.stream()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$HttpResponseBody_StreamImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(String field0) text,
required TResult Function(Uint8List field0) bytes,
required TResult Function() stream,
}) {
return stream();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(String field0)? text,
TResult? Function(Uint8List field0)? bytes,
TResult? Function()? stream,
}) {
return stream?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(String field0)? text,
TResult Function(Uint8List field0)? bytes,
TResult Function()? stream,
required TResult orElse(),
}) {
if (stream != null) {
return stream();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(HttpResponseBody_Text value) text,
required TResult Function(HttpResponseBody_Bytes value) bytes,
required TResult Function(HttpResponseBody_Stream value) stream,
}) {
return stream(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(HttpResponseBody_Text value)? text,
TResult? Function(HttpResponseBody_Bytes value)? bytes,
TResult? Function(HttpResponseBody_Stream value)? stream,
}) {
return stream?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(HttpResponseBody_Text value)? text,
TResult Function(HttpResponseBody_Bytes value)? bytes,
TResult Function(HttpResponseBody_Stream value)? stream,
required TResult orElse(),
}) {
if (stream != null) {
return stream(this);
}
return orElse();
}
}
abstract class HttpResponseBody_Stream extends HttpResponseBody {
const factory HttpResponseBody_Stream() = _$HttpResponseBody_StreamImpl;
const HttpResponseBody_Stream._() : super._();
}

File diff suppressed because it is too large Load diff

View file

@ -4,10 +4,14 @@
// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field
import 'api/image.dart';
import 'api/rhttp/client.dart';
import 'api/rhttp/error.dart';
import 'api/rhttp/http.dart';
import 'dart:async';
import 'dart:convert';
import 'dart:ffi' as ffi;
import 'frb_generated.dart';
import 'lib.dart';
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_io.dart';
abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@ -18,24 +22,414 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
required super.portManager,
});
CrossPlatformFinalizerArg
get rust_arc_decrement_strong_count_CancellationTokenPtr => wire
._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationTokenPtr;
CrossPlatformFinalizerArg
get rust_arc_decrement_strong_count_RequestClientPtr => wire
._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClientPtr;
@protected
AnyhowException dco_decode_AnyhowException(dynamic raw);
@protected
RequestClient
dco_decode_AutoExplicit_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
dynamic raw);
@protected
CancellationToken
dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
dynamic raw);
@protected
RequestClient
dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
dynamic raw);
@protected
CancellationToken
dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
dynamic raw);
@protected
RequestClient
dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
dynamic raw);
@protected
Duration dco_decode_Chrono_Duration(dynamic raw);
@protected
FutureOr<void> Function(CancellationToken)
dco_decode_DartFn_Inputs_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken_Output_unit_AnyhowException(
dynamic raw);
@protected
FutureOr<void> Function(HttpResponse)
dco_decode_DartFn_Inputs_http_response_Output_unit_AnyhowException(
dynamic raw);
@protected
FutureOr<void> Function(RhttpError)
dco_decode_DartFn_Inputs_rhttp_error_Output_unit_AnyhowException(
dynamic raw);
@protected
Object dco_decode_DartOpaque(dynamic raw);
@protected
Map<String, String> dco_decode_Map_String_String(dynamic raw);
@protected
CancellationToken
dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
dynamic raw);
@protected
RequestClient
dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
dynamic raw);
@protected
RustStreamSink<Uint8List> dco_decode_StreamSink_list_prim_u_8_strict_Sse(
dynamic raw);
@protected
String dco_decode_String(dynamic raw);
@protected
bool dco_decode_bool(dynamic raw);
@protected
Duration dco_decode_box_autoadd_Chrono_Duration(dynamic raw);
@protected
ClientCertificate dco_decode_box_autoadd_client_certificate(dynamic raw);
@protected
ClientSettings dco_decode_box_autoadd_client_settings(dynamic raw);
@protected
HttpHeaders dco_decode_box_autoadd_http_headers(dynamic raw);
@protected
HttpResponseBody dco_decode_box_autoadd_http_response_body(dynamic raw);
@protected
ProxySettings dco_decode_box_autoadd_proxy_settings(dynamic raw);
@protected
RedirectSettings dco_decode_box_autoadd_redirect_settings(dynamic raw);
@protected
TlsSettings dco_decode_box_autoadd_tls_settings(dynamic raw);
@protected
TlsVersion dco_decode_box_autoadd_tls_version(dynamic raw);
@protected
ClientCertificate dco_decode_client_certificate(dynamic raw);
@protected
ClientSettings dco_decode_client_settings(dynamic raw);
@protected
HttpHeaders dco_decode_http_headers(dynamic raw);
@protected
HttpMethod dco_decode_http_method(dynamic raw);
@protected
HttpResponse dco_decode_http_response(dynamic raw);
@protected
HttpResponseBody dco_decode_http_response_body(dynamic raw);
@protected
HttpVersion dco_decode_http_version(dynamic raw);
@protected
int dco_decode_i_32(dynamic raw);
@protected
PlatformInt64 dco_decode_i_64(dynamic raw);
@protected
List<Uint8List> dco_decode_list_list_prim_u_8_strict(dynamic raw);
@protected
List<int> dco_decode_list_prim_u_8_loose(dynamic raw);
@protected
Uint8List dco_decode_list_prim_u_8_strict(dynamic raw);
@protected
List<(String, String)> dco_decode_list_record_string_string(dynamic raw);
@protected
RequestClient?
dco_decode_opt_AutoExplicit_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
dynamic raw);
@protected
Duration? dco_decode_opt_box_autoadd_Chrono_Duration(dynamic raw);
@protected
ClientCertificate? dco_decode_opt_box_autoadd_client_certificate(dynamic raw);
@protected
ClientSettings? dco_decode_opt_box_autoadd_client_settings(dynamic raw);
@protected
HttpHeaders? dco_decode_opt_box_autoadd_http_headers(dynamic raw);
@protected
ProxySettings? dco_decode_opt_box_autoadd_proxy_settings(dynamic raw);
@protected
RedirectSettings? dco_decode_opt_box_autoadd_redirect_settings(dynamic raw);
@protected
TlsSettings? dco_decode_opt_box_autoadd_tls_settings(dynamic raw);
@protected
TlsVersion? dco_decode_opt_box_autoadd_tls_version(dynamic raw);
@protected
Uint8List? dco_decode_opt_list_prim_u_8_strict(dynamic raw);
@protected
List<(String, String)>? dco_decode_opt_list_record_string_string(dynamic raw);
@protected
ProxySettings dco_decode_proxy_settings(dynamic raw);
@protected
(String, String) dco_decode_record_string_string(dynamic raw);
@protected
RedirectSettings dco_decode_redirect_settings(dynamic raw);
@protected
RhttpError dco_decode_rhttp_error(dynamic raw);
@protected
TlsSettings dco_decode_tls_settings(dynamic raw);
@protected
TlsVersion dco_decode_tls_version(dynamic raw);
@protected
int dco_decode_u_16(dynamic raw);
@protected
int dco_decode_u_8(dynamic raw);
@protected
void dco_decode_unit(dynamic raw);
@protected
BigInt dco_decode_usize(dynamic raw);
@protected
AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer);
@protected
RequestClient
sse_decode_AutoExplicit_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
SseDeserializer deserializer);
@protected
CancellationToken
sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
SseDeserializer deserializer);
@protected
RequestClient
sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
SseDeserializer deserializer);
@protected
CancellationToken
sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
SseDeserializer deserializer);
@protected
RequestClient
sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
SseDeserializer deserializer);
@protected
Duration sse_decode_Chrono_Duration(SseDeserializer deserializer);
@protected
Object sse_decode_DartOpaque(SseDeserializer deserializer);
@protected
Map<String, String> sse_decode_Map_String_String(
SseDeserializer deserializer);
@protected
CancellationToken
sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
SseDeserializer deserializer);
@protected
RequestClient
sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
SseDeserializer deserializer);
@protected
RustStreamSink<Uint8List> sse_decode_StreamSink_list_prim_u_8_strict_Sse(
SseDeserializer deserializer);
@protected
String sse_decode_String(SseDeserializer deserializer);
@protected
bool sse_decode_bool(SseDeserializer deserializer);
@protected
Duration sse_decode_box_autoadd_Chrono_Duration(SseDeserializer deserializer);
@protected
ClientCertificate sse_decode_box_autoadd_client_certificate(
SseDeserializer deserializer);
@protected
ClientSettings sse_decode_box_autoadd_client_settings(
SseDeserializer deserializer);
@protected
HttpHeaders sse_decode_box_autoadd_http_headers(SseDeserializer deserializer);
@protected
HttpResponseBody sse_decode_box_autoadd_http_response_body(
SseDeserializer deserializer);
@protected
ProxySettings sse_decode_box_autoadd_proxy_settings(
SseDeserializer deserializer);
@protected
RedirectSettings sse_decode_box_autoadd_redirect_settings(
SseDeserializer deserializer);
@protected
TlsSettings sse_decode_box_autoadd_tls_settings(SseDeserializer deserializer);
@protected
TlsVersion sse_decode_box_autoadd_tls_version(SseDeserializer deserializer);
@protected
ClientCertificate sse_decode_client_certificate(SseDeserializer deserializer);
@protected
ClientSettings sse_decode_client_settings(SseDeserializer deserializer);
@protected
HttpHeaders sse_decode_http_headers(SseDeserializer deserializer);
@protected
HttpMethod sse_decode_http_method(SseDeserializer deserializer);
@protected
HttpResponse sse_decode_http_response(SseDeserializer deserializer);
@protected
HttpResponseBody sse_decode_http_response_body(SseDeserializer deserializer);
@protected
HttpVersion sse_decode_http_version(SseDeserializer deserializer);
@protected
int sse_decode_i_32(SseDeserializer deserializer);
@protected
PlatformInt64 sse_decode_i_64(SseDeserializer deserializer);
@protected
List<Uint8List> sse_decode_list_list_prim_u_8_strict(
SseDeserializer deserializer);
@protected
List<int> sse_decode_list_prim_u_8_loose(SseDeserializer deserializer);
@protected
Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer);
@protected
List<(String, String)> sse_decode_list_record_string_string(
SseDeserializer deserializer);
@protected
RequestClient?
sse_decode_opt_AutoExplicit_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
SseDeserializer deserializer);
@protected
Duration? sse_decode_opt_box_autoadd_Chrono_Duration(
SseDeserializer deserializer);
@protected
ClientCertificate? sse_decode_opt_box_autoadd_client_certificate(
SseDeserializer deserializer);
@protected
ClientSettings? sse_decode_opt_box_autoadd_client_settings(
SseDeserializer deserializer);
@protected
HttpHeaders? sse_decode_opt_box_autoadd_http_headers(
SseDeserializer deserializer);
@protected
ProxySettings? sse_decode_opt_box_autoadd_proxy_settings(
SseDeserializer deserializer);
@protected
RedirectSettings? sse_decode_opt_box_autoadd_redirect_settings(
SseDeserializer deserializer);
@protected
TlsSettings? sse_decode_opt_box_autoadd_tls_settings(
SseDeserializer deserializer);
@protected
TlsVersion? sse_decode_opt_box_autoadd_tls_version(
SseDeserializer deserializer);
@protected
Uint8List? sse_decode_opt_list_prim_u_8_strict(SseDeserializer deserializer);
@protected
List<(String, String)>? sse_decode_opt_list_record_string_string(
SseDeserializer deserializer);
@protected
ProxySettings sse_decode_proxy_settings(SseDeserializer deserializer);
@protected
(String, String) sse_decode_record_string_string(
SseDeserializer deserializer);
@protected
RedirectSettings sse_decode_redirect_settings(SseDeserializer deserializer);
@protected
RhttpError sse_decode_rhttp_error(SseDeserializer deserializer);
@protected
TlsSettings sse_decode_tls_settings(SseDeserializer deserializer);
@protected
TlsVersion sse_decode_tls_version(SseDeserializer deserializer);
@protected
int sse_decode_u_16(SseDeserializer deserializer);
@protected
int sse_decode_u_8(SseDeserializer deserializer);
@ -43,10 +437,150 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
void sse_decode_unit(SseDeserializer deserializer);
@protected
int sse_decode_i_32(SseDeserializer deserializer);
BigInt sse_decode_usize(SseDeserializer deserializer);
@protected
bool sse_decode_bool(SseDeserializer deserializer);
void sse_encode_AnyhowException(
AnyhowException self, SseSerializer serializer);
@protected
void
sse_encode_AutoExplicit_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
RequestClient self, SseSerializer serializer);
@protected
void
sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
CancellationToken self, SseSerializer serializer);
@protected
void
sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
RequestClient self, SseSerializer serializer);
@protected
void
sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
CancellationToken self, SseSerializer serializer);
@protected
void
sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
RequestClient self, SseSerializer serializer);
@protected
void sse_encode_Chrono_Duration(Duration self, SseSerializer serializer);
@protected
void
sse_encode_DartFn_Inputs_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken_Output_unit_AnyhowException(
FutureOr<void> Function(CancellationToken) self,
SseSerializer serializer);
@protected
void sse_encode_DartFn_Inputs_http_response_Output_unit_AnyhowException(
FutureOr<void> Function(HttpResponse) self, SseSerializer serializer);
@protected
void sse_encode_DartFn_Inputs_rhttp_error_Output_unit_AnyhowException(
FutureOr<void> Function(RhttpError) self, SseSerializer serializer);
@protected
void sse_encode_DartOpaque(Object self, SseSerializer serializer);
@protected
void sse_encode_Map_String_String(
Map<String, String> self, SseSerializer serializer);
@protected
void
sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
CancellationToken self, SseSerializer serializer);
@protected
void
sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
RequestClient self, SseSerializer serializer);
@protected
void sse_encode_StreamSink_list_prim_u_8_strict_Sse(
RustStreamSink<Uint8List> self, SseSerializer serializer);
@protected
void sse_encode_String(String self, SseSerializer serializer);
@protected
void sse_encode_bool(bool self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_Chrono_Duration(
Duration self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_client_certificate(
ClientCertificate self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_client_settings(
ClientSettings self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_http_headers(
HttpHeaders self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_http_response_body(
HttpResponseBody self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_proxy_settings(
ProxySettings self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_redirect_settings(
RedirectSettings self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_tls_settings(
TlsSettings self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_tls_version(
TlsVersion self, SseSerializer serializer);
@protected
void sse_encode_client_certificate(
ClientCertificate self, SseSerializer serializer);
@protected
void sse_encode_client_settings(
ClientSettings self, SseSerializer serializer);
@protected
void sse_encode_http_headers(HttpHeaders self, SseSerializer serializer);
@protected
void sse_encode_http_method(HttpMethod self, SseSerializer serializer);
@protected
void sse_encode_http_response(HttpResponse self, SseSerializer serializer);
@protected
void sse_encode_http_response_body(
HttpResponseBody self, SseSerializer serializer);
@protected
void sse_encode_http_version(HttpVersion self, SseSerializer serializer);
@protected
void sse_encode_i_32(int self, SseSerializer serializer);
@protected
void sse_encode_i_64(PlatformInt64 self, SseSerializer serializer);
@protected
void sse_encode_list_list_prim_u_8_strict(
List<Uint8List> self, SseSerializer serializer);
@protected
void sse_encode_list_prim_u_8_loose(List<int> self, SseSerializer serializer);
@ -55,6 +589,78 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
void sse_encode_list_prim_u_8_strict(
Uint8List self, SseSerializer serializer);
@protected
void sse_encode_list_record_string_string(
List<(String, String)> self, SseSerializer serializer);
@protected
void
sse_encode_opt_AutoExplicit_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
RequestClient? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_Chrono_Duration(
Duration? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_client_certificate(
ClientCertificate? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_client_settings(
ClientSettings? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_http_headers(
HttpHeaders? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_proxy_settings(
ProxySettings? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_redirect_settings(
RedirectSettings? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_tls_settings(
TlsSettings? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_tls_version(
TlsVersion? self, SseSerializer serializer);
@protected
void sse_encode_opt_list_prim_u_8_strict(
Uint8List? self, SseSerializer serializer);
@protected
void sse_encode_opt_list_record_string_string(
List<(String, String)>? self, SseSerializer serializer);
@protected
void sse_encode_proxy_settings(ProxySettings self, SseSerializer serializer);
@protected
void sse_encode_record_string_string(
(String, String) self, SseSerializer serializer);
@protected
void sse_encode_redirect_settings(
RedirectSettings self, SseSerializer serializer);
@protected
void sse_encode_rhttp_error(RhttpError self, SseSerializer serializer);
@protected
void sse_encode_tls_settings(TlsSettings self, SseSerializer serializer);
@protected
void sse_encode_tls_version(TlsVersion self, SseSerializer serializer);
@protected
void sse_encode_u_16(int self, SseSerializer serializer);
@protected
void sse_encode_u_8(int self, SseSerializer serializer);
@ -62,10 +668,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
void sse_encode_unit(void self, SseSerializer serializer);
@protected
void sse_encode_i_32(int self, SseSerializer serializer);
@protected
void sse_encode_bool(bool self, SseSerializer serializer);
void sse_encode_usize(BigInt self, SseSerializer serializer);
}
// Section: wire_class
@ -81,4 +684,68 @@ 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_generatedRustAutoOpaqueInnerCancellationToken(
ffi.Pointer<ffi.Void> ptr,
) {
return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
ptr,
);
}
late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationTokenPtr =
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
'frbgen_mangayomi_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken');
late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken =
_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationTokenPtr
.asFunction<void Function(ffi.Pointer<ffi.Void>)>();
void
rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
ffi.Pointer<ffi.Void> ptr,
) {
return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
ptr,
);
}
late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationTokenPtr =
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
'frbgen_mangayomi_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken');
late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken =
_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationTokenPtr
.asFunction<void Function(ffi.Pointer<ffi.Void>)>();
void
rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
ffi.Pointer<ffi.Void> ptr,
) {
return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
ptr,
);
}
late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClientPtr =
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
'frbgen_mangayomi_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient');
late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient =
_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClientPtr
.asFunction<void Function(ffi.Pointer<ffi.Void>)>();
void
rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
ffi.Pointer<ffi.Void> ptr,
) {
return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
ptr,
);
}
late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClientPtr =
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
'frbgen_mangayomi_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient');
late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient =
_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClientPtr
.asFunction<void Function(ffi.Pointer<ffi.Void>)>();
}

View file

@ -7,9 +7,13 @@
// ignore_for_file: argument_type_not_assignable
import 'api/image.dart';
import 'api/rhttp/client.dart';
import 'api/rhttp/error.dart';
import 'api/rhttp/http.dart';
import 'dart:async';
import 'dart:convert';
import 'frb_generated.dart';
import 'lib.dart';
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_web.dart';
abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@ -20,24 +24,414 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
required super.portManager,
});
CrossPlatformFinalizerArg
get rust_arc_decrement_strong_count_CancellationTokenPtr => wire
.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken;
CrossPlatformFinalizerArg
get rust_arc_decrement_strong_count_RequestClientPtr => wire
.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient;
@protected
AnyhowException dco_decode_AnyhowException(dynamic raw);
@protected
RequestClient
dco_decode_AutoExplicit_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
dynamic raw);
@protected
CancellationToken
dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
dynamic raw);
@protected
RequestClient
dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
dynamic raw);
@protected
CancellationToken
dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
dynamic raw);
@protected
RequestClient
dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
dynamic raw);
@protected
Duration dco_decode_Chrono_Duration(dynamic raw);
@protected
FutureOr<void> Function(CancellationToken)
dco_decode_DartFn_Inputs_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken_Output_unit_AnyhowException(
dynamic raw);
@protected
FutureOr<void> Function(HttpResponse)
dco_decode_DartFn_Inputs_http_response_Output_unit_AnyhowException(
dynamic raw);
@protected
FutureOr<void> Function(RhttpError)
dco_decode_DartFn_Inputs_rhttp_error_Output_unit_AnyhowException(
dynamic raw);
@protected
Object dco_decode_DartOpaque(dynamic raw);
@protected
Map<String, String> dco_decode_Map_String_String(dynamic raw);
@protected
CancellationToken
dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
dynamic raw);
@protected
RequestClient
dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
dynamic raw);
@protected
RustStreamSink<Uint8List> dco_decode_StreamSink_list_prim_u_8_strict_Sse(
dynamic raw);
@protected
String dco_decode_String(dynamic raw);
@protected
bool dco_decode_bool(dynamic raw);
@protected
Duration dco_decode_box_autoadd_Chrono_Duration(dynamic raw);
@protected
ClientCertificate dco_decode_box_autoadd_client_certificate(dynamic raw);
@protected
ClientSettings dco_decode_box_autoadd_client_settings(dynamic raw);
@protected
HttpHeaders dco_decode_box_autoadd_http_headers(dynamic raw);
@protected
HttpResponseBody dco_decode_box_autoadd_http_response_body(dynamic raw);
@protected
ProxySettings dco_decode_box_autoadd_proxy_settings(dynamic raw);
@protected
RedirectSettings dco_decode_box_autoadd_redirect_settings(dynamic raw);
@protected
TlsSettings dco_decode_box_autoadd_tls_settings(dynamic raw);
@protected
TlsVersion dco_decode_box_autoadd_tls_version(dynamic raw);
@protected
ClientCertificate dco_decode_client_certificate(dynamic raw);
@protected
ClientSettings dco_decode_client_settings(dynamic raw);
@protected
HttpHeaders dco_decode_http_headers(dynamic raw);
@protected
HttpMethod dco_decode_http_method(dynamic raw);
@protected
HttpResponse dco_decode_http_response(dynamic raw);
@protected
HttpResponseBody dco_decode_http_response_body(dynamic raw);
@protected
HttpVersion dco_decode_http_version(dynamic raw);
@protected
int dco_decode_i_32(dynamic raw);
@protected
PlatformInt64 dco_decode_i_64(dynamic raw);
@protected
List<Uint8List> dco_decode_list_list_prim_u_8_strict(dynamic raw);
@protected
List<int> dco_decode_list_prim_u_8_loose(dynamic raw);
@protected
Uint8List dco_decode_list_prim_u_8_strict(dynamic raw);
@protected
List<(String, String)> dco_decode_list_record_string_string(dynamic raw);
@protected
RequestClient?
dco_decode_opt_AutoExplicit_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
dynamic raw);
@protected
Duration? dco_decode_opt_box_autoadd_Chrono_Duration(dynamic raw);
@protected
ClientCertificate? dco_decode_opt_box_autoadd_client_certificate(dynamic raw);
@protected
ClientSettings? dco_decode_opt_box_autoadd_client_settings(dynamic raw);
@protected
HttpHeaders? dco_decode_opt_box_autoadd_http_headers(dynamic raw);
@protected
ProxySettings? dco_decode_opt_box_autoadd_proxy_settings(dynamic raw);
@protected
RedirectSettings? dco_decode_opt_box_autoadd_redirect_settings(dynamic raw);
@protected
TlsSettings? dco_decode_opt_box_autoadd_tls_settings(dynamic raw);
@protected
TlsVersion? dco_decode_opt_box_autoadd_tls_version(dynamic raw);
@protected
Uint8List? dco_decode_opt_list_prim_u_8_strict(dynamic raw);
@protected
List<(String, String)>? dco_decode_opt_list_record_string_string(dynamic raw);
@protected
ProxySettings dco_decode_proxy_settings(dynamic raw);
@protected
(String, String) dco_decode_record_string_string(dynamic raw);
@protected
RedirectSettings dco_decode_redirect_settings(dynamic raw);
@protected
RhttpError dco_decode_rhttp_error(dynamic raw);
@protected
TlsSettings dco_decode_tls_settings(dynamic raw);
@protected
TlsVersion dco_decode_tls_version(dynamic raw);
@protected
int dco_decode_u_16(dynamic raw);
@protected
int dco_decode_u_8(dynamic raw);
@protected
void dco_decode_unit(dynamic raw);
@protected
BigInt dco_decode_usize(dynamic raw);
@protected
AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer);
@protected
RequestClient
sse_decode_AutoExplicit_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
SseDeserializer deserializer);
@protected
CancellationToken
sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
SseDeserializer deserializer);
@protected
RequestClient
sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
SseDeserializer deserializer);
@protected
CancellationToken
sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
SseDeserializer deserializer);
@protected
RequestClient
sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
SseDeserializer deserializer);
@protected
Duration sse_decode_Chrono_Duration(SseDeserializer deserializer);
@protected
Object sse_decode_DartOpaque(SseDeserializer deserializer);
@protected
Map<String, String> sse_decode_Map_String_String(
SseDeserializer deserializer);
@protected
CancellationToken
sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
SseDeserializer deserializer);
@protected
RequestClient
sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
SseDeserializer deserializer);
@protected
RustStreamSink<Uint8List> sse_decode_StreamSink_list_prim_u_8_strict_Sse(
SseDeserializer deserializer);
@protected
String sse_decode_String(SseDeserializer deserializer);
@protected
bool sse_decode_bool(SseDeserializer deserializer);
@protected
Duration sse_decode_box_autoadd_Chrono_Duration(SseDeserializer deserializer);
@protected
ClientCertificate sse_decode_box_autoadd_client_certificate(
SseDeserializer deserializer);
@protected
ClientSettings sse_decode_box_autoadd_client_settings(
SseDeserializer deserializer);
@protected
HttpHeaders sse_decode_box_autoadd_http_headers(SseDeserializer deserializer);
@protected
HttpResponseBody sse_decode_box_autoadd_http_response_body(
SseDeserializer deserializer);
@protected
ProxySettings sse_decode_box_autoadd_proxy_settings(
SseDeserializer deserializer);
@protected
RedirectSettings sse_decode_box_autoadd_redirect_settings(
SseDeserializer deserializer);
@protected
TlsSettings sse_decode_box_autoadd_tls_settings(SseDeserializer deserializer);
@protected
TlsVersion sse_decode_box_autoadd_tls_version(SseDeserializer deserializer);
@protected
ClientCertificate sse_decode_client_certificate(SseDeserializer deserializer);
@protected
ClientSettings sse_decode_client_settings(SseDeserializer deserializer);
@protected
HttpHeaders sse_decode_http_headers(SseDeserializer deserializer);
@protected
HttpMethod sse_decode_http_method(SseDeserializer deserializer);
@protected
HttpResponse sse_decode_http_response(SseDeserializer deserializer);
@protected
HttpResponseBody sse_decode_http_response_body(SseDeserializer deserializer);
@protected
HttpVersion sse_decode_http_version(SseDeserializer deserializer);
@protected
int sse_decode_i_32(SseDeserializer deserializer);
@protected
PlatformInt64 sse_decode_i_64(SseDeserializer deserializer);
@protected
List<Uint8List> sse_decode_list_list_prim_u_8_strict(
SseDeserializer deserializer);
@protected
List<int> sse_decode_list_prim_u_8_loose(SseDeserializer deserializer);
@protected
Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer);
@protected
List<(String, String)> sse_decode_list_record_string_string(
SseDeserializer deserializer);
@protected
RequestClient?
sse_decode_opt_AutoExplicit_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
SseDeserializer deserializer);
@protected
Duration? sse_decode_opt_box_autoadd_Chrono_Duration(
SseDeserializer deserializer);
@protected
ClientCertificate? sse_decode_opt_box_autoadd_client_certificate(
SseDeserializer deserializer);
@protected
ClientSettings? sse_decode_opt_box_autoadd_client_settings(
SseDeserializer deserializer);
@protected
HttpHeaders? sse_decode_opt_box_autoadd_http_headers(
SseDeserializer deserializer);
@protected
ProxySettings? sse_decode_opt_box_autoadd_proxy_settings(
SseDeserializer deserializer);
@protected
RedirectSettings? sse_decode_opt_box_autoadd_redirect_settings(
SseDeserializer deserializer);
@protected
TlsSettings? sse_decode_opt_box_autoadd_tls_settings(
SseDeserializer deserializer);
@protected
TlsVersion? sse_decode_opt_box_autoadd_tls_version(
SseDeserializer deserializer);
@protected
Uint8List? sse_decode_opt_list_prim_u_8_strict(SseDeserializer deserializer);
@protected
List<(String, String)>? sse_decode_opt_list_record_string_string(
SseDeserializer deserializer);
@protected
ProxySettings sse_decode_proxy_settings(SseDeserializer deserializer);
@protected
(String, String) sse_decode_record_string_string(
SseDeserializer deserializer);
@protected
RedirectSettings sse_decode_redirect_settings(SseDeserializer deserializer);
@protected
RhttpError sse_decode_rhttp_error(SseDeserializer deserializer);
@protected
TlsSettings sse_decode_tls_settings(SseDeserializer deserializer);
@protected
TlsVersion sse_decode_tls_version(SseDeserializer deserializer);
@protected
int sse_decode_u_16(SseDeserializer deserializer);
@protected
int sse_decode_u_8(SseDeserializer deserializer);
@ -45,10 +439,150 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
void sse_decode_unit(SseDeserializer deserializer);
@protected
int sse_decode_i_32(SseDeserializer deserializer);
BigInt sse_decode_usize(SseDeserializer deserializer);
@protected
bool sse_decode_bool(SseDeserializer deserializer);
void sse_encode_AnyhowException(
AnyhowException self, SseSerializer serializer);
@protected
void
sse_encode_AutoExplicit_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
RequestClient self, SseSerializer serializer);
@protected
void
sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
CancellationToken self, SseSerializer serializer);
@protected
void
sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
RequestClient self, SseSerializer serializer);
@protected
void
sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
CancellationToken self, SseSerializer serializer);
@protected
void
sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
RequestClient self, SseSerializer serializer);
@protected
void sse_encode_Chrono_Duration(Duration self, SseSerializer serializer);
@protected
void
sse_encode_DartFn_Inputs_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken_Output_unit_AnyhowException(
FutureOr<void> Function(CancellationToken) self,
SseSerializer serializer);
@protected
void sse_encode_DartFn_Inputs_http_response_Output_unit_AnyhowException(
FutureOr<void> Function(HttpResponse) self, SseSerializer serializer);
@protected
void sse_encode_DartFn_Inputs_rhttp_error_Output_unit_AnyhowException(
FutureOr<void> Function(RhttpError) self, SseSerializer serializer);
@protected
void sse_encode_DartOpaque(Object self, SseSerializer serializer);
@protected
void sse_encode_Map_String_String(
Map<String, String> self, SseSerializer serializer);
@protected
void
sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
CancellationToken self, SseSerializer serializer);
@protected
void
sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
RequestClient self, SseSerializer serializer);
@protected
void sse_encode_StreamSink_list_prim_u_8_strict_Sse(
RustStreamSink<Uint8List> self, SseSerializer serializer);
@protected
void sse_encode_String(String self, SseSerializer serializer);
@protected
void sse_encode_bool(bool self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_Chrono_Duration(
Duration self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_client_certificate(
ClientCertificate self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_client_settings(
ClientSettings self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_http_headers(
HttpHeaders self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_http_response_body(
HttpResponseBody self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_proxy_settings(
ProxySettings self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_redirect_settings(
RedirectSettings self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_tls_settings(
TlsSettings self, SseSerializer serializer);
@protected
void sse_encode_box_autoadd_tls_version(
TlsVersion self, SseSerializer serializer);
@protected
void sse_encode_client_certificate(
ClientCertificate self, SseSerializer serializer);
@protected
void sse_encode_client_settings(
ClientSettings self, SseSerializer serializer);
@protected
void sse_encode_http_headers(HttpHeaders self, SseSerializer serializer);
@protected
void sse_encode_http_method(HttpMethod self, SseSerializer serializer);
@protected
void sse_encode_http_response(HttpResponse self, SseSerializer serializer);
@protected
void sse_encode_http_response_body(
HttpResponseBody self, SseSerializer serializer);
@protected
void sse_encode_http_version(HttpVersion self, SseSerializer serializer);
@protected
void sse_encode_i_32(int self, SseSerializer serializer);
@protected
void sse_encode_i_64(PlatformInt64 self, SseSerializer serializer);
@protected
void sse_encode_list_list_prim_u_8_strict(
List<Uint8List> self, SseSerializer serializer);
@protected
void sse_encode_list_prim_u_8_loose(List<int> self, SseSerializer serializer);
@ -57,6 +591,78 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
void sse_encode_list_prim_u_8_strict(
Uint8List self, SseSerializer serializer);
@protected
void sse_encode_list_record_string_string(
List<(String, String)> self, SseSerializer serializer);
@protected
void
sse_encode_opt_AutoExplicit_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
RequestClient? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_Chrono_Duration(
Duration? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_client_certificate(
ClientCertificate? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_client_settings(
ClientSettings? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_http_headers(
HttpHeaders? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_proxy_settings(
ProxySettings? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_redirect_settings(
RedirectSettings? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_tls_settings(
TlsSettings? self, SseSerializer serializer);
@protected
void sse_encode_opt_box_autoadd_tls_version(
TlsVersion? self, SseSerializer serializer);
@protected
void sse_encode_opt_list_prim_u_8_strict(
Uint8List? self, SseSerializer serializer);
@protected
void sse_encode_opt_list_record_string_string(
List<(String, String)>? self, SseSerializer serializer);
@protected
void sse_encode_proxy_settings(ProxySettings self, SseSerializer serializer);
@protected
void sse_encode_record_string_string(
(String, String) self, SseSerializer serializer);
@protected
void sse_encode_redirect_settings(
RedirectSettings self, SseSerializer serializer);
@protected
void sse_encode_rhttp_error(RhttpError self, SseSerializer serializer);
@protected
void sse_encode_tls_settings(TlsSettings self, SseSerializer serializer);
@protected
void sse_encode_tls_version(TlsVersion self, SseSerializer serializer);
@protected
void sse_encode_u_16(int self, SseSerializer serializer);
@protected
void sse_encode_u_8(int self, SseSerializer serializer);
@ -64,16 +670,37 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
void sse_encode_unit(void self, SseSerializer serializer);
@protected
void sse_encode_i_32(int self, SseSerializer serializer);
@protected
void sse_encode_bool(bool self, SseSerializer serializer);
void sse_encode_usize(BigInt self, SseSerializer serializer);
}
// Section: wire_class
class RustLibWire implements BaseWire {
RustLibWire.fromExternalLibrary(ExternalLibrary lib);
void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
int ptr) =>
wasmModule
.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
ptr);
void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
int ptr) =>
wasmModule
.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
ptr);
void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
int ptr) =>
wasmModule
.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
ptr);
void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
int ptr) =>
wasmModule
.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
ptr);
}
@JS('wasm_bindgen')
@ -81,4 +708,20 @@ external RustLibWasmModule get wasmModule;
@JS()
@anonymous
extension type RustLibWasmModule._(JSObject _) implements JSObject {}
extension type RustLibWasmModule._(JSObject _) implements JSObject {
external void
rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
int ptr);
external void
rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCancellationToken(
int ptr);
external void
rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
int ptr);
external void
rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRequestClient(
int ptr);
}

10
lib/src/rust/lib.dart Normal file
View file

@ -0,0 +1,10 @@
// This file is automatically generated, so please do not edit it.
// Generated by `flutter_rust_bridge`@ 2.3.0.
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
import 'frb_generated.dart';
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
// Rust type: RustOpaqueMoi<flutter_rust_bridge::for_generated::RustAutoOpaqueInner<CancellationToken>>
abstract class CancellationToken implements RustOpaqueInterface {}

View file

@ -15,7 +15,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
list(APPEND FLUTTER_FFI_PLUGIN_LIST
media_kit_native_event_loop
rhttp
rust_lib_mangayomi
)

View file

@ -254,14 +254,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.0"
cupertino_http:
dependency: "direct main"
description:
name: cupertino_http
sha256: "7e75c45a27cc13a886ab0a1e4d8570078397057bd612de9d24fe5df0d9387717"
url: "https://pub.dev"
source: hosted
version: "1.5.1"
cupertino_icons:
dependency: "direct main"
description:
@ -290,10 +282,10 @@ packages:
dependency: transitive
description:
name: dart_style
sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9"
sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab"
url: "https://pub.dev"
source: hosted
version: "2.3.6"
version: "2.3.7"
dartx:
dependency: transitive
description:
@ -371,18 +363,18 @@ packages:
dependency: transitive
description:
name: expressions
sha256: "0a3a207dc4697bbb0e17c731c7f10f2df6f88d9dbb99ac83c4168a10b57e7a20"
sha256: "308a621b602923dd8a0cf3072793b24850d06453eb49c6b698cbda41a282e904"
url: "https://pub.dev"
source: hosted
version: "0.2.5+1"
version: "0.2.5+2"
extended_image:
dependency: "direct main"
description:
name: extended_image
sha256: "9786aab821aac117763d6e4419cd49f5031fbaacfe3fd212c5b313d0334c37a9"
sha256: "1733803146df102c66e71af8099afd0e5dafc96ff6aa4802825e82108e8fb897"
url: "https://pub.dev"
source: hosted
version: "8.2.1"
version: "8.2.2"
extended_image_library:
dependency: transitive
description:
@ -581,8 +573,16 @@ packages:
url: "https://pub.dev"
source: hosted
version: "10.7.0"
freezed:
dependency: "direct dev"
description:
name: freezed
sha256: "44c19278dd9d89292cf46e97dc0c1e52ce03275f40a97c5a348e802a924bf40e"
url: "https://pub.dev"
source: hosted
version: "2.5.7"
freezed_annotation:
dependency: transitive
dependency: "direct main"
description:
name: freezed_annotation
sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2
@ -701,14 +701,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.1.0"
http_profile:
dependency: transitive
description:
name: http_profile
sha256: "7e679e355b09aaee2ab5010915c932cce3f2d1c11c3b2dc177891687014ffa78"
url: "https://pub.dev"
source: hosted
version: "0.1.0"
image:
dependency: transitive
description:
@ -1124,10 +1116,10 @@ packages:
dependency: transitive
description:
name: permission_handler_platform_interface
sha256: fe0ffe274d665be8e34f9c59705441a7d248edebbe5d9e3ec2665f88b79358ea
sha256: e9c8eadee926c4532d0305dff94b85bf961f16759c3af791486613152af4b4f9
url: "https://pub.dev"
source: hosted
version: "4.2.2"
version: "4.2.3"
permission_handler_windows:
dependency: transitive
description:
@ -1232,15 +1224,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.2.0"
rhttp:
dependency: "direct main"
description:
path: rhttp
ref: main
resolved-ref: e2c8dd04320936213c1f6ae66a3768b2b4f3a49a
url: "https://github.com/kodjodevf/rhttp.git"
source: git
version: "0.7.0"
riverpod:
dependency: transitive
description:
@ -1284,10 +1267,10 @@ packages:
dependency: transitive
description:
name: rxdart
sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb"
sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
url: "https://pub.dev"
source: hosted
version: "0.27.7"
version: "0.28.0"
safe_local_storage:
dependency: transitive
description:

View file

@ -75,14 +75,9 @@ dependencies:
rust_lib_mangayomi:
path: rust_builder
pseudom: ^1.0.1
rhttp:
git:
url: https://github.com/kodjodevf/rhttp.git
path: rhttp
ref: main
cupertino_http: ^1.5.1
shelf: ^1.4.2
path: ^1.9.0
freezed_annotation: ^2.0.0
dependency_overrides:
http: ^1.2.1
@ -116,6 +111,7 @@ dev_dependencies:
flutter_launcher_icons: ^0.13.1
isar_generator: ^3.1.0+1
flutter_lints: ^4.0.0
freezed: ^2.0.0
flutter:
uses-material-design: true

973
rust/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -7,5 +7,10 @@ edition = "2021"
crate-type = ["cdylib", "staticlib"]
[dependencies]
flutter_rust_bridge = "=2.3.0"
flutter_rust_bridge = { version = "=2.3.0", features = ["chrono"] }
image = "0.25.0"
chrono = "0.4.38"
futures-util = "0.3.30"
reqwest = { version = "0.12.7", default-features = false, features = ["charset", "http2", "rustls-tls", "rustls-tls-native-roots", "stream", "multipart"] }
tokio = { version = "1.39.3", features = ["full"] }
tokio-util = "0.7.11"

View file

@ -3,3 +3,4 @@
//
pub mod image;
pub mod rhttp;

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Tien Do Nam
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,165 @@
use crate::api::rhttp::error::RhttpError;
use chrono::Duration;
use reqwest::{tls, Certificate};
pub use tokio_util::sync::CancellationToken;
pub struct ClientSettings {
pub timeout: Option<Duration>,
pub connect_timeout: Option<Duration>,
pub throw_on_status_code: bool,
pub proxy_settings: Option<ProxySettings>,
pub redirect_settings: Option<RedirectSettings>,
pub tls_settings: Option<TlsSettings>,
}
pub enum ProxySettings {
NoProxy,
}
pub enum RedirectSettings {
NoRedirect,
LimitedRedirects(i32),
}
pub struct TlsSettings {
pub trust_root_certificates: bool,
pub trusted_root_certificates: Vec<Vec<u8>>,
pub verify_certificates: bool,
pub client_certificate: Option<ClientCertificate>,
pub min_tls_version: Option<TlsVersion>,
pub max_tls_version: Option<TlsVersion>,
}
pub struct ClientCertificate {
pub certificate: Vec<u8>,
pub private_key: Vec<u8>,
}
pub enum TlsVersion {
Tls1_2,
Tls1_3,
}
impl Default for ClientSettings {
fn default() -> Self {
ClientSettings {
timeout: None,
connect_timeout: None,
throw_on_status_code: true,
proxy_settings: None,
redirect_settings: None,
tls_settings: None,
}
}
}
#[derive(Clone)]
pub struct RequestClient {
pub(crate) client: reqwest::Client,
pub(crate) throw_on_status_code: bool,
/// A token that can be used to cancel all requests made by this client.
pub(crate) cancel_token: CancellationToken,
}
impl RequestClient {
pub(crate) fn new_default() -> Self {
create_client(ClientSettings::default()).unwrap()
}
pub(crate) fn new(settings: ClientSettings) -> Result<RequestClient, RhttpError> {
create_client(settings)
}
}
fn create_client(settings: ClientSettings) -> Result<RequestClient, RhttpError> {
let client: reqwest::Client = {
let mut client = reqwest::Client::builder();
if let Some(proxy_settings) = settings.proxy_settings {
match proxy_settings {
ProxySettings::NoProxy => client = client.no_proxy(),
}
}
if let Some(redirect_settings) = settings.redirect_settings {
client = match redirect_settings {
RedirectSettings::NoRedirect => client.redirect(reqwest::redirect::Policy::none()),
RedirectSettings::LimitedRedirects(max_redirects) => {
client.redirect(reqwest::redirect::Policy::limited(max_redirects as usize))
}
};
}
if let Some(timeout) = settings.timeout {
client = client.timeout(
timeout
.to_std()
.map_err(|e| RhttpError::RhttpUnknownError(e.to_string()))?,
);
}
if let Some(timeout) = settings.connect_timeout {
client = client.connect_timeout(
timeout
.to_std()
.map_err(|e| RhttpError::RhttpUnknownError(e.to_string()))?,
);
}
if let Some(tls_settings) = settings.tls_settings {
if !tls_settings.trust_root_certificates {
client = client.tls_built_in_root_certs(false);
}
for cert in tls_settings.trusted_root_certificates {
client =
client.add_root_certificate(Certificate::from_pem(&cert).map_err(|e| {
RhttpError::RhttpUnknownError(format!(
"Error adding trusted certificate: {e:?}"
))
})?);
}
if !tls_settings.verify_certificates {
client = client.danger_accept_invalid_certs(true);
}
if let Some(client_certificate) = tls_settings.client_certificate {
let identity = &[
client_certificate.certificate.as_slice(),
"\n".as_bytes(),
client_certificate.private_key.as_slice(),
]
.concat();
client = client.identity(
reqwest::Identity::from_pem(identity)
.map_err(|e| RhttpError::RhttpUnknownError(format!("{e:?}")))?,
);
}
if let Some(min_tls_version) = tls_settings.min_tls_version {
client = client.min_tls_version(match min_tls_version {
TlsVersion::Tls1_2 => tls::Version::TLS_1_2,
TlsVersion::Tls1_3 => tls::Version::TLS_1_3,
});
}
if let Some(max_tls_version) = tls_settings.max_tls_version {
client = client.max_tls_version(match max_tls_version {
TlsVersion::Tls1_2 => tls::Version::TLS_1_2,
TlsVersion::Tls1_3 => tls::Version::TLS_1_3,
});
}
}
client
.build()
.map_err(|e| RhttpError::RhttpUnknownError(format!("{e:?}")))?
};
Ok(RequestClient {
client,
throw_on_status_code: settings.throw_on_status_code,
cancel_token: CancellationToken::new(),
})
}

View file

@ -0,0 +1,33 @@
use crate::api::rhttp::http::HttpResponseBody;
use std::fmt::Display;
#[derive(Clone, Debug)]
pub enum RhttpError {
RhttpCancelError,
RhttpTimeoutError,
RhttpRedirectError,
RhttpStatusCodeError(u16, Vec<(String, String)>, HttpResponseBody),
RhttpInvalidCertificateError(String),
RhttpConnectionError(String),
RhttpUnknownError(String),
}
impl Display for RhttpError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RhttpError::RhttpCancelError => write!(f, "RhttpCancelError"),
RhttpError::RhttpTimeoutError => write!(f, "RhttpTimeoutError"),
RhttpError::RhttpRedirectError => write!(f, "RhttpRedirectError"),
RhttpError::RhttpStatusCodeError(i, _, _) => {
write!(f, "RhttpStatusCodeError: {i}")
}
RhttpError::RhttpInvalidCertificateError(d) => {
write!(f, "RhttpInvalidCertificateError: {d}")
}
RhttpError::RhttpConnectionError(e) => write!(f, "RhttpConnectionError: {e}"),
RhttpError::RhttpUnknownError(e) => write!(f, "{}", e),
}
}
}
impl std::error::Error for RhttpError {}

335
rust/src/api/rhttp/http.rs Normal file
View file

@ -0,0 +1,335 @@
use flutter_rust_bridge::{frb, DartFnFuture};
use futures_util::StreamExt;
use reqwest::header::{HeaderName, HeaderValue};
use reqwest::{Method, Response, Url, Version};
use std::collections::HashMap;
use std::error::Error;
use std::str::FromStr;
use tokio_util::sync::CancellationToken;
use crate::api::rhttp::client::{ClientSettings, RequestClient};
use crate::api::rhttp::error::RhttpError;
use crate::frb_generated::{RustAutoOpaque, StreamSink};
pub enum HttpMethod {
Options,
Get,
Post,
Put,
Delete,
Head,
Trace,
Connect,
Patch,
}
impl HttpMethod {
fn to_method(&self) -> Method {
match self {
HttpMethod::Options => Method::OPTIONS,
HttpMethod::Get => Method::GET,
HttpMethod::Post => Method::POST,
HttpMethod::Put => Method::PUT,
HttpMethod::Delete => Method::DELETE,
HttpMethod::Head => Method::HEAD,
HttpMethod::Trace => Method::TRACE,
HttpMethod::Connect => Method::CONNECT,
HttpMethod::Patch => Method::PATCH,
}
}
}
pub enum HttpHeaders {
Map(HashMap<String, String>),
List(Vec<(String, String)>),
}
#[derive(Clone, Copy)]
pub enum HttpExpectBody {
Text,
Bytes,
}
pub enum HttpVersion {
Http09,
Http10,
Http11,
Other,
}
impl HttpVersion {
fn from_version(version: Version) -> HttpVersion {
match version {
Version::HTTP_09 => HttpVersion::Http09,
Version::HTTP_10 => HttpVersion::Http10,
Version::HTTP_11 => HttpVersion::Http11,
_ => HttpVersion::Other,
}
}
}
pub struct HttpResponse {
pub headers: Vec<(String, String)>,
pub version: HttpVersion,
pub status_code: u16,
pub body: HttpResponseBody,
}
#[derive(Clone, Debug)]
pub enum HttpResponseBody {
Text(String),
Bytes(Vec<u8>),
Stream,
}
// It must be async so that frb provides an async context.
pub async fn register_client(settings: ClientSettings) -> Result<RequestClient, RhttpError> {
register_client_internal(settings)
}
#[frb(sync)]
pub fn register_client_sync(settings: ClientSettings) -> Result<RequestClient, RhttpError> {
register_client_internal(settings)
}
fn register_client_internal(settings: ClientSettings) -> Result<RequestClient, RhttpError> {
let client = RequestClient::new(settings)?;
Ok(client)
}
pub fn cancel_running_requests(client: &RequestClient) {
client.cancel_token.cancel();
}
struct RequestCancelTokens {
request_cancel_token: CancellationToken,
client_cancel_token: CancellationToken,
}
fn build_cancel_tokens(client: Option<RustAutoOpaque<RequestClient>>) -> RequestCancelTokens {
let client_cancel_token = match client {
Some(client) => Some(client.try_read().unwrap().cancel_token.clone()),
None => None,
}
.unwrap_or_else(|| CancellationToken::new());
RequestCancelTokens {
request_cancel_token: CancellationToken::new(),
client_cancel_token,
}
}
pub async fn make_http_request_receive_stream(
client: Option<RustAutoOpaque<RequestClient>>,
settings: Option<ClientSettings>,
method: HttpMethod,
url: String,
query: Option<Vec<(String, String)>>,
headers: Option<HttpHeaders>,
body: Option<Vec<u8>>,
stream_sink: StreamSink<Vec<u8>>,
on_response: impl Fn(HttpResponse) -> DartFnFuture<()>,
on_error: impl Fn(RhttpError) -> DartFnFuture<()>,
on_cancel_token: impl Fn(CancellationToken) -> DartFnFuture<()>,
cancelable: bool,
) -> Result<(), RhttpError> {
let cancel_tokens = build_cancel_tokens(client.clone());
if cancelable {
on_cancel_token(cancel_tokens.request_cancel_token.clone()).await;
}
tokio::select! {
_ = cancel_tokens.request_cancel_token.cancelled() => Err(RhttpError::RhttpCancelError),
_ = cancel_tokens.client_cancel_token.cancelled() => Err(RhttpError::RhttpCancelError),
_ = make_http_request_receive_stream_inner(
client,
settings,
method,
url.to_owned(),
query,
headers,
body,
stream_sink,
on_response,
on_error,
) => Ok(()),
}
}
async fn make_http_request_receive_stream_inner(
client: Option<RustAutoOpaque<RequestClient>>,
settings: Option<ClientSettings>,
method: HttpMethod,
url: String,
query: Option<Vec<(String, String)>>,
headers: Option<HttpHeaders>,
body: Option<Vec<u8>>,
stream_sink: StreamSink<Vec<u8>>,
on_response: impl Fn(HttpResponse) -> DartFnFuture<()>,
on_error: impl Fn(RhttpError) -> DartFnFuture<()>,
) -> Result<(), RhttpError> {
let response =
make_http_request_helper(client, settings, method, url, query, headers, body, None).await;
let response = match response {
Ok(_) => response,
Err(e) => {
on_error(e.clone()).await;
Err(e)
}
}?;
let http_response = HttpResponse {
headers: header_to_vec(response.headers()),
version: HttpVersion::from_version(response.version()),
status_code: response.status().as_u16(),
body: HttpResponseBody::Stream,
};
on_response(http_response).await;
let mut stream = response.bytes_stream();
while let Some(chunk) = stream.next().await {
let chunk = chunk.map_err(|e| {
let _ = stream_sink.add_error(RhttpError::RhttpUnknownError(e.to_string()));
RhttpError::RhttpUnknownError(e.to_string())
})?;
stream_sink.add(chunk.to_vec()).map_err(|e| {
let _ = stream_sink.add_error(RhttpError::RhttpUnknownError(e.to_string()));
RhttpError::RhttpUnknownError(e.to_string())
})?;
}
Ok(())
}
/// This function is used to make an HTTP request without any response handling.
async fn make_http_request_helper(
client: Option<RustAutoOpaque<RequestClient>>,
settings: Option<ClientSettings>,
method: HttpMethod,
url: String,
query: Option<Vec<(String, String)>>,
headers: Option<HttpHeaders>,
body: Option<Vec<u8>>,
expect_body: Option<HttpExpectBody>,
) -> Result<Response, RhttpError> {
let client: RequestClient = match client {
Some(client) => client.try_read().unwrap().clone(),
None => match settings {
Some(settings) => RequestClient::new(settings)
.map_err(|e| RhttpError::RhttpUnknownError(e.to_string()))?,
None => RequestClient::new_default(),
},
};
let request = {
let mut request = client.client.request(
method.to_method(),
Url::parse(&url).map_err(|e| RhttpError::RhttpUnknownError(e.to_string()))?,
);
if let Some(query) = query {
request = request.query(&query);
}
match headers {
Some(HttpHeaders::Map(map)) => {
for (k, v) in map {
let header_name = HeaderName::from_str(&k)
.map_err(|e| RhttpError::RhttpUnknownError(e.to_string()))?;
let header_value = HeaderValue::from_str(&v)
.map_err(|e| RhttpError::RhttpUnknownError(e.to_string()))?;
request = request.header(header_name, header_value);
}
}
Some(HttpHeaders::List(list)) => {
for (k, v) in list {
let header_name = HeaderName::from_str(&k)
.map_err(|e| RhttpError::RhttpUnknownError(e.to_string()))?;
let header_value = HeaderValue::from_str(&v)
.map_err(|e| RhttpError::RhttpUnknownError(e.to_string()))?;
request = request.header(header_name, header_value);
}
}
None => (),
};
request = match body {
Some(body) => request.body(body),
None => request,
};
request
.build()
.map_err(|e| RhttpError::RhttpUnknownError(e.to_string()))?
};
let response = client.client.execute(request).await.map_err(|e| {
if e.is_redirect() {
RhttpError::RhttpRedirectError
} else if e.is_timeout() {
RhttpError::RhttpTimeoutError
} else {
// We use the debug string because it contains more information
let inner = e.source();
let is_cert_error = match inner {
// TODO: This is a hacky way to check if the error is a certificate error
Some(inner) => format!("{:?}", inner).contains("InvalidCertificate"),
None => false,
};
if is_cert_error {
RhttpError::RhttpInvalidCertificateError(format!("{:?}", inner.unwrap()))
} else if e.is_connect() {
RhttpError::RhttpConnectionError(format!("{:?}", inner.unwrap()))
} else {
RhttpError::RhttpUnknownError(match inner {
Some(inner) => format!("{inner:?}"),
None => format!("{e:?}"),
})
}
}
})?;
if client.throw_on_status_code {
let status = response.status();
if status.is_client_error() || status.is_server_error() {
return Err(RhttpError::RhttpStatusCodeError(
response.status().as_u16(),
header_to_vec(response.headers()),
match expect_body {
Some(HttpExpectBody::Text) => HttpResponseBody::Text(
response
.text()
.await
.map_err(|e| RhttpError::RhttpUnknownError(e.to_string()))?,
),
Some(HttpExpectBody::Bytes) => HttpResponseBody::Bytes(
response
.bytes()
.await
.map_err(|e| RhttpError::RhttpUnknownError(e.to_string()))?
.to_vec(),
),
_ => HttpResponseBody::Stream,
},
));
}
}
Ok(response)
}
fn header_to_vec(headers: &reqwest::header::HeaderMap) -> Vec<(String, String)> {
headers
.iter()
.map(|(k, v)| (k.as_str().to_string(), v.to_str().unwrap().to_string()))
.collect()
}
pub fn cancel_request(token: &CancellationToken) {
token.cancel();
}

View file

@ -0,0 +1,3 @@
pub mod client;
pub mod error;
pub mod http;

File diff suppressed because it is too large Load diff

View file

@ -19,7 +19,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
list(APPEND FLUTTER_FFI_PLUGIN_LIST
media_kit_native_event_loop
rhttp
rust_lib_mangayomi
)