diff --git a/lib/src/rust/api/plugin/commands.dart b/lib/src/rust/api/plugin/commands.dart index ae34c0fc..34ee478c 100644 --- a/lib/src/rust/api/plugin/commands.dart +++ b/lib/src/rust/api/plugin/commands.dart @@ -7,6 +7,7 @@ import '../../frb_generated.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `AlbumCommands`, `ArtistCommands`, `AudioSourceCommands`, `AuthCommands`, `BrowseCommands`, `CoreCommands`, `PlaylistCommands`, `SearchCommands`, `TrackCommands`, `UserCommands` +// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt` // Rust type: RustOpaqueMoi> abstract class PluginCommand implements RustOpaqueInterface {} diff --git a/lib/src/rust/api/plugin/plugin.dart b/lib/src/rust/api/plugin/plugin.dart index 33c3f8d3..c18bef0e 100644 --- a/lib/src/rust/api/plugin/plugin.dart +++ b/lib/src/rust/api/plugin/plugin.dart @@ -4,13 +4,13 @@ // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import import '../../frb_generated.dart'; +import '../../lib.dart'; import 'models/core.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'senders.dart'; -// These functions are ignored because they are not marked as `pub`: `js_executor_thread` +// These functions are ignored because they are not marked as `pub`: `console_log`, `js_executor_thread`, `register_globals`, `set_timeout` // 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` -// These functions are ignored (category: IgnoreBecauseExplicitAttribute): `create_context` // Rust type: RustOpaqueMoi> abstract class OpaqueSender implements RustOpaqueInterface { @@ -19,9 +19,6 @@ abstract class OpaqueSender implements RustOpaqueInterface { set sender(SenderPluginCommand sender); } -// Rust type: RustOpaqueMoi>> -abstract class SenderPluginCommand implements RustOpaqueInterface {} - class SpotubePlugin { final PluginArtistSender artist; final PluginAlbumSender album; diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index ccf493a3..8fd49a36 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -22,6 +22,7 @@ import 'dart:convert'; import 'frb_generated.dart'; import 'frb_generated.io.dart' if (dart.library.js_interop) 'frb_generated.web.dart'; +import 'lib.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; /// Main entrypoint of the Rust API diff --git a/lib/src/rust/frb_generated.io.dart b/lib/src/rust/frb_generated.io.dart index b9895671..10ad8003 100644 --- a/lib/src/rust/frb_generated.io.dart +++ b/lib/src/rust/frb_generated.io.dart @@ -21,6 +21,7 @@ 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 { diff --git a/lib/src/rust/internal/core.dart b/lib/src/rust/internal/core.dart new file mode 100644 index 00000000..dabb11a4 --- /dev/null +++ b/lib/src/rust/internal/core.dart @@ -0,0 +1,10 @@ +// 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'; + +// Rust type: RustOpaqueMoi> +abstract class PluginCoreEndpoint implements RustOpaqueInterface {} diff --git a/lib/src/rust/lib.dart b/lib/src/rust/lib.dart new file mode 100644 index 00000000..c2138dda --- /dev/null +++ b/lib/src/rust/lib.dart @@ -0,0 +1,10 @@ +// 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'; + +// Rust type: RustOpaqueMoi>> +abstract class SenderPluginCommand implements RustOpaqueInterface {} diff --git a/rust/Cargo.lock b/rust/Cargo.lock index ce61e4ce..69860ca7 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -17,6 +17,56 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aead" +version = "0.6.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d2d54c4d9e7006f132f615a167865bff927a79ca63d8f637237575ce0a9795" +dependencies = [ + "crypto-common 0.2.0-rc.5", + "inout", +] + +[[package]] +name = "aes" +version = "0.9.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd9e1c818b25efb32214df89b0ec22f01aa397aaeb718d1022bf0635a3bfd1a8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.11.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f5c07f414d7dc0755870f84c7900425360288d24e0eae4836f9dee19a30fa5f" +dependencies = [ + "aead", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "aes-kw" +version = "0.3.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02eaa2d54d0fad0116e4b1efb65803ea0bf059ce970a67cd49718d87e807cb51" +dependencies = [ + "aes", + "const-oid", +] + [[package]] name = "aho-corasick" version = "1.1.2" @@ -26,15 +76,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "aligned-vec" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" -dependencies = [ - "equator", -] - [[package]] name = "allo-isolate" version = "0.1.27" @@ -84,12 +125,6 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - [[package]] name = "async-lock" version = "3.4.0" @@ -129,22 +164,32 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.1", "object", "rustc-demangle", ] [[package]] -name = "base64" -version = "0.22.1" +name = "base16ct" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +checksum = "d8b59d472eab27ade8d770dcb11da7201c11234bef9f82ce7aa517be028d462b" [[package]] -name = "bitflags" -version = "1.3.2" +name = "base64-simd" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[package]] name = "bitflags" @@ -162,164 +207,39 @@ dependencies = [ ] [[package]] -name = "boa_ast" -version = "0.21.0" +name = "block-buffer" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc119a5ad34c3f459062a96907f53358989b173d104258891bb74f95d93747e8" +checksum = "96eb4cdd6cf1b31d671e9efe75c5d1ec614776856cefbe109ca373554a6d514f" dependencies = [ - "bitflags 2.10.0", - "boa_interner", - "boa_macros", - "boa_string", - "indexmap", - "num-bigint", - "rustc-hash", + "hybrid-array", ] [[package]] -name = "boa_engine" -version = "0.21.0" +name = "block-padding" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e637ec52ea66d76b0ca86180c259d6c7bb6e6a6e14b2f36b85099306d8b00cc3" +checksum = "710f1dd022ef4e93f8a438b4ba958de7f64308434fa6a87104481645cc30068b" dependencies = [ - "aligned-vec", - "arrayvec", - "bitflags 2.10.0", - "boa_ast", - "boa_gc", - "boa_interner", - "boa_macros", - "boa_parser", - "boa_string", - "bytemuck", - "cfg-if", - "cow-utils", - "dashmap 6.1.0", - "dynify", - "either", - "fast-float2", - "float16", - "futures-channel", - "futures-concurrency", - "futures-lite", - "hashbrown 0.16.1", - "icu_normalizer", - "indexmap", - "intrusive-collections", - "itertools", - "num-bigint", - "num-integer", - "num-traits", - "num_enum", - "paste", - "portable-atomic", - "rand", - "regress", - "rustc-hash", - "ryu-js", - "serde", - "serde_json", - "small_btree", - "static_assertions", - "tag_ptr", - "tap", - "thin-vec", - "thiserror", - "time", - "xsum", + "hybrid-array", ] [[package]] -name = "boa_gc" -version = "0.21.0" +name = "brotlic" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1179f690cbfcbe5364cceee5f1cb577265bb6f07b0be6f210aabe270adcf9da" +checksum = "f552f56f302af0006c32b50bfa2bdb4696fd6ba33c3ab9f6225fefdb1efdc680" dependencies = [ - "boa_macros", - "boa_string", - "either", - "hashbrown 0.16.1", - "thin-vec", + "brotlic-sys", ] [[package]] -name = "boa_interner" -version = "0.21.0" +name = "brotlic-sys" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9626505d33dc63d349662437297df1d3afd9d5fc4a2b3ad34e5e1ce879a78848" +checksum = "afdec5c62bc97b56349053cf66ba503af5c2448591be61c3ad70a5f11b57e574" dependencies = [ - "boa_gc", - "boa_macros", - "hashbrown 0.16.1", - "indexmap", - "once_cell", - "phf", - "rustc-hash", - "static_assertions", -] - -[[package]] -name = "boa_macros" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f36418a46544b152632c141b0a0b7a453cd69ca150caeef83aee9e2f4b48b7d" -dependencies = [ - "cfg-if", - "cow-utils", - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "boa_parser" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f99bf5b684f0de946378fcfe5f38c3a0fbd51cbf83a0f39ff773a0e218541f" -dependencies = [ - "bitflags 2.10.0", - "boa_ast", - "boa_interner", - "boa_macros", - "fast-float2", - "icu_properties", - "num-bigint", - "num-traits", - "regress", - "rustc-hash", -] - -[[package]] -name = "boa_runtime" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ee83c5e3634de25fe80c785c4a240483daedf9e346a9848ec87f7a13250471" -dependencies = [ - "boa_engine", - "boa_gc", - "bytemuck", - "either", - "futures", - "futures-lite", - "http", - "rustc-hash", - "serde_json", - "url", -] - -[[package]] -name = "boa_string" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ce9d7aa5563a2e14eab111e2ae1a06a69a812f6c0c3d843196c9d03fbef440" -dependencies = [ - "fast-float2", - "itoa", - "paste", - "rustc-hash", - "ryu-js", - "static_assertions", + "cc", ] [[package]] @@ -339,20 +259,6 @@ name = "bytemuck" version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] [[package]] name = "byteorder" @@ -366,6 +272,15 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +[[package]] +name = "cbc" +version = "0.2.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c34a745c272d1f6124df3006881364190a8f033ff3857ce196a17aa4a753096" +dependencies = [ + "cipher", +] + [[package]] name = "cc" version = "1.2.47" @@ -373,6 +288,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd405d82c84ff7f35739f175f67d8b9fb7687a0e84ccdc78bd3568839827cf07" dependencies = [ "find-msvc-tools", + "jobserver", + "libc", "shlex", ] @@ -382,6 +299,17 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "chacha20" +version = "0.10.0-rc.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cbf41c6ec3c4b9eaf7f8f5c11a72cd7d3aa0428125c20d5ef4d09907a0f019" +dependencies = [ + "cfg-if", + "cpufeatures", + "rand_core", +] + [[package]] name = "chrono" version = "0.4.42" @@ -395,6 +323,26 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "cipher" +version = "0.5.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "155e4a260750fa4f7754649f049748aacc31db238a358d85fd721002f230f92f" +dependencies = [ + "block-buffer 0.11.0", + "crypto-common 0.2.0-rc.5", + "inout", +] + +[[package]] +name = "cmake" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +dependencies = [ + "cc", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -415,23 +363,18 @@ dependencies = [ ] [[package]] -name = "cordyceps" -version = "0.3.4" +name = "const-oid" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688d7fbb8092b8de775ef2536f36c8c31f2bc4006ece2e8d8ad2d17d00ce0a2a" -dependencies = [ - "loom", - "tracing", -] +checksum = "0dabb6555f92fb9ee4140454eb5dcd14c7960e1225c6d1a6cc361f032947713e" [[package]] -name = "core-foundation" -version = "0.9.4" +name = "convert_case" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" dependencies = [ - "core-foundation-sys", - "libc", + "unicode-segmentation", ] [[package]] @@ -441,10 +384,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "cow-utils" -version = "0.1.3" +name = "cpufeatures" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "417bef24afe1460300965a25ff4a24b8b45ad011948302ec221e8a0a81eb2c79" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32c" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] [[package]] name = "crossbeam-utils" @@ -452,6 +416,20 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crypto-bigint" +version = "0.7.0-rc.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6715836b4946e8585016e80b79c7561476aff3b22f7b756778e7b109d86086c6" +dependencies = [ + "hybrid-array", + "num-traits", + "rand_core", + "serdect", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -462,6 +440,61 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.0-rc.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919bd05924682a5480aec713596b9e2aabed3a0a6022fab6847f85a99e5f190a" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "crypto-primes" +version = "0.7.0-pre.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd9b2855017318a49714c07ee8895b89d3510d54fa6d86be5835de74c389609" +dependencies = [ + "crypto-bigint", + "libm", + "rand_core", +] + +[[package]] +name = "ctr" +version = "0.10.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d0ec605a95e78815a4c4b8040217d56d5a1ab37043851ee9e7e65b89afa00e3" +dependencies = [ + "cipher", +] + +[[package]] +name = "curve25519-dalek" +version = "5.0.0-pre.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d8cfa313d59919eda35b420bd37db85bf58d6754d6f128b9949932b0c0fcce7" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "dart-sys" version = "4.1.5" @@ -484,20 +517,6 @@ dependencies = [ "parking_lot_core", ] -[[package]] -name = "dashmap" -version = "6.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" -dependencies = [ - "cfg-if", - "crossbeam-utils", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - [[package]] name = "delegate-attr" version = "0.3.0" @@ -510,19 +529,27 @@ dependencies = [ ] [[package]] -name = "deranged" -version = "0.5.5" +name = "der" +version = "0.8.0-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "02c1d73e9668ea6b6a28172aa55f3ebec38507131ce179051c8033b5c6037653" dependencies = [ - "powerfmt", + "const-oid", + "der_derive", + "pem-rfc7468", + "zeroize", ] [[package]] -name = "diatomic-waker" -version = "0.2.3" +name = "der_derive" +version = "0.8.0-rc.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c" +checksum = "be645fee2afe89d293b96c19e4456e6ac69520fc9c6b8a58298550138e361ffe" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "digest" @@ -530,8 +557,20 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", - "crypto-common", + "block-buffer 0.10.4", + "crypto-common 0.1.6", +] + +[[package]] +name = "digest" +version = "0.11.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea390c940e465846d64775e55e3115d5dc934acb953de6f6e6360bc232fe2bf7" +dependencies = [ + "block-buffer 0.11.0", + "const-oid", + "crypto-common 0.2.0-rc.5", + "subtle", ] [[package]] @@ -546,23 +585,17 @@ dependencies = [ ] [[package]] -name = "dynify" -version = "0.1.2" +name = "ecdsa" +version = "0.17.0-rc.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81acb15628a3e22358bf73de5e7e62360b8a777dbcb5fc9ac7dfa9ae73723747" +checksum = "e914ecb8e11a02f42cc05f6b43675d1e5aa4d446cd207f9f818903a1ab34f19f" dependencies = [ - "dynify-macros", -] - -[[package]] -name = "dynify-macros" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec431cd708430d5029356535259c5d645d60edd3d39c54e5eea9782d46caa7d" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "der", + "digest 0.11.0-rc.4", + "elliptic-curve", + "rfc6979", + "signature", + "zeroize", ] [[package]] @@ -572,12 +605,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] -name = "encoding_rs" -version = "0.8.35" +name = "elliptic-curve" +version = "0.14.0-rc.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +checksum = "39ecd2903524729de5d0cba7589121744513feadd56d71980cb480c48caceb11" dependencies = [ - "cfg-if", + "base16ct", + "crypto-bigint", + "digest 0.11.0-rc.4", + "hkdf", + "hybrid-array", + "pkcs8", + "rand_core", + "rustcrypto-ff", + "rustcrypto-group", + "sec1", + "subtle", + "zeroize", ] [[package]] @@ -590,42 +634,12 @@ dependencies = [ "regex", ] -[[package]] -name = "equator" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" -dependencies = [ - "equator-macro", -] - -[[package]] -name = "equator-macro" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - [[package]] name = "event-listener" version = "5.4.0" @@ -646,18 +660,18 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "fast-float2" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8eb564c5c7423d25c886fb561d1e4ee69f72354d16918afa32c08811f6b6a55" - [[package]] name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "fiat-crypto" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" + [[package]] name = "find-msvc-tools" version = "0.1.5" @@ -665,19 +679,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" [[package]] -name = "fixedbitset" -version = "0.5.7" +name = "flate2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +dependencies = [ + "crc32fast", + "libz-ng-sys", + "miniz_oxide 0.8.9", +] [[package]] -name = "float16" -version = "0.1.5" +name = "float-cmp" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bffafbd079d520191c7c2779ae9cf757601266cf4167d3f659ff09617ff8483" +checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" dependencies = [ - "cfg-if", - "rustc_version", + "num-traits", ] [[package]] @@ -716,7 +734,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f0420326b13675321b194928bb7830043b68cf8b810e1c651285c747abb080" dependencies = [ "hex", - "md-5", + "md-5 0.10.6", "proc-macro2", "quote", "syn", @@ -734,21 +752,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.2" @@ -773,19 +776,6 @@ dependencies = [ "futures-util", ] -[[package]] -name = "futures-buffered" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e0e1f38ec07ba4abbde21eed377082f17ccb988be9d988a5adbf4bafc118fd" -dependencies = [ - "cordyceps", - "diatomic-waker", - "futures-core", - "pin-project-lite", - "spin", -] - [[package]] name = "futures-channel" version = "0.3.31" @@ -796,21 +786,6 @@ dependencies = [ "futures-sink", ] -[[package]] -name = "futures-concurrency" -version = "7.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eb68017df91f2e477ed4bea586c59eaecaa47ed885a770d0444e21e62572cd2" -dependencies = [ - "fixedbitset", - "futures-buffered", - "futures-core", - "futures-lite", - "pin-project", - "slab", - "smallvec", -] - [[package]] name = "futures-core" version = "0.3.31" @@ -834,19 +809,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" -[[package]] -name = "futures-lite" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - [[package]] name = "futures-macro" version = "0.3.31" @@ -888,20 +850,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generator" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" -dependencies = [ - "cc", - "cfg-if", - "libc", - "log", - "rustversion", - "windows", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -935,6 +883,15 @@ dependencies = [ "wasip2", ] +[[package]] +name = "ghash" +version = "0.6.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "333de57ed9494a40df4bbb866752b100819dde0d18f2264c48f5a08a85fe673d" +dependencies = [ + "polyval", +] + [[package]] name = "gimli" version = "0.28.1" @@ -960,6 +917,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "halfbrown" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7ed2f2edad8a14c8186b847909a41fbb9c3eafa44f88bd891114ed5019da09" +dependencies = [ + "hashbrown 0.16.1", +] + [[package]] name = "hashbrown" version = "0.14.5" @@ -995,6 +961,43 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f7685beb53fc20efc2605f32f5d51e9ba18b8ef237961d1760169d2290d3bee" +dependencies = [ + "outref", + "vsimd", +] + +[[package]] +name = "hkdf" +version = "0.13.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfbb4225acf2b5cc4e12d384672cd6d1f0cb980ff5859ffcf144db25b593a24d" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.13.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1c597ac7d6cc8143e30e83ef70915e7f883b18d8bec2e2b2bce47f5bbb06d57" +dependencies = [ + "digest 0.11.0-rc.4", +] + +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "http" version = "1.4.0" @@ -1034,6 +1037,17 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" +[[package]] +name = "hybrid-array" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f471e0a81b2f90ffc0cb2f951ae04da57de8baa46fa99112b062a5173a5088d0" +dependencies = [ + "subtle", + "typenum", + "zeroize", +] + [[package]] name = "hyper" version = "1.8.1" @@ -1070,22 +1084,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", + "webpki-roots", ] [[package]] @@ -1094,7 +1093,6 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56" dependencies = [ - "base64", "bytes", "futures-channel", "futures-core", @@ -1102,16 +1100,12 @@ dependencies = [ "http", "http-body", "hyper", - "ipnet", "libc", - "percent-encoding", "pin-project-lite", "socket2", - "system-configuration", "tokio", "tower-service", "tracing", - "windows-registry", ] [[package]] @@ -1177,8 +1171,6 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "write16", "zerovec", ] @@ -1227,6 +1219,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "1.1.0" @@ -1259,37 +1257,13 @@ dependencies = [ ] [[package]] -name = "intrusive-collections" -version = "0.9.7" +name = "inout" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "189d0897e4cbe8c75efedf3502c18c887b05046e59d28404d4d8e46cbc4d1e86" +checksum = "c7357b6e7aa75618c7864ebd0634b115a7218b0615f4cb1df33ac3eca23943d4" dependencies = [ - "memoffset", -] - -[[package]] -name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iri-string" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", + "block-padding", + "hybrid-array", ] [[package]] @@ -1298,6 +1272,16 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "js-sys" version = "0.3.82" @@ -1321,10 +1305,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] -name = "linux-raw-sys" -version = "0.11.0" +name = "libm" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "libredox" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +dependencies = [ + "bitflags", + "libc", + "redox_syscall", +] + +[[package]] +name = "libz-ng-sys" +version = "1.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bf914b7dd154ca9193afec311d8e39345c1bd93b48b3faa77329f0db8f553c0" +dependencies = [ + "cmake", + "libc", +] [[package]] name = "litemap" @@ -1332,6 +1337,537 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +[[package]] +name = "llrt_abort" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_async_hooks", + "llrt_events", + "llrt_exceptions", + "llrt_timers", + "llrt_utils", + "rquickjs", +] + +[[package]] +name = "llrt_assert" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_utils", + "rquickjs", +] + +[[package]] +name = "llrt_async_hooks" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_hooking", + "llrt_utils", + "rquickjs", + "tracing", +] + +[[package]] +name = "llrt_buffer" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "itoa", + "llrt_encoding", + "llrt_utils", + "rquickjs", + "ryu", +] + +[[package]] +name = "llrt_build" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "llrt_child_process" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "itoa", + "libc", + "llrt_buffer", + "llrt_context", + "llrt_events", + "llrt_stream", + "llrt_utils", + "rquickjs", + "tokio", +] + +[[package]] +name = "llrt_compression" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "brotlic", + "flate2", + "zstd", +] + +[[package]] +name = "llrt_console" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_logging", + "llrt_utils", + "rquickjs", +] + +[[package]] +name = "llrt_context" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_build", + "llrt_utils", + "rquickjs", + "tokio", + "tracing", +] + +[[package]] +name = "llrt_crypto" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "aes", + "aes-gcm", + "aes-kw", + "cbc", + "const-oid", + "crc32c", + "crc32fast", + "ctr", + "der", + "ecdsa", + "elliptic-curve", + "llrt_buffer", + "llrt_context", + "llrt_encoding", + "llrt_json", + "llrt_utils", + "md-5 0.11.0-rc.3", + "once_cell", + "p256", + "p384", + "p521", + "pkcs8", + "rand", + "ring", + "rquickjs", + "rsa", + "spki", + "x25519-dalek", +] + +[[package]] +name = "llrt_dns" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "either", + "llrt_context", + "llrt_hooking", + "llrt_utils", + "rquickjs", + "tokio", +] + +[[package]] +name = "llrt_dns_cache" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "hyper-util", + "llrt_context", + "llrt_utils", + "quick_cache", + "tokio", + "tower-service", +] + +[[package]] +name = "llrt_encoding" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "base64-simd", + "hex-simd", + "llrt_build", + "memchr", + "phf", +] + +[[package]] +name = "llrt_events" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_utils", + "rquickjs", + "tracing", +] + +[[package]] +name = "llrt_exceptions" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_utils", + "rquickjs", +] + +[[package]] +name = "llrt_fetch" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "bytes", + "either", + "http-body-util", + "hyper", + "itoa", + "llrt_abort", + "llrt_buffer", + "llrt_compression", + "llrt_context", + "llrt_encoding", + "llrt_http", + "llrt_json", + "llrt_url", + "llrt_utils", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rand", + "rquickjs", + "tokio", + "tracing", +] + +[[package]] +name = "llrt_fs" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "either", + "llrt_buffer", + "llrt_encoding", + "llrt_path", + "llrt_utils", + "ring", + "rquickjs", + "tokio", +] + +[[package]] +name = "llrt_hooking" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_utils", + "once_cell", + "rquickjs", +] + +[[package]] +name = "llrt_http" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "llrt_dns_cache", + "llrt_tls", + "llrt_utils", + "once_cell", + "rquickjs", + "rustls", +] + +[[package]] +name = "llrt_json" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "itoa", + "llrt_build", + "llrt_utils", + "rquickjs", + "ryu", + "simd-json", +] + +[[package]] +name = "llrt_logging" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "itoa", + "llrt_context", + "llrt_encoding", + "llrt_json", + "llrt_numbers", + "llrt_utils", + "rquickjs", + "ryu", +] + +[[package]] +name = "llrt_modules" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "home", + "llrt_abort", + "llrt_assert", + "llrt_async_hooks", + "llrt_buffer", + "llrt_child_process", + "llrt_console", + "llrt_crypto", + "llrt_dns", + "llrt_events", + "llrt_exceptions", + "llrt_fetch", + "llrt_fs", + "llrt_hooking", + "llrt_http", + "llrt_json", + "llrt_navigator", + "llrt_net", + "llrt_os", + "llrt_path", + "llrt_perf_hooks", + "llrt_process", + "llrt_stream_web", + "llrt_string_decoder", + "llrt_timers", + "llrt_tls", + "llrt_tty", + "llrt_url", + "llrt_util", + "llrt_utils", + "llrt_zlib", + "once_cell", + "rquickjs", + "simd-json", + "tokio", + "tracing", +] + +[[package]] +name = "llrt_navigator" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "rquickjs", +] + +[[package]] +name = "llrt_net" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "itoa", + "llrt_buffer", + "llrt_context", + "llrt_events", + "llrt_stream", + "llrt_utils", + "rquickjs", + "tokio", + "tracing", +] + +[[package]] +name = "llrt_numbers" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "itoa", + "llrt_utils", + "rquickjs", + "ryu", +] + +[[package]] +name = "llrt_os" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "home", + "libc", + "llrt_utils", + "num_cpus", + "once_cell", + "rquickjs", + "users", + "whoami", + "windows-registry", + "windows-result 0.4.1", + "windows-version", +] + +[[package]] +name = "llrt_path" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_utils", + "memchr", + "rquickjs", +] + +[[package]] +name = "llrt_perf_hooks" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_utils", + "rquickjs", +] + +[[package]] +name = "llrt_process" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "libc", + "llrt_utils", + "rquickjs", +] + +[[package]] +name = "llrt_stream" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_buffer", + "llrt_context", + "llrt_events", + "llrt_utils", + "rquickjs", + "tokio", +] + +[[package]] +name = "llrt_stream_web" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_abort", + "llrt_utils", + "rquickjs", +] + +[[package]] +name = "llrt_string_decoder" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_buffer", + "llrt_encoding", + "llrt_utils", + "rquickjs", +] + +[[package]] +name = "llrt_timers" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_context", + "llrt_hooking", + "llrt_utils", + "once_cell", + "rquickjs", + "tokio", +] + +[[package]] +name = "llrt_tls" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "once_cell", + "rustls", + "webpki-roots", +] + +[[package]] +name = "llrt_tty" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "libc", + "llrt_utils", + "rquickjs", +] + +[[package]] +name = "llrt_url" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_utils", + "rquickjs", + "url", +] + +[[package]] +name = "llrt_util" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_context", + "llrt_encoding", + "llrt_logging", + "llrt_utils", + "rquickjs", +] + +[[package]] +name = "llrt_utils" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "libc", + "llrt_build", + "rquickjs", + "tokio", + "tracing", + "windows-sys 0.61.2", +] + +[[package]] +name = "llrt_zlib" +version = "0.7.0-beta" +source = "git+https://github.com/awslabs/llrt.git?rev=7d749dd18cf26a2e51119094c3b945975ae57bd4#7d749dd18cf26a2e51119094c3b945975ae57bd4" +dependencies = [ + "llrt_buffer", + "llrt_compression", + "llrt_context", + "llrt_utils", + "rquickjs", +] + [[package]] name = "lock_api" version = "0.4.14" @@ -1347,28 +1883,6 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -[[package]] -name = "loom" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "matchers" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata", -] - [[package]] name = "md-5" version = "0.10.6" @@ -1376,7 +1890,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ "cfg-if", - "digest", + "digest 0.10.7", +] + +[[package]] +name = "md-5" +version = "0.11.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64dd2c9099caf8e29b629305199dddb1c6d981562b62c089afea54b0b4b5c333" +dependencies = [ + "cfg-if", + "digest 0.11.0-rc.4", ] [[package]] @@ -1385,21 +1909,6 @@ version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -1409,6 +1918,16 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + [[package]] name = "mio" version = "1.1.0" @@ -1420,58 +1939,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "nu-ansi-term" -version = "0.50.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", - "serde", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -1491,37 +1958,6 @@ dependencies = [ "libc", ] -[[package]] -name = "num_enum" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" -dependencies = [ - "num_enum_derive", - "rustversion", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - [[package]] name = "object" version = "0.32.1" @@ -1537,50 +1973,6 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -[[package]] -name = "openssl" -version = "0.10.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" -dependencies = [ - "bitflags 2.10.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-sys" -version = "0.9.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "oslog" version = "0.2.0" @@ -1588,15 +1980,56 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80d2043d1f61d77cb2f4b1f7b7b2295f40507f5f8e9d1c8bf10a1ca5f97a3969" dependencies = [ "cc", - "dashmap 5.5.3", + "dashmap", "log", ] [[package]] -name = "parking" -version = "2.2.1" +name = "outref" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" +checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" + +[[package]] +name = "p256" +version = "0.14.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdbe8d6ac92e515ca2179ac331c1e4def09db2217d394683e73dace705c2f0c5" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primefield", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.14.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c729847b7cf17b9c96f9e6504400f64ae90cb1cdf23610cc1a51f18538ff95" +dependencies = [ + "ecdsa", + "elliptic-curve", + "fiat-crypto", + "primefield", + "primeorder", + "sha2", +] + +[[package]] +name = "p521" +version = "0.14.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75296e7cb5d53c8a5083ff26b5707177962cd5851af961a56316e863f1ea757c" +dependencies = [ + "base16ct", + "ecdsa", + "elliptic-curve", + "primefield", + "primeorder", + "sha2", +] [[package]] name = "parking_lot" @@ -1622,10 +2055,13 @@ dependencies = [ ] [[package]] -name = "paste" -version = "1.0.15" +name = "pem-rfc7468" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +checksum = "a6305423e0e7738146434843d1694d621cce767262b2a86910beab705e4493d9" +dependencies = [ + "base64ct", +] [[package]] name = "percent-encoding" @@ -1675,26 +2111,6 @@ dependencies = [ "siphasher", ] -[[package]] -name = "pin-project" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "pin-project-lite" version = "0.2.13" @@ -1707,12 +2123,43 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.8.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "986d2e952779af96ea048f160fd9194e1751b4faea78bcf3ceb456efe008088e" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.11.0-rc.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77089aec8290d0b7bb01b671b091095cf1937670725af4fd73d47249f03b12c0" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "polyval" +version = "0.7.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad60831c19edda4b20878a676595c357e93a9b4e6dca2ba98d75b01066b317b" +dependencies = [ + "cfg-if", + "cpufeatures", + "universal-hash", +] + [[package]] name = "portable-atomic" version = "1.11.1" @@ -1729,18 +2176,25 @@ dependencies = [ ] [[package]] -name = "powerfmt" -version = "0.2.0" +name = "primefield" +version = "0.14.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +checksum = "1c3ad342f52c70a953d95acb09a55450fdc07c2214283b81536c3f83f714568e" +dependencies = [ + "crypto-bigint", + "rand_core", + "rustcrypto-ff", + "subtle", + "zeroize", +] [[package]] -name = "ppv-lite86" -version = "0.2.21" +name = "primeorder" +version = "0.14.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +checksum = "f5e84a5f07d7a7c85f299e17753a98d8a09f10799894a637c9ce08d834b6ca02" dependencies = [ - "zerocopy", + "elliptic-curve", ] [[package]] @@ -1761,6 +2215,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quick_cache" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ada44a88ef953a3294f6eb55d2007ba44646015e18613d2f213016379203ef3" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", +] + [[package]] name = "quote" version = "1.0.42" @@ -1778,32 +2242,20 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" -version = "0.9.2" +version = "0.10.0-rc.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "be866deebbade98028b705499827ad6967c8bb1e21f96a2609913c8c076e9307" dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", + "chacha20", + "getrandom 0.3.4", "rand_core", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.10.0-rc-2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.4", -] +checksum = "104a23e4e8b77312a823b6b5613edbac78397e2f34320bc7ac4277013ec4478e" [[package]] name = "redox_syscall" @@ -1811,7 +2263,27 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1843,16 +2315,6 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" -[[package]] -name = "regress" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2057b2325e68a893284d1538021ab90279adac1139957ca2a74426c6f118fb48" -dependencies = [ - "hashbrown 0.16.1", - "memchr", -] - [[package]] name = "relative-path" version = "2.0.1" @@ -1863,43 +2325,13 @@ dependencies = [ ] [[package]] -name = "reqwest" -version = "0.12.24" +name = "rfc6979" +version = "0.5.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" +checksum = "63b8e2323084c987a72875b2fd682b7307d5cf14d47e3875bb5e89948e8809d4" dependencies = [ - "base64", - "bytes", - "encoding_rs", - "futures-core", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-tls", - "hyper-util", - "js-sys", - "log", - "mime", - "native-tls", - "percent-encoding", - "pin-project-lite", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-native-tls", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", + "hmac", + "subtle", ] [[package]] @@ -1922,7 +2354,9 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a135375fbac5ba723bb6a48f432a72f81539cedde422f0121a86c7c4e96d8e0d" dependencies = [ + "either", "rquickjs-core", + "rquickjs-macro", ] [[package]] @@ -1933,11 +2367,29 @@ checksum = "bccb7121a123865c8ace4dea42e7ed84d78b90cbaf4ca32c59849d8d210c9672" dependencies = [ "async-lock", "chrono", + "either", "hashbrown 0.16.1", "relative-path", "rquickjs-sys", ] +[[package]] +name = "rquickjs-macro" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89f93602cc3112c7f30bf5f29e722784232138692c7df4c52ebbac7e035d900d" +dependencies = [ + "convert_case", + "fnv", + "ident_case", + "indexmap", + "proc-macro-crate", + "proc-macro2", + "quote", + "rquickjs-core", + "syn", +] + [[package]] name = "rquickjs-sys" version = "0.10.0" @@ -1947,20 +2399,35 @@ dependencies = [ "cc", ] +[[package]] +name = "rsa" +version = "0.10.0-rc.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e499c52862d75a86c0024cc99dcb6d7127d15af3beae7b03573d62fab7ade08a" +dependencies = [ + "const-oid", + "crypto-bigint", + "crypto-primes", + "digest 0.11.0-rc.4", + "pkcs1", + "pkcs8", + "rand", + "rand_core", + "sha2", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rust_lib_spotube" version = "0.1.0" dependencies = [ "anyhow", - "boa_engine", - "boa_gc", - "boa_runtime", "flutter_rust_bridge", - "futures-concurrency", - "futures-lite", "heck", - "http", - "reqwest", + "llrt_modules", "rquickjs", "serde", "serde_json", @@ -1973,32 +2440,34 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - [[package]] name = "rustc_version" -version = "0.2.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] -name = "rustix" -version = "1.1.2" +name = "rustcrypto-ff" +version = "0.14.0-pre.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "aa9cd37111549306f79b09aa2618e15b1e8241b7178c286821e3dd71579db4db" dependencies = [ - "bitflags 2.10.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.61.2", + "rand_core", + "subtle", +] + +[[package]] +name = "rustcrypto-group" +version = "0.14.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e394cd734b5f97dfc3484fa42aad7acd912961c2bcd96c99aa05b3d6cab7cafd" +dependencies = [ + "rand_core", + "rustcrypto-ff", + "subtle", ] [[package]] @@ -2008,6 +2477,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -2046,27 +2516,6 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" -[[package]] -name = "ryu-js" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd29631678d6fb0903b69223673e122c32e9ae559d0960a38d574695ebc0ea15" - -[[package]] -name = "schannel" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.2.0" @@ -2074,42 +2523,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "security-framework" -version = "2.11.1" +name = "sec1" +version = "0.8.0-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +checksum = "1dff52f6118bc9f0ac974a54a639d499ac26a6cad7a6e39bc0990c19625e793b" dependencies = [ - "bitflags 2.10.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" -dependencies = [ - "core-foundation-sys", - "libc", + "base16ct", + "der", + "hybrid-array", + "subtle", + "zeroize", ] [[package]] name = "semver" -version = "0.9.0" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" @@ -2155,24 +2585,24 @@ dependencies = [ ] [[package]] -name = "serde_urlencoded" -version = "0.7.1" +name = "serdect" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +checksum = "d3ef0e35b322ddfaecbc60f34ab448e157e48531288ee49fafbb053696b8ffe2" dependencies = [ - "form_urlencoded", - "itoa", - "ryu", + "base16ct", "serde", ] [[package]] -name = "sharded-slab" -version = "0.1.7" +name = "sha2" +version = "0.11.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +checksum = "19d43dc0354d88b791216bb5c1bfbb60c0814460cc653ae0ebd71f286d0bd927" dependencies = [ - "lazy_static", + "cfg-if", + "cpufeatures", + "digest 0.11.0-rc.4", ] [[package]] @@ -2190,6 +2620,40 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "3.0.0-rc.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0251c9d6468f4ba853b6352b190fb7c1e405087779917c238445eb03993826" +dependencies = [ + "digest 0.11.0-rc.4", + "rand_core", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd-json" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4255126f310d2ba20048db6321c81ab376f6a6735608bf11f0785c41f01f64e3" +dependencies = [ + "halfbrown", + "ref-cast", + "simdutf8", + "value-trait", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "siphasher" version = "1.0.1" @@ -2205,15 +2669,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "small_btree" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ba60d2df92ba73864714808ca68c059734853e6ab722b40e1cf543ebb3a057a" -dependencies = [ - "arrayvec", -] - [[package]] name = "smallvec" version = "1.15.1" @@ -2231,10 +2686,14 @@ dependencies = [ ] [[package]] -name = "spin" -version = "0.10.0" +name = "spki" +version = "0.8.0-rc.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" +checksum = "8baeff88f34ed0691978ec34440140e1572b68c7dd4a495fd14a3dc1944daa80" +dependencies = [ + "base64ct", + "der", +] [[package]] name = "stable_deref_trait" @@ -2242,12 +2701,6 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "subtle" version = "2.6.1" @@ -2265,15 +2718,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] - [[package]] name = "synstructure" version = "0.13.2" @@ -2285,87 +2729,6 @@ dependencies = [ "syn", ] -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tag_ptr" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0e973b34477b7823833469eb0f5a3a60370fef7a453e02d751b59180d0a5a05" - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tempfile" -version = "3.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" -dependencies = [ - "fastrand", - "getrandom 0.3.4", - "once_cell", - "rustix", - "windows-sys 0.61.2", -] - -[[package]] -name = "thin-vec" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "144f754d318415ac792f9d69fc87abbbfc043ce2ef041c60f16ad828f638717d" - -[[package]] -name = "thiserror" -version = "2.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thread_local" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" -dependencies = [ - "cfg-if", -] - [[package]] name = "threadpool" version = "1.8.1" @@ -2375,40 +2738,6 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "time" -version = "0.3.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" -dependencies = [ - "deranged", - "itoa", - "js-sys", - "libc", - "num-conv", - "num_threads", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" - -[[package]] -name = "time-macros" -version = "0.2.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" -dependencies = [ - "num-conv", - "time-core", -] - [[package]] name = "tinystr" version = "0.8.2" @@ -2448,16 +2777,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.4" @@ -2511,45 +2830,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "tower" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-http" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456" -dependencies = [ - "bitflags 2.10.0", - "bytes", - "futures-util", - "http", - "http-body", - "iri-string", - "pin-project-lite", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - [[package]] name = "tower-service" version = "0.3.3" @@ -2563,21 +2843,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tracing-core" version = "0.1.34" @@ -2585,36 +2853,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex-automata", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", ] [[package]] @@ -2635,6 +2873,22 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "universal-hash" +version = "0.6.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ad6682ddb0189a4d3c2a5c54b8920ab6231ae911db53fc61a0709507bf1713b" +dependencies = [ + "crypto-common 0.2.0-rc.5", + "subtle", +] + [[package]] name = "untrusted" version = "0.9.0" @@ -2654,10 +2908,13 @@ dependencies = [ ] [[package]] -name = "utf16_iter" -version = "1.0.5" +name = "users" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" +checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" +dependencies = [ + "libc", +] [[package]] name = "utf8_iter" @@ -2666,16 +2923,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] -name = "valuable" -version = "0.1.1" +name = "value-trait" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +checksum = "8e80f0c733af0720a501b3905d22e2f97662d8eacfe082a75ed7ffb5ab08cb59" +dependencies = [ + "float-cmp", + "halfbrown", + "itoa", + "ryu", +] [[package]] name = "version_check" @@ -2683,6 +2940,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + [[package]] name = "want" version = "0.3.1" @@ -2707,6 +2970,12 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" version = "0.2.105" @@ -2775,25 +3044,22 @@ dependencies = [ ] [[package]] -name = "windows" -version = "0.61.3" +name = "webpki-roots" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" dependencies = [ - "windows-collections", - "windows-core", - "windows-future", - "windows-link 0.1.3", - "windows-numerics", + "rustls-pki-types", ] [[package]] -name = "windows-collections" -version = "0.2.0" +name = "whoami" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" dependencies = [ - "windows-core", + "libredox", + "wasite", ] [[package]] @@ -2809,17 +3075,6 @@ dependencies = [ "windows-strings 0.4.2", ] -[[package]] -name = "windows-future" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" -dependencies = [ - "windows-core", - "windows-link 0.1.3", - "windows-threading", -] - [[package]] name = "windows-implement" version = "0.60.2" @@ -2854,16 +3109,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-numerics" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" -dependencies = [ - "windows-core", - "windows-link 0.1.3", -] - [[package]] name = "windows-registry" version = "0.6.1" @@ -2972,12 +3217,12 @@ dependencies = [ ] [[package]] -name = "windows-threading" -version = "0.1.0" +name = "windows-version" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631" dependencies = [ - "windows-link 0.1.3", + "windows-link 0.2.1", ] [[package]] @@ -3091,12 +3336,6 @@ version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - [[package]] name = "writeable" version = "0.6.2" @@ -3104,10 +3343,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] -name = "xsum" -version = "0.1.6" +name = "x25519-dalek" +version = "3.0.0-pre.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0637d3a5566a82fa5214bae89087bc8c9fb94cd8e8a3c07feb691bb8d9c632db" +checksum = "7a1de04376e841a39a324c95b2b099eb13b8b81d0c0a5adec29f322c205761d6" +dependencies = [ + "curve25519-dalek", + "rand_core", + "zeroize", +] [[package]] name = "yoke" @@ -3132,26 +3376,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zerocopy" -version = "0.8.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea879c944afe8a2b25fef16bb4ba234f47c694565e97383b36f3a878219065c" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf955aa904d6040f70dc8e9384444cb1030aed272ba3cb09bbc4ab9e7c1f34f5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "zerofrom" version = "0.1.6" @@ -3212,3 +3436,31 @@ dependencies = [ "quote", "syn", ] + +[[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", +] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index ea093787..91ec64c2 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -12,20 +12,16 @@ path = "src/main.rs" [dependencies] flutter_rust_bridge = "=2.11.1" -boa_engine = "0.21.0" -boa_runtime = "0.21.0" -boa_gc = "0.21.0" anyhow = "1" -reqwest = { version = "0.12.x" } -http = { version = "1.3.1" } serde_json = "1" serde = { version = "1.0.228", features = ["derive"] } rquickjs = { version = "0", features = ["chrono", "futures"] } tokio = { version = "1.48.0", features = ["full"] } heck = "0.5.0" -futures-concurrency = "7.6.3" -futures-lite = "2.6.1" +llrt_modules = { git = "https://github.com/awslabs/llrt.git", rev = "7d749dd18cf26a2e51119094c3b945975ae57bd4", features = ["abort", "buffer", "console", "crypto", "events", "exceptions", "fetch", "navigator", "url", "timers"] } +[patch."https://github.com/DelSkayn/rquickjs"] +rquickjs = "0.10.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(frb_expand)'] } diff --git a/rust/src/api/plugin/event_loop.rs b/rust/src/api/plugin/event_loop.rs deleted file mode 100644 index 5aaca95b..00000000 --- a/rust/src/api/plugin/event_loop.rs +++ /dev/null @@ -1,121 +0,0 @@ -use boa_engine::context::time::JsInstant; -use boa_engine::job::{GenericJob, Job, JobExecutor, NativeAsyncJob, PromiseJob, TimeoutJob}; -use boa_engine::{Context, JsResult}; -use flutter_rust_bridge::frb; -use futures_concurrency::future::FutureGroup; -use futures_lite::{future, StreamExt}; -use std::cell::RefCell; -use std::collections::{BTreeMap, VecDeque}; -use std::ops::DerefMut; -use std::rc::Rc; -use tokio::task; - -#[frb(ignore)] -pub struct Queue { - async_jobs: RefCell>, - promise_jobs: RefCell>, - timeout_jobs: RefCell>, - generic_jobs: RefCell>, -} - -impl Queue { - pub fn new() -> Self { - Self { - async_jobs: RefCell::default(), - promise_jobs: RefCell::default(), - timeout_jobs: RefCell::default(), - generic_jobs: RefCell::default(), - } - } - - fn drain_timeout_jobs(&self, context: &mut Context) { - let now = context.clock().now(); - - let mut timeouts_borrow = self.timeout_jobs.borrow_mut(); - let mut jobs_to_keep = timeouts_borrow.split_off(&now); - jobs_to_keep.retain(|_, job| !job.is_cancelled()); - let jobs_to_run = std::mem::replace(timeouts_borrow.deref_mut(), jobs_to_keep); - drop(timeouts_borrow); - - for job in jobs_to_run.into_values() { - if let Err(e) = job.call(context) { - eprintln!("Uncaught {e}"); - } - } - } - - fn drain_jobs(&self, context: &mut Context) { - // Run the timeout jobs first. - self.drain_timeout_jobs(context); - - let job = self.generic_jobs.borrow_mut().pop_front(); - if let Some(generic) = job { - if let Err(err) = generic.call(context) { - eprintln!("Uncaught {err}"); - } - } - - let jobs = std::mem::take(&mut *self.promise_jobs.borrow_mut()); - for job in jobs { - if let Err(e) = job.call(context) { - eprintln!("Uncaught {e}"); - } - } - context.clear_kept_objects(); - } -} - -impl JobExecutor for Queue { - fn enqueue_job(self: Rc, job: Job, context: &mut Context) { - match job { - Job::PromiseJob(job) => self.promise_jobs.borrow_mut().push_back(job), - Job::AsyncJob(job) => self.async_jobs.borrow_mut().push_back(job), - Job::TimeoutJob(t) => { - let now = context.clock().now(); - self.timeout_jobs.borrow_mut().insert(now + t.timeout(), t); - } - Job::GenericJob(g) => self.generic_jobs.borrow_mut().push_back(g), - _ => panic!("unsupported job type"), - } - } - - // While the sync flavor of `run_jobs` will block the current thread until all the jobs have finished... - fn run_jobs(self: Rc, context: &mut Context) -> JsResult<()> { - task::block_in_place(|| { - let runtime = tokio::runtime::Handle::current(); // Get the existing runtime handle - - // Use LocalSet to run the async job on the current thread - runtime.block_on(self.run_jobs_async(&RefCell::new(context))) - }) - } - - // ...the async flavor won't, which allows concurrent execution with external async tasks. - async fn run_jobs_async(self: Rc, context: &RefCell<&mut Context>) -> JsResult<()> { - let mut group = FutureGroup::new(); - loop { - for job in std::mem::take(&mut *self.async_jobs.borrow_mut()) { - group.insert(job.call(context)); - } - - if group.is_empty() - && self.promise_jobs.borrow().is_empty() - && self.timeout_jobs.borrow().is_empty() - && self.generic_jobs.borrow().is_empty() - { - // All queues are empty. We can exit. - return Ok(()); - } - - // We have some jobs pending on the microtask queue. Try to poll the pending - // tasks once to see if any of them finished, and run the pending microtasks - // otherwise. - if let Some(Err(err)) = future::poll_once(group.next()).await.flatten() { - eprintln!("Uncaught {err}"); - }; - - // Only one macrotask can be executed before the next drain of the microtask queue. - self.drain_jobs(&mut context.borrow_mut()); - task::yield_now().await - } - } -} diff --git a/rust/src/api/plugin/executors.rs b/rust/src/api/plugin/executors.rs index 9a6e0e5e..b725c3ff 100644 --- a/rust/src/api/plugin/executors.rs +++ b/rust/src/api/plugin/executors.rs @@ -12,9 +12,9 @@ use crate::internal::playlist::PluginPlaylistEndpoint; use crate::internal::search::PluginSearchEndpoint; use crate::internal::track::PluginTrackEndpoint; use crate::internal::user::PluginUserEndpoint; -use boa_engine::Context; use flutter_rust_bridge::frb; use std::fmt::Debug; +use rquickjs::AsyncContext; use tokio::sync::oneshot; fn send_response(tx: oneshot::Sender, response: T) -> anyhow::Result<()> @@ -26,8 +26,8 @@ where } #[frb(ignore)] -pub async fn execute_artists(command: ArtistCommands, context: &mut Context) -> anyhow::Result<()> { - let mut artist = PluginArtistEndpoint::new(context); +pub async fn execute_artists(command: ArtistCommands, context: &AsyncContext) -> anyhow::Result<()> { + let artist = PluginArtistEndpoint::new(context); match command { ArtistCommands::GetArtist { id, response_tx } => { let artist = artist.get_artist(id).await; @@ -72,8 +72,8 @@ pub async fn execute_artists(command: ArtistCommands, context: &mut Context) -> } #[frb(ignore)] -pub async fn execute_albums(command: AlbumCommands, context: &mut Context) -> anyhow::Result<()> { - let mut album = PluginAlbumEndpoint::new(context); +pub async fn execute_albums(command: AlbumCommands, context: &AsyncContext) -> anyhow::Result<()> { + let album = PluginAlbumEndpoint::new(context); match command { AlbumCommands::GetAlbum { id, response_tx } => { let album = album.get_album(id).await; @@ -110,9 +110,9 @@ pub async fn execute_albums(command: AlbumCommands, context: &mut Context) -> an #[frb(ignore)] pub async fn execute_audio_source( command: AudioSourceCommands, - context: &mut Context, + context: &AsyncContext, ) -> anyhow::Result<()> { - let mut audio_source = PluginAudioSourceEndpoint::new(context); + let audio_source = PluginAudioSourceEndpoint::new(context); match command { AudioSourceCommands::Matches { track, response_tx } => { let audio_source = audio_source.matches(track).await; @@ -129,15 +129,15 @@ pub async fn execute_audio_source( } #[frb(ignore)] -pub async fn execute_auth(command: AuthCommands, context: &mut Context) -> anyhow::Result<()> { - let mut auth = PluginAuthEndpoint::new(context); +pub async fn execute_auth(command: AuthCommands, context: &AsyncContext) -> anyhow::Result<()> { + let auth = PluginAuthEndpoint::new(context); match command { AuthCommands::Authenticate { response_tx } => { let res = auth.authenticate().await; send_response(response_tx, res) } AuthCommands::IsAuthenticated { response_tx } => { - let res = auth.is_authenticated(); + let res = auth.is_authenticated().await; send_response(response_tx, res) } AuthCommands::Logout { response_tx } => { @@ -148,8 +148,8 @@ pub async fn execute_auth(command: AuthCommands, context: &mut Context) -> anyho } #[frb(ignore)] -pub async fn execute_browse(command: BrowseCommands, context: &mut Context) -> anyhow::Result<()> { - let mut browse = PluginBrowseEndpoint::new(context); +pub async fn execute_browse(command: BrowseCommands, context: &AsyncContext) -> anyhow::Result<()> { + let browse = PluginBrowseEndpoint::new(context); match command { BrowseCommands::Sections { offset, @@ -172,8 +172,8 @@ pub async fn execute_browse(command: BrowseCommands, context: &mut Context) -> a } #[frb(ignore)] -pub async fn execute_core(command: CoreCommands, context: &mut Context) -> anyhow::Result<()> { - let mut core = PluginCoreEndpoint::new(context); +pub async fn execute_core(command: CoreCommands, context: &AsyncContext) -> anyhow::Result<()> { + let core = PluginCoreEndpoint::new(context); match command { CoreCommands::CheckUpdate { response_tx, @@ -190,7 +190,7 @@ pub async fn execute_core(command: CoreCommands, context: &mut Context) -> anyho send_response(response_tx, res) } CoreCommands::Support { response_tx } => { - let res = core.support(); + let res = core.support().await; send_response(response_tx, res) } } @@ -199,9 +199,9 @@ pub async fn execute_core(command: CoreCommands, context: &mut Context) -> anyho #[frb(ignore)] pub async fn execute_playlist( command: PlaylistCommands, - context: &mut Context, + context: &AsyncContext, ) -> anyhow::Result<()> { - let mut playlist = PluginPlaylistEndpoint::new(context); + let playlist = PluginPlaylistEndpoint::new(context); match command { PlaylistCommands::GetPlaylist { id, response_tx } => { let playlist = playlist.get_playlist(id).await; @@ -284,11 +284,11 @@ pub async fn execute_playlist( } #[frb(ignore)] -pub async fn execute_search(command: SearchCommands, context: &mut Context) -> anyhow::Result<()> { - let mut search = PluginSearchEndpoint::new(context); +pub async fn execute_search(command: SearchCommands, context: &AsyncContext) -> anyhow::Result<()> { + let search = PluginSearchEndpoint::new(context); match command { SearchCommands::Chips { response_tx } => { - let chips = search.chips(); + let chips = search.chips().await; send_response(response_tx, chips) } SearchCommands::All { query, response_tx } => { @@ -335,8 +335,8 @@ pub async fn execute_search(command: SearchCommands, context: &mut Context) -> a } #[frb(ignore)] -pub async fn execute_track(command: TrackCommands, context: &mut Context) -> anyhow::Result<()> { - let mut track = PluginTrackEndpoint::new(context); +pub async fn execute_track(command: TrackCommands, context: &AsyncContext) -> anyhow::Result<()> { + let track = PluginTrackEndpoint::new(context); match command { TrackCommands::GetTrack { id, response_tx } => { let res = track.get_track(id).await; @@ -358,8 +358,8 @@ pub async fn execute_track(command: TrackCommands, context: &mut Context) -> any } #[frb(ignore)] -pub async fn execute_user(command: UserCommands, context: &mut Context) -> anyhow::Result<()> { - let mut user = PluginUserEndpoint::new(context); +pub async fn execute_user(command: UserCommands, context: &AsyncContext) -> anyhow::Result<()> { + let user = PluginUserEndpoint::new(context); match command { UserCommands::Me { response_tx } => { let me = user.me().await; diff --git a/rust/src/api/plugin/mod.rs b/rust/src/api/plugin/mod.rs index 7eadff58..14a1d763 100644 --- a/rust/src/api/plugin/mod.rs +++ b/rust/src/api/plugin/mod.rs @@ -2,5 +2,4 @@ pub mod commands; pub mod plugin; pub mod executors; pub mod senders; -pub mod models; -mod event_loop; \ No newline at end of file +pub mod models; \ No newline at end of file diff --git a/rust/src/api/plugin/plugin.rs b/rust/src/api/plugin/plugin.rs index 54daeffc..5a2e1e56 100644 --- a/rust/src/api/plugin/plugin.rs +++ b/rust/src/api/plugin/plugin.rs @@ -1,5 +1,4 @@ use crate::api::plugin::commands::PluginCommand; -use crate::api::plugin::event_loop::Queue; use crate::api::plugin::executors::{ execute_albums, execute_artists, execute_audio_source, execute_auth, execute_browse, execute_core, execute_playlist, execute_search, execute_track, execute_user, @@ -10,122 +9,96 @@ use crate::api::plugin::senders::{ PluginBrowseSender, PluginCoreSender, PluginPlaylistSender, PluginSearchSender, PluginTrackSender, PluginUserSender, }; -use crate::internal::apis::fetcher::ReqwestFetcher; use anyhow::anyhow; -use boa_engine::job::JobExecutor; -use boa_engine::{Context, Source}; -use boa_runtime::{fetch, interval, microtask, text, Console, DefaultLogger}; use flutter_rust_bridge::frb; -use std::cell::RefCell; -use std::rc::Rc; -use std::sync::Arc; +use llrt_modules::{abort, buffer, console, crypto, events, exceptions, fetch, navigator, timers, url, util}; +use llrt_modules::module_builder::ModuleBuilder; +use rquickjs::{async_with, AsyncContext, AsyncRuntime, Error}; use std::thread; -use std::time::Duration; -use tokio::runtime::Runtime; +use tokio::sync::mpsc; use tokio::sync::mpsc::Sender; -use tokio::sync::{mpsc, Mutex}; use tokio::task; +use tokio::task::LocalSet; #[derive(Debug, Clone)] -#[frb(opaque)] pub struct OpaqueSender { pub sender: Sender, } -async fn js_poller_thread(context: Arc>, queue: Rc) -> anyhow::Result<()> { - let local_set = task::LocalSet::new(); +#[frb(ignore)] +async fn create_context() -> anyhow::Result<(AsyncContext, AsyncRuntime)> { + let runtime = AsyncRuntime::new().expect("Unable to create async runtime"); - local_set - .run_until(async { - let mut ctx = context.lock().await; - queue.run_jobs_async(&RefCell::new(&mut *ctx)).await - }) + let mut module_builder = ModuleBuilder::new(); + + module_builder = module_builder + .with_global(abort::init) + .with_global(buffer::init) + .with_global(console::init) + .with_global(crypto::init) + .with_global(events::init) + .with_global(exceptions::init) + .with_global(fetch::init) + .with_global(navigator::init) + .with_global(url::init) + .with_global(timers::init) + .with_global(util::init) + ; + + let (module_resolver, module_loader, global_attachment) = module_builder.build(); + runtime + .set_loader((module_resolver,), (module_loader,)) + .await; + + let context = AsyncContext::full(&runtime) .await - .map_err(|e| anyhow!("{}", e))?; - Ok(()) -} + .expect("Unable to create async context"); -// #[frb(ignore)] + async_with!(context => |ctx| { + global_attachment.attach(&ctx)?; + Ok::<(), Error>(()) + }) + .await + .map_err(|e| anyhow!("Failed to register globals: {}", e))?; + + Ok((context, runtime)) +} +#[frb(ignore)] async fn js_executor_thread( rx: &mut mpsc::Receiver, - context: Arc>, + ctx: &AsyncContext, ) -> anyhow::Result<()> { - if let Some(command) = rx.recv().await { - let result = { - println!("JS Executor thread received command: {:?}", command); - match command { - PluginCommand::Artist(commands) => { - let mut ctx = context.lock().await; - execute_artists(commands, &mut *ctx).await - } - PluginCommand::Album(commands) => { - let mut ctx = context.lock().await; - execute_albums(commands, &mut *ctx).await - } - PluginCommand::AudioSource(commands) => { - let mut ctx = context.lock().await; - execute_audio_source(commands, &mut *ctx).await - } - PluginCommand::Auth(commands) => { - let mut ctx = context.lock().await; - execute_auth(commands, &mut *ctx).await - } - PluginCommand::Browse(commands) => { - let mut ctx = context.lock().await; - execute_browse(commands, &mut *ctx).await - } - PluginCommand::Core(commands) => { - let mut ctx = context.lock().await; - execute_core(commands, &mut *ctx).await - } - PluginCommand::Playlist(commands) => { - let mut ctx = context.lock().await; - execute_playlist(commands, &mut *ctx).await - } - PluginCommand::Search(commands) => { - let mut ctx = context.lock().await; - execute_search(commands, &mut *ctx).await - } - PluginCommand::Track(commands) => { - let mut ctx = context.lock().await; - execute_track(commands, &mut *ctx).await - } - PluginCommand::User(commands) => { - let mut ctx = context.lock().await; - execute_user(commands, &mut *ctx).await - } - PluginCommand::Shutdown => { - println!("JS Executor thread shutting down."); - return anyhow::Ok(()); - } - } - }; + while let Some(command) = rx.recv().await { + println!("JS Executor thread received command: {:?}", command); + if let PluginCommand::Shutdown = command { + println!("JS Executor thread shutting down."); + return anyhow::Ok(()); + } - println!("JS executor command completed"); - return result; + let ctx = ctx.clone(); + task::spawn_local(async move { + let result = match command { + PluginCommand::Artist(commands) => execute_artists(commands, &ctx).await, + PluginCommand::Album(commands) => execute_albums(commands, &ctx).await, + PluginCommand::AudioSource(commands) => execute_audio_source(commands, &ctx).await, + PluginCommand::Auth(commands) => execute_auth(commands, &ctx).await, + PluginCommand::Browse(commands) => execute_browse(commands, &ctx).await, + PluginCommand::Core(commands) => execute_core(commands, &ctx).await, + PluginCommand::Playlist(commands) => execute_playlist(commands, &ctx).await, + PluginCommand::Search(commands) => execute_search(commands, &ctx).await, + PluginCommand::Track(commands) => execute_track(commands, &ctx).await, + PluginCommand::User(commands) => execute_user(commands, &ctx).await, + PluginCommand::Shutdown => unreachable!(), + }; + + if let Err(e) = result { + eprintln!("Error executing command: {:?}", e); + } + }); } Ok(()) } -#[frb(ignore)] -pub async fn create_context() -> anyhow::Result<(Context, Rc)> { - let queue = Rc::new(Queue::new()); - let mut context = Context::builder() - .job_executor(queue.clone()) - .build() - .map_err(|e| anyhow!("{}", e))?; - - Console::register_with_logger(DefaultLogger, &mut context).map_err(|e| anyhow!("{}", e))?; - fetch::register(ReqwestFetcher::new(), None, &mut context).map_err(|e| anyhow!("{}", e))?; - interval::register(&mut context).map_err(|e| anyhow!("{}", e))?; - microtask::register(None, &mut context).map_err(|e| anyhow!("{}", e))?; - text::register(None, &mut context).map_err(|e| anyhow!("{}", e))?; - interval::register(&mut context).map_err(|e| anyhow!("{}", e))?; - microtask::register(None, &mut context).map_err(|e| anyhow!("{}", e))?; - - Ok((context, queue)) -} - pub struct SpotubePlugin { pub artist: PluginArtistSender, pub album: PluginAlbumSender, @@ -156,7 +129,7 @@ impl SpotubePlugin { } } - // #[frb(sync)] + #[frb(sync)] pub fn new_context( plugin_script: String, plugin_config: PluginConfiguration, @@ -164,10 +137,13 @@ impl SpotubePlugin { let (command_tx, mut command_rx) = mpsc::channel(32); let _thread_handle = thread::spawn(move || { - let rt = Runtime::new().unwrap(); - if let Err(e) = rt.block_on(async { - let (context, queue) = create_context().await.unwrap(); - let context_arc_mutex = Arc::new(Mutex::new(context)); + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap(); + let local = LocalSet::new(); + if let Err(e) = local.block_on(&rt, async { + let (ctx, runtime) = create_context().await?; let injection = format!( "globalThis.pluginInstance = new {}();", @@ -175,38 +151,11 @@ impl SpotubePlugin { ); let script = format!("{}\n{}", plugin_script, injection); - { - let context_refcell = context_arc_mutex.clone(); + ctx.with(|cx| cx.eval::<(), _>(script.as_str())).await?; - context_refcell - .lock() - .await - .eval(Source::from_bytes(script.as_bytes())) - .map_err(|e| anyhow!("{}", e))?; + if let Err(e) = js_executor_thread(&mut command_rx, &ctx).await { + eprintln!("JS executor error: {}", e); } - - loop { - let executor = js_executor_thread(&mut command_rx, context_arc_mutex.clone()); - let poller = js_poller_thread(context_arc_mutex.clone(), queue.clone()); - let sleep_timer = tokio::time::sleep(Duration::from_millis(10)); - - tokio::select!( - res = executor => { - if let Err(e) = res { - eprintln!("JS Executor task error: {}", e); - break; - } - }, - res = poller => { - if let Err(e) = res { - eprintln!("JS Poller task error: {}", e); - break; - } - }, - _ = sleep_timer => {}, - ); - } - anyhow::Ok(()) }) { eprintln!("JS Executor thread error: {}", e); diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 794d6cc0..546cc92b 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -27,6 +27,7 @@ use crate::api::plugin::commands::*; use crate::api::plugin::plugin::*; +use crate::*; use flutter_rust_bridge::for_generated::byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt}; use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable}; use flutter_rust_bridge::{Handler, IntoIntoDart}; @@ -5764,6 +5765,7 @@ mod io { use super::*; use crate::api::plugin::commands::*; use crate::api::plugin::plugin::*; + use crate::*; use flutter_rust_bridge::for_generated::byteorder::{ NativeEndian, ReadBytesExt, WriteBytesExt, }; diff --git a/rust/src/internal/album.rs b/rust/src/internal/album.rs index accdca46..eb1151c2 100644 --- a/rust/src/internal/album.rs +++ b/rust/src/internal/album.rs @@ -1,148 +1,94 @@ use crate::api::plugin::models::album::SpotubeFullAlbumObject; use crate::api::plugin::models::pagination::SpotubePaginationResponseObject; -use crate::internal::utils; -use anyhow::anyhow; -use boa_engine::{js_string, Context, JsValue}; +use crate::internal::utils::js_invoke_async_method_to_json; use flutter_rust_bridge::frb; +use rquickjs::{async_with, AsyncContext}; +use serde_json::Value; -#[derive(Debug)] -pub struct PluginAlbumEndpoint<'a>(&'a mut Context); +pub struct PluginAlbumEndpoint<'a>(&'a AsyncContext); impl<'a> PluginAlbumEndpoint<'a> { #[frb(ignore)] - pub fn new(context: &'a mut Context) -> PluginAlbumEndpoint<'a> { + pub fn new(context: &'a AsyncContext) -> PluginAlbumEndpoint<'a> { PluginAlbumEndpoint(context) } - fn album_obj(&mut self) -> anyhow::Result { - let global = self.0.global_object(); - - let plugin_instance = global - .get(js_string!("pluginInstance"), self.0) - .map_err(|e| anyhow!("{}", e)) - .and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?; - - plugin_instance - .get(js_string!("album"), self.0) - .or_else(|e| Err(anyhow!("album not found: \n{}", e))) - } - - pub async fn get_album(&mut self, id: String) -> anyhow::Result { - let album_val = self.album_obj()?; - let album_object = album_val.as_object().ok_or(anyhow!("Not an object"))?; - - let get_album_fn = album_object - .get(js_string!("getAlbum"), self.0) - .map_err(|e| anyhow!("JS error while accessing getAlbum: {}", e))? - .as_function() - .ok_or(anyhow!("getAlbum is not a function"))?; - - let args = [JsValue::from(js_string!(id))]; - - let res_json = - utils::js_call_to_json(get_album_fn.call(&album_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + pub async fn get_album(&self, id: String) -> anyhow::Result { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json(ctx.clone(), "album", "getAlbum", &[id]).await + ?.expect("[hey][smartypants] album.getAlbum should return a SpotifyFullAlbumObject") + ) + }) + .await } pub async fn tracks( - &mut self, - + &self, id: String, offset: Option, limit: Option, ) -> anyhow::Result { - let album_val = self.album_obj()?; - let album_object = album_val.as_object().ok_or(anyhow!("Not an object"))?; - - let tracks_fn = album_object - .get(js_string!("tracks"), self.0) - .map_err(|e| anyhow!("JS error while accessing tracks: {}", e))? - .as_function() - .ok_or(anyhow!("tracks is not a function"))?; - - let args: [JsValue; 3] = [ - JsValue::from(js_string!(id)), - match offset { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - match limit { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - let res_json = utils::js_call_to_json(tracks_fn.call(&album_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx.clone(), + "album", + "tracks", + &[Value::String(id), serde_json::to_value(offset)?, serde_json::to_value(limit.unwrap())?] + ) + .await? + .expect("[hey][smartypants] album.tracks should return a SpotifyPaginationResponseObject") + ) + }).await } pub async fn releases( - &mut self, - + &self, offset: Option, limit: Option, ) -> anyhow::Result { - let album_val = self.album_obj()?; - let album_object = album_val.as_object().ok_or(anyhow!("Not an object"))?; - - let releases_fn = album_object - .get(js_string!("releases"), self.0) - .map_err(|e| anyhow!("JS error while accessing releases: {}", e))? - .as_function() - .ok_or(anyhow!("releases is not a function"))?; - - let args: [JsValue; 2] = [ - match offset { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - match limit { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - let res_json = - utils::js_call_to_json(releases_fn.call(&album_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx.clone(), + "album", + "releases", + &[serde_json::to_value(offset)?, serde_json::to_value(limit.unwrap())?] + ) + .await? + .expect("[hey][smartypants] album.releases should return a SpotifyPaginationResponseObject") + ) + }).await } - pub async fn save(&mut self, ids: Vec) -> anyhow::Result<()> { - let album_val = self.album_obj()?; - let album_object = album_val.as_object().ok_or(anyhow!("Not an object"))?; - - let save_fn = album_object - .get(js_string!("save"), self.0) - .map_err(|e| anyhow!("JS error while accessing save: {}", e))? - .as_function() - .ok_or(anyhow!("save is not a function"))?; - - let ids_val = utils::vec_string_to_js_array(ids, self.0)?; - let args = [ids_val.into()]; - - utils::js_call_to_void(save_fn.call(&album_val, &args, self.0), self.0).await?; - - Ok(()) + pub async fn save(&self, ids: Vec) -> anyhow::Result<()> { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, ()>( + ctx.clone(), + "album", + "save", + &[Value::Array(ids.into_iter().map(|id| Value::String(id)).collect())] + ) + .await? + .expect("[hey][smartypants] album.save should return a SpotifyPaginationResponseObject") + ) + }).await } - pub async fn unsave(&mut self, ids: Vec) -> anyhow::Result<()> { - let album_val = self.album_obj()?; - let album_object = album_val.as_object().ok_or(anyhow!("Not an object"))?; - - let unsave_fn = album_object - .get(js_string!("unsave"), self.0) - .map_err(|e| anyhow!("JS error while accessing save: {}", e))? - .as_function() - .ok_or(anyhow!("save is not a function"))?; - - let ids_val = utils::vec_string_to_js_array(ids, self.0)?; - let args = [ids_val.into()]; - - utils::js_call_to_void(unsave_fn.call(&album_val, &args, self.0), self.0).await?; - - Ok(()) + pub async fn unsave(&self, ids: Vec) -> anyhow::Result<()> { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, ()>( + ctx.clone(), + "album", + "unsave", + &[Value::Array(ids.into_iter().map(|id| Value::String(id)).collect())] + ) + .await? + .expect("[hey][smartypants] album.unsave should return a SpotifyPaginationResponseObject") + ) + }).await } } diff --git a/rust/src/internal/apis/fetcher.rs b/rust/src/internal/apis/fetcher.rs index 50713ed4..e69de29b 100644 --- a/rust/src/internal/apis/fetcher.rs +++ b/rust/src/internal/apis/fetcher.rs @@ -1,59 +0,0 @@ -use std::{cell::RefCell, rc::Rc}; - -use boa_engine::{Context, Finalize, JsData, JsResult, Trace}; -use boa_runtime::fetch::{request::JsRequest, response::JsResponse, Fetcher}; - -#[derive(Default, Debug, Clone, Trace, Finalize, JsData)] -pub struct ReqwestFetcher { - #[unsafe_ignore_trace] - client: reqwest::Client, -} - -impl ReqwestFetcher { - pub fn new() -> Self { - ReqwestFetcher { - client: reqwest::Client::new(), - } - } -} - -impl Fetcher for ReqwestFetcher { - async fn fetch( - self: Rc, - request: JsRequest, - _context: &RefCell<&mut Context>, - ) -> JsResult { - use boa_engine::{JsError, JsString}; - - let request = request.into_inner(); - let method = request.method().clone(); - let url = request.uri().to_string(); - let req = self - .client - .request(method, &url) - .headers(request.headers().clone()); - - let req = req - .body(request.body().clone()) - .build() - .map_err(JsError::from_rust)?; - - let resp = self.client.execute(req).await.map_err(JsError::from_rust)?; - - let status = resp.status(); - let headers = resp.headers().clone(); - let bytes = resp.bytes().await.map_err(JsError::from_rust)?; - let mut builder = http::Response::builder().status(status.as_u16()); - - for k in headers.keys() { - for v in headers.get_all(k) { - builder = builder.header(k.as_str(), v); - } - } - - builder - .body(bytes.to_vec()) - .map_err(JsError::from_rust) - .map(|request| JsResponse::basic(JsString::from(url), request)) - } -} diff --git a/rust/src/internal/artist.rs b/rust/src/internal/artist.rs index 6e98591c..a017390f 100644 --- a/rust/src/internal/artist.rs +++ b/rust/src/internal/artist.rs @@ -1,178 +1,115 @@ +use flutter_rust_bridge::frb; use crate::api::plugin::models::artist::SpotubeFullArtistObject; use crate::api::plugin::models::pagination::SpotubePaginationResponseObject; -use crate::internal::utils; -use anyhow::anyhow; -use boa_engine::{js_string, Context, JsValue}; -use flutter_rust_bridge::frb; +use crate::internal::utils::js_invoke_async_method_to_json; +use rquickjs::{async_with, AsyncContext}; +use serde_json::Value; -#[derive(Debug)] -pub struct PluginArtistEndpoint<'a>(&'a mut Context); +pub struct PluginArtistEndpoint<'a>(&'a AsyncContext); impl<'a> PluginArtistEndpoint<'a> { #[frb(ignore)] - pub fn new(context: &'a mut Context) -> PluginArtistEndpoint<'a> { + pub fn new(context: &'a AsyncContext) -> PluginArtistEndpoint<'a> { PluginArtistEndpoint(context) } - fn artist_obj(&mut self) -> anyhow::Result { - let global = self.0.global_object(); - - let plugin_instance = global - .get(js_string!("pluginInstance"), self.0) - .map_err(|e| anyhow!("{}", e)) - .and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?; - - return plugin_instance - .get(js_string!("artist"), self.0) - .or_else(|e| Err(anyhow!("artist not found: \n{}", e))); - } - - pub async fn get_artist(&mut self, id: String) -> anyhow::Result { - let artist_val = self.artist_obj()?; - let artist_object = artist_val.as_object().ok_or(anyhow!("Not an object"))?; - - let get_artist_fn = artist_object - .get(js_string!("getArtist"), self.0) - .map_err(|e| anyhow!("JS error while accessing getArtist: {}", e))? - .as_function() - .ok_or(anyhow!("getArtist is not a function"))?; - - let args = [JsValue::from(js_string!(id))]; - - let res_json = - utils::js_call_to_json(get_artist_fn.call(&artist_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + pub async fn get_artist(&self, id: String) -> anyhow::Result { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json(ctx.clone(), "artist", "getArtist", &[id]).await + ?.expect("[hey][smartypants] artist.getArtist should return a SpotifyFullArtistObject") + ) + }) + .await } pub async fn top_tracks( - &mut self, + &self, id: String, offset: Option, limit: Option, ) -> anyhow::Result { - let artist_val = self.artist_obj()?; - let artist_object = artist_val.as_object().ok_or(anyhow!("Not an object"))?; - - let top_tracks_fn = artist_object - .get(js_string!("topTracks"), self.0) - .map_err(|e| anyhow!("JS error while accessing getArtist: {}", e))? - .as_function() - .ok_or(anyhow!("getArtist is not a function"))?; - - let args: [JsValue; 3] = [ - JsValue::from(js_string!(id)), - match offset { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - match limit { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - let res_json = - utils::js_call_to_json(top_tracks_fn.call(&artist_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx.clone(), + "artist", + "topTracks", + &[Value::String(id), serde_json::to_value(offset)?, serde_json::to_value(limit.unwrap())?] + ) + .await? + .expect("[hey][smartypants] album.tracks should return a SpotifyPaginationResponseObject") + ) + }).await } pub async fn albums( - &mut self, + &self, id: String, offset: Option, limit: Option, ) -> anyhow::Result { - let artist_val = self.artist_obj()?; - let artist_object = artist_val.as_object().ok_or(anyhow!("Not an object"))?; - - let albums_fn = artist_object - .get(js_string!("albums"), self.0) - .map_err(|e| anyhow!("JS error while accessing albums: {}", e))? - .as_function() - .ok_or(anyhow!("albums is not a function"))?; - - let args: [JsValue; 3] = [ - JsValue::from(js_string!(id)), - match offset { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - match limit { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - let res_json = - utils::js_call_to_json(albums_fn.call(&artist_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx.clone(), + "artist", + "albums", + &[Value::String(id), serde_json::to_value(offset)?, serde_json::to_value(limit.unwrap())?] + ) + .await? + .expect("[hey][smartypants] artist.albums should return a SpotifyPaginationResponseObject") + ) + }).await } pub async fn related( - &mut self, + &self, id: String, offset: Option, limit: Option, ) -> anyhow::Result { - let artist_val = self.artist_obj()?; - let artist_object = artist_val.as_object().ok_or(anyhow!("Not an object"))?; - - let related_fn = artist_object - .get(js_string!("related"), self.0) - .map_err(|e| anyhow!("JS error while accessing related: {}", e))? - .as_function() - .ok_or(anyhow!("related is not a function"))?; - - let args = [ - JsValue::from(js_string!(id)), - match offset { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - match limit { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - let res_json = - utils::js_call_to_json(related_fn.call(&artist_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx.clone(), + "artist", + "related", + &[Value::String(id), serde_json::to_value(offset)?, serde_json::to_value(limit.unwrap())?] + ) + .await? + .expect("[hey][smartypants] artist.related should return a SpotifyPaginationResponseObject") + ) + }).await } - pub async fn save(&mut self, ids: Vec) -> anyhow::Result<()> { - let artist_val = self.artist_obj()?; - let artist_object = artist_val.as_object().ok_or(anyhow!("Not an object"))?; - - let save_fn = artist_object - .get(js_string!("save"), self.0) - .map_err(|e| anyhow!("JS error while accessing save: {}", e))? - .as_function() - .ok_or(anyhow!("save is not a function"))?; - - let ids_val = utils::vec_string_to_js_array(ids, self.0)?; - let args = [ids_val.into()]; - - utils::js_call_to_void(save_fn.call(&artist_val, &args, self.0), self.0).await + pub async fn save(&self, ids: Vec) -> anyhow::Result<()> { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, ()>( + ctx.clone(), + "artist", + "save", + &[Value::Array(ids.into_iter().map(|id| Value::String(id)).collect())] + ) + .await? + .expect("[hey][smartypants] artist.save should return a SpotifyPaginationResponseObject") + ) + }).await } - pub async fn unsave(&mut self, ids: Vec) -> anyhow::Result<()> { - let artist_val = self.artist_obj()?; - let artist_object = artist_val.as_object().ok_or(anyhow!("Not an object"))?; - - let unsave_fn = artist_object - .get(js_string!("unsave"), self.0) - .map_err(|e| anyhow!("JS error while accessing save: {}", e))? - .as_function() - .ok_or(anyhow!("save is not a function"))?; - - let ids_val = utils::vec_string_to_js_array(ids, self.0)?; - let args = [ids_val.into()]; - - utils::js_call_to_void(unsave_fn.call(&artist_val, &args, self.0), self.0).await + pub async fn unsave(&self, ids: Vec) -> anyhow::Result<()> { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, ()>( + ctx.clone(), + "artist", + "unsave", + &[Value::Array(ids.into_iter().map(|id| Value::String(id)).collect())] + ) + .await? + .expect("[hey][smartypants] artist.unsave should return a SpotifyPaginationResponseObject") + ) + }).await } } diff --git a/rust/src/internal/audio_source.rs b/rust/src/internal/audio_source.rs index ca4dd15a..870d6bc2 100644 --- a/rust/src/internal/audio_source.rs +++ b/rust/src/internal/audio_source.rs @@ -2,80 +2,51 @@ use crate::api::plugin::models::audio_source::{ SpotubeAudioSourceMatchObject, SpotubeAudioSourceStreamObject, }; use crate::api::plugin::models::track::SpotubeTrackObject; -use crate::internal::utils; -use anyhow::anyhow; -use boa_engine::{js_string, Context, JsValue}; +use crate::internal::utils::js_invoke_async_method_to_json; use flutter_rust_bridge::frb; +use rquickjs::{async_with, AsyncContext}; -#[derive(Debug)] -pub struct PluginAudioSourceEndpoint<'a>(&'a mut Context); +pub struct PluginAudioSourceEndpoint<'a>(&'a AsyncContext); impl<'a> PluginAudioSourceEndpoint<'a> { #[frb(ignore)] - pub fn new(context: &'a mut Context) -> PluginAudioSourceEndpoint<'a> { + pub fn new(context: &'a AsyncContext) -> PluginAudioSourceEndpoint<'a> { PluginAudioSourceEndpoint(context) } - fn audio_source_obj(&mut self) -> anyhow::Result { - let global = self.0.global_object(); - - let plugin_instance = global - .get(js_string!("pluginInstance"), self.0) - .map_err(|e| anyhow!("{}", e)) - .and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?; - - plugin_instance - .get(js_string!("audioSource"), self.0) - .or_else(|e| Err(anyhow!("artist not found: \n{}", e))) - } - pub async fn matches( - &mut self, + &self, track: SpotubeTrackObject, ) -> anyhow::Result> { - let audio_source_val = self.audio_source_obj()?; - let audio_source_object = audio_source_val - .as_object() - .ok_or(anyhow!("Not an object"))?; - - let matches_fn = audio_source_object - .get(js_string!("matches"), self.0) - .map_err(|e| anyhow!("JS error while accessing matches: {}", e))? - .as_function() - .ok_or(anyhow!("matches is not a function"))?; - - let value = serde_json::to_value(track)?; - let track_val = utils::json_value_to_js(&value, self.0).map_err(|e| anyhow!("{}", e))?; - let args = [track_val]; - - let res = - utils::js_call_to_json(matches_fn.call(&audio_source_val, &args, self.0), self.0).await?; - - serde_json::from_value(res).map_err(|e| anyhow!("{}", e)) + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json( + ctx.clone(), + "audioSource", + "matches", + &[track] + ) + .await? + .expect("[hey][smartypants] album.tracks should return a SpotifyPaginationResponseObject") + ) + }).await } pub async fn streams( - &mut self, + &self, matched: SpotubeAudioSourceMatchObject, ) -> anyhow::Result> { - let audio_source_val = self.audio_source_obj()?; - let audio_source_object = audio_source_val - .as_object() - .ok_or(anyhow!("Not an object"))?; - - let matches_fn = audio_source_object - .get(js_string!("streams"), self.0) - .map_err(|e| anyhow!("JS error while accessing matches: {}", e))? - .as_function() - .ok_or(anyhow!("matches is not a function"))?; - - let value = serde_json::to_value(matched)?; - let matched_val = utils::json_value_to_js(&value, self.0).map_err(|e| anyhow!("{}", e))?; - let args = [matched_val]; - - let res = - utils::js_call_to_json(matches_fn.call(&audio_source_val, &args, self.0), self.0).await?; - - serde_json::from_value(res).map_err(|e| anyhow!("{}", e)) + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json( + ctx.clone(), + "audioSource", + "streams", + &[matched] + ) + .await? + .expect("[hey][smartypants] audioSource.streams should return a SpotifyPaginationResponseObject") + ) + }).await } -} +} \ No newline at end of file diff --git a/rust/src/internal/auth.rs b/rust/src/internal/auth.rs index a6ac7632..f46cb92a 100644 --- a/rust/src/internal/auth.rs +++ b/rust/src/internal/auth.rs @@ -1,74 +1,60 @@ -use crate::internal::utils; -use anyhow::anyhow; -use boa_engine::{js_string, Context, JsValue}; +use crate::internal::utils::js_invoke_async_method_to_json; use flutter_rust_bridge::frb; +use rquickjs::{async_with, AsyncContext}; -#[derive(Debug)] -pub struct PluginAuthEndpoint<'a>(&'a mut Context); +pub struct PluginAuthEndpoint<'a>(&'a AsyncContext); impl<'a> PluginAuthEndpoint<'a> { #[frb(ignore)] - pub fn new(context: &'a mut Context) -> PluginAuthEndpoint<'a> { + pub fn new(context: &'a AsyncContext) -> PluginAuthEndpoint<'a> { PluginAuthEndpoint(context) } - fn auth_obj(&mut self) -> anyhow::Result { - let global = self.0.global_object(); - - let plugin_instance = global - .get(js_string!("pluginInstance"), self.0) - .map_err(|e| anyhow!("{}", e)) - .and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?; - - return plugin_instance - .get(js_string!("auth"), self.0) - .or_else(|e| Err(anyhow!("auth not found:\n{}", e))); + pub async fn authenticate(&self) -> anyhow::Result<()> { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<(), ()>( + ctx.clone(), + "auth", + "authenticate", + &[] + ) + .await? + .expect("[hey][smartypants] auth.authenticate should return a void") + ) + }) + .await } - pub async fn authenticate(&mut self) -> anyhow::Result<()> { - let auth_val = self.auth_obj()?; - let auth_object = auth_val.as_object().ok_or(anyhow!("Not an object"))?; - - let authenticate_fn = auth_object - .get(js_string!("authenticate"), self.0) - .map_err(|e| anyhow!("JS error while accessing authenticate: {}", e))? - .as_function() - .ok_or(anyhow!("authenticate is not a function"))?; - - let args = []; - - utils::js_call_to_void(authenticate_fn.call(&auth_val, &args, self.0), self.0).await + pub async fn is_authenticated(&self) -> anyhow::Result { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<(), bool>( + ctx.clone(), + "auth", + "is_authenticated", + &[] + ) + .await? + .expect("[hey][smartypants] auth.is_authenticated should return a boolean") + ) + }) + .await } - pub fn is_authenticated(&mut self) -> anyhow::Result { - let auth_val = self.auth_obj()?; - let auth_object = auth_val.as_object().ok_or(anyhow!("Not an object"))?; - - let authenticate_fn = auth_object - .get(js_string!("is_authenticated"), self.0) - .map_err(|e| anyhow!("JS error while accessing authenticate: {}", e))? - .as_function() - .ok_or(anyhow!("authenticate is not a function"))?; - - authenticate_fn - .call(&auth_val, &[], self.0) - .map_err(|e| anyhow!("{}", e))? - .as_boolean() - .ok_or(anyhow!("Not a boolean")) - } - - pub async fn logout(&mut self) -> anyhow::Result<()> { - let auth_val = self.auth_obj()?; - let auth_object = auth_val.as_object().ok_or(anyhow!("Not an object"))?; - - let logout_fn = auth_object - .get(js_string!("logout"), self.0) - .map_err(|e| anyhow!("JS error while accessing authenticate: {}", e))? - .as_function() - .ok_or(anyhow!("authenticate is not a function"))?; - - let args = []; - - utils::js_call_to_void(logout_fn.call(&auth_val, &args, self.0), self.0).await + pub async fn logout(&self) -> anyhow::Result<()> { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<(), ()>( + ctx.clone(), + "auth", + "logout", + &[] + ) + .await? + .expect("[hey][smartypants] auth.logout should return a void") + ) + }) + .await } } diff --git a/rust/src/internal/browse.rs b/rust/src/internal/browse.rs index 1c1bf292..82811def 100644 --- a/rust/src/internal/browse.rs +++ b/rust/src/internal/browse.rs @@ -1,91 +1,56 @@ -use crate::internal::utils; -use anyhow::anyhow; -use boa_engine::{js_string, Context, JsValue}; -use flutter_rust_bridge::frb; use crate::api::plugin::models::pagination::SpotubePaginationResponseObject; +use crate::internal::utils::js_invoke_async_method_to_json; +use flutter_rust_bridge::frb; +use rquickjs::{async_with, AsyncContext}; -#[derive(Debug)] -pub struct PluginBrowseEndpoint<'a>(&'a mut Context); +pub struct PluginBrowseEndpoint<'a>(&'a AsyncContext); impl<'a> PluginBrowseEndpoint<'a> { #[frb(ignore)] - pub fn new(context: &'a mut Context) -> PluginBrowseEndpoint<'a> { + pub fn new(context: &'a AsyncContext) -> PluginBrowseEndpoint<'a> { PluginBrowseEndpoint(context) } - fn browse_obj(&mut self) -> anyhow::Result { - let global = self.0.global_object(); - - let plugin_instance = global - .get(js_string!("pluginInstance"), self.0) - .map_err(|e| anyhow!("{}", e)) - .and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?; - - plugin_instance - .get(js_string!("browse"), self.0) - .or_else(|e| Err(anyhow!("browse not found:\n{}", e))) - } - pub async fn sections( - &mut self, + &self, offset: Option, limit: Option, ) -> anyhow::Result { - let browse_val = self.browse_obj()?; - let browse_object = browse_val.as_object().ok_or(anyhow!("Not an object"))?; - - let sections_fn = browse_object - .get(js_string!("sections"), self.0) - .map_err(|e| anyhow!("JS error while accessing sections: {}", e))? - .as_function() - .ok_or(anyhow!("sections is not a function"))?; - - let args = [ - match offset { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - match limit { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - let res = utils::js_call_to_json(sections_fn.call(&browse_val, &args, self.0), self.0).await?; - - serde_json::from_value(res).map_err(|e| anyhow!("{}", e)) + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx.clone(), + "browse", + "sections", + &[serde_json::to_value(offset)?, serde_json::to_value(limit)?] + ) + .await? + .expect("[hey][smartypants] browse.sections should return a SpotifyPaginationResponseObject") + ) + }).await } pub async fn section_items( - &mut self, + &self, id: String, offset: Option, limit: Option, ) -> anyhow::Result { - let browse_val = self.browse_obj()?; - let browse_object = browse_val.as_object().ok_or(anyhow!("Not an object"))?; - - let section_items_fn = browse_object - .get(js_string!("sectionItems"), self.0) - .map_err(|e| anyhow!("JS error while accessing sectionItems: {}", e))? - .as_function() - .ok_or(anyhow!("sectionItems is not a function"))?; - - let args = [ - JsValue::from(js_string!(id)), - match offset { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - match limit { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - let res = - utils::js_call_to_json(section_items_fn.call(&browse_val, &args, self.0), self.0).await?; - - serde_json::from_value(res).map_err(|e| anyhow!("{}", e)) + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx.clone(), + "browse", + "sectionItems", + &[ + serde_json::to_value(id)?, + serde_json::to_value(offset)?, + serde_json::to_value(limit)?, + ] + ) + .await? + .expect("[hey][smartypants] browse.sectionItems should return a SpotifyPaginationResponseObject") + ) + }).await } } diff --git a/rust/src/internal/core.rs b/rust/src/internal/core.rs index c7b8b95e..0f4917a2 100644 --- a/rust/src/internal/core.rs +++ b/rust/src/internal/core.rs @@ -1,85 +1,49 @@ -use crate::api::plugin::models::core::{PluginConfiguration, PluginUpdateAvailable, ScrobbleDetails}; -use crate::internal::utils; +use crate::api::plugin::models::core::{ + PluginConfiguration, PluginUpdateAvailable, ScrobbleDetails, +}; +use crate::internal::utils::{js_invoke_async_method_to_json, js_invoke_method_to_json}; use anyhow::anyhow; -use boa_engine::{js_string, Context, JsValue}; use flutter_rust_bridge::frb; +use rquickjs::{async_with, AsyncContext}; -#[derive(Debug)] -pub struct PluginCoreEndpoint<'a>(&'a mut Context); +pub struct PluginCoreEndpoint<'a>(&'a AsyncContext); impl<'a> PluginCoreEndpoint<'a> { #[frb(ignore)] - pub fn new(context: &'a mut Context) -> PluginCoreEndpoint<'a> { + pub fn new(context: &'a AsyncContext) -> PluginCoreEndpoint<'a> { PluginCoreEndpoint(context) } - fn core_obj(&mut self) -> anyhow::Result { - let global = self.0.global_object(); - - let plugin_instance = global - .get(js_string!("pluginInstance"), self.0) - .map_err(|e| anyhow!("{}", e)) - .and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?; - - plugin_instance - .get(js_string!("core"), self.0) - .or_else(|e| Err(anyhow!("core not found:\n{}", e))) - } - pub async fn check_update( - &mut self, + &self, plugin_config: PluginConfiguration, ) -> anyhow::Result> { - let core_val = self.core_obj()?; - let core_object = core_val.as_object().ok_or(anyhow!("Not an object"))?; - - let check_update_fn = core_object - .get(js_string!("checkUpdate"), self.0) - .map_err(|e| anyhow!("JS error while accessing checkUpdate: {}", e))? - .as_function() - .ok_or(anyhow!("checkUpdate is not a function"))?; - - let value = serde_json::to_value(plugin_config)?; - let config_val = utils::json_value_to_js(&value, self.0).map_err(|e| anyhow!("{}", e))?; - let args = [config_val]; - - let res = utils::js_call_to_json(check_update_fn.call(&core_val, &args, self.0), self.0).await?; - if res.is_null() { - Ok(None) - } else { - serde_json::from_value(res).map_err(|e| anyhow!("{}", e)) - } + async_with!(self.0 => |ctx| { + js_invoke_async_method_to_json(ctx.clone(), "core", "checkUpdate", &[plugin_config]).await + }).await } - pub fn support(&mut self) -> anyhow::Result { - let core_val = self.core_obj()?; - let core_object = core_val.as_object().ok_or(anyhow!("Not an object"))?; - - let support_val = core_object - .get(js_string!("support"), self.0) - .map_err(|e| anyhow!("JS error while accessing support: {}", e))?; - - support_val - .as_string() - .ok_or(anyhow!("support is not a string"))? - .to_std_string() - .map_err(|e| anyhow!("{}", e)) + pub async fn support(&self) -> anyhow::Result { + self.0 + .with(|ctx| { + anyhow::Ok( + js_invoke_method_to_json::( + ctx.clone(), + "core", + "support", + &[], + )? + .expect("[hey][smartypants] core.support should return a string"), + ) + }) + .await } - pub async fn scrobble(&mut self, details: ScrobbleDetails) -> anyhow::Result<()> { - let core_val = self.core_obj()?; - let core_object = core_val.as_object().ok_or(anyhow!("Not an object"))?; - - let scrobble_fn = core_object - .get(js_string!("scrobble"), self.0) - .map_err(|e| anyhow!("JS error while accessing scrobble: {}", e))? - .as_function() - .ok_or(anyhow!("scrobble is not a function"))?; - - let value = serde_json::to_value(details)?; - let details_val = utils::json_value_to_js(&value, self.0).map_err(|e| anyhow!("{}", e))?; - let args = [details_val]; - - utils::js_call_to_void(scrobble_fn.call(&core_val, &args, self.0), self.0).await + pub async fn scrobble(&self, details: ScrobbleDetails) -> anyhow::Result<()> { + async_with!(self.0 => |ctx| { + js_invoke_async_method_to_json::<_, ()>(ctx.clone(), "core", "scrobble", &[details]).await?; + anyhow::Ok(()) + }) + .await } } diff --git a/rust/src/internal/playlist.rs b/rust/src/internal/playlist.rs index 9d07ba5e..f8cc2b5d 100644 --- a/rust/src/internal/playlist.rs +++ b/rust/src/internal/playlist.rs @@ -1,134 +1,82 @@ use crate::api::plugin::models::pagination::SpotubePaginationResponseObject; use crate::api::plugin::models::playlist::SpotubeFullPlaylistObject; -use crate::internal::utils; -use anyhow::anyhow; -use boa_engine::{js_string, Context, JsValue}; +use crate::internal::utils::js_invoke_async_method_to_json; use flutter_rust_bridge::frb; +use rquickjs::{async_with, AsyncContext}; +use serde_json::Value; -#[derive(Debug)] -pub struct PluginPlaylistEndpoint<'a>(&'a mut Context); +pub struct PluginPlaylistEndpoint<'a>(&'a AsyncContext); impl<'a> PluginPlaylistEndpoint<'a> { #[frb(ignore)] - pub fn new(context: &'a mut Context) -> PluginPlaylistEndpoint<'a> { + pub fn new(context: &'a AsyncContext) -> PluginPlaylistEndpoint<'a> { PluginPlaylistEndpoint(context) } - fn playlist_obj(&mut self) -> anyhow::Result { - let global = self.0.global_object(); - - let plugin_instance = global - .get(js_string!("pluginInstance"), self.0) - .map_err(|e| anyhow!("{}", e)) - .and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?; - - plugin_instance - .get(js_string!("playlist"), self.0) - .or_else(|e| Err(anyhow!("playlist not found: \n{}", e))) - } - - pub async fn get_playlist(&mut self, id: String) -> anyhow::Result { - let playlist_val = self.playlist_obj()?; - let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?; - - let get_playlist_fn = playlist_object - .get(js_string!("getPlaylist"), self.0) - .map_err(|e| anyhow!("{}", e))? - .as_function() - .ok_or(anyhow!("getPlaylist is not a function"))?; - - let args = [JsValue::from(js_string!(id))]; - - let res_json = - utils::js_call_to_json(get_playlist_fn.call(&playlist_val, &args, self.0), self.0) - .await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + pub async fn get_playlist(&self, id: String) -> anyhow::Result { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json( + ctx.clone(), + "playlist", + "getPlaylist", + &[id] + ) + .await? + .expect("[hey][smartypants] playlist.getPlaylist should return a SpotifyFullPlaylistObject") + ) + }).await } pub async fn tracks( - &mut self, + &self, id: String, offset: Option, limit: Option, ) -> anyhow::Result { - let playlist_val = self.playlist_obj()?; - let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?; - - let tracks_fn = playlist_object - .get(js_string!("tracks"), self.0) - .map_err(|e| anyhow!("{}", e))? - .as_function() - .ok_or(anyhow!("tracks is not a function"))?; - - let args: [JsValue; 3] = [ - JsValue::from(js_string!(id)), - match offset { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - match limit { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - let res_json = - utils::js_call_to_json(tracks_fn.call(&playlist_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx.clone(), + "playlist", + "tracks", + &[Value::String(id), serde_json::to_value(offset)?, serde_json::to_value(limit.unwrap())?] + ) + .await? + .expect("[hey][smartypants] artist.related should return a SpotifyPaginationResponseObject") + ) + }).await } pub async fn create( - &mut self, - + &self, user_id: String, name: String, description: Option, public: Option, collaborative: Option, ) -> anyhow::Result> { - let playlist_val = self.playlist_obj()?; - let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?; - - let create_fn = playlist_object - .get(js_string!("create"), self.0) - .map_err(|e| anyhow!("{}", e))? - .as_function() - .ok_or(anyhow!("create is not a function"))?; - - let args = [ - JsValue::from(js_string!(user_id)), - JsValue::from(js_string!(name)), - match description { - Some(o) => JsValue::from(js_string!(o)), - None => JsValue::undefined(), - }, - match public { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - match collaborative { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - let res_json = - utils::js_call_to_json(create_fn.call(&playlist_val, &args, self.0), self.0).await?; - - if res_json.is_null() { - Ok(None) - } else { - serde_json::from_value(res_json) - .map(Some) - .map_err(|e| anyhow!("{}", e)) - } + async_with!(self.0 => |ctx| { + js_invoke_async_method_to_json( + ctx.clone(), + "playlist", + "create", + &[ + Value::String(user_id), + Value::String(name), + Value::String(description.unwrap_or_default()), + serde_json::to_value(public.unwrap_or_default())?, + serde_json::to_value(collaborative.unwrap_or_default())?, + ] + ) + .await + }) + .await } pub async fn update( - &mut self, + &self, playlist_id: String, name: Option, @@ -136,135 +84,104 @@ impl<'a> PluginPlaylistEndpoint<'a> { public: Option, collaborative: Option, ) -> anyhow::Result<()> { - let playlist_val = self.playlist_obj()?; - let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?; - - let update_fn = playlist_object - .get(js_string!("update"), self.0) - .map_err(|e| anyhow!("{}", e))? - .as_function() - .ok_or(anyhow!("update is not a function"))?; - - let args = [ - JsValue::from(js_string!(playlist_id)), - match name { - Some(o) => JsValue::from(js_string!(o)), - None => JsValue::undefined(), - }, - match description { - Some(o) => JsValue::from(js_string!(o)), - None => JsValue::undefined(), - }, - match public { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - match collaborative { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - utils::js_call_to_void(update_fn.call(&playlist_val, &args, self.0), self.0).await + async_with!(self.0 => |ctx| { + js_invoke_async_method_to_json::<_, ()>( + ctx.clone(), + "playlist", + "update", + &[ + Value::String(playlist_id), + serde_json::to_value(name)?, + Value::String(description.unwrap_or_default()), + serde_json::to_value(public.unwrap_or_default())?, + serde_json::to_value(collaborative.unwrap_or_default())?, + ] + ) + .await.and_then(|_| Ok(())) + }) + .await } pub async fn add_tracks( - &mut self, + &self, playlist_id: String, track_ids: Vec, position: Option, ) -> anyhow::Result<()> { - let playlist_val = self.playlist_obj()?; - let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?; - - let add_tracks_fn = playlist_object - .get(js_string!("addTracks"), self.0) - .map_err(|e| anyhow!("{}", e))? - .as_function() - .ok_or(anyhow!("addTracks is not a function"))?; - - let args = [ - JsValue::from(js_string!(playlist_id)), - utils::vec_string_to_js_array(track_ids, self.0)?, - match position { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - utils::js_call_to_void(add_tracks_fn.call(&playlist_val, &args, self.0), self.0).await + async_with!(self.0 => |ctx| { + js_invoke_async_method_to_json::<_, ()>( + ctx.clone(), + "playlist", + "addTracks", + &[ + Value::String(playlist_id), + Value::Array(track_ids.into_iter().map(|id| Value::String(id)).collect()), + serde_json::to_value(position)?, + ] + ) + .await.and_then(|_| Ok(())) + }) + .await } pub async fn remove_tracks( - &mut self, + &self, playlist_id: String, track_ids: Vec, ) -> anyhow::Result<()> { - let playlist_val = self.playlist_obj()?; - let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?; - - let remove_tracks_fn = playlist_object - .get(js_string!("removeTracks"), self.0) - .map_err(|e| anyhow!("{}", e))? - .as_function() - .ok_or(anyhow!("removeTracks is not a function"))?; - - let args = [ - JsValue::from(js_string!(playlist_id)), - utils::vec_string_to_js_array(track_ids, self.0)?, - ]; - - utils::js_call_to_void(remove_tracks_fn.call(&playlist_val, &args, self.0), self.0).await + async_with!(self.0 => |ctx| { + js_invoke_async_method_to_json::<_, ()>( + ctx.clone(), + "playlist", + "removeTracks", + &[ + Value::String(playlist_id), + Value::Array(track_ids.into_iter().map(|id| Value::String(id)).collect()), + ] + ) + .await.and_then(|_| Ok(())) + }) + .await } - pub async fn save(&mut self, playlist_id: String) -> anyhow::Result<()> { - let playlist_val = self.playlist_obj()?; - let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?; - - let save_fn = playlist_object - .get(js_string!("save"), self.0) - .map_err(|e| anyhow!("{}", e))? - .as_function() - .ok_or(anyhow!("save is not a function"))?; - - let args = [JsValue::from(js_string!(playlist_id))]; - - utils::js_call_to_void(save_fn.call(&playlist_val, &args, self.0), self.0).await + pub async fn save(&self, playlist_id: String) -> anyhow::Result<()> { + async_with!(self.0 => |ctx| { + js_invoke_async_method_to_json::<_, ()>( + ctx.clone(), + "playlist", + "save", + &[Value::String(playlist_id)] + ) + .await.and_then(|_| Ok(())) + }) + .await } - pub async fn unsave(&mut self, playlist_id: String) -> anyhow::Result<()> { - let playlist_val = self.playlist_obj()?; - let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?; - - let unsave_fn = playlist_object - .get(js_string!("unsave"), self.0) - .map_err(|e| anyhow!("{}", e))? - .as_function() - .ok_or(anyhow!("unsave is not a function"))?; - - let args = [JsValue::from(js_string!(playlist_id))]; - - utils::js_call_to_void(unsave_fn.call(&playlist_val, &args, self.0), self.0).await + pub async fn unsave(&self, playlist_id: String) -> anyhow::Result<()> { + async_with!(self.0 => |ctx| { + js_invoke_async_method_to_json::<_, ()>( + ctx.clone(), + "playlist", + "unsave", + &[Value::String(playlist_id)] + ) + .await.and_then(|_| Ok(())) + }) + .await } - pub async fn delete_playlist(&mut self, playlist_id: String) -> anyhow::Result<()> { - let playlist_val = self.playlist_obj()?; - let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?; - - let delete_playlist_fn = playlist_object - .get(js_string!("deletePlaylist"), self.0) - .map_err(|e| anyhow!("{}", e))? - .as_function() - .ok_or(anyhow!("deletePlaylist is not a function"))?; - - let args = [JsValue::from(js_string!(playlist_id))]; - - utils::js_call_to_void( - delete_playlist_fn.call(&playlist_val, &args, self.0), - self.0, - ) + pub async fn delete_playlist(&self, playlist_id: String) -> anyhow::Result<()> { + async_with!(self.0 => |ctx| { + js_invoke_async_method_to_json::<_, ()>( + ctx.clone(), + "playlist", + "deletePlaylist", + &[Value::String(playlist_id)] + ) + .await.and_then(|_| Ok(())) + }) .await } } diff --git a/rust/src/internal/search.rs b/rust/src/internal/search.rs index ff10a2b0..ff4bc5b0 100644 --- a/rust/src/internal/search.rs +++ b/rust/src/internal/search.rs @@ -1,201 +1,149 @@ use crate::api::plugin::models::pagination::SpotubePaginationResponseObject; use crate::api::plugin::models::search::SpotubeSearchResponseObject; -use crate::internal::utils; -use anyhow::anyhow; -use boa_engine::object::builtins::JsArray; -use boa_engine::{js_string, Context, JsValue}; +use crate::internal::utils::{js_invoke_async_method_to_json, js_invoke_method_to_json}; use flutter_rust_bridge::frb; +use rquickjs::{async_with, AsyncContext}; +use serde_json::Value; -#[derive(Debug)] -pub struct PluginSearchEndpoint<'a>(&'a mut Context); +pub struct PluginSearchEndpoint<'a>(&'a AsyncContext); impl<'a> PluginSearchEndpoint<'a> { #[frb(ignore)] - pub fn new(context: &'a mut Context) -> PluginSearchEndpoint<'a> { + pub fn new(context: &'a AsyncContext) -> PluginSearchEndpoint<'a> { PluginSearchEndpoint(context) } - fn search_obj(&mut self) -> anyhow::Result { - let global = self.0.global_object(); - let plugin_instance = global - .get(js_string!("pluginInstance"), self.0) - .map_err(|e| anyhow!("{}", e)) - .and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?; - - plugin_instance - .get(js_string!("search"), self.0) - .or_else(|e| Err(anyhow!("search not found: \n{}", e))) + pub async fn chips(&self) -> anyhow::Result> { + self.0 + .with(|ctx| { + anyhow::Ok( + js_invoke_method_to_json::<(), Vec>( + ctx.clone(), + "search", + "chips", + &[], + )? + .expect("[hey][smartypants] search.chips should return a string"), + ) + }) + .await } - pub fn chips(&mut self) -> anyhow::Result> { - let search_val = self.search_obj()?; - let search_object = search_val.as_object().ok_or(anyhow!("Not an object"))?; - - let chips_val = search_object - .get(js_string!("chips"), self.0) - .map_err(|e| anyhow!("{}", e))?; - let chips_obj = chips_val.as_object().ok_or(anyhow!("Not an object"))?; - - if !chips_obj.is_array() { - return Err(anyhow!("chips is not an array")); - } - - let chips_array = JsArray::from_object(chips_obj.clone()).map_err(|e| anyhow!("{}", e))?; - let length = chips_array.length(self.0).map_err(|e| anyhow!("{}", e))?; - let mut result = Vec::new(); - for i in 0..length { - let item = chips_array.get(i, self.0).map_err(|e| anyhow!("{}", e))?; - if let Some(s) = item.as_string() { - result.push(s.to_std_string().map_err(|e| anyhow!("{}", e))?); - } - } - Ok(result) - } - - pub async fn all(&mut self, query: String) -> anyhow::Result { - let search_val = self.search_obj()?; - let search_object = search_val.as_object().ok_or(anyhow!("Not an object"))?; - - let all_fn = search_object - .get(js_string!("all"), self.0) - .map_err(|e| anyhow!("{}", e))? - .as_function() - .ok_or(anyhow!("all is not a function"))?; - - let args = [JsValue::from(js_string!(query))]; - - let res_json = utils::js_call_to_json(all_fn.call(&search_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + pub async fn all(&self, query: String) -> anyhow::Result { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, SpotubeSearchResponseObject>( + ctx.clone(), + "search", + "all", + &[query], + ) + .await? + .expect("[hey][smartypants] search.all should return a SpotifySearchResponseObject") + ) + }) + .await } pub async fn albums( - &mut self, + &self, query: String, offset: Option, limit: Option, ) -> anyhow::Result { - let search_val = self.search_obj()?; - let search_object = search_val.as_object().ok_or(anyhow!("Not an object"))?; - - let albums_fn = search_object - .get(js_string!("albums"), self.0) - .map_err(|e| anyhow!("{}", e))? - .as_function() - .ok_or(anyhow!("albums is not a function"))?; - - let args: [JsValue; 3] = [ - JsValue::from(js_string!(query)), - match offset { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - match limit { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - let res_json = utils::js_call_to_json(albums_fn.call(&search_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx.clone(), + "search", + "albums", + &[ + Value::String(query), + serde_json::to_value(offset)?, + serde_json::to_value(limit)? + ], + ) + .await? + .expect("[hey][smartypants] search.albums should return a SpotifyPaginationResponseObject") + ) + }) + .await } + pub async fn artists( - &mut self, + &self, query: String, offset: Option, limit: Option, ) -> anyhow::Result { - let search_val = self.search_obj()?; - let search_object = search_val.as_object().ok_or(anyhow!("Not an object"))?; - - let artists_fn = search_object - .get(js_string!("artists"), self.0) - .map_err(|e| anyhow!("{}", e))? - .as_function() - .ok_or(anyhow!("artists is not a function"))?; - - let args: [JsValue; 3] = [ - JsValue::from(js_string!(query)), - match offset { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - match limit { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - let res_json = utils::js_call_to_json(artists_fn.call(&search_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx.clone(), + "search", + "artists", + &[ + Value::String(query), + serde_json::to_value(offset)?, + serde_json::to_value(limit)? + ], + ) + .await? + .expect("[hey][smartypants] search.artists should return a SpotifyPaginationResponseObject") + ) + }) + .await } pub async fn playlists( - &mut self, + &self, query: String, offset: Option, limit: Option, ) -> anyhow::Result { - let search_val = self.search_obj()?; - let search_object = search_val.as_object().ok_or(anyhow!("Not an object"))?; - - let playlists_fn = search_object - .get(js_string!("playlists"), self.0) - .map_err(|e| anyhow!("{}", e))? - .as_function() - .ok_or(anyhow!("playlists is not a function"))?; - - let args: [JsValue; 3] = [ - JsValue::from(js_string!(query)), - match offset { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - match limit { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - let res_json = - utils::js_call_to_json(playlists_fn.call(&search_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx.clone(), + "search", + "playlists", + &[ + Value::String(query), + serde_json::to_value(offset)?, + serde_json::to_value(limit)? + ], + ) + .await? + .expect("[hey][smartypants] search.playlists should return a SpotifyPaginationResponseObject") + ) + }) + .await } pub async fn tracks( - &mut self, + &self, query: String, offset: Option, limit: Option, ) -> anyhow::Result { - let search_val = self.search_obj()?; - let search_object = search_val.as_object().ok_or(anyhow!("Not an object"))?; - - let tracks_fn = search_object - .get(js_string!("tracks"), self.0) - .map_err(|e| anyhow!("{}", e))? - .as_function() - .ok_or(anyhow!("tracks is not a function"))?; - - let args: [JsValue; 3] = [ - JsValue::from(js_string!(query)), - match offset { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - match limit { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - let res_json = utils::js_call_to_json(tracks_fn.call(&search_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx.clone(), + "search", + "tracks", + &[ + Value::String(query), + serde_json::to_value(offset)?, + serde_json::to_value(limit)? + ], + ) + .await? + .expect("[hey][smartypants] search.tracks should return a SpotifyPaginationResponseObject") + ) + }) + .await } } diff --git a/rust/src/internal/track.rs b/rust/src/internal/track.rs index fdba2efd..611fc114 100644 --- a/rust/src/internal/track.rs +++ b/rust/src/internal/track.rs @@ -1,96 +1,77 @@ use crate::api::plugin::models::track::SpotubeTrackObject; -use crate::internal::utils; -use anyhow::anyhow; -use boa_engine::{js_string, Context, JsValue}; +use crate::internal::utils::js_invoke_async_method_to_json; use flutter_rust_bridge::frb; +use rquickjs::{async_with, AsyncContext}; +use serde_json::Value; -#[derive(Debug)] -pub struct PluginTrackEndpoint<'a>(&'a mut Context); +pub struct PluginTrackEndpoint<'a>(&'a AsyncContext); impl<'a> PluginTrackEndpoint<'a> { #[frb(ignore)] - pub fn new(context: &'a mut Context) -> PluginTrackEndpoint<'a> { + pub fn new(context: &'a AsyncContext) -> PluginTrackEndpoint<'a> { PluginTrackEndpoint(context) } - fn track_obj(&mut self) -> anyhow::Result { - let global = self.0.global_object(); - - let plugin_instance = global - .get(js_string!("pluginInstance"), self.0) - .map_err(|e| anyhow!("{}", e)) - .and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?; - - plugin_instance - .get(js_string!("track"), self.0) - .or_else(|e| Err(anyhow!("track not found: \n{}", e))) + pub async fn get_track(&self, id: String) -> anyhow::Result { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json( + ctx.clone(), + "track", + "getTrack", + &[ + id + ], + ) + .await? + .expect("[hey][smartypants] track.getTrack should return a SpotifyTrackObject") + ) + }) + .await } - pub async fn get_track(&mut self, id: String) -> anyhow::Result { - let track_val = self.track_obj()?; - let track_object = track_val.as_object().ok_or(anyhow!("Not an object"))?; - - let get_track_fn = track_object - .get(js_string!("getTrack"), self.0) - .map_err(|e| anyhow!("JS error while accessing getTrack: {}", e))? - .as_function() - .ok_or(anyhow!("getTrack is not a function"))?; - - let args = [JsValue::from(js_string!(id))]; - - let res_json = - utils::js_call_to_json(get_track_fn.call(&track_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + pub async fn save(&self, ids: Vec) -> anyhow::Result<()> { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, ()>( + ctx.clone(), + "track", + "save", + &[Value::Array(ids.into_iter().map(|id| Value::String(id)).collect())] + ) + .await? + .expect("[hey][smartypants] track.save should return a SpotifyPaginationResponseObject") + ) + }).await } - pub async fn save(&mut self, ids: Vec) -> anyhow::Result<()> { - let track_val = self.track_obj()?; - let track_object = track_val.as_object().ok_or(anyhow!("Not an object"))?; - - let save_fn = track_object - .get(js_string!("save"), self.0) - .map_err(|e| anyhow!("JS error while accessing save: {}", e))? - .as_function() - .ok_or(anyhow!("save is not a function"))?; - - let ids_val = utils::vec_string_to_js_array(ids, self.0)?; - let args = [ids_val.into()]; - - utils::js_call_to_void(save_fn.call(&track_val, &args, self.0), self.0).await + pub async fn unsave(&self, ids: Vec) -> anyhow::Result<()> { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, ()>( + ctx.clone(), + "track", + "unsave", + &[Value::Array(ids.into_iter().map(|id| Value::String(id)).collect())] + ) + .await? + .expect("[hey][smartypants] track.unsave should return a SpotifyPaginationResponseObject") + ) + }).await } - pub async fn unsave(&mut self, ids: Vec) -> anyhow::Result<()> { - let track_val = self.track_obj()?; - let track_object = track_val.as_object().ok_or(anyhow!("Not an object"))?; - - let unsave_fn = track_object - .get(js_string!("unsave"), self.0) - .map_err(|e| anyhow!("JS error while accessing save: {}", e))? - .as_function() - .ok_or(anyhow!("save is not a function"))?; - - let ids_val = utils::vec_string_to_js_array(ids, self.0)?; - let args = [ids_val.into()]; - - utils::js_call_to_void(unsave_fn.call(&track_val, &args, self.0), self.0).await - } - - pub async fn radio(&mut self, id: String) -> anyhow::Result> { - let track_val = self.track_obj()?; - let track_object = track_val.as_object().ok_or(anyhow!("Not an object"))?; - - let get_track_fn = track_object - .get(js_string!("radio"), self.0) - .map_err(|e| anyhow!("JS error while accessing radio: {}", e))? - .as_function() - .ok_or(anyhow!("radio is not a function"))?; - - let args = [JsValue::from(js_string!(id))]; - - let res_json = - utils::js_call_to_json(get_track_fn.call(&track_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + pub async fn radio(&self, id: String) -> anyhow::Result> { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<_, Vec>( + ctx.clone(), + "track", + "radio", + &[id], + ) + .await? + .expect("[hey][smartypants] track.radio should return a SpotifyPaginationResponseObject") + ) + }).await } } diff --git a/rust/src/internal/user.rs b/rust/src/internal/user.rs index dc9c6821..281da1f4 100644 --- a/rust/src/internal/user.rs +++ b/rust/src/internal/user.rs @@ -1,107 +1,106 @@ use crate::api::plugin::models::pagination::SpotubePaginationResponseObject; -use crate::internal::utils; -use anyhow::anyhow; -use boa_engine::{js_string, Context, JsValue}; -use flutter_rust_bridge::frb; use crate::api::plugin::models::user::SpotubeUserObject; +use crate::internal::utils::js_invoke_async_method_to_json; +use flutter_rust_bridge::frb; +use rquickjs::{async_with, AsyncContext}; -#[derive(Debug)] -pub struct PluginUserEndpoint<'a>(&'a mut Context); +pub struct PluginUserEndpoint<'a>(&'a AsyncContext); impl<'a> PluginUserEndpoint<'a> { #[frb(ignore)] - pub fn new(context: &'a mut Context) -> PluginUserEndpoint<'a> { + pub fn new(context: &'a AsyncContext) -> PluginUserEndpoint<'a> { PluginUserEndpoint(context) } - fn user_obj(&mut self) -> anyhow::Result { - let global = self.0.global_object(); - - let plugin_instance = global - .get(js_string!("pluginInstance"), self.0) - .map_err(|e| anyhow!("{}", e)) - .and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?; - - plugin_instance - .get(js_string!("user"), self.0) - .or_else(|e| Err(anyhow!("user not found: \n{}", e))) - } - - pub async fn me(&mut self) -> anyhow::Result { - let user_val = self.user_obj()?; - let user_object = user_val.as_object().ok_or(anyhow!("Not an object"))?; - - let me_fn = user_object - .get(js_string!("me"), self.0) - .map_err(|e| anyhow!("JS error while accessing me: {}", e))? - .as_function() - .ok_or(anyhow!("me is not a function"))?; - - let res_json = utils::js_call_to_json(me_fn.call(&user_val, &[], self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) - } - - async fn get_saved( - &mut self, - method: &str, - offset: Option, - limit: Option, - ) -> anyhow::Result { - let user_val = self.user_obj()?; - let user_object = user_val.as_object().ok_or(anyhow!("Not an object"))?; - - let saved_fn = user_object - .get(js_string!(method), self.0) - .map_err(|e| anyhow!("JS error while accessing {}: {}", method, e))? - .as_function() - .ok_or(anyhow!("{} is not a function", method))?; - - let args: [JsValue; 2] = [ - match offset { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - match limit { - Some(o) => JsValue::from(o), - None => JsValue::undefined(), - }, - ]; - - let res_json = utils::js_call_to_json(saved_fn.call(&user_val, &args, self.0), self.0).await?; - - serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e)) + pub async fn me(&self) -> anyhow::Result { + async_with!(self.0 => |ctx| { + Ok( + js_invoke_async_method_to_json::<(), SpotubeUserObject>( + ctx.clone(), + "user", + "me", + &[], + ) + .await? + .expect("[hey][smartypants] user.me should return a SpotifyUserObject") + ) + }) + .await } pub async fn saved_playlists( - &mut self, + &self, offset: Option, limit: Option, ) -> anyhow::Result { - self.get_saved("savedPlaylists", offset, limit).await + async_with!(self.0 => |ctx| { + let res= js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx, + "user", + "savedPlaylists", + &[serde_json::to_value(offset)?, serde_json::to_value(limit.unwrap())?] + ) + .await? + .expect("[hey][smartypants] user.savedPlaylists should return a SpotifyPaginationResponseObject"); + + Ok(res) + }).await } pub async fn saved_tracks( - &mut self, + &self, offset: Option, limit: Option, ) -> anyhow::Result { - self.get_saved("savedTracks", offset, limit).await + async_with!(self.0 => |ctx| { + let res= js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx, + "user", + "savedTracks", + &[serde_json::to_value(offset)?, serde_json::to_value(limit.unwrap())?] + ) + .await? + .expect("[hey][smartypants] user.savedTracks should return a SpotifyPaginationResponseObject"); + + Ok(res) + }).await } pub async fn saved_albums( - &mut self, + &self, offset: Option, limit: Option, ) -> anyhow::Result { - self.get_saved("savedAlbums", offset, limit).await + async_with!(self.0 => |ctx| { + let res= js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx, + "user", + "savedAlbums", + &[serde_json::to_value(offset)?, serde_json::to_value(limit.unwrap())?] + ) + .await? + .expect("[hey][smartypants] user.savedAlbums should return a SpotifyPaginationResponseObject"); + + Ok(res) + }).await } pub async fn saved_artists( - &mut self, + &self, offset: Option, limit: Option, ) -> anyhow::Result { - self.get_saved("savedArtists", offset, limit).await + async_with!(self.0 => |ctx| { + let res= js_invoke_async_method_to_json::<_, SpotubePaginationResponseObject>( + ctx, + "user", + "savedArtists", + &[serde_json::to_value(offset)?, serde_json::to_value(limit.unwrap())?] + ) + .await? + .expect("[hey][smartypants] user.savedArtists should return a SpotifyPaginationResponseObject"); + + Ok(res) + }).await } } diff --git a/rust/src/internal/utils.rs b/rust/src/internal/utils.rs index 79187834..4e6aa92a 100644 --- a/rust/src/internal/utils.rs +++ b/rust/src/internal/utils.rs @@ -1,116 +1,57 @@ use anyhow::anyhow; -use boa_engine::property::PropertyKey; -use boa_engine::{object::builtins::JsArray, Context, JsObject, JsResult, JsString, JsValue}; +use rquickjs::function::Args; +use rquickjs::{Array, CatchResultExt, Ctx, Filter, FromJs, Function, IntoJs, Object, Promise}; +use serde::de::DeserializeOwned; +use serde::{Deserialize, Deserializer, Serialize}; use serde_json::{Map, Value}; - -pub fn vec_string_to_js_array( - rust_vec: Vec, - context: &mut Context, -) -> anyhow::Result { - let builder = JsArray::new(context); - - for (index, rust_string) in rust_vec.into_iter().enumerate() { - let js_string_value = JsString::from(rust_string); - builder - .set(index as u32, js_string_value, true, context) - .map_err(|e| anyhow::anyhow!(e.to_string()))?; - } - - Ok(builder.into()) -} - -#[allow(dead_code)] -pub async fn js_call_to_string( - result: JsResult, - context: &mut Context, -) -> anyhow::Result { - let res = result - .map_err(|e| anyhow!("{}", e)) - .and_then(|f| f.as_promise().ok_or(anyhow!("Not a promise")))? - .into_js_future(context) - .await - .map_err(|e| anyhow!("{}", e))? - .as_string() - .ok_or(anyhow!("No response string returned"))? - .to_std_string() - .map_err(|e| anyhow!("{}", e))?; - - Ok(res) -} - -pub async fn js_call_to_json( - result: JsResult, - context: &mut Context, -) -> anyhow::Result { - let res = result - .map_err(|e| anyhow!("{}", e)) - .and_then(|f| f.as_promise().ok_or(anyhow!("Not a promise")))? - .into_js_future(context) - .await - .map_err(|e| anyhow!("{}", e))?; - let ls = js_value_to_json(&res, context)?; - Ok(ls) -} - -pub async fn js_call_to_void( - result: JsResult, - context: &mut Context, -) -> anyhow::Result<()> { - result - .map_err(|e| anyhow!("{}", e)) - .and_then(|f| f.as_promise().ok_or(anyhow!("Not a promise")))? - .into_js_future(context) - .await - .map_err(|e| anyhow!("{}", e))?; - - Ok(()) -} +use std::collections::HashMap; /// Convert a `serde_json::Value` into a Boa `JsValue` -pub fn json_value_to_js(value: &Value, ctx: &mut Context) -> JsResult { +pub fn json_value_to_js<'a>(value: &Value, ctx: Ctx<'a>) -> anyhow::Result> { match value { - Value::Null => Ok(JsValue::null()), - Value::Bool(b) => Ok(JsValue::from(*b)), + Value::Null => Ok(rquickjs::Value::new_null(ctx)), + Value::Bool(b) => Ok(rquickjs::Value::new_bool(ctx, *b)), Value::Number(n) => { if let Some(i) = n.as_i64() { - Ok(JsValue::new(i)) + Ok(rquickjs::Value::new_int(ctx, i as i32)) } else if let Some(f) = n.as_f64() { - Ok(JsValue::new(f)) + Ok(rquickjs::Value::new_float(ctx, f)) } else { - Ok(JsValue::null()) // fallback (rare) + Ok(rquickjs::Value::new_null(ctx)) // fallback (rare) } } - Value::String(s) => Ok(JsValue::from(JsString::from(s.as_str()))), - + Value::String(s) => { + let sts = rquickjs::String::from_str(ctx, s.as_str())?; + Ok(rquickjs::Value::from_string(sts)) + } Value::Array(arr) => { - let js_arr = JsArray::new(ctx); - for (idx, item) in arr.iter().enumerate() { - let js_val = json_value_to_js(item, ctx)?; - js_arr.set(idx, js_val, false, ctx)?; + let mut js_arr = Vec::::with_capacity(arr.len()); + for item in arr.iter() { + let js_val = json_value_to_js(item, ctx.clone())?; + js_arr.push(js_val); } - Ok(JsValue::from(js_arr)) + js_arr.into_js(&ctx).map_err(|e| anyhow!(e)) } - Value::Object(obj) => { - let js_obj = JsObject::with_null_proto(); + let mut js_obj = HashMap::::with_capacity(obj.len()); for (key, val) in obj { - let js_val = json_value_to_js(val, ctx)?; - js_obj.set(JsString::from(key.as_str()), js_val, true, ctx)?; + let js_val = json_value_to_js(val, ctx.clone())?; + js_obj.insert(key.clone(), js_val); } - Ok(JsValue::from(js_obj)) + js_obj.into_js(&ctx).map_err(|e| anyhow!(e)) } } } /// Convert a Boa `JsValue` into a `serde_json::Value` -pub fn js_value_to_json(value: &JsValue, ctx: &mut Context) -> anyhow::Result { +pub fn js_value_to_json<'a>(value: rquickjs::Value<'a>, ctx: Ctx<'a>) -> anyhow::Result { if value.is_null() || value.is_undefined() { return Ok(Value::Null); } - if let Some(b) = value.as_boolean() { + if let Some(b) = value.as_bool() { return Ok(Value::Bool(b)); } @@ -120,27 +61,22 @@ pub fn js_value_to_json(value: &JsValue, ctx: &mut Context) -> anyhow::Result::with_capacity(length as usize); + let obj: Array = Array::from_value(obj.into_value()).map_err(|e| anyhow!("{}", e))?; + let length = obj.len(); + let mut json_arr = Vec::::with_capacity(length); for i in 0..length { - let item = obj.get(i, ctx).unwrap_or(JsValue::null()); - let item_json = js_value_to_json(&item, ctx)?; + let item = obj.get(i).unwrap_or(rquickjs::Value::new_null(ctx.clone())); + let item_json = js_value_to_json(item, ctx.clone())?; json_arr.push(item_json); } @@ -150,19 +86,14 @@ pub fn js_value_to_json(value: &JsValue, ctx: &mut Context) -> anyhow::Result::new(); - for key in obj.own_property_keys(ctx).map_err(|e| anyhow!("{}", e))? { - let key_val: Option = match key.clone() { - PropertyKey::String(s) => Some(s.to_std_string().map_err(|e| anyhow!("{}", e))?), - PropertyKey::Index(i) => Some(serde_json::Number::from(i.get()).to_string()), - _ => None, - }; + for key in obj.own_keys::(Filter::default()) { + let key = key?; + let v_js = obj + .get(key.clone()) + .unwrap_or(rquickjs::Value::new_null(ctx.clone())); + let v_json = js_value_to_json(v_js, ctx.clone())?; - let v_js = obj.get(key, ctx).unwrap_or(JsValue::null()); - let v_json = js_value_to_json(&v_js, ctx)?; - - if let Some(key_val) = key_val { - map.insert(key_val, v_json); - } + map.insert(key.clone().to_string()?, v_json); } return Ok(Value::Object(map)); @@ -171,3 +102,79 @@ pub fn js_value_to_json(value: &JsValue, ctx: &mut Context) -> anyhow::Result( + ctx: Ctx<'b>, + endpoint_name: &'b str, + name: &'b str, + args: &[T], +) -> anyhow::Result> +where + T: Serialize, + R: DeserializeOwned, +{ + let global = ctx.globals(); + let plugin_instance: Object<'b> = global.get("pluginInstance").map_err(|e| anyhow!("{e}"))?; + let core_val: Object<'b> = plugin_instance + .get(endpoint_name) + .map_err(|e| anyhow!("{e}"))?; + let js_fn: Function<'b> = core_val.get(name).map_err(|e| anyhow!("{e}"))?; + let mut args_js = Args::new(ctx.clone(), args.len() as usize); + for (i, arg) in args.iter().enumerate() { + let arg_value = serde_json::to_value(arg).map_err(|e| anyhow!("{e}"))?; + let arg_js = json_value_to_js(&arg_value, ctx.clone()).map_err(|e| anyhow!("{e}"))?; + args_js.push_arg(arg_js).map_err(|e| anyhow!("{e}"))?; + } + + let result_promise: Promise = js_fn.call_arg(args_js).map_err(|e| anyhow!("{e}"))?; + let result_future: rquickjs::Value = result_promise + .into_future() + .await + .catch(&ctx) + .map_err(|e| anyhow!("{e}"))?; + + let value = js_value_to_json(result_future, ctx.clone()).map_err(|e| anyhow!("{e}"))?; + + if value.is_null() { + return Ok(None); + } + + Ok(Some( + serde_json::from_value::(value).map_err(|e| anyhow!("{e}"))?, + )) +} + +pub fn js_invoke_method_to_json<'b, T, R>( + ctx: Ctx<'b>, + endpoint_name: &'b str, + name: &'b str, + args: &[T], +) -> anyhow::Result> +where + T: Serialize, + R: DeserializeOwned, +{ + let global = ctx.globals(); + let plugin_instance: Object<'b> = global.get("pluginInstance").map_err(|e| anyhow!("{e}"))?; + let core_val: Object<'b> = plugin_instance + .get(endpoint_name) + .map_err(|e| anyhow!("{e}"))?; + let js_fn: Function<'b> = core_val.get(name).map_err(|e| anyhow!("{e}"))?; + let mut args_js = Args::new(ctx.clone(), args.len() as usize); + for (i, arg) in args.iter().enumerate() { + let arg_value = serde_json::to_value(arg).map_err(|e| anyhow!("{e}"))?; + let arg_js = json_value_to_js(&arg_value, ctx.clone()).map_err(|e| anyhow!("{e}"))?; + args_js.push_arg(arg_js).map_err(|e| anyhow!("{e}"))?; + } + + let result: rquickjs::Value = js_fn.call_arg(args_js).map_err(|e| anyhow!("{e}"))?; + let value = js_value_to_json(result, ctx.clone()).map_err(|e| anyhow!("{e}"))?; + + if value.is_null() { + return Ok(None); + } + + Ok(Some( + serde_json::from_value::(value).map_err(|e| anyhow!("{e}"))?, + )) +} diff --git a/rust/src/main.rs b/rust/src/main.rs index 873ff4bc..b8711ab6 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -1,22 +1,24 @@ -use rquickjs::function::Async; -use rquickjs::prelude::Func; -use rquickjs::{ - async_with, AsyncContext, AsyncRuntime, CatchResultExt, CaughtError, Function, Object, Promise, - Result, -}; -use std::time::Duration; +mod api; +mod internal; + +use rquickjs::function::{Async, Func}; +use rquickjs::{async_with, AsyncContext, AsyncRuntime, Function, Object, Promise}; +use tokio::time::Instant; + +use crate::api::plugin::models::core::{PluginAbility, PluginConfiguration}; +use crate::api::plugin::plugin::SpotubePlugin; + +async fn set_timeout(func: Function<'_>, timeout: u64) { + tokio::time::sleep(std::time::Duration::from_millis(timeout)).await; + func.call::<_, ()>(()).unwrap(); +} fn print(msg: String) { println!("{}", msg); } -async fn set_timeout<'js>(cb: Function<'js>, number: f64) -> Result<()> { - tokio::time::sleep(Duration::from_millis(number as u64)).await; - cb.call::<_, ()>(()) -} - -#[tokio::main] -async fn main() -> Result<()> { +async fn non_plugin() -> anyhow::Result<()> { + let start = Instant::now(); let rt = AsyncRuntime::new()?; let ctx = AsyncContext::full(&rt).await?; @@ -30,23 +32,85 @@ async fn main() -> Result<()> { Function::new(ctx.clone(), Async(set_timeout)).unwrap().with_name("setTimeout") ).unwrap(); - if let Ok(function) = ctx.eval::(r#" - (function(){ - return new Promise((resolve, reject) => { - setTimeout(() => { - console.log("hello world"); - resolve(); - }, 100); - }) - }) - "#) { - let promise: Promise = function.call(()).unwrap(); - if let Err(err) = promise.into_future::<()>().await.catch(&ctx) { - eprintln!("{:?}", err); + let check_update_fn: Function = ctx.eval(r#" + function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); } - } + (async function checkUpdate() { + console.log('Core checkUpdate'); + await sleep(1000); + console.log('No update available'); + }) + "#)?; + + let (r1, r2) = tokio::join!( + check_update_fn.call::<_, Promise>(()).unwrap().into_future::<()>(), + check_update_fn.call::<_, Promise>(()).unwrap().into_future::<()>() + ); + r1?; + r2?; + Ok::<(), rquickjs::Error>(()) }) - .await; + .await + .map_err(|e| anyhow::anyhow!(e))?; + + let duration = start.elapsed(); + println!("[NON-PLUGIN] Execution time: {:?}", duration); + Ok(()) +} + +const PLUGIN_JS: &str = "\ +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +class Core { + async checkUpdate() { + console.log(globalThis); + } + support() { + return 'Metadata'; + } +} + +class TestingPlugin { + constructor() { + this.core = new Core(); + } +} +"; + +async fn plugin() -> anyhow::Result<()> { + let start = Instant::now(); + let plugin = SpotubePlugin::new(); + let config = PluginConfiguration { + entry_point: "TestingPlugin".to_string(), + abilities: vec![PluginAbility::Metadata], + apis: vec![], + author: "KRTirtho".to_string(), + description: "Testing Plugin".to_string(), + name: "Testing Plugin".to_string(), + plugin_api_version: "2.0.0".to_string(), + repository: None, + version: "0.1.0".to_string(), + }; + let sender = SpotubePlugin::new_context(PLUGIN_JS.to_string(), config.clone())?; + let (r1, r2) = tokio::join!( + plugin.core.check_update(sender.clone(), config.clone()), + plugin.core.check_update(sender.clone(), config.clone()) + ); + r1?; + r2?; + + let duration = start.elapsed(); + println!("[PLUGIN] Execution time: {:?}", duration); Ok(()) } + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + non_plugin().await?; + plugin().await?; + Ok(()) +}