This commit is contained in:
Moustapha Kodjo Amadou 2026-01-26 17:28:25 +01:00
parent bf6949a834
commit d5aecf66dc
19 changed files with 1559 additions and 132 deletions

View file

@ -1,10 +1,10 @@
import 'dart:convert';
import 'dart:io';
import 'package:epubx/epubx.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_qjs/flutter_qjs.dart';
import 'package:flutter_qjs/quickjs/ffi.dart';
import 'package:http/http.dart' as http;
import 'package:mangayomi/src/rust/api/epub.dart';
import 'package:path/path.dart' as p;
import 'package:http_interceptor/http/intercepted_client.dart';
import 'package:js_packer/js_packer.dart';
@ -60,25 +60,25 @@ class JsUtils {
});
runtime.onMessage('parseEpub', (dynamic args) async {
final bytes = await _toBytesResponse(client(), "GET", args);
final book = await EpubReader.readBook(bytes);
final book = await parseEpubFromBytes(epubBytes: bytes, fullData: true);
final List<String> chapters = [];
for (var chapter in book.Chapters ?? []) {
final chapterTitle = chapter.Title;
for (var chapter in book.chapters) {
final chapterTitle = chapter.name;
chapters.add(chapterTitle);
}
return jsonEncode({
"title": book.Title,
"author": book.Author,
"title": book.name,
"author": book.author,
"chapters": chapters,
});
});
runtime.onMessage('parseEpubChapter', (dynamic args) async {
final bytes = await _toBytesResponse(client(), "GET", args);
final book = await EpubReader.readBook(bytes);
final chapter = book.Chapters?.where(
(element) => element.Title == args[3],
).firstOrNull;
return chapter?.HtmlContent;
final book = await parseEpubFromBytes(epubBytes: bytes, fullData: true);
final chapter = book.chapters.firstWhereOrNull(
(element) => element.name == args[3],
);
return chapter?.content;
});
runtime.evaluate('''

View file

@ -1,11 +1,11 @@
import 'dart:convert';
import 'dart:io'; // For I/O-operations
import 'dart:typed_data';
import 'package:epubx/epubx.dart';
import 'package:isar_community/isar.dart'; // Isar database package for local storage
import 'package:mangayomi/main.dart'; // Exposes the global `isar` instance
import 'package:mangayomi/models/settings.dart';
import 'package:mangayomi/modules/library/providers/local_archive.dart';
import 'package:mangayomi/src/rust/api/epub.dart';
import 'package:mangayomi/utils/extensions/others.dart';
import 'package:path/path.dart' as p; // For manipulating file system paths
import 'package:bot_toast/bot_toast.dart'; // For Exceptions
@ -292,31 +292,26 @@ Future<void> _scanDirectory(Ref ref, Directory? dir) async {
final itemName = p.basename(p.dirname(chapterPath));
final manga = mangaByName[itemName];
if (manga != null) {
final chapterFile = File(chapterPath);
if (manga.itemType == ItemType.novel) {
final bytes = await chapterFile.readAsBytes();
final book = await EpubReader.readBook(bytes);
if (book.Content != null && book.Content!.Images != null) {
final coverImage =
book.Content!.Images!.containsKey("media/file0.png")
? book.Content!.Images!["media/file0.png"]!.Content
: book.Content!.Images!.values.first.Content;
manga.customCoverImage = coverImage == null
? null
: Uint8List.fromList(coverImage).getCoverImage;
final book = await parseEpubFromPath(
epubPath: chapterPath,
fullData: false,
);
if (book.cover != null) {
manga.customCoverImage = book.cover!.getCoverImage;
saveManga++;
}
chaptersToSave.add(
Chapter(
mangaId: manga.id,
name: book.Title,
name: book.name,
archivePath: chapterPath,
downloadSize: chapterFile.existsSync()
? chapterFile.lengthSync().formattedFileSize()
: null,
downloadSize: null,
)..manga.value = manga,
);
} else {
final chapterFile = File(chapterPath);
final chap = Chapter(
mangaId: manga.id,
name:

View file

@ -1,6 +1,4 @@
import 'dart:io';
import 'dart:typed_data';
import 'package:epubx/epubx.dart';
import 'package:file_picker/file_picker.dart';
import 'package:mangayomi/eval/model/m_bridge.dart';
import 'package:mangayomi/main.dart';
@ -8,6 +6,7 @@ import 'package:mangayomi/models/chapter.dart';
import 'package:mangayomi/models/manga.dart';
import 'package:mangayomi/modules/manga/archive_reader/models/models.dart';
import 'package:mangayomi/modules/manga/archive_reader/providers/archive_reader_providers.dart';
import 'package:mangayomi/src/rust/api/epub.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'local_archive.g.dart';
@ -71,24 +70,20 @@ Future importArchivesFromFile(
final mangaId = await isar.mangas.put(manga);
final List<Chapter> chapters = [];
if (itemType == ItemType.novel) {
final bytes = await File(file.path!).readAsBytes();
final book = await EpubReader.readBook(bytes);
if (book.Content != null && book.Content!.Images != null) {
final coverImage =
book.Content!.Images!.containsKey("media/file0.png")
? book.Content!.Images!["media/file0.png"]!.Content
: book.Content!.Images!.values.first.Content;
final book = await parseEpubFromPath(
epubPath: file.path!,
fullData: false,
);
if (book.cover != null) {
await isar.mangas.put(
manga
..customCoverImage = coverImage == null
? null
: Uint8List.fromList(coverImage).getCoverImage,
manga..customCoverImage = book.cover!.getCoverImage,
);
}
chapters.add(
Chapter(
mangaId: mangaId,
name: book.Title,
name: book.name,
archivePath: file.path,
updatedAt: DateTime.now().millisecondsSinceEpoch,
)..manga.value = manga,

View file

@ -65,7 +65,7 @@ final class ImportArchivesFromFileProvider
}
String _$importArchivesFromFileHash() =>
r'8a26aaed0c29e76899ab37c6f64a1f8b80792e41';
r'52d80a07200627e1bc650b06d1fd8aed66c03e4c';
final class ImportArchivesFromFileFamily extends $Family
with

View file

@ -65,7 +65,7 @@ final class DoBackUpProvider
}
}
String _$doBackUpHash() => r'5b410047be9b7dc6f7c3651750ab4b2531bedc3e';
String _$doBackUpHash() => r'231b70e9de3a2ed8d01c92569ce786c4de38ddc3';
final class DoBackUpFamily extends $Family
with

View file

@ -1,7 +1,6 @@
import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'package:epubx/epubx.dart';
import 'package:extended_image/extended_image.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
@ -20,6 +19,7 @@ import 'package:mangayomi/modules/novel/widgets/novel_reader_settings_sheet.dart
import 'package:mangayomi/modules/widgets/custom_draggable_tabbar.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/services/get_html_content.dart';
import 'package:mangayomi/src/rust/api/epub.dart';
import 'package:mangayomi/utils/extensions/dom_extensions.dart';
import 'package:mangayomi/utils/utils.dart';
import 'package:mangayomi/modules/manga/reader/providers/push_router.dart';
@ -48,7 +48,7 @@ class NovelWebView extends ConsumerStatefulWidget {
const NovelWebView({super.key, required this.chapter, required this.result});
final Chapter chapter;
final AsyncValue<(String, EpubBook?)> result;
final AsyncValue<(String, EpubNovel?)> result;
@override
ConsumerState createState() {
@ -103,7 +103,7 @@ class _NovelWebViewState extends ConsumerState<NovelWebView>
}
late Chapter chapter = widget.chapter;
EpubBook? epubBook;
EpubNovel? epubBook;
final StreamController<double> _rebuildDetail =
StreamController<double>.broadcast();
@ -1201,14 +1201,13 @@ class _NovelWebViewState extends ConsumerState<NovelWebView>
if (element.localName == "img" && element.getSrc != null) {
final src = element.getSrc!;
final fileName = src.split("/").last;
final image = epubBook!.Content?.Images?.entries
final image = epubBook!.images
.firstWhereOrNull(
(img) =>
img.key.endsWith(fileName) ||
img.key.contains(fileName.replaceAll('%20', ' ')),
img.name.endsWith(fileName) ||
img.name.contains(fileName.replaceAll('%20', ' ')),
)
?.value
.Content;
?.content;
if (image != null) {
return Padding(
@ -1232,7 +1231,7 @@ class _NovelWebViewState extends ConsumerState<NovelWebView>
),
),
fit: BoxFit.contain,
image: MemoryImage(image as Uint8List) as ImageProvider,
image: MemoryImage(image) as ImageProvider,
),
);
}

View file

@ -1,6 +1,7 @@
import 'dart:io';
import 'package:mangayomi/src/rust/api/epub.dart';
import 'package:path/path.dart' as p;
import 'package:epubx/epubx.dart';
// import 'package:epubx/epubx.dart';
import 'package:html/parser.dart';
import 'package:mangayomi/eval/lib.dart';
import 'package:mangayomi/models/chapter.dart';
@ -11,28 +12,29 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'get_html_content.g.dart';
@riverpod
Future<(String, EpubBook?)> getHtmlContent(
Future<(String, EpubNovel?)> getHtmlContent(
Ref ref, {
required Chapter chapter,
}) async {
final keepAlive = ref.keepAlive();
(String, EpubBook?)? result;
(String, EpubNovel?)? result;
try {
if (!chapter.manga.isLoaded) {
chapter.manga.loadSync();
}
if (chapter.archivePath != null && chapter.archivePath!.isNotEmpty) {
final htmlFile = File(chapter.archivePath!);
if (await htmlFile.exists()) {
final bytes = await htmlFile.readAsBytes();
final book = await EpubReader.readBook(bytes);
try {
final okk = await parseEpubFromPath(
epubPath: chapter.archivePath!,
fullData: true,
);
String htmlContent = "";
for (var subChapter in book.Content!.Html!.values) {
htmlContent += "\n<hr/>\n${subChapter.Content}";
for (var subChapter in okk.chapters) {
htmlContent += "\n<hr/>\n${subChapter.content}";
}
result = (_buildHtml(htmlContent), okk);
} catch (_) {}
result = (_buildHtml(htmlContent), book);
}
result ??= (_buildHtml("Local epub file not found!"), null);
}
if (result == null) {

View file

@ -15,13 +15,13 @@ final getHtmlContentProvider = GetHtmlContentFamily._();
final class GetHtmlContentProvider
extends
$FunctionalProvider<
AsyncValue<(String, EpubBook?)>,
(String, EpubBook?),
FutureOr<(String, EpubBook?)>
AsyncValue<(String, EpubNovel?)>,
(String, EpubNovel?),
FutureOr<(String, EpubNovel?)>
>
with
$FutureModifier<(String, EpubBook?)>,
$FutureProvider<(String, EpubBook?)> {
$FutureModifier<(String, EpubNovel?)>,
$FutureProvider<(String, EpubNovel?)> {
GetHtmlContentProvider._({
required GetHtmlContentFamily super.from,
required Chapter super.argument,
@ -45,12 +45,12 @@ final class GetHtmlContentProvider
@$internal
@override
$FutureProviderElement<(String, EpubBook?)> $createElement(
$FutureProviderElement<(String, EpubNovel?)> $createElement(
$ProviderPointer pointer,
) => $FutureProviderElement(pointer);
@override
FutureOr<(String, EpubBook?)> create(Ref ref) {
FutureOr<(String, EpubNovel?)> create(Ref ref) {
final argument = this.argument as Chapter;
return getHtmlContent(ref, chapter: argument);
}
@ -66,10 +66,10 @@ final class GetHtmlContentProvider
}
}
String _$getHtmlContentHash() => r'ca2fec040211e0700e31baed0616e89ac1f20a7d';
String _$getHtmlContentHash() => r'dbce709ba154704c7e9d1465bdc21c926a42a723';
final class GetHtmlContentFamily extends $Family
with $FunctionalFamilyOverride<FutureOr<(String, EpubBook?)>, Chapter> {
with $FunctionalFamilyOverride<FutureOr<(String, EpubNovel?)>, Chapter> {
GetHtmlContentFamily._()
: super(
retry: null,

124
lib/src/rust/api/epub.dart Normal file
View file

@ -0,0 +1,124 @@
// This file is automatically generated, so please do not edit it.
// @generated by `flutter_rust_bridge`@ 2.11.1.
// 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';
// These functions are ignored because they are not marked as `pub`: `extract_resources_from_archive`, `extract_resources_with_content_from_bytes`, `extract_resources_with_content`, `find_chapter_name_from_toc`, `parse_epub_with_doc`
// 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`, `clone`, `fmt`, `fmt`, `fmt`
Future<EpubNovel> parseEpubFromPath({
required String epubPath,
required bool fullData,
}) => RustLib.instance.api.crateApiEpubParseEpubFromPath(
epubPath: epubPath,
fullData: fullData,
);
Future<EpubNovel> parseEpubFromBytes({
required List<int> epubBytes,
required bool fullData,
}) => RustLib.instance.api.crateApiEpubParseEpubFromBytes(
epubBytes: epubBytes,
fullData: fullData,
);
/// Get chapter content from EPUB by path
Future<String> getChapterContent({
required String epubPath,
required String chapterPath,
}) => RustLib.instance.api.crateApiEpubGetChapterContent(
epubPath: epubPath,
chapterPath: chapterPath,
);
class EpubChapter {
final String name;
final String content;
final String path;
const EpubChapter({
required this.name,
required this.content,
required this.path,
});
@override
int get hashCode => name.hashCode ^ content.hashCode ^ path.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is EpubChapter &&
runtimeType == other.runtimeType &&
name == other.name &&
content == other.content &&
path == other.path;
}
class EpubNovel {
final String name;
final Uint8List? cover;
final String? summary;
final String? author;
final String? artist;
final List<EpubChapter> chapters;
final List<EpubResource> images;
final List<EpubResource> stylesheets;
const EpubNovel({
required this.name,
this.cover,
this.summary,
this.author,
this.artist,
required this.chapters,
required this.images,
required this.stylesheets,
});
@override
int get hashCode =>
name.hashCode ^
cover.hashCode ^
summary.hashCode ^
author.hashCode ^
artist.hashCode ^
chapters.hashCode ^
images.hashCode ^
stylesheets.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is EpubNovel &&
runtimeType == other.runtimeType &&
name == other.name &&
cover == other.cover &&
summary == other.summary &&
author == other.author &&
artist == other.artist &&
chapters == other.chapters &&
images == other.images &&
stylesheets == other.stylesheets;
}
class EpubResource {
final String name;
final Uint8List content;
const EpubResource({required this.name, required this.content});
@override
int get hashCode => name.hashCode ^ content.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is EpubResource &&
runtimeType == other.runtimeType &&
name == other.name &&
content == other.content;
}

View file

@ -3,6 +3,7 @@
// 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/epub.dart';
import 'api/image.dart';
import 'api/rhttp/client.dart';
import 'api/rhttp/error.dart';
@ -68,7 +69,7 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> {
String get codegenVersion => '2.11.1';
@override
int get rustContentHash => 885218533;
int get rustContentHash => 2140434025;
static const kDefaultExternalLibraryLoaderConfig =
ExternalLibraryLoaderConfig(
@ -97,6 +98,11 @@ abstract class RustLibApi extends BaseApi {
required StaticDnsSettings settings,
});
Future<String> crateApiEpubGetChapterContent({
required String epubPath,
required String chapterPath,
});
Stream<Uint8List> crateApiRhttpHttpMakeHttpRequestReceiveStream({
RequestClient? client,
ClientSettings? settings,
@ -111,6 +117,16 @@ abstract class RustLibApi extends BaseApi {
required bool cancelable,
});
Future<EpubNovel> crateApiEpubParseEpubFromBytes({
required List<int> epubBytes,
required bool fullData,
});
Future<EpubNovel> crateApiEpubParseEpubFromPath({
required String epubPath,
required bool fullData,
});
Uint8List crateApiImageProcessCropImage({required List<int> image});
Future<RequestClient> crateApiRhttpHttpRegisterClient({
@ -313,6 +329,41 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
argNames: ["settings"],
);
@override
Future<String> crateApiEpubGetChapterContent({
required String epubPath,
required String chapterPath,
}) {
return handler.executeNormal(
NormalTask(
callFfi: (port_) {
final serializer = SseSerializer(generalizedFrbRustBinding);
sse_encode_String(epubPath, serializer);
sse_encode_String(chapterPath, serializer);
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 7,
port: port_,
);
},
codec: SseCodec(
decodeSuccessData: sse_decode_String,
decodeErrorData: sse_decode_String,
),
constMeta: kCrateApiEpubGetChapterContentConstMeta,
argValues: [epubPath, chapterPath],
apiImpl: this,
),
);
}
TaskConstMeta get kCrateApiEpubGetChapterContentConstMeta =>
const TaskConstMeta(
debugName: "get_chapter_content",
argNames: ["epubPath", "chapterPath"],
);
@override
Stream<Uint8List> crateApiRhttpHttpMakeHttpRequestReceiveStream({
RequestClient? client,
@ -363,7 +414,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 7,
funcId: 8,
port: port_,
);
},
@ -412,6 +463,76 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
],
);
@override
Future<EpubNovel> crateApiEpubParseEpubFromBytes({
required List<int> epubBytes,
required bool fullData,
}) {
return handler.executeNormal(
NormalTask(
callFfi: (port_) {
final serializer = SseSerializer(generalizedFrbRustBinding);
sse_encode_list_prim_u_8_loose(epubBytes, serializer);
sse_encode_bool(fullData, serializer);
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 9,
port: port_,
);
},
codec: SseCodec(
decodeSuccessData: sse_decode_epub_novel,
decodeErrorData: sse_decode_String,
),
constMeta: kCrateApiEpubParseEpubFromBytesConstMeta,
argValues: [epubBytes, fullData],
apiImpl: this,
),
);
}
TaskConstMeta get kCrateApiEpubParseEpubFromBytesConstMeta =>
const TaskConstMeta(
debugName: "parse_epub_from_bytes",
argNames: ["epubBytes", "fullData"],
);
@override
Future<EpubNovel> crateApiEpubParseEpubFromPath({
required String epubPath,
required bool fullData,
}) {
return handler.executeNormal(
NormalTask(
callFfi: (port_) {
final serializer = SseSerializer(generalizedFrbRustBinding);
sse_encode_String(epubPath, serializer);
sse_encode_bool(fullData, serializer);
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 10,
port: port_,
);
},
codec: SseCodec(
decodeSuccessData: sse_decode_epub_novel,
decodeErrorData: sse_decode_String,
),
constMeta: kCrateApiEpubParseEpubFromPathConstMeta,
argValues: [epubPath, fullData],
apiImpl: this,
),
);
}
TaskConstMeta get kCrateApiEpubParseEpubFromPathConstMeta =>
const TaskConstMeta(
debugName: "parse_epub_from_path",
argNames: ["epubPath", "fullData"],
);
@override
Uint8List crateApiImageProcessCropImage({required List<int> image}) {
return handler.executeSync(
@ -419,7 +540,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
callFfi: () {
final serializer = SseSerializer(generalizedFrbRustBinding);
sse_encode_list_prim_u_8_loose(image, serializer);
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 8)!;
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 11)!;
},
codec: SseCodec(
decodeSuccessData: sse_decode_list_prim_u_8_strict,
@ -447,7 +568,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 9,
funcId: 12,
port: port_,
);
},
@ -475,7 +596,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
callFfi: () {
final serializer = SseSerializer(generalizedFrbRustBinding);
sse_encode_box_autoadd_client_settings(settings, serializer);
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 10)!;
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 13)!;
},
codec: SseCodec(
decodeSuccessData:
@ -967,6 +1088,49 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
);
}
@protected
EpubChapter dco_decode_epub_chapter(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
final arr = raw as List<dynamic>;
if (arr.length != 3)
throw Exception('unexpected arr length: expect 3 but see ${arr.length}');
return EpubChapter(
name: dco_decode_String(arr[0]),
content: dco_decode_String(arr[1]),
path: dco_decode_String(arr[2]),
);
}
@protected
EpubNovel dco_decode_epub_novel(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
final arr = raw as List<dynamic>;
if (arr.length != 8)
throw Exception('unexpected arr length: expect 8 but see ${arr.length}');
return EpubNovel(
name: dco_decode_String(arr[0]),
cover: dco_decode_opt_list_prim_u_8_strict(arr[1]),
summary: dco_decode_opt_String(arr[2]),
author: dco_decode_opt_String(arr[3]),
artist: dco_decode_opt_String(arr[4]),
chapters: dco_decode_list_epub_chapter(arr[5]),
images: dco_decode_list_epub_resource(arr[6]),
stylesheets: dco_decode_list_epub_resource(arr[7]),
);
}
@protected
EpubResource dco_decode_epub_resource(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
final arr = raw as List<dynamic>;
if (arr.length != 2)
throw Exception('unexpected arr length: expect 2 but see ${arr.length}');
return EpubResource(
name: dco_decode_String(arr[0]),
content: dco_decode_list_prim_u_8_strict(arr[1]),
);
}
@protected
HttpHeaders dco_decode_http_headers(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
@ -1051,6 +1215,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
return (raw as List<dynamic>).map(dco_decode_custom_proxy).toList();
}
@protected
List<EpubChapter> dco_decode_list_epub_chapter(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
return (raw as List<dynamic>).map(dco_decode_epub_chapter).toList();
}
@protected
List<EpubResource> dco_decode_list_epub_resource(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
return (raw as List<dynamic>).map(dco_decode_epub_resource).toList();
}
@protected
List<Uint8List> dco_decode_list_list_prim_u_8_strict(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
@ -1657,6 +1833,46 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
return CustomProxy(url: var_url, condition: var_condition);
}
@protected
EpubChapter sse_decode_epub_chapter(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
var var_name = sse_decode_String(deserializer);
var var_content = sse_decode_String(deserializer);
var var_path = sse_decode_String(deserializer);
return EpubChapter(name: var_name, content: var_content, path: var_path);
}
@protected
EpubNovel sse_decode_epub_novel(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
var var_name = sse_decode_String(deserializer);
var var_cover = sse_decode_opt_list_prim_u_8_strict(deserializer);
var var_summary = sse_decode_opt_String(deserializer);
var var_author = sse_decode_opt_String(deserializer);
var var_artist = sse_decode_opt_String(deserializer);
var var_chapters = sse_decode_list_epub_chapter(deserializer);
var var_images = sse_decode_list_epub_resource(deserializer);
var var_stylesheets = sse_decode_list_epub_resource(deserializer);
return EpubNovel(
name: var_name,
cover: var_cover,
summary: var_summary,
author: var_author,
artist: var_artist,
chapters: var_chapters,
images: var_images,
stylesheets: var_stylesheets,
);
}
@protected
EpubResource sse_decode_epub_resource(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
var var_name = sse_decode_String(deserializer);
var var_content = sse_decode_list_prim_u_8_strict(deserializer);
return EpubResource(name: var_name, content: var_content);
}
@protected
HttpHeaders sse_decode_http_headers(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
@ -1764,6 +1980,32 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
return ans_;
}
@protected
List<EpubChapter> sse_decode_list_epub_chapter(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
var len_ = sse_decode_i_32(deserializer);
var ans_ = <EpubChapter>[];
for (var idx_ = 0; idx_ < len_; ++idx_) {
ans_.add(sse_decode_epub_chapter(deserializer));
}
return ans_;
}
@protected
List<EpubResource> sse_decode_list_epub_resource(
SseDeserializer deserializer,
) {
// Codec=Sse (Serialization based), see doc to use other codecs
var len_ = sse_decode_i_32(deserializer);
var ans_ = <EpubResource>[];
for (var idx_ = 0; idx_ < len_; ++idx_) {
ans_.add(sse_decode_epub_resource(deserializer));
}
return ans_;
}
@protected
List<Uint8List> sse_decode_list_list_prim_u_8_strict(
SseDeserializer deserializer,
@ -2591,6 +2833,34 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
sse_encode_proxy_condition(self.condition, serializer);
}
@protected
void sse_encode_epub_chapter(EpubChapter self, SseSerializer serializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
sse_encode_String(self.name, serializer);
sse_encode_String(self.content, serializer);
sse_encode_String(self.path, serializer);
}
@protected
void sse_encode_epub_novel(EpubNovel self, SseSerializer serializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
sse_encode_String(self.name, serializer);
sse_encode_opt_list_prim_u_8_strict(self.cover, serializer);
sse_encode_opt_String(self.summary, serializer);
sse_encode_opt_String(self.author, serializer);
sse_encode_opt_String(self.artist, serializer);
sse_encode_list_epub_chapter(self.chapters, serializer);
sse_encode_list_epub_resource(self.images, serializer);
sse_encode_list_epub_resource(self.stylesheets, serializer);
}
@protected
void sse_encode_epub_resource(EpubResource self, SseSerializer serializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
sse_encode_String(self.name, serializer);
sse_encode_list_prim_u_8_strict(self.content, serializer);
}
@protected
void sse_encode_http_headers(HttpHeaders self, SseSerializer serializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
@ -2682,6 +2952,30 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
}
}
@protected
void sse_encode_list_epub_chapter(
List<EpubChapter> self,
SseSerializer serializer,
) {
// Codec=Sse (Serialization based), see doc to use other codecs
sse_encode_i_32(self.length, serializer);
for (final item in self) {
sse_encode_epub_chapter(item, serializer);
}
}
@protected
void sse_encode_list_epub_resource(
List<EpubResource> self,
SseSerializer serializer,
) {
// Codec=Sse (Serialization based), see doc to use other codecs
sse_encode_i_32(self.length, serializer);
for (final item in self) {
sse_encode_epub_resource(item, serializer);
}
}
@protected
void sse_encode_list_list_prim_u_8_strict(
List<Uint8List> self,

View file

@ -3,6 +3,7 @@
// 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/epub.dart';
import 'api/image.dart';
import 'api/rhttp/client.dart';
import 'api/rhttp/error.dart';
@ -187,6 +188,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@protected
CustomProxy dco_decode_custom_proxy(dynamic raw);
@protected
EpubChapter dco_decode_epub_chapter(dynamic raw);
@protected
EpubNovel dco_decode_epub_novel(dynamic raw);
@protected
EpubResource dco_decode_epub_resource(dynamic raw);
@protected
HttpHeaders dco_decode_http_headers(dynamic raw);
@ -217,6 +227,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@protected
List<CustomProxy> dco_decode_list_custom_proxy(dynamic raw);
@protected
List<EpubChapter> dco_decode_list_epub_chapter(dynamic raw);
@protected
List<EpubResource> dco_decode_list_epub_resource(dynamic raw);
@protected
List<Uint8List> dco_decode_list_list_prim_u_8_strict(dynamic raw);
@ -470,6 +486,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@protected
CustomProxy sse_decode_custom_proxy(SseDeserializer deserializer);
@protected
EpubChapter sse_decode_epub_chapter(SseDeserializer deserializer);
@protected
EpubNovel sse_decode_epub_novel(SseDeserializer deserializer);
@protected
EpubResource sse_decode_epub_resource(SseDeserializer deserializer);
@protected
HttpHeaders sse_decode_http_headers(SseDeserializer deserializer);
@ -500,6 +525,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@protected
List<CustomProxy> sse_decode_list_custom_proxy(SseDeserializer deserializer);
@protected
List<EpubChapter> sse_decode_list_epub_chapter(SseDeserializer deserializer);
@protected
List<EpubResource> sse_decode_list_epub_resource(
SseDeserializer deserializer,
);
@protected
List<Uint8List> sse_decode_list_list_prim_u_8_strict(
SseDeserializer deserializer,
@ -849,6 +882,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@protected
void sse_encode_custom_proxy(CustomProxy self, SseSerializer serializer);
@protected
void sse_encode_epub_chapter(EpubChapter self, SseSerializer serializer);
@protected
void sse_encode_epub_novel(EpubNovel self, SseSerializer serializer);
@protected
void sse_encode_epub_resource(EpubResource self, SseSerializer serializer);
@protected
void sse_encode_http_headers(HttpHeaders self, SseSerializer serializer);
@ -885,6 +927,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
SseSerializer serializer,
);
@protected
void sse_encode_list_epub_chapter(
List<EpubChapter> self,
SseSerializer serializer,
);
@protected
void sse_encode_list_epub_resource(
List<EpubResource> self,
SseSerializer serializer,
);
@protected
void sse_encode_list_list_prim_u_8_strict(
List<Uint8List> self,

View file

@ -6,6 +6,7 @@
// Static analysis wrongly picks the IO variant, thus ignore this
// ignore_for_file: argument_type_not_assignable
import 'api/epub.dart';
import 'api/image.dart';
import 'api/rhttp/client.dart';
import 'api/rhttp/error.dart';
@ -189,6 +190,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@protected
CustomProxy dco_decode_custom_proxy(dynamic raw);
@protected
EpubChapter dco_decode_epub_chapter(dynamic raw);
@protected
EpubNovel dco_decode_epub_novel(dynamic raw);
@protected
EpubResource dco_decode_epub_resource(dynamic raw);
@protected
HttpHeaders dco_decode_http_headers(dynamic raw);
@ -219,6 +229,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@protected
List<CustomProxy> dco_decode_list_custom_proxy(dynamic raw);
@protected
List<EpubChapter> dco_decode_list_epub_chapter(dynamic raw);
@protected
List<EpubResource> dco_decode_list_epub_resource(dynamic raw);
@protected
List<Uint8List> dco_decode_list_list_prim_u_8_strict(dynamic raw);
@ -472,6 +488,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@protected
CustomProxy sse_decode_custom_proxy(SseDeserializer deserializer);
@protected
EpubChapter sse_decode_epub_chapter(SseDeserializer deserializer);
@protected
EpubNovel sse_decode_epub_novel(SseDeserializer deserializer);
@protected
EpubResource sse_decode_epub_resource(SseDeserializer deserializer);
@protected
HttpHeaders sse_decode_http_headers(SseDeserializer deserializer);
@ -502,6 +527,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@protected
List<CustomProxy> sse_decode_list_custom_proxy(SseDeserializer deserializer);
@protected
List<EpubChapter> sse_decode_list_epub_chapter(SseDeserializer deserializer);
@protected
List<EpubResource> sse_decode_list_epub_resource(
SseDeserializer deserializer,
);
@protected
List<Uint8List> sse_decode_list_list_prim_u_8_strict(
SseDeserializer deserializer,
@ -851,6 +884,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@protected
void sse_encode_custom_proxy(CustomProxy self, SseSerializer serializer);
@protected
void sse_encode_epub_chapter(EpubChapter self, SseSerializer serializer);
@protected
void sse_encode_epub_novel(EpubNovel self, SseSerializer serializer);
@protected
void sse_encode_epub_resource(EpubResource self, SseSerializer serializer);
@protected
void sse_encode_http_headers(HttpHeaders self, SseSerializer serializer);
@ -887,6 +929,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
SseSerializer serializer,
);
@protected
void sse_encode_list_epub_chapter(
List<EpubChapter> self,
SseSerializer serializer,
);
@protected
void sse_encode_list_epub_resource(
List<EpubResource> self,
SseSerializer serializer,
);
@protected
void sse_encode_list_list_prim_u_8_strict(
List<Uint8List> self,

View file

@ -378,15 +378,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.0.3"
epubx:
dependency: "direct main"
description:
path: "."
ref: dev
resolved-ref: c8203a489fae5683001556b1d323e35f356294fb
url: "https://github.com/kodjodevf/epubx.dart.git"
source: git
version: "4.0.3"
expressions:
dependency: transitive
description:

View file

@ -87,10 +87,6 @@ dependencies:
protobuf: ^5.0.0
device_info_plus: ^12.2.0
marquee: ^2.2.3
epubx:
git:
url: https://github.com/kodjodevf/epubx.dart.git
ref: dev
d4rt: ^0.1.9
hive: ^2.2.3
hive_flutter: ^1.1.0

476
rust/Cargo.lock generated
View file

@ -23,6 +23,17 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "aes"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
]
[[package]]
name = "aho-corasick"
version = "1.1.2"
@ -99,9 +110,12 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "arbitrary"
version = "1.3.2"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
dependencies = [
"derive_arbitrary",
]
[[package]]
name = "arg_enum_proc_macro"
@ -258,9 +272,9 @@ checksum = "c6a6c0b39c38fd754ac338b00a88066436389c0f029da5d37d1e01091d9b7c17"
[[package]]
name = "bumpalo"
version = "3.14.0"
version = "3.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
[[package]]
name = "bytemuck"
@ -286,6 +300,15 @@ version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
[[package]]
name = "bzip2"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c"
dependencies = [
"libbz2-rs-sys",
]
[[package]]
name = "cc"
version = "1.0.83"
@ -325,6 +348,16 @@ dependencies = [
"windows-link 0.2.1",
]
[[package]]
name = "cipher"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"crypto-common",
"inout",
]
[[package]]
name = "color_quant"
version = "1.1.0"
@ -341,6 +374,12 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "constant_time_eq"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
@ -348,10 +387,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "crc32fast"
version = "1.4.2"
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
dependencies = [
"libc",
]
[[package]]
name = "crc"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675"
dependencies = [
"crc-catalog",
]
[[package]]
name = "crc-catalog"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
[[package]]
name = "crc32fast"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
dependencies = [
"cfg-if",
]
@ -419,6 +482,12 @@ dependencies = [
"parking_lot_core",
]
[[package]]
name = "deflate64"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26bf8fc351c5ed29b5c2f0cbbac1b209b74f60ecd62e675a998df72c49af5204"
[[package]]
name = "delegate-attr"
version = "0.3.0"
@ -430,6 +499,26 @@ dependencies = [
"syn",
]
[[package]]
name = "deranged"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587"
dependencies = [
"powerfmt",
]
[[package]]
name = "derive_arbitrary"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "digest"
version = "0.10.7"
@ -438,6 +527,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
@ -465,6 +555,19 @@ dependencies = [
"regex",
]
[[package]]
name = "epub"
version = "2.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95518004c0a638e03a17589d2d336b7c936d92184d81bf1e66d3b1555de89f2d"
dependencies = [
"percent-encoding",
"regex",
"thiserror 2.0.18",
"xml-rs",
"zip 3.0.0",
]
[[package]]
name = "equivalent"
version = "1.0.1"
@ -523,6 +626,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
dependencies = [
"crc32fast",
"libz-rs-sys",
"miniz_oxide 0.8.9",
]
@ -703,6 +807,20 @@ dependencies = [
"wasi",
]
[[package]]
name = "getrandom"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"r-efi",
"wasip2",
"wasm-bindgen",
]
[[package]]
name = "gif"
version = "0.13.1"
@ -772,6 +890,15 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
]
[[package]]
name = "http"
version = "1.1.0"
@ -953,6 +1080,15 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "inout"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
dependencies = [
"generic-array",
]
[[package]]
name = "interpolate_name"
version = "0.2.4"
@ -1016,6 +1152,12 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
[[package]]
name = "libbz2-rs-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7"
[[package]]
name = "libc"
version = "0.2.177"
@ -1033,6 +1175,15 @@ dependencies = [
"once_cell",
]
[[package]]
name = "libz-rs-sys"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c10501e7805cee23da17c7790e59df2870c0d4043ec6d03f67d31e2b53e77415"
dependencies = [
"zlib-rs",
]
[[package]]
name = "lock_api"
version = "0.4.12"
@ -1045,9 +1196,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.20"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "loop9"
@ -1058,6 +1209,16 @@ dependencies = [
"imgref",
]
[[package]]
name = "lzma-rust2"
version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1670343e58806300d87950e3401e820b519b9384281bbabfb15e3636689ffd69"
dependencies = [
"crc",
"sha2",
]
[[package]]
name = "maybe-rayon"
version = "0.1.1"
@ -1080,9 +1241,9 @@ dependencies = [
[[package]]
name = "memchr"
version = "2.6.4"
version = "2.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
[[package]]
name = "mime"
@ -1179,6 +1340,12 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-conv"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050"
[[package]]
name = "num-derive"
version = "0.4.2"
@ -1285,10 +1452,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "percent-encoding"
version = "2.3.1"
name = "pbkdf2"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [
"digest",
"hmac",
]
[[package]]
name = "percent-encoding"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "pin-project-lite"
@ -1327,6 +1504,18 @@ version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2"
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "ppmd-rust"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efca4c95a19a79d1c98f791f10aebd5c1363b473244630bb7dbde1dc98455a24"
[[package]]
name = "ppv-lite86"
version = "0.2.17"
@ -1335,9 +1524,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.84"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
@ -1398,7 +1587,7 @@ dependencies = [
"rustc-hash",
"rustls",
"socket2 0.5.9",
"thiserror",
"thiserror 1.0.63",
"tokio",
"tracing",
]
@ -1415,7 +1604,7 @@ dependencies = [
"rustc-hash",
"rustls",
"slab",
"thiserror",
"thiserror 1.0.63",
"tinyvec",
"tracing",
]
@ -1442,6 +1631,12 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "r-efi"
version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "rand"
version = "0.8.5"
@ -1469,7 +1664,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
"getrandom 0.2.14",
]
[[package]]
@ -1502,7 +1697,7 @@ dependencies = [
"rand_chacha",
"simd_helpers",
"system-deps",
"thiserror",
"thiserror 1.0.63",
"v_frame",
"wasm-bindgen",
]
@ -1553,9 +1748,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.10.6"
version = "1.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
dependencies = [
"aho-corasick",
"memchr",
@ -1565,9 +1760,9 @@ dependencies = [
[[package]]
name = "regex-automata"
version = "0.4.7"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
dependencies = [
"aho-corasick",
"memchr",
@ -1576,9 +1771,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.8.2"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
[[package]]
name = "reqwest"
@ -1644,7 +1839,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
dependencies = [
"cc",
"cfg-if",
"getrandom",
"getrandom 0.2.14",
"libc",
"spin",
"untrusted",
@ -1656,12 +1851,14 @@ name = "rust_lib_mangayomi"
version = "0.1.0"
dependencies = [
"chrono",
"epub",
"flutter_rust_bridge",
"futures-util",
"image",
"reqwest",
"tokio",
"tokio-util",
"zip 7.2.0",
]
[[package]]
@ -1737,18 +1934,27 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.209"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.209"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
@ -1788,6 +1994,28 @@ dependencies = [
"serde",
]
[[package]]
name = "sha1"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sha2"
version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.2"
@ -1864,9 +2092,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.77"
version = "2.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
dependencies = [
"proc-macro2",
"quote",
@ -1907,7 +2135,16 @@ version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
dependencies = [
"thiserror-impl",
"thiserror-impl 1.0.63",
]
[[package]]
name = "thiserror"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
dependencies = [
"thiserror-impl 2.0.18",
]
[[package]]
@ -1921,6 +2158,17 @@ dependencies = [
"syn",
]
[[package]]
name = "thiserror-impl"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "threadpool"
version = "1.8.1"
@ -1944,6 +2192,26 @@ dependencies = [
"zune-jpeg",
]
[[package]]
name = "time"
version = "0.3.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9da98b7d9b7dad93488a84b8248efc35352b0b2657397d4167e7ad67e5d535e5"
dependencies = [
"deranged",
"js-sys",
"num-conv",
"powerfmt",
"serde_core",
"time-core",
]
[[package]]
name = "time-core"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
[[package]]
name = "tinyvec"
version = "1.8.0"
@ -2006,7 +2274,7 @@ checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f"
dependencies = [
"either",
"futures-util",
"thiserror",
"thiserror 1.0.63",
"tokio",
]
@ -2109,6 +2377,12 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "typed-path"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e43ffa54726cdc9ea78392023ffe9fe9cf9ac779e1c6fcb0d23f9862e3879d20"
[[package]]
name = "typenum"
version = "1.17.0"
@ -2200,6 +2474,15 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasip2"
version = "1.0.2+wasi-0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
dependencies = [
"wit-bindgen",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.100"
@ -2532,11 +2815,134 @@ dependencies = [
"memchr",
]
[[package]]
name = "wit-bindgen"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
[[package]]
name = "xml"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8aa498d22c9bbaf482329839bc5620c46be275a19a812e9a22a2b07529a642a"
[[package]]
name = "xml-rs"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3a56132a0d6ecbe77352edc10232f788fc4ceefefff4cab784a98e0e16b6b51"
dependencies = [
"xml",
]
[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
dependencies = [
"zeroize_derive",
]
[[package]]
name = "zeroize_derive"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "zip"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12598812502ed0105f607f941c386f43d441e00148fce9dec3ca5ffb0bde9308"
dependencies = [
"arbitrary",
"crc32fast",
"flate2",
"indexmap",
"memchr",
"zopfli",
]
[[package]]
name = "zip"
version = "7.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c42e33efc22a0650c311c2ef19115ce232583abbe80850bc8b66509ebef02de0"
dependencies = [
"aes",
"bzip2",
"constant_time_eq",
"crc32fast",
"deflate64",
"flate2",
"generic-array",
"getrandom 0.3.4",
"hmac",
"indexmap",
"lzma-rust2",
"memchr",
"pbkdf2",
"ppmd-rust",
"sha1",
"time",
"typed-path",
"zeroize",
"zopfli",
"zstd",
]
[[package]]
name = "zlib-rs"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3"
[[package]]
name = "zopfli"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7"
dependencies = [
"bumpalo",
"crc32fast",
"log",
"simd-adler32",
]
[[package]]
name = "zstd"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
version = "7.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
dependencies = [
"zstd-sys",
]
[[package]]
name = "zstd-sys"
version = "2.0.16+zstd.1.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748"
dependencies = [
"cc",
"pkg-config",
]
[[package]]
name = "zune-core"

View file

@ -14,3 +14,5 @@ futures-util = "0.3.31"
reqwest = { version = "0.12.15", default-features = false, features = ["charset", "http2", "rustls-tls-webpki-roots", "stream", "multipart", "socks", "brotli", "gzip"] }
tokio = { version = "1.47.1", features = ["full"] }
tokio-util = "0.7.16"
epub = "2.1.5"
zip = "7.2.0"

213
rust/src/api/epub.rs Normal file
View file

@ -0,0 +1,213 @@
use epub::doc::EpubDoc;
use std::fs;
use std::io::{Cursor, Read, Seek};
use std::path::Path;
use zip::ZipArchive;
#[derive(Debug, Clone)]
pub struct EpubChapter {
pub name: String,
pub content: String,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct EpubResource {
pub name: String,
pub content: Vec<u8>,
}
#[derive(Debug, Clone)]
pub struct EpubNovel {
pub name: String,
pub cover: Option<Vec<u8>>,
pub summary: Option<String>,
pub author: Option<String>,
pub artist: Option<String>,
pub chapters: Vec<EpubChapter>,
pub images: Vec<EpubResource>,
pub stylesheets: Vec<EpubResource>,
}
pub fn parse_epub_from_path(epub_path: String, full_data: bool) -> Result<EpubNovel, String> {
let path = Path::new(&epub_path);
if !path.exists() {
return Err(format!("EPUB file not found: {}", epub_path));
}
// Open EPUB file
let mut doc = EpubDoc::new(&epub_path).map_err(|e| format!("Failed to open EPUB: {}", e))?;
// Parse using common logic
parse_epub_with_doc(&mut doc, Some(&epub_path), None, full_data)
}
pub fn parse_epub_from_bytes(epub_bytes: Vec<u8>, full_data: bool) -> Result<EpubNovel, String> {
let cursor = Cursor::new(epub_bytes.clone());
// Try to parse as ZIP archive first to extract metadata
let mut doc =
EpubDoc::from_reader(cursor).map_err(|e| format!("Failed to parse EPUB: {}", e))?;
// Parse using common logic (no file path available for resource extraction)
parse_epub_with_doc(&mut doc, None, Some(epub_bytes), full_data)
}
/// Internal function to parse EPUB from EpubDoc
/// Handles both file path and bytes sources
fn parse_epub_with_doc<R: Read + Seek>(
doc: &mut EpubDoc<R>,
epub_path: Option<&str>,
epub_bytes: Option<Vec<u8>>,
full_data: bool,
) -> Result<EpubNovel, String> {
// Extract metadata
let name = doc
.mdata("title")
.map(|m| m.value.clone())
.unwrap_or_else(|| "Untitled".to_string());
let author = doc.mdata("creator").map(|m| m.value.clone());
let artist = doc.mdata("contributor").map(|m| m.value.clone());
let summary = doc.mdata("description").map(|m| m.value.clone());
// Extract cover
let cover = doc.get_cover().map(|(data, _mime)| data);
// Only extract chapters, cover, and resources if full_data is true
let (chapters, images, stylesheets) = if full_data {
// Extract chapters from spine with real names from TOC
let spine = doc.spine.clone();
let toc = doc.toc.clone();
let chapters: Vec<EpubChapter> = spine
.iter()
.enumerate()
.map(|(idx, item)| {
let content = doc
.get_resource_str(&item.idref)
.map(|(c, _)| c)
.unwrap_or_default();
// Try to find chapter name from TOC
let chapter_name = find_chapter_name_from_toc(&toc, &item.idref)
.unwrap_or_else(|| format!("Chapter {}", idx + 1));
EpubChapter {
name: chapter_name,
content,
path: item.idref.clone(),
}
})
.collect();
// Extract resources with content only if we have a file path
let (stylesheets, images) = if let Some(path) = epub_path {
extract_resources_with_content(path).unwrap_or_else(|_| (vec![], vec![]))
} else {
extract_resources_with_content_from_bytes(epub_bytes.unwrap_or_default())
.unwrap_or_else(|_| (vec![], vec![]))
};
(chapters, images, stylesheets)
} else {
// Only metadata, no full data
(vec![], vec![], vec![])
};
Ok(EpubNovel {
name,
cover,
summary,
author,
artist,
chapters,
images,
stylesheets,
})
}
/// Extract CSS and image files with their binary content from EPUB (file path version)
fn extract_resources_with_content(
epub_path: &str,
) -> Result<(Vec<EpubResource>, Vec<EpubResource>), String> {
let file = fs::File::open(epub_path).map_err(|e| format!("Cannot open EPUB file: {}", e))?;
let archive = ZipArchive::new(file).map_err(|e| format!("Invalid ZIP archive: {}", e))?;
extract_resources_from_archive(archive)
}
/// Extract CSS and image files with their binary content from EPUB (bytes version)
fn extract_resources_with_content_from_bytes(
epub_bytes: Vec<u8>,
) -> Result<(Vec<EpubResource>, Vec<EpubResource>), String> {
let cursor = Cursor::new(epub_bytes);
let archive = ZipArchive::new(cursor).map_err(|e| format!("Invalid ZIP archive: {}", e))?;
extract_resources_from_archive(archive)
}
/// Internal function to extract resources from a ZipArchive
fn extract_resources_from_archive<R: Read + Seek>(
mut archive: ZipArchive<R>,
) -> Result<(Vec<EpubResource>, Vec<EpubResource>), String> {
let mut stylesheets = Vec::new();
let mut images = Vec::new();
for i in 0..archive.len() {
let mut file = archive
.by_index(i)
.map_err(|e| format!("Cannot read archive entry: {}", e))?;
let name = file.name().to_string();
if name.ends_with(".css") {
let mut content = Vec::new();
file.read_to_end(&mut content)
.map_err(|e| format!("Cannot read CSS file: {}", e))?;
stylesheets.push(EpubResource { name, content });
} else if name.ends_with(".jpg")
|| name.ends_with(".jpeg")
|| name.ends_with(".png")
|| name.ends_with(".gif")
|| name.ends_with(".svg")
|| name.ends_with(".webp")
{
let mut content = Vec::new();
file.read_to_end(&mut content)
.map_err(|e| format!("Cannot read image file: {}", e))?;
images.push(EpubResource { name, content });
}
}
Ok((stylesheets, images))
}
/// Helper function to find chapter name from TOC by resource ID
/// Recursively searches through navigation points to match the chapter ID
fn find_chapter_name_from_toc(toc: &[epub::doc::NavPoint], resource_id: &str) -> Option<String> {
for nav_point in toc {
let path_str = nav_point.content.to_string_lossy();
// Check if this TOC entry matches the resource ID
if path_str.contains(resource_id) || path_str.ends_with(&format!("{}.xhtml", resource_id)) {
return Some(nav_point.label.clone());
}
// Recursively search in children
if let Some(found_name) = find_chapter_name_from_toc(&nav_point.children, resource_id) {
return Some(found_name);
}
}
None
}
/// Get chapter content from EPUB by path
pub fn get_chapter_content(epub_path: String, chapter_path: String) -> Result<String, String> {
let mut doc = EpubDoc::new(&epub_path).map_err(|e| format!("Failed to open EPUB: {}", e))?;
// Find and get the chapter content
let (content, _mime) = doc
.get_resource_str(&chapter_path)
.ok_or_else(|| format!("Failed to read chapter: {}", chapter_path))?;
Ok(content)
}

View file

@ -2,5 +2,8 @@
// Do not put code in `mod.rs`, but put in e.g. `simple.rs`.
//
pub mod epub;
pub mod image;
pub mod rhttp;
pub mod rhttp;
pub use epub::{EpubChapter, EpubNovel, EpubResource};

View file

@ -39,7 +39,7 @@ flutter_rust_bridge::frb_generated_boilerplate!(
default_rust_auto_opaque = RustAutoOpaqueMoi,
);
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.11.1";
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 885218533;
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 2140434025;
// Section: executor
@ -251,6 +251,41 @@ fn wire__crate__api__rhttp__client__create_static_resolver_sync_impl(
},
)
}
fn wire__crate__api__epub__get_chapter_content_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len_: i32,
data_len_: i32,
) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec, _, _>(
flutter_rust_bridge::for_generated::TaskInfo {
debug_name: "get_chapter_content",
port: Some(port_),
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
},
move || {
let message = unsafe {
flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(
ptr_,
rust_vec_len_,
data_len_,
)
};
let mut deserializer =
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
let api_epub_path = <String>::sse_decode(&mut deserializer);
let api_chapter_path = <String>::sse_decode(&mut deserializer);
deserializer.end();
move |context| {
transform_result_sse::<_, String>((move || {
let output_ok =
crate::api::epub::get_chapter_content(api_epub_path, api_chapter_path)?;
Ok(output_ok)
})())
}
},
)
}
fn wire__crate__api__rhttp__http__make_http_request_receive_stream_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
@ -277,6 +312,76 @@ let api_cancelable = <bool>::sse_decode(&mut deserializer);deserializer.end(); m
})().await)
} })
}
fn wire__crate__api__epub__parse_epub_from_bytes_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len_: i32,
data_len_: i32,
) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec, _, _>(
flutter_rust_bridge::for_generated::TaskInfo {
debug_name: "parse_epub_from_bytes",
port: Some(port_),
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
},
move || {
let message = unsafe {
flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(
ptr_,
rust_vec_len_,
data_len_,
)
};
let mut deserializer =
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
let api_epub_bytes = <Vec<u8>>::sse_decode(&mut deserializer);
let api_full_data = <bool>::sse_decode(&mut deserializer);
deserializer.end();
move |context| {
transform_result_sse::<_, String>((move || {
let output_ok =
crate::api::epub::parse_epub_from_bytes(api_epub_bytes, api_full_data)?;
Ok(output_ok)
})())
}
},
)
}
fn wire__crate__api__epub__parse_epub_from_path_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len_: i32,
data_len_: i32,
) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec, _, _>(
flutter_rust_bridge::for_generated::TaskInfo {
debug_name: "parse_epub_from_path",
port: Some(port_),
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
},
move || {
let message = unsafe {
flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(
ptr_,
rust_vec_len_,
data_len_,
)
};
let mut deserializer =
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
let api_epub_path = <String>::sse_decode(&mut deserializer);
let api_full_data = <bool>::sse_decode(&mut deserializer);
deserializer.end();
move |context| {
transform_result_sse::<_, String>((move || {
let output_ok =
crate::api::epub::parse_epub_from_path(api_epub_path, api_full_data)?;
Ok(output_ok)
})())
}
},
)
}
fn wire__crate__api__image__process_crop_image_impl(
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len_: i32,
@ -708,6 +813,56 @@ impl SseDecode for crate::api::rhttp::client::CustomProxy {
}
}
impl SseDecode for crate::api::epub::EpubChapter {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
let mut var_name = <String>::sse_decode(deserializer);
let mut var_content = <String>::sse_decode(deserializer);
let mut var_path = <String>::sse_decode(deserializer);
return crate::api::epub::EpubChapter {
name: var_name,
content: var_content,
path: var_path,
};
}
}
impl SseDecode for crate::api::epub::EpubNovel {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
let mut var_name = <String>::sse_decode(deserializer);
let mut var_cover = <Option<Vec<u8>>>::sse_decode(deserializer);
let mut var_summary = <Option<String>>::sse_decode(deserializer);
let mut var_author = <Option<String>>::sse_decode(deserializer);
let mut var_artist = <Option<String>>::sse_decode(deserializer);
let mut var_chapters = <Vec<crate::api::epub::EpubChapter>>::sse_decode(deserializer);
let mut var_images = <Vec<crate::api::epub::EpubResource>>::sse_decode(deserializer);
let mut var_stylesheets = <Vec<crate::api::epub::EpubResource>>::sse_decode(deserializer);
return crate::api::epub::EpubNovel {
name: var_name,
cover: var_cover,
summary: var_summary,
author: var_author,
artist: var_artist,
chapters: var_chapters,
images: var_images,
stylesheets: var_stylesheets,
};
}
}
impl SseDecode for crate::api::epub::EpubResource {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
let mut var_name = <String>::sse_decode(deserializer);
let mut var_content = <Vec<u8>>::sse_decode(deserializer);
return crate::api::epub::EpubResource {
name: var_name,
content: var_content,
};
}
}
impl SseDecode for crate::api::rhttp::http::HttpHeaders {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
@ -848,6 +1003,30 @@ impl SseDecode for Vec<crate::api::rhttp::client::CustomProxy> {
}
}
impl SseDecode for Vec<crate::api::epub::EpubChapter> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
let mut len_ = <i32>::sse_decode(deserializer);
let mut ans_ = vec![];
for idx_ in 0..len_ {
ans_.push(<crate::api::epub::EpubChapter>::sse_decode(deserializer));
}
return ans_;
}
}
impl SseDecode for Vec<crate::api::epub::EpubResource> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
let mut len_ = <i32>::sse_decode(deserializer);
let mut ans_ = vec![];
for idx_ in 0..len_ {
ans_.push(<crate::api::epub::EpubResource>::sse_decode(deserializer));
}
return ans_;
}
}
impl SseDecode for Vec<Vec<u8>> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
@ -1292,13 +1471,18 @@ fn pde_ffi_dispatcher_primary_impl(
rust_vec_len,
data_len,
),
7 => wire__crate__api__rhttp__http__make_http_request_receive_stream_impl(
7 => wire__crate__api__epub__get_chapter_content_impl(port, ptr, rust_vec_len, data_len),
8 => wire__crate__api__rhttp__http__make_http_request_receive_stream_impl(
port,
ptr,
rust_vec_len,
data_len,
),
9 => wire__crate__api__rhttp__http__register_client_impl(port, ptr, rust_vec_len, data_len),
9 => wire__crate__api__epub__parse_epub_from_bytes_impl(port, ptr, rust_vec_len, data_len),
10 => wire__crate__api__epub__parse_epub_from_path_impl(port, ptr, rust_vec_len, data_len),
12 => {
wire__crate__api__rhttp__http__register_client_impl(port, ptr, rust_vec_len, data_len)
}
_ => unreachable!(),
}
}
@ -1321,8 +1505,8 @@ fn pde_ffi_dispatcher_sync_impl(
rust_vec_len,
data_len,
),
8 => wire__crate__api__image__process_crop_image_impl(ptr, rust_vec_len, data_len),
10 => wire__crate__api__rhttp__http__register_client_sync_impl(ptr, rust_vec_len, data_len),
11 => wire__crate__api__image__process_crop_image_impl(ptr, rust_vec_len, data_len),
13 => wire__crate__api__rhttp__http__register_client_sync_impl(ptr, rust_vec_len, data_len),
_ => unreachable!(),
}
}
@ -1442,6 +1626,70 @@ impl flutter_rust_bridge::IntoIntoDart<crate::api::rhttp::client::CustomProxy>
}
}
// Codec=Dco (DartCObject based), see doc to use other codecs
impl flutter_rust_bridge::IntoDart for crate::api::epub::EpubChapter {
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
[
self.name.into_into_dart().into_dart(),
self.content.into_into_dart().into_dart(),
self.path.into_into_dart().into_dart(),
]
.into_dart()
}
}
impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::epub::EpubChapter {}
impl flutter_rust_bridge::IntoIntoDart<crate::api::epub::EpubChapter>
for crate::api::epub::EpubChapter
{
fn into_into_dart(self) -> crate::api::epub::EpubChapter {
self
}
}
// Codec=Dco (DartCObject based), see doc to use other codecs
impl flutter_rust_bridge::IntoDart for crate::api::epub::EpubNovel {
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
[
self.name.into_into_dart().into_dart(),
self.cover.into_into_dart().into_dart(),
self.summary.into_into_dart().into_dart(),
self.author.into_into_dart().into_dart(),
self.artist.into_into_dart().into_dart(),
self.chapters.into_into_dart().into_dart(),
self.images.into_into_dart().into_dart(),
self.stylesheets.into_into_dart().into_dart(),
]
.into_dart()
}
}
impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::epub::EpubNovel {}
impl flutter_rust_bridge::IntoIntoDart<crate::api::epub::EpubNovel>
for crate::api::epub::EpubNovel
{
fn into_into_dart(self) -> crate::api::epub::EpubNovel {
self
}
}
// Codec=Dco (DartCObject based), see doc to use other codecs
impl flutter_rust_bridge::IntoDart for crate::api::epub::EpubResource {
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
[
self.name.into_into_dart().into_dart(),
self.content.into_into_dart().into_dart(),
]
.into_dart()
}
}
impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive
for crate::api::epub::EpubResource
{
}
impl flutter_rust_bridge::IntoIntoDart<crate::api::epub::EpubResource>
for crate::api::epub::EpubResource
{
fn into_into_dart(self) -> crate::api::epub::EpubResource {
self
}
}
// Codec=Dco (DartCObject based), see doc to use other codecs
impl flutter_rust_bridge::IntoDart for crate::api::rhttp::http::HttpHeaders {
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
match self {
@ -1931,6 +2179,37 @@ impl SseEncode for crate::api::rhttp::client::CustomProxy {
}
}
impl SseEncode for crate::api::epub::EpubChapter {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<String>::sse_encode(self.name, serializer);
<String>::sse_encode(self.content, serializer);
<String>::sse_encode(self.path, serializer);
}
}
impl SseEncode for crate::api::epub::EpubNovel {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<String>::sse_encode(self.name, serializer);
<Option<Vec<u8>>>::sse_encode(self.cover, serializer);
<Option<String>>::sse_encode(self.summary, serializer);
<Option<String>>::sse_encode(self.author, serializer);
<Option<String>>::sse_encode(self.artist, serializer);
<Vec<crate::api::epub::EpubChapter>>::sse_encode(self.chapters, serializer);
<Vec<crate::api::epub::EpubResource>>::sse_encode(self.images, serializer);
<Vec<crate::api::epub::EpubResource>>::sse_encode(self.stylesheets, serializer);
}
}
impl SseEncode for crate::api::epub::EpubResource {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<String>::sse_encode(self.name, serializer);
<Vec<u8>>::sse_encode(self.content, serializer);
}
}
impl SseEncode for crate::api::rhttp::http::HttpHeaders {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
@ -2067,6 +2346,26 @@ impl SseEncode for Vec<crate::api::rhttp::client::CustomProxy> {
}
}
impl SseEncode for Vec<crate::api::epub::EpubChapter> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<i32>::sse_encode(self.len() as _, serializer);
for item in self {
<crate::api::epub::EpubChapter>::sse_encode(item, serializer);
}
}
}
impl SseEncode for Vec<crate::api::epub::EpubResource> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<i32>::sse_encode(self.len() as _, serializer);
for item in self {
<crate::api::epub::EpubResource>::sse_encode(item, serializer);
}
}
}
impl SseEncode for Vec<Vec<u8>> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {