Upgrade Rinf

This commit is contained in:
DongHyun Kim 2023-11-15 15:53:40 +09:00
parent fa29bc9d24
commit f9820d2215
41 changed files with 135 additions and 8071 deletions

637
Cargo.lock generated
View file

@ -26,40 +26,12 @@ dependencies = [
"atomic",
]
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "anyhow"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "async_wasm_task"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8daff5f108e2aaea387e7bbd080c3c61fb9533b6b78345b8ff49d11bd31892ad"
dependencies = [
"futures-channel",
"js-sys",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "atomic"
version = "0.5.3"
@ -99,15 +71,6 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "bumpalo"
version = "3.14.0"
@ -147,42 +110,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"serde",
"wasm-bindgen",
"windows-targets",
]
[[package]]
name = "color_quant"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "core-foundation-sys"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
[[package]]
name = "cpufeatures"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
dependencies = [
"libc",
]
[[package]]
name = "crc32fast"
version = "1.3.2"
@ -231,16 +164,6 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "dart-sys"
version = "4.0.2"
@ -250,17 +173,6 @@ dependencies = [
"cc",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
name = "either"
version = "1.9.0"
@ -311,21 +223,6 @@ dependencies = [
"spin",
]
[[package]]
name = "futures"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.28"
@ -333,7 +230,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
@ -342,85 +238,6 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
[[package]]
name = "futures-executor"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
[[package]]
name = "futures-macro"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.38",
]
[[package]]
name = "futures-sink"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
[[package]]
name = "futures-task"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
[[package]]
name = "futures-util"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "gif"
version = "0.12.0"
@ -452,63 +269,15 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
]
[[package]]
name = "hub"
version = "0.1.0"
dependencies = [
"allo-isolate",
"async_wasm_task",
"backtrace",
"bytemuck",
"dart-sys",
"image",
"js-sys",
"lazy_static",
"libc",
"os-thread-local",
"prost",
"tokio",
"rinf",
"tokio_with_wasm",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "iana-time-zone"
version = "0.1.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
@ -539,12 +308,6 @@ dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "jpeg-decoder"
version = "0.3.0"
@ -597,36 +360,6 @@ version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "machineid-rs"
version = "1.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35ceb4d434d69d7199abc3036541ba6ef86767a4356e3077d5a3419f85b70b14"
dependencies = [
"hex",
"hmac",
"md-5",
"serde",
"serde_json",
"sha-1",
"sha2",
"sysinfo",
"uuid",
"whoami",
"winreg",
"wmi",
]
[[package]]
name = "md-5"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
dependencies = [
"cfg-if",
"digest",
]
[[package]]
name = "memchr"
version = "2.6.4"
@ -653,46 +386,14 @@ dependencies = [
]
[[package]]
name = "ntapi"
version = "0.4.1"
name = "mio"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
dependencies = [
"winapi",
]
[[package]]
name = "num"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
dependencies = [
"num-bigint",
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
dependencies = [
"num-traits",
"libc",
"wasi",
"windows-sys",
]
[[package]]
@ -705,17 +406,6 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.1"
@ -723,7 +413,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
dependencies = [
"autocfg",
"num-bigint",
"num-integer",
"num-traits",
]
@ -772,18 +461,35 @@ dependencies = [
"winapi",
]
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets",
]
[[package]]
name = "pin-project-lite"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "png"
version = "0.17.10"
@ -826,7 +532,7 @@ dependencies = [
"itertools",
"proc-macro2",
"quote",
"syn 2.0.38",
"syn",
]
[[package]]
@ -867,28 +573,39 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags",
]
[[package]]
name = "rinf"
version = "4.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d805a4a3ba0e2564baa19a9360d2b334c3a7b016e434512ece130ce74d4ca76c"
dependencies = [
"allo-isolate",
"backtrace",
"bytemuck",
"dart-sys",
"js-sys",
"lazy_static",
"libc",
"os-thread-local",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "ryu"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "sample_crate"
version = "0.1.0"
dependencies = [
"chrono",
"image",
"machineid-rs",
"num",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
@ -896,56 +613,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.189"
name = "signal-hook-registry"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.38",
]
[[package]]
name = "serde_json"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "sha-1"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
"libc",
]
[[package]]
@ -954,21 +627,22 @@ version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
[[package]]
name = "socket2"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "spin"
version = "0.9.8"
@ -978,23 +652,6 @@ dependencies = [
"lock_api",
]
[[package]]
name = "subtle"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.38"
@ -1006,41 +663,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "sysinfo"
version = "0.29.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a18d114d420ada3a891e6bc8e96a2023402203296a47cdd65083377dad18ba5"
dependencies = [
"cfg-if",
"core-foundation-sys",
"libc",
"ntapi",
"once_cell",
"rayon",
"winapi",
]
[[package]]
name = "thiserror"
version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.38",
]
[[package]]
name = "tiff"
version = "0.9.0"
@ -1059,9 +681,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"num_cpus",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys",
]
[[package]]
@ -1072,14 +701,22 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.38",
"syn",
]
[[package]]
name = "typenum"
version = "1.17.0"
name = "tokio_with_wasm"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
checksum = "22578519b09a4fd0f3e55e1b4fdf337fe0b8ce53c6a853009f37bee1b0b7127c"
dependencies = [
"futures-channel",
"js-sys",
"tokio",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "unicode-ident"
@ -1087,21 +724,6 @@ version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "uuid"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc"
dependencies = [
"getrandom",
]
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
@ -1129,7 +751,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.38",
"syn",
"wasm-bindgen-shared",
]
@ -1163,7 +785,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.38",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -1190,16 +812,6 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
[[package]]
name = "whoami"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50"
dependencies = [
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "winapi"
version = "0.3.9"
@ -1223,47 +835,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
dependencies = [
"windows-implement",
"windows-interface",
"windows-targets",
]
[[package]]
name = "windows-core"
version = "0.51.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-implement"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e2ee588991b9e7e6c8338edf3333fbe4da35dc72092643958ebb43f0ab2c49c"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "windows-interface"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6fb8df20c9bcaa8ad6ab513f7b40104840c8867d5751126e4df3b08388d0cc7"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
@ -1321,30 +900,6 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "winreg"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76a1a57ff50e9b408431e8f97d5456f2807f8eb2a2cd79b06068fc87f8ecf189"
dependencies = [
"cfg-if",
"winapi",
]
[[package]]
name = "wmi"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daffb44abb7d2e87a1233aa17fdbde0d55b890b32a23a1f908895b87fa6f1a00"
dependencies = [
"chrono",
"futures",
"log",
"serde",
"thiserror",
"windows",
]
[[package]]
name = "zune-inflate"
version = "0.2.54"

View file

@ -259,7 +259,6 @@ class _MangaChapterPageGalleryState
_processCropBorders();
final backgroundColor = ref.watch(backgroundColorStateProvider);
final cropBorders = ref.watch(cropBordersStateProvider);
;
final l10n = l10nLocalizations(context)!;
return WillPopScope(
onWillPop: () async {

View file

@ -11,34 +11,9 @@ edition = "2021"
# `staticlib` is for iOS and macOS.
crate-type = ["lib", "cdylib", "staticlib"]
# These are dependencies for non-web platforms.
[target.'cfg(not(target_family = "wasm"))'.dependencies]
libc = "0.2"
dart-sys = { version = "4.0.2" }
allo-isolate = { version = "0.1.20", features = ["zero-copy"] }
tokio = { version = "1.28.2", features = ["rt-multi-thread", "time"] }
os-thread-local = "0.1.3"
backtrace = "0.3.69"
# These are dependencies for the web.
[target.'cfg(target_family = "wasm")'.dependencies]
wasm-bindgen = { version = "0.2.87" }
wasm-bindgen-futures = "0.4.37"
js-sys = "0.3.64"
web-sys = { version = "0.3.64", features = [
"DedicatedWorkerGlobalScope",
"MessagePort",
"Blob",
"BlobPropertyBag",
"Worker",
"Url",
"BroadcastChannel",
] }
async_wasm_task = "0.2.3"
[dependencies]
bytemuck = "1.11.0"
lazy_static = "1.4.0"
tokio = { version = "1.28.2", features = ["sync", "macros"] }
rinf = "4.16.3"
tokio_with_wasm = "0.3.2"
wasm-bindgen = "0.2.87"
prost = "0.12.0"
image = "0.24.7"

View file

@ -1,23 +0,0 @@
# Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
import("../../sdk_args.gni")
# This rule copies header files to include/
copy("copy_headers") {
visibility = [ "../../sdk:copy_headers" ]
sources = [
"dart_api.h",
"dart_api_dl.c",
"dart_api_dl.h",
"dart_native_api.h",
"dart_tools_api.h",
"dart_version.h",
"internal/dart_api_dl_impl.h",
]
outputs =
[ "$root_out_dir/$dart_sdk_output/include/{{source_target_relative}}" ]
}

View file

@ -1,6 +0,0 @@
This folder contains a copy of Dart SDK [include/](https://github.com/dart-lang/sdk/tree/master/runtime/include) folder.
Current version of Dart API is `2.0`. On breaking changes the major version is increased. Minor versions are allowed to be
different. If the DartVM has a higher minor version, it will provide more symbols than we initialize here.
Note that you might need to update if Dart SDK makes an incompatible change to its DL C API.

View file

@ -1,30 +0,0 @@
/*
* Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
* for details. All rights reserved. Use of this source code is governed by a
* BSD-style license that can be found in the LICENSE file.
*/
#ifndef RUNTIME_INCLUDE_ANALYZE_SNAPSHOT_API_H_
#define RUNTIME_INCLUDE_ANALYZE_SNAPSHOT_API_H_
#include <stdint.h>
namespace dart {
namespace snapshot_analyzer {
typedef struct {
const uint8_t* vm_snapshot_data;
const uint8_t* vm_snapshot_instructions;
const uint8_t* vm_isolate_data;
const uint8_t* vm_isolate_instructions;
} Dart_SnapshotAnalyzerInformation;
void Dart_DumpSnapshotInformationAsJson(char** buffer,
intptr_t* buffer_length,
Dart_SnapshotAnalyzerInformation* info);
void Dart_DumpSnapshotInformationPP(Dart_SnapshotAnalyzerInformation* info);
} // namespace snapshot_analyzer
} // namespace dart
#endif // RUNTIME_INCLUDE_ANALYZE_SNAPSHOT_API_H_

View file

@ -1,69 +0,0 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_INCLUDE_BIN_DART_IO_API_H_
#define RUNTIME_INCLUDE_BIN_DART_IO_API_H_
#include "dart_tools_api.h"
namespace dart {
namespace bin {
// Bootstraps 'dart:io'.
void BootstrapDartIo();
// Cleans up 'dart:io'.
void CleanupDartIo();
// Lets dart:io know where the system temporary directory is located.
// Currently only wired up on Android.
void SetSystemTempDirectory(const char* system_temp);
// Tells the system whether to capture Stdout events.
void SetCaptureStdout(bool value);
// Tells the system whether to capture Stderr events.
void SetCaptureStderr(bool value);
// Should Stdout events be captured?
bool ShouldCaptureStdout();
// Should Stderr events be captured?
bool ShouldCaptureStderr();
// Set the executable name used by Platform.executable.
void SetExecutableName(const char* executable_name);
// Set the arguments used by Platform.executableArguments.
void SetExecutableArguments(int script_index, char** argv);
// Set dart:io implementation specific fields of Dart_EmbedderInformation.
void GetIOEmbedderInformation(Dart_EmbedderInformation* info);
// Appropriate to assign to Dart_InitializeParams.file_open/read/write/close.
void* OpenFile(const char* name, bool write);
void ReadFile(uint8_t** data, intptr_t* file_len, void* stream);
void WriteFile(const void* buffer, intptr_t num_bytes, void* stream);
void CloseFile(void* stream);
// Generates 'length' random bytes into 'buffer'. Returns true on success
// and false on failure. This is appropriate to assign to
// Dart_InitializeParams.entropy_source.
bool GetEntropy(uint8_t* buffer, intptr_t length);
// Performs a lookup of the I/O Dart_NativeFunction with a specified 'name' and
// 'argument_count'. Returns NULL if no I/O native function with a matching
// name and parameter count is found.
Dart_NativeFunction LookupIONative(Dart_Handle name,
int argument_count,
bool* auto_setup_scope);
// Returns the symbol for I/O native function 'nf'. Returns NULL if 'nf' is not
// a valid I/O native function.
const uint8_t* LookupIONativeSymbol(Dart_NativeFunction nf);
} // namespace bin
} // namespace dart
#endif // RUNTIME_INCLUDE_BIN_DART_IO_API_H_

File diff suppressed because it is too large Load diff

View file

@ -1,59 +0,0 @@
/*
* Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
* for details. All rights reserved. Use of this source code is governed by a
* BSD-style license that can be found in the LICENSE file.
*/
#include "dart_api_dl.h" /* NOLINT */
#include "dart_version.h" /* NOLINT */
#include "internal/dart_api_dl_impl.h" /* NOLINT */
#include <string.h>
#define DART_API_DL_DEFINITIONS(name, R, A) name##_Type name##_DL = NULL;
DART_API_ALL_DL_SYMBOLS(DART_API_DL_DEFINITIONS)
#undef DART_API_DL_DEFINITIONS
typedef void* DartApiEntry_function;
DartApiEntry_function FindFunctionPointer(const DartApiEntry* entries,
const char* name) {
while (entries->name != NULL) {
if (strcmp(entries->name, name) == 0) return entries->function;
entries++;
}
return NULL;
}
intptr_t Dart_InitializeApiDL(void* data) {
DartApi* dart_api_data = (DartApi*)data;
if (dart_api_data->major != DART_API_DL_MAJOR_VERSION) {
// If the DartVM we're running on does not have the same version as this
// file was compiled against, refuse to initialize. The symbols are not
// compatible.
return -1;
}
// Minor versions are allowed to be different.
// If the DartVM has a higher minor version, it will provide more symbols
// than we initialize here.
// If the DartVM has a lower minor version, it will not provide all symbols.
// In that case, we leave the missing symbols un-initialized. Those symbols
// should not be used by the Dart and native code. The client is responsible
// for checking the minor version number himself based on which symbols it
// is using.
// (If we would error out on this case, recompiling native code against a
// newer SDK would break all uses on older SDKs, which is too strict.)
const DartApiEntry* dart_api_function_pointers = dart_api_data->functions;
#define DART_API_DL_INIT(name, R, A) \
name##_DL = \
(name##_Type)(FindFunctionPointer(dart_api_function_pointers, #name));
DART_API_ALL_DL_SYMBOLS(DART_API_DL_INIT)
#undef DART_API_DL_INIT
return 0;
}

View file

@ -1,152 +0,0 @@
/*
* Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
* for details. All rights reserved. Use of this source code is governed by a
* BSD-style license that can be found in the LICENSE file.
*/
#ifndef RUNTIME_INCLUDE_DART_API_DL_H_
#define RUNTIME_INCLUDE_DART_API_DL_H_
#include "dart_api.h" /* NOLINT */
#include "dart_native_api.h" /* NOLINT */
/** \mainpage Dynamically Linked Dart API
*
* This exposes a subset of symbols from dart_api.h and dart_native_api.h
* available in every Dart embedder through dynamic linking.
*
* All symbols are postfixed with _DL to indicate that they are dynamically
* linked and to prevent conflicts with the original symbol.
*
* Link `dart_api_dl.c` file into your library and invoke
* `Dart_InitializeApiDL` with `NativeApi.initializeApiDLData`.
*/
DART_EXPORT intptr_t Dart_InitializeApiDL(void* data);
// ============================================================================
// IMPORTANT! Never update these signatures without properly updating
// DART_API_DL_MAJOR_VERSION and DART_API_DL_MINOR_VERSION.
//
// Verbatim copy of `dart_native_api.h` and `dart_api.h` symbol names and types
// to trigger compile-time errors if the symbols in those files are updated
// without updating these.
//
// Function return and argument types, and typedefs are carbon copied. Structs
// are typechecked nominally in C/C++, so they are not copied, instead a
// comment is added to their definition.
typedef int64_t Dart_Port_DL;
typedef void (*Dart_NativeMessageHandler_DL)(Dart_Port_DL dest_port_id,
Dart_CObject* message);
// dart_native_api.h symbols can be called on any thread.
#define DART_NATIVE_API_DL_SYMBOLS(F) \
/***** dart_native_api.h *****/ \
/* Dart_Port */ \
F(Dart_PostCObject, bool, (Dart_Port_DL port_id, Dart_CObject * message)) \
F(Dart_PostInteger, bool, (Dart_Port_DL port_id, int64_t message)) \
F(Dart_NewNativePort, Dart_Port_DL, \
(const char* name, Dart_NativeMessageHandler_DL handler, \
bool handle_concurrently)) \
F(Dart_CloseNativePort, bool, (Dart_Port_DL native_port_id))
// dart_api.h symbols can only be called on Dart threads.
#define DART_API_DL_SYMBOLS(F) \
/***** dart_api.h *****/ \
/* Errors */ \
F(Dart_IsError, bool, (Dart_Handle handle)) \
F(Dart_IsApiError, bool, (Dart_Handle handle)) \
F(Dart_IsUnhandledExceptionError, bool, (Dart_Handle handle)) \
F(Dart_IsCompilationError, bool, (Dart_Handle handle)) \
F(Dart_IsFatalError, bool, (Dart_Handle handle)) \
F(Dart_GetError, const char*, (Dart_Handle handle)) \
F(Dart_ErrorHasException, bool, (Dart_Handle handle)) \
F(Dart_ErrorGetException, Dart_Handle, (Dart_Handle handle)) \
F(Dart_ErrorGetStackTrace, Dart_Handle, (Dart_Handle handle)) \
F(Dart_NewApiError, Dart_Handle, (const char* error)) \
F(Dart_NewCompilationError, Dart_Handle, (const char* error)) \
F(Dart_NewUnhandledExceptionError, Dart_Handle, (Dart_Handle exception)) \
F(Dart_PropagateError, void, (Dart_Handle handle)) \
/* Dart_Handle, Dart_PersistentHandle, Dart_WeakPersistentHandle */ \
F(Dart_HandleFromPersistent, Dart_Handle, (Dart_PersistentHandle object)) \
F(Dart_HandleFromWeakPersistent, Dart_Handle, \
(Dart_WeakPersistentHandle object)) \
F(Dart_NewPersistentHandle, Dart_PersistentHandle, (Dart_Handle object)) \
F(Dart_SetPersistentHandle, void, \
(Dart_PersistentHandle obj1, Dart_Handle obj2)) \
F(Dart_DeletePersistentHandle, void, (Dart_PersistentHandle object)) \
F(Dart_NewWeakPersistentHandle, Dart_WeakPersistentHandle, \
(Dart_Handle object, void* peer, intptr_t external_allocation_size, \
Dart_HandleFinalizer callback)) \
F(Dart_DeleteWeakPersistentHandle, void, (Dart_WeakPersistentHandle object)) \
F(Dart_UpdateExternalSize, void, \
(Dart_WeakPersistentHandle object, intptr_t external_allocation_size)) \
F(Dart_NewFinalizableHandle, Dart_FinalizableHandle, \
(Dart_Handle object, void* peer, intptr_t external_allocation_size, \
Dart_HandleFinalizer callback)) \
F(Dart_DeleteFinalizableHandle, void, \
(Dart_FinalizableHandle object, Dart_Handle strong_ref_to_object)) \
F(Dart_UpdateFinalizableExternalSize, void, \
(Dart_FinalizableHandle object, Dart_Handle strong_ref_to_object, \
intptr_t external_allocation_size)) \
/* Dart_Port */ \
F(Dart_Post, bool, (Dart_Port_DL port_id, Dart_Handle object)) \
F(Dart_NewSendPort, Dart_Handle, (Dart_Port_DL port_id)) \
F(Dart_SendPortGetId, Dart_Handle, \
(Dart_Handle port, Dart_Port_DL * port_id)) \
/* Scopes */ \
F(Dart_EnterScope, void, (void)) \
F(Dart_ExitScope, void, (void)) \
/* Objects */ \
F(Dart_IsNull, bool, (Dart_Handle))
#define DART_API_ALL_DL_SYMBOLS(F) \
DART_NATIVE_API_DL_SYMBOLS(F) \
DART_API_DL_SYMBOLS(F)
// IMPORTANT! Never update these signatures without properly updating
// DART_API_DL_MAJOR_VERSION and DART_API_DL_MINOR_VERSION.
//
// End of verbatim copy.
// ============================================================================
// Copy of definition of DART_EXPORT without 'used' attribute.
//
// The 'used' attribute cannot be used with DART_API_ALL_DL_SYMBOLS because
// they are not function declarations, but variable declarations with a
// function pointer type.
//
// The function pointer variables are initialized with the addresses of the
// functions in the VM. If we were to use function declarations instead, we
// would need to forward the call to the VM adding indirection.
#if defined(__CYGWIN__)
#error Tool chain and platform not supported.
#elif defined(_WIN32)
#if defined(DART_SHARED_LIB)
#define DART_EXPORT_DL DART_EXTERN_C __declspec(dllexport)
#else
#define DART_EXPORT_DL DART_EXTERN_C
#endif
#else
#if __GNUC__ >= 4
#if defined(DART_SHARED_LIB)
#define DART_EXPORT_DL DART_EXTERN_C __attribute__((visibility("default")))
#else
#define DART_EXPORT_DL DART_EXTERN_C
#endif
#else
#error Tool chain not supported.
#endif
#endif
#define DART_API_DL_DECLARATIONS(name, R, A) \
typedef R(*name##_Type) A; \
DART_EXPORT_DL name##_Type name##_DL;
DART_API_ALL_DL_SYMBOLS(DART_API_DL_DECLARATIONS)
#undef DART_API_DL_DECLARATIONS
#undef DART_EXPORT_DL
#endif /* RUNTIME_INCLUDE_DART_API_DL_H_ */ /* NOLINT */

View file

@ -1,108 +0,0 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_INCLUDE_DART_EMBEDDER_API_H_
#define RUNTIME_INCLUDE_DART_EMBEDDER_API_H_
#include "include/dart_api.h"
#include "include/dart_tools_api.h"
namespace dart {
namespace embedder {
// Initialize all subsystems of the embedder.
//
// Must be called before the `Dart_Initialize()` call to initialize the
// Dart VM.
//
// Returns true on success and false otherwise, in which case error would
// contain error message.
DART_WARN_UNUSED_RESULT bool InitOnce(char** error);
// Cleans up all subsystems of the embedder.
//
// Must be called after the `Dart_Cleanup()` call to initialize the
// Dart VM.
void Cleanup();
// Common arguments that are passed to isolate creation callback and to
// API methods that create isolates.
struct IsolateCreationData {
// URI for the main script that will be running in the isolate.
const char* script_uri;
// Advisory name of the main method that will be run by isolate.
// Only used for error messages.
const char* main;
// Isolate creation flags. Might be absent.
Dart_IsolateFlags* flags;
// Isolate group callback data.
void* isolate_group_data;
// Isolate callback data.
void* isolate_data;
};
// Create and initialize kernel-service isolate. This method should be used
// when VM invokes isolate creation callback with DART_KERNEL_ISOLATE_NAME as
// script_uri.
// The isolate is created from the given snapshot (might be kernel data or
// app-jit snapshot).
DART_WARN_UNUSED_RESULT Dart_Isolate
CreateKernelServiceIsolate(const IsolateCreationData& data,
const uint8_t* buffer,
intptr_t buffer_size,
char** error);
// Service isolate configuration.
struct VmServiceConfiguration {
enum {
kBindHttpServerToAFreePort = 0,
kDoNotAutoStartHttpServer = -1
};
// Address to which HTTP server will be bound.
const char* ip;
// Default port. See enum above for special values.
int port;
// If non-null, connection information for the VM service will be output to a
// file in JSON format at the location specified.
const char* write_service_info_filename;
// TODO(vegorov) document these ones.
bool dev_mode;
bool deterministic;
bool disable_auth_codes;
};
// Create and initialize vm-service isolate from the given AOT snapshot, which
// is expected to contain all necessary 'vm-service' libraries.
// This method should be used when VM invokes isolate creation callback with
// DART_VM_SERVICE_ISOLATE_NAME as script_uri.
DART_WARN_UNUSED_RESULT Dart_Isolate
CreateVmServiceIsolate(const IsolateCreationData& data,
const VmServiceConfiguration& config,
const uint8_t* isolate_data,
const uint8_t* isolate_instr,
char** error);
// Create and initialize vm-service isolate from the given kernel binary, which
// is expected to contain all necessary 'vm-service' libraries.
// This method should be used when VM invokes isolate creation callback with
// DART_VM_SERVICE_ISOLATE_NAME as script_uri.
DART_WARN_UNUSED_RESULT Dart_Isolate
CreateVmServiceIsolateFromKernel(const IsolateCreationData& data,
const VmServiceConfiguration& config,
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size,
char** error);
} // namespace embedder
} // namespace dart
#endif // RUNTIME_INCLUDE_DART_EMBEDDER_API_H_

View file

@ -1,207 +0,0 @@
/*
* Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
* for details. All rights reserved. Use of this source code is governed by a
* BSD-style license that can be found in the LICENSE file.
*/
#ifndef RUNTIME_INCLUDE_DART_NATIVE_API_H_
#define RUNTIME_INCLUDE_DART_NATIVE_API_H_
#include "dart_api.h" /* NOLINT */
/*
* ==========================================
* Message sending/receiving from native code
* ==========================================
*/
/**
* A Dart_CObject is used for representing Dart objects as native C
* data outside the Dart heap. These objects are totally detached from
* the Dart heap. Only a subset of the Dart objects have a
* representation as a Dart_CObject.
*
* The string encoding in the 'value.as_string' is UTF-8.
*
* All the different types from dart:typed_data are exposed as type
* kTypedData. The specific type from dart:typed_data is in the type
* field of the as_typed_data structure. The length in the
* as_typed_data structure is always in bytes.
*
* The data for kTypedData is copied on message send and ownership remains with
* the caller. The ownership of data for kExternalTyped is passed to the VM on
* message send and returned when the VM invokes the
* Dart_HandleFinalizer callback; a non-NULL callback must be provided.
*
* Note that Dart_CObject_kNativePointer is intended for internal use by
* dart:io implementation and has no connection to dart:ffi Pointer class.
* It represents a pointer to a native resource of a known type.
* The receiving side will only see this pointer as an integer and will not
* see the specified finalizer.
* The specified finalizer will only be invoked if the message is not delivered.
*/
typedef enum {
Dart_CObject_kNull = 0,
Dart_CObject_kBool,
Dart_CObject_kInt32,
Dart_CObject_kInt64,
Dart_CObject_kDouble,
Dart_CObject_kString,
Dart_CObject_kArray,
Dart_CObject_kTypedData,
Dart_CObject_kExternalTypedData,
Dart_CObject_kSendPort,
Dart_CObject_kCapability,
Dart_CObject_kNativePointer,
Dart_CObject_kUnsupported,
Dart_CObject_kUnmodifiableExternalTypedData,
Dart_CObject_kNumberOfTypes
} Dart_CObject_Type;
// This enum is versioned by DART_API_DL_MAJOR_VERSION, only add at the end
// and bump the DART_API_DL_MINOR_VERSION.
typedef struct _Dart_CObject {
Dart_CObject_Type type;
union {
bool as_bool;
int32_t as_int32;
int64_t as_int64;
double as_double;
const char* as_string;
struct {
Dart_Port id;
Dart_Port origin_id;
} as_send_port;
struct {
int64_t id;
} as_capability;
struct {
intptr_t length;
struct _Dart_CObject** values;
} as_array;
struct {
Dart_TypedData_Type type;
intptr_t length; /* in elements, not bytes */
const uint8_t* values;
} as_typed_data;
struct {
Dart_TypedData_Type type;
intptr_t length; /* in elements, not bytes */
uint8_t* data;
void* peer;
Dart_HandleFinalizer callback;
} as_external_typed_data;
struct {
intptr_t ptr;
intptr_t size;
Dart_HandleFinalizer callback;
} as_native_pointer;
} value;
} Dart_CObject;
// This struct is versioned by DART_API_DL_MAJOR_VERSION, bump the version when
// changing this struct.
/**
* Posts a message on some port. The message will contain the Dart_CObject
* object graph rooted in 'message'.
*
* While the message is being sent the state of the graph of Dart_CObject
* structures rooted in 'message' should not be accessed, as the message
* generation will make temporary modifications to the data. When the message
* has been sent the graph will be fully restored.
*
* If true is returned, the message was enqueued, and finalizers for external
* typed data will eventually run, even if the receiving isolate shuts down
* before processing the message. If false is returned, the message was not
* enqueued and ownership of external typed data in the message remains with the
* caller.
*
* This function may be called on any thread when the VM is running (that is,
* after Dart_Initialize has returned and before Dart_Cleanup has been called).
*
* \param port_id The destination port.
* \param message The message to send.
*
* \return True if the message was posted.
*/
DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject* message);
/**
* Posts a message on some port. The message will contain the integer 'message'.
*
* \param port_id The destination port.
* \param message The message to send.
*
* \return True if the message was posted.
*/
DART_EXPORT bool Dart_PostInteger(Dart_Port port_id, int64_t message);
/**
* A native message handler.
*
* This handler is associated with a native port by calling
* Dart_NewNativePort.
*
* The message received is decoded into the message structure. The
* lifetime of the message data is controlled by the caller. All the
* data references from the message are allocated by the caller and
* will be reclaimed when returning to it.
*/
typedef void (*Dart_NativeMessageHandler)(Dart_Port dest_port_id,
Dart_CObject* message);
/**
* Creates a new native port. When messages are received on this
* native port, then they will be dispatched to the provided native
* message handler.
*
* \param name The name of this port in debugging messages.
* \param handler The C handler to run when messages arrive on the port.
* \param handle_concurrently Is it okay to process requests on this
* native port concurrently?
*
* \return If successful, returns the port id for the native port. In
* case of error, returns ILLEGAL_PORT.
*/
DART_EXPORT Dart_Port Dart_NewNativePort(const char* name,
Dart_NativeMessageHandler handler,
bool handle_concurrently);
/* TODO(turnidge): Currently handle_concurrently is ignored. */
/**
* Closes the native port with the given id.
*
* The port must have been allocated by a call to Dart_NewNativePort.
*
* \param native_port_id The id of the native port to close.
*
* \return Returns true if the port was closed successfully.
*/
DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id);
/*
* ==================
* Verification Tools
* ==================
*/
/**
* Forces all loaded classes and functions to be compiled eagerly in
* the current isolate..
*
* TODO(turnidge): Document.
*/
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_CompileAll(void);
/**
* Finalizes all classes.
*/
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_FinalizeAllClasses(void);
/* This function is intentionally undocumented.
*
* It should not be used outside internal tests.
*/
DART_EXPORT void* Dart_ExecuteInternalCommand(const char* command, void* arg);
#endif /* INCLUDE_DART_NATIVE_API_H_ */ /* NOLINT */

View file

@ -1,582 +0,0 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_INCLUDE_DART_TOOLS_API_H_
#define RUNTIME_INCLUDE_DART_TOOLS_API_H_
#include "dart_api.h" /* NOLINT */
/** \mainpage Dart Tools Embedding API Reference
*
* This reference describes the Dart embedding API for tools. Tools include
* a debugger, service protocol, and timeline.
*
* NOTE: The APIs described in this file are unstable and subject to change.
*
* This reference is generated from the header include/dart_tools_api.h.
*/
/*
* ========
* Debugger
* ========
*/
/**
* ILLEGAL_ISOLATE_ID is a number guaranteed never to be associated with a
* valid isolate.
*/
#define ILLEGAL_ISOLATE_ID ILLEGAL_PORT
/**
* ILLEGAL_ISOLATE_GROUP_ID is a number guaranteed never to be associated with a
* valid isolate group.
*/
#define ILLEGAL_ISOLATE_GROUP_ID 0
/*
* =======
* Service
* =======
*/
/**
* A service request callback function.
*
* These callbacks, registered by the embedder, are called when the VM receives
* a service request it can't handle and the service request command name
* matches one of the embedder registered handlers.
*
* The return value of the callback indicates whether the response
* should be used as a regular result or an error result.
* Specifically, if the callback returns true, a regular JSON-RPC
* response is built in the following way:
*
* {
* "jsonrpc": "2.0",
* "result": <json_object>,
* "id": <some sequence id>,
* }
*
* If the callback returns false, a JSON-RPC error is built like this:
*
* {
* "jsonrpc": "2.0",
* "error": <json_object>,
* "id": <some sequence id>,
* }
*
* \param method The rpc method name.
* \param param_keys Service requests can have key-value pair parameters. The
* keys and values are flattened and stored in arrays.
* \param param_values The values associated with the keys.
* \param num_params The length of the param_keys and param_values arrays.
* \param user_data The user_data pointer registered with this handler.
* \param result A C string containing a valid JSON object. The returned
* pointer will be freed by the VM by calling free.
*
* \return True if the result is a regular JSON-RPC response, false if the
* result is a JSON-RPC error.
*/
typedef bool (*Dart_ServiceRequestCallback)(const char* method,
const char** param_keys,
const char** param_values,
intptr_t num_params,
void* user_data,
const char** json_object);
/**
* Register a Dart_ServiceRequestCallback to be called to handle
* requests for the named rpc on a specific isolate. The callback will
* be invoked with the current isolate set to the request target.
*
* \param method The name of the method that this callback is responsible for.
* \param callback The callback to invoke.
* \param user_data The user data passed to the callback.
*
* NOTE: If multiple callbacks with the same name are registered, only
* the last callback registered will be remembered.
*/
DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
const char* method,
Dart_ServiceRequestCallback callback,
void* user_data);
/**
* Register a Dart_ServiceRequestCallback to be called to handle
* requests for the named rpc. The callback will be invoked without a
* current isolate.
*
* \param method The name of the command that this callback is responsible for.
* \param callback The callback to invoke.
* \param user_data The user data passed to the callback.
*
* NOTE: If multiple callbacks with the same name are registered, only
* the last callback registered will be remembered.
*/
DART_EXPORT void Dart_RegisterRootServiceRequestCallback(
const char* method,
Dart_ServiceRequestCallback callback,
void* user_data);
/**
* Embedder information which can be requested by the VM for internal or
* reporting purposes.
*
* The pointers in this structure are not going to be cached or freed by the VM.
*/
#define DART_EMBEDDER_INFORMATION_CURRENT_VERSION (0x00000001)
typedef struct {
int32_t version;
const char* name; // [optional] The name of the embedder
int64_t current_rss; // [optional] the current RSS of the embedder
int64_t max_rss; // [optional] the maximum RSS of the embedder
} Dart_EmbedderInformation;
/**
* Callback provided by the embedder that is used by the VM to request
* information.
*
* \return Returns a pointer to a Dart_EmbedderInformation structure.
* The embedder keeps the ownership of the structure and any field in it.
* The embedder must ensure that the structure will remain valid until the
* next invocation of the callback.
*/
typedef void (*Dart_EmbedderInformationCallback)(
Dart_EmbedderInformation* info);
/**
* Register a Dart_ServiceRequestCallback to be called to handle
* requests for the named rpc. The callback will be invoked without a
* current isolate.
*
* \param method The name of the command that this callback is responsible for.
* \param callback The callback to invoke.
* \param user_data The user data passed to the callback.
*
* NOTE: If multiple callbacks are registered, only the last callback registered
* will be remembered.
*/
DART_EXPORT void Dart_SetEmbedderInformationCallback(
Dart_EmbedderInformationCallback callback);
/**
* Invoke a vm-service method and wait for its result.
*
* \param request_json The utf8-encoded json-rpc request.
* \param request_json_length The length of the json-rpc request.
*
* \param response_json The returned utf8-encoded json response, must be
* free()ed by caller.
* \param response_json_length The length of the returned json response.
* \param error An optional error, must be free()ed by caller.
*
* \return Whether the call was successfully performed.
*
* NOTE: This method does not need a current isolate and must not have the
* vm-isolate being the current isolate. It must be called after
* Dart_Initialize() and before Dart_Cleanup().
*/
DART_EXPORT bool Dart_InvokeVMServiceMethod(uint8_t* request_json,
intptr_t request_json_length,
uint8_t** response_json,
intptr_t* response_json_length,
char** error);
/*
* ========
* Event Streams
* ========
*/
/**
* A callback invoked when the VM service gets a request to listen to
* some stream.
*
* \return Returns true iff the embedder supports the named stream id.
*/
typedef bool (*Dart_ServiceStreamListenCallback)(const char* stream_id);
/**
* A callback invoked when the VM service gets a request to cancel
* some stream.
*/
typedef void (*Dart_ServiceStreamCancelCallback)(const char* stream_id);
/**
* Adds VM service stream callbacks.
*
* \param listen_callback A function pointer to a listen callback function.
* A listen callback function should not be already set when this function
* is called. A NULL value removes the existing listen callback function
* if any.
*
* \param cancel_callback A function pointer to a cancel callback function.
* A cancel callback function should not be already set when this function
* is called. A NULL value removes the existing cancel callback function
* if any.
*
* \return Success if the callbacks were added. Otherwise, returns an
* error handle.
*/
DART_EXPORT char* Dart_SetServiceStreamCallbacks(
Dart_ServiceStreamListenCallback listen_callback,
Dart_ServiceStreamCancelCallback cancel_callback);
/**
* Sends a data event to clients of the VM Service.
*
* A data event is used to pass an array of bytes to subscribed VM
* Service clients. For example, in the standalone embedder, this is
* function used to provide WriteEvents on the Stdout and Stderr
* streams.
*
* If the embedder passes in a stream id for which no client is
* subscribed, then the event is ignored.
*
* \param stream_id The id of the stream on which to post the event.
*
* \param event_kind A string identifying what kind of event this is.
* For example, 'WriteEvent'.
*
* \param bytes A pointer to an array of bytes.
*
* \param bytes_length The length of the byte array.
*
* \return NULL if the arguments are well formed. Otherwise, returns an
* error string. The caller is responsible for freeing the error message.
*/
DART_EXPORT char* Dart_ServiceSendDataEvent(const char* stream_id,
const char* event_kind,
const uint8_t* bytes,
intptr_t bytes_length);
/*
* ========
* Reload support
* ========
*
* These functions are used to implement reloading in the Dart VM.
* This is an experimental feature, so embedders should be prepared
* for these functions to change.
*/
/**
* A callback which determines whether the file at some url has been
* modified since some time. If the file cannot be found, true should
* be returned.
*/
typedef bool (*Dart_FileModifiedCallback)(const char* url, int64_t since);
DART_EXPORT char* Dart_SetFileModifiedCallback(
Dart_FileModifiedCallback file_modified_callback);
/**
* Returns true if isolate is currently reloading.
*/
DART_EXPORT bool Dart_IsReloading();
/*
* ========
* Timeline
* ========
*/
/**
* Enable tracking of specified timeline category. This is operational
* only when systrace timeline functionality is turned on.
*
* \param categories A comma separated list of categories that need to
* be enabled, the categories are
* "all" : All categories
* "API" - Execution of Dart C API functions
* "Compiler" - Execution of Dart JIT compiler
* "CompilerVerbose" - More detailed Execution of Dart JIT compiler
* "Dart" - Execution of Dart code
* "Debugger" - Execution of Dart debugger
* "Embedder" - Execution of Dart embedder code
* "GC" - Execution of Dart Garbage Collector
* "Isolate" - Dart Isolate lifecycle execution
* "VM" - Execution in Dart VM runtime code
* "" - None
*
* When "all" is specified all the categories are enabled.
* When a comma separated list of categories is specified, the categories
* that are specified will be enabled and the rest will be disabled.
* When "" is specified all the categories are disabled.
* The category names are case sensitive.
* eg: Dart_EnableTimelineCategory("all");
* Dart_EnableTimelineCategory("GC,API,Isolate");
* Dart_EnableTimelineCategory("GC,Debugger,Dart");
*
* \return True if the categories were successfully enabled, False otherwise.
*/
DART_EXPORT bool Dart_SetEnabledTimelineCategory(const char* categories);
/**
* Returns a timestamp in microseconds. This timestamp is suitable for
* passing into the timeline system, and uses the same monotonic clock
* as dart:developer's Timeline.now.
*
* \return A timestamp that can be passed to the timeline system.
*/
DART_EXPORT int64_t Dart_TimelineGetMicros();
/**
* Returns a raw timestamp in from the monotonic clock.
*
* \return A raw timestamp from the monotonic clock.
*/
DART_EXPORT int64_t Dart_TimelineGetTicks();
/**
* Returns the frequency of the monotonic clock.
*
* \return The frequency of the monotonic clock.
*/
DART_EXPORT int64_t Dart_TimelineGetTicksFrequency();
typedef enum {
Dart_Timeline_Event_Begin, // Phase = 'B'.
Dart_Timeline_Event_End, // Phase = 'E'.
Dart_Timeline_Event_Instant, // Phase = 'i'.
Dart_Timeline_Event_Duration, // Phase = 'X'.
Dart_Timeline_Event_Async_Begin, // Phase = 'b'.
Dart_Timeline_Event_Async_End, // Phase = 'e'.
Dart_Timeline_Event_Async_Instant, // Phase = 'n'.
Dart_Timeline_Event_Counter, // Phase = 'C'.
Dart_Timeline_Event_Flow_Begin, // Phase = 's'.
Dart_Timeline_Event_Flow_Step, // Phase = 't'.
Dart_Timeline_Event_Flow_End, // Phase = 'f'.
} Dart_Timeline_Event_Type;
/**
* Add a timeline event to the embedder stream.
*
* \param label The name of the event. Its lifetime must extend at least until
* Dart_Cleanup.
* \param timestamp0 The first timestamp of the event.
* \param timestamp1_or_async_id The second timestamp of the event or
* the async id.
* \param argument_count The number of argument names and values.
* \param argument_names An array of names of the arguments. The lifetime of the
* names must extend at least until Dart_Cleanup. The array may be reclaimed
* when this call returns.
* \param argument_values An array of values of the arguments. The values and
* the array may be reclaimed when this call returns.
*/
DART_EXPORT void Dart_TimelineEvent(const char* label,
int64_t timestamp0,
int64_t timestamp1_or_async_id,
Dart_Timeline_Event_Type type,
intptr_t argument_count,
const char** argument_names,
const char** argument_values);
/**
* Associates a name with the current thread. This name will be used to name
* threads in the timeline. Can only be called after a call to Dart_Initialize.
*
* \param name The name of the thread.
*/
DART_EXPORT void Dart_SetThreadName(const char* name);
typedef struct {
const char* name;
const char* value;
} Dart_TimelineRecorderEvent_Argument;
#define DART_TIMELINE_RECORDER_CURRENT_VERSION (0x00000001)
typedef struct {
/* Set to DART_TIMELINE_RECORDER_CURRENT_VERSION */
int32_t version;
/* The event's type / phase. */
Dart_Timeline_Event_Type type;
/* The event's timestamp according to the same clock as
* Dart_TimelineGetMicros. For a duration event, this is the beginning time.
*/
int64_t timestamp0;
/* For a duration event, this is the end time. For an async event, this is the
* async id. */
int64_t timestamp1_or_async_id;
/* The current isolate of the event, as if by Dart_GetMainPortId, or
* ILLEGAL_PORT if the event had no current isolate. */
Dart_Port isolate;
/* The current isolate group of the event, as if by
* Dart_CurrentIsolateGroupId, or ILLEGAL_PORT if the event had no current
* isolate group. */
Dart_IsolateGroupId isolate_group;
/* The name / label of the event. */
const char* label;
/* The stream / category of the event. */
const char* stream;
intptr_t argument_count;
Dart_TimelineRecorderEvent_Argument* arguments;
} Dart_TimelineRecorderEvent;
/**
* Callback provided by the embedder to handle the completion of timeline
* events.
*
* \param event A timeline event that has just been completed. The VM keeps
* ownership of the event and any field in it (i.e., the embedder should copy
* any values it needs after the callback returns).
*/
typedef void (*Dart_TimelineRecorderCallback)(
Dart_TimelineRecorderEvent* event);
/**
* Register a `Dart_TimelineRecorderCallback` to be called as timeline events
* are completed.
*
* The callback will be invoked without a current isolate.
*
* The callback will be invoked on the thread completing the event. Because
* `Dart_TimelineEvent` may be called by any thread, the callback may be called
* on any thread.
*
* The callback may be invoked at any time after `Dart_Initialize` is called and
* before `Dart_Cleanup` returns.
*
* If multiple callbacks are registered, only the last callback registered
* will be remembered. Providing a NULL callback will clear the registration
* (i.e., a NULL callback produced a no-op instead of a crash).
*
* Setting a callback is insufficient to receive events through the callback. The
* VM flag `timeline_recorder` must also be set to `callback`.
*/
DART_EXPORT void Dart_SetTimelineRecorderCallback(
Dart_TimelineRecorderCallback callback);
/*
* =======
* Metrics
* =======
*/
/**
* Return metrics gathered for the VM and individual isolates.
*/
DART_EXPORT int64_t
Dart_IsolateGroupHeapOldUsedMetric(Dart_IsolateGroup group); // Byte
DART_EXPORT int64_t
Dart_IsolateGroupHeapOldCapacityMetric(Dart_IsolateGroup group); // Byte
DART_EXPORT int64_t
Dart_IsolateGroupHeapOldExternalMetric(Dart_IsolateGroup group); // Byte
DART_EXPORT int64_t
Dart_IsolateGroupHeapNewUsedMetric(Dart_IsolateGroup group); // Byte
DART_EXPORT int64_t
Dart_IsolateGroupHeapNewCapacityMetric(Dart_IsolateGroup group); // Byte
DART_EXPORT int64_t
Dart_IsolateGroupHeapNewExternalMetric(Dart_IsolateGroup group); // Byte
/*
* ========
* UserTags
* ========
*/
/*
* Gets the current isolate's currently set UserTag instance.
*
* \return The currently set UserTag instance.
*/
DART_EXPORT Dart_Handle Dart_GetCurrentUserTag();
/*
* Gets the current isolate's default UserTag instance.
*
* \return The default UserTag with label 'Default'
*/
DART_EXPORT Dart_Handle Dart_GetDefaultUserTag();
/*
* Creates a new UserTag instance.
*
* \param label The name of the new UserTag.
*
* \return The newly created UserTag instance or an error handle.
*/
DART_EXPORT Dart_Handle Dart_NewUserTag(const char* label);
/*
* Updates the current isolate's UserTag to a new value.
*
* \param user_tag The UserTag to be set as the current UserTag.
*
* \return The previously set UserTag instance or an error handle.
*/
DART_EXPORT Dart_Handle Dart_SetCurrentUserTag(Dart_Handle user_tag);
/*
* Returns the label of a given UserTag instance.
*
* \param user_tag The UserTag from which the label will be retrieved.
*
* \return The UserTag's label. NULL if the user_tag is invalid. The caller is
* responsible for freeing the returned label.
*/
DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_GetUserTagLabel(
Dart_Handle user_tag);
/*
* =======
* Heap Snapshot
* =======
*/
/**
* Callback provided by the caller of `Dart_WriteHeapSnapshot` which is
* used to write out chunks of the requested heap snapshot.
*
* \param context An opaque context which was passed to `Dart_WriteHeapSnapshot`
* together with this callback.
*
* \param buffer Pointer to the buffer containing a chunk of the snapshot.
* The callback owns the buffer and needs to `free` it.
*
* \param size Number of bytes in the `buffer` to be written.
*
* \param is_last Set to `true` for the last chunk. The callback will not
* be invoked again after it was invoked once with `is_last` set to `true`.
*/
typedef void (*Dart_HeapSnapshotWriteChunkCallback)(void* context,
uint8_t* buffer,
intptr_t size,
bool is_last);
/**
* Generate heap snapshot of the current isolate group and stream it into the
* given `callback`. VM would produce snapshot in chunks and send these chunks
* one by one back to the embedder by invoking the provided `callback`.
*
* This API enables embedder to stream snapshot into a file or socket without
* allocating a buffer to hold the whole snapshot in memory.
*
* The isolate group will be paused for the duration of this operation.
*
* \param write Callback used to write chunks of the heap snapshot.
*
* \param context Opaque context which would be passed on each invocation of
* `write` callback.
*
* \returns `nullptr` if the operation is successful otherwise error message.
* Caller owns error message string and needs to `free` it.
*/
DART_EXPORT char* Dart_WriteHeapSnapshot(
Dart_HeapSnapshotWriteChunkCallback write,
void* context);
#endif // RUNTIME_INCLUDE_DART_TOOLS_API_H_

View file

@ -1,16 +0,0 @@
/*
* Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
* for details. All rights reserved. Use of this source code is governed by a
* BSD-style license that can be found in the LICENSE file.
*/
#ifndef RUNTIME_INCLUDE_DART_VERSION_H_
#define RUNTIME_INCLUDE_DART_VERSION_H_
// On breaking changes the major version is increased.
// On backwards compatible changes the minor version is increased.
// The versioning covers the symbols exposed in dart_api_dl.h
#define DART_API_DL_MAJOR_VERSION 2
#define DART_API_DL_MINOR_VERSION 2
#endif /* RUNTIME_INCLUDE_DART_VERSION_H_ */ /* NOLINT */

View file

@ -1,21 +0,0 @@
/*
* Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
* for details. All rights reserved. Use of this source code is governed by a
* BSD-style license that can be found in the LICENSE file.
*/
#ifndef RUNTIME_INCLUDE_INTERNAL_DART_API_DL_IMPL_H_
#define RUNTIME_INCLUDE_INTERNAL_DART_API_DL_IMPL_H_
typedef struct {
const char* name;
void (*function)(void);
} DartApiEntry;
typedef struct {
const int major;
const int minor;
const DartApiEntry* const functions;
} DartApi;
#endif /* RUNTIME_INCLUDE_INTERNAL_DART_API_DL_IMPL_H_ */ /* NOLINT */

View file

@ -1,104 +0,0 @@
use crate::bridge::bridge_engine::Channel;
pub use super::DartAbi;
pub use super::MessagePort;
pub use allo_isolate::*;
use dart_sys::Dart_DeletePersistentHandle_DL;
use dart_sys::Dart_Handle;
use dart_sys::Dart_HandleFromPersistent_DL;
use dart_sys::Dart_InitializeApiDL;
use dart_sys::Dart_NewPersistentHandle_DL;
use dart_sys::Dart_PersistentHandle;
use libc::c_void;
/// # Safety
///
/// This function should never be called manually.
#[no_mangle]
pub unsafe extern "C" fn new_dart_opaque(handle: Dart_Handle) -> usize {
Dart_NewPersistentHandle_DL.expect("dart_api_dl has not been initialized")(handle) as _
}
/// # Safety
///
/// This function should never be called manually.
#[no_mangle]
pub unsafe extern "C" fn get_dart_object(ptr: usize) -> Dart_Handle {
let handle = ptr as _;
let res = Dart_HandleFromPersistent_DL.expect("dart_api_dl has not been initialized")(handle);
Dart_DeletePersistentHandle_DL.expect("dart_api_dl has not been initialized")(handle);
res
}
/// # Safety
///
/// This function should never be called manually.
#[no_mangle]
pub unsafe extern "C" fn drop_dart_object(ptr: usize) {
Dart_DeletePersistentHandle_DL.expect("dart_api_dl has not been initialized")(ptr as _);
}
/// # Safety
///
/// This function should never be called manually.
#[no_mangle]
pub unsafe extern "C" fn init_frb_dart_api_dl(data: *mut c_void) -> isize {
Dart_InitializeApiDL(data)
}
#[derive(Debug)]
/// Option for correct drop.
pub struct DartHandleWrap(Option<Dart_PersistentHandle>);
impl DartHandleWrap {
pub fn from_raw(ptr: Dart_PersistentHandle) -> Self {
Self(Some(ptr))
}
pub fn into_raw(mut self) -> Dart_PersistentHandle {
self.0.take().unwrap()
}
}
impl From<DartHandleWrap> for Dart_PersistentHandle {
fn from(warp: DartHandleWrap) -> Self {
warp.into_raw()
}
}
impl Drop for DartHandleWrap {
fn drop(&mut self) {
if let Some(inner) = self.0 {
unsafe {
Dart_DeletePersistentHandle_DL.expect("dart_api_dl has not been initialized")(inner)
}
}
}
}
#[derive(Debug)]
pub struct DartOpaqueBase {
inner: DartHandleWrap,
drop_port: Option<MessagePort>,
}
impl DartOpaqueBase {
pub fn new(handle: Dart_PersistentHandle, drop_port: Option<MessagePort>) -> Self {
Self {
inner: DartHandleWrap::from_raw(handle),
drop_port,
}
}
pub fn into_raw(self) -> Dart_PersistentHandle {
self.inner.into_raw()
}
pub fn unwrap(self) -> DartHandleWrap {
self.inner
}
pub fn channel(&self) -> Option<Channel> {
Some(Channel::new(self.drop_port?))
}
}

View file

@ -1,262 +0,0 @@
#[cfg(target_family = "wasm")]
pub type DartAbi = wasm_bindgen::JsValue;
#[cfg(not(target_family = "wasm"))]
pub type DartAbi = allo_isolate::ffi::DartCObject;
#[cfg(not(target_family = "wasm"))]
use dart_sys::Dart_PersistentHandle;
use std::{mem, ops, sync::Arc, thread::ThreadId};
#[cfg(not(target_family = "wasm"))]
pub use allo_isolate::IntoDart;
#[cfg(target_family = "wasm")]
pub type MessagePort = web::PortLike;
#[cfg(not(target_family = "wasm"))]
pub type MessagePort = i64;
#[cfg(target_family = "wasm")]
pub type OpaqueMessagePort = wasm_bindgen::JsValue;
#[cfg(not(target_family = "wasm"))]
pub type OpaqueMessagePort = i64;
#[cfg(target_family = "wasm")]
pub type DartWrapObject = wasm_bindgen::JsValue;
#[cfg(not(target_family = "wasm"))]
pub type DartWrapObject = DartHandleWrap;
#[cfg(target_family = "wasm")]
pub type DartObject = wasm_bindgen::JsValue;
#[cfg(not(target_family = "wasm"))]
pub type DartObject = Dart_PersistentHandle;
#[cfg(target_family = "wasm")]
pub mod web;
#[cfg(target_family = "wasm")]
pub use web::*;
#[cfg(not(target_family = "wasm"))]
pub type Channel = allo_isolate::Isolate;
#[cfg(not(target_family = "wasm"))]
pub mod io;
#[cfg(not(target_family = "wasm"))]
pub use io::*;
use crate::bridge::bridge_engine::DartSafe;
/// A wrapper to transfer ownership of T to Dart.
///
/// This type is equivalent to an [`Option<Arc<T>>`]. The inner pointer may
/// be None if a nullptr is received from Dart, signifying that this pointer
/// has been disposed.
///
/// Extensions for [`sync::RwLock`] and [`sync::Mutex`] are provided.
///
/// ## Naming the inner type
///
/// When an `RustOpaque<T>` is transformed into a Dart type, T's string
/// representation undergoes some transformations to become a valid Dart type:
/// - Rust keywords (dyn, 'static, DartSafe, etc.) are automatically removed.
/// - ASCII alphanumerics are kept, all other characters are ignored.
///
/// ## Trait objects
///
/// Trait objects may be put behind opaque pointers, but they must implement
/// [`DartSafe`] to be safely sent to Dart. For example, this declaration can
/// be used across the FFI border:
///
/// ```rust
/// use crate::*;
/// use std::fmt::Debug;
/// use std::panic::{UnwindSafe, RefUnwindSafe};
///
/// // Rust does not allow multiple non-auto traits in trait objects, so this
/// // is one workaround.
/// pub trait DartDebug: DartSafe + Debug {}
///
/// impl<T: DartSafe + Debug> DartDebug for T {}
///
/// pub struct DebugWrapper(pub RustOpaque<Box<dyn DartDebug>>);
///
/// // creating a DebugWrapper using the opaque_dyn macro
/// let wrap = DebugWrapper(opaque_dyn!("foobar"));
/// // it's possible to name it directly
/// pub struct DebugWrapper2(pub RustOpaque<Box<dyn Debug + Send + Sync + UnwindSafe + RefUnwindSafe>>);
/// ```
#[repr(transparent)]
#[derive(Debug)]
pub struct RustOpaque<T: ?Sized + DartSafe> {
ptr: Option<Arc<T>>,
}
impl<T: DartSafe> RustOpaque<T> {
pub fn try_unwrap(self) -> Result<T, Self> {
if let Some(ptr) = self.ptr {
Arc::try_unwrap(ptr).map_err(RustOpaque::from)
} else {
panic!("Use after free.")
}
}
}
impl<T: ?Sized + DartSafe> Clone for RustOpaque<T> {
fn clone(&self) -> Self {
Self {
ptr: self.ptr.clone(),
}
}
}
/// # Safety
///
/// This function should never be called manually.
/// Retrieving an opaque pointer from Dart is an implementation detail, so this
/// function is not guaranteed to be API-stable.
pub unsafe fn opaque_from_dart<T: DartSafe>(ptr: *const T) -> RustOpaque<T> {
// The raw pointer is the same one created from Arc::into_raw,
// owned and artificially incremented by Dart.
RustOpaque {
ptr: (!ptr.is_null()).then(|| Arc::from_raw(ptr)),
}
}
impl<T: ?Sized + DartSafe> ops::Deref for RustOpaque<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
if let Some(ptr) = &self.ptr {
ptr.as_ref()
} else {
panic!("Use after free.")
}
}
}
impl<T: ?Sized + DartSafe> From<Arc<T>> for RustOpaque<T> {
fn from(ptr: Arc<T>) -> Self {
Self { ptr: Some(ptr) }
}
}
impl<T: DartSafe> RustOpaque<T> {
pub fn new(value: T) -> Self {
Self {
ptr: Some(Arc::new(value)),
}
}
}
impl<T: DartSafe> From<RustOpaque<T>> for DartAbi {
fn from(value: RustOpaque<T>) -> Self {
let ptr = if let Some(ptr) = value.ptr {
Arc::into_raw(ptr)
} else {
std::ptr::null()
};
let size = mem::size_of::<T>();
vec![ptr.into_dart(), size.into_dart()].into_dart()
}
}
#[derive(Debug)]
pub struct DartOpaque {
/// Dart object
handle: Option<DartOpaqueBase>,
/// The ID of the thread on which the Dart Object was created.
thread_id: ThreadId,
}
/// # Safety
///
/// The implementation checks the current thread
/// and delegates it to the Dart thread when it is drops.
unsafe impl Send for DartOpaque {}
unsafe impl Sync for DartOpaque {}
impl DartOpaque {
/// Creates a new [DartOpaque].
///
/// # Safety
///
/// The [DartObject] must be created on the current thread.
pub unsafe fn new(handle: DartObject, port: OpaqueMessagePort) -> Self {
Self {
handle: Some(DartOpaqueBase::new(handle, Some(port))),
thread_id: std::thread::current().id(),
}
}
/// Creates a [DartOpaque] for sending to dart.
///
/// # Safety
///
/// The [DartObject] must be created on the current thread.
///
/// The [DartOpaque] created by this method must not be dropped
/// on a non-parent [DartObject] thread.
pub unsafe fn new_non_droppable(handle: DartObject) -> Self {
Self {
handle: Some(DartOpaqueBase::new(handle, None)),
thread_id: std::thread::current().id(),
}
}
/// Tries to get a Dart [DartObject].
/// Returns the [DartObject] if the [DartOpaque] was created on the current thread.
pub fn try_unwrap(mut self) -> Result<DartWrapObject, Self> {
if std::thread::current().id() == self.thread_id {
Ok(self.handle.take().unwrap().unwrap())
} else {
Err(self)
}
}
}
impl From<DartOpaque> for DartAbi {
fn from(mut data: DartOpaque) -> Self {
data.handle.take().unwrap().into_raw().into_dart()
}
}
impl Drop for DartOpaque {
fn drop(&mut self) {
if let Some(inner) = self.handle.take() {
if std::thread::current().id() != self.thread_id {
if let Some(channel) = inner.channel() {
let ptr = inner.into_raw();
if !channel.post(ptr) {
println!("Drop DartOpaque after closing the port.");
};
} else {
println!("Drop non droppable DartOpaque.");
}
}
}
}
}
/// Macro helper to instantiate an `RustOpaque<dyn Trait>`, as Rust does not
/// support custom DSTs on stable.
///
/// Example:
/// ```rust
/// use std::fmt::Debug;
/// use crate::*;
///
/// pub trait MyDebug: DartSafe + Debug {}
///
/// impl<T: DartSafe + Debug> MyDebug for T {}
///
/// let opaque: RustOpaque<Box<dyn MyDebug>> = opaque_dyn!("foobar");
/// ```
#[macro_export]
macro_rules! opaque_dyn {
($ex:expr) => {
$crate::RustOpaque::new(::std::boxed::Box::new($ex))
};
}

View file

@ -1,409 +0,0 @@
use std::iter::FromIterator;
use super::DartAbi;
use super::MessagePort;
use crate::bridge::bridge_engine::support;
pub use crate::bridge::bridge_engine::wasm_bindgen_src::transfer::*;
use crate::bridge::bridge_engine::DartOpaque;
use crate::bridge::bridge_engine::DartSafe;
use crate::bridge::bridge_engine::RustOpaque;
pub use js_sys;
pub use js_sys::Array as JsArray;
use js_sys::*;
pub use wasm_bindgen;
pub use wasm_bindgen::closure::Closure;
pub use wasm_bindgen::prelude::*;
pub use wasm_bindgen::JsCast;
use web_sys::BroadcastChannel;
pub use crate::bridge::bridge_engine::wasm_bindgen_src::transfer::*;
pub trait IntoDart {
fn into_dart(self) -> DartAbi;
}
pub trait IntoDartExceptPrimitive: IntoDart {}
impl IntoDartExceptPrimitive for JsValue {}
impl<T: DartSafe> IntoDartExceptPrimitive for RustOpaque<T> {}
impl IntoDartExceptPrimitive for DartOpaque {}
impl IntoDartExceptPrimitive for String {}
impl<T: IntoDart> IntoDartExceptPrimitive for Option<T> {}
impl IntoDart for () {
#[inline]
fn into_dart(self) -> DartAbi {
JsValue::undefined()
}
}
macro_rules! delegate {
($( $ty:ty )*) => {$(
impl IntoDart for $ty {
#[inline]
fn into_dart(self) -> DartAbi {
DartAbi::from(self)
}
}
)*};
}
macro_rules! delegate_buffer {
($( $ty:ty => $buffer:ty )*) => {$(
impl IntoDart for $ty {
#[inline]
fn into_dart(self) -> DartAbi {
<$buffer>::from(self.as_slice()).into()
}
}
)*};
}
// Orphan rules disallow blanket implementations, so we have to manually delegate here.
delegate! {
bool
i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize
f32 f64
&str String JsValue
}
delegate_buffer! {
Vec<i8> => js_sys::Int8Array
Vec<u8> => js_sys::Uint8Array
Vec<i16> => js_sys::Int16Array
Vec<u16> => js_sys::Uint16Array
Vec<i32> => js_sys::Int32Array
Vec<u32> => js_sys::Uint32Array
Vec<f32> => js_sys::Float32Array
Vec<f64> => js_sys::Float64Array
ZeroCopyBuffer<Vec<i8>> => js_sys::Int8Array
ZeroCopyBuffer<Vec<u8>> => js_sys::Uint8Array
ZeroCopyBuffer<Vec<i16>> => js_sys::Int16Array
ZeroCopyBuffer<Vec<u16>> => js_sys::Uint16Array
ZeroCopyBuffer<Vec<i32>> => js_sys::Int32Array
ZeroCopyBuffer<Vec<u32>> => js_sys::Uint32Array
ZeroCopyBuffer<Vec<f32>> => js_sys::Float32Array
ZeroCopyBuffer<Vec<f64>> => js_sys::Float64Array
}
impl<T: IntoDartExceptPrimitive> IntoDart for Vec<T> {
#[inline]
fn into_dart(self) -> DartAbi {
Array::from_iter(self.into_iter().map(IntoDart::into_dart)).into()
}
}
impl<T: IntoDart> IntoDart for Option<T> {
#[inline]
fn into_dart(self) -> DartAbi {
self.map(T::into_dart).unwrap_or_else(JsValue::null)
}
}
impl<T> IntoDart for *const T {
#[inline]
fn into_dart(self) -> DartAbi {
(self as usize).into_dart()
}
}
impl<T> IntoDart for *mut T {
#[inline]
fn into_dart(self) -> DartAbi {
(self as usize).into_dart()
}
}
impl<T: DartSafe> IntoDart for RustOpaque<T> {
#[inline]
fn into_dart(self) -> DartAbi {
self.into()
}
}
impl IntoDart for DartOpaque {
#[inline]
fn into_dart(self) -> DartAbi {
self.into()
}
}
impl<const N: usize, T: IntoDartExceptPrimitive> IntoDart for [T; N] {
#[inline]
fn into_dart(self) -> DartAbi {
let boxed: Box<[T]> = Box::new(self);
boxed.into_vec().into_dart()
}
}
macro_rules! impl_into_dart_for_primitive {
($($prim:ty)*) => {$(
impl<const N: usize> IntoDart for [$prim; N] {
#[inline]
fn into_dart(self) -> DartAbi {
Vec::from(self).into_dart()
}
}
)*};
}
impl_into_dart_for_primitive!(i8 u8 i16 u16 i32 u32 f32 f64);
macro_rules! delegate_big_buffers {
($($buf:ty => $buffer:ty)*) => {$(
impl IntoDart for $buf {
fn into_dart(self) -> DartAbi {
let buf: &[i32] = bytemuck::cast_slice(&self[..]);
let buf = Int32Array::from(buf);
<$buffer>::new(&buf.buffer()).into()
}
}
)*};
}
delegate_big_buffers! {
Vec<i64> => BigInt64Array
Vec<u64> => BigUint64Array
}
macro_rules! impl_into_dart_for_tuple {
($( ($($T:ident)+) )*) => {$(
impl<$($T: IntoDart),+> IntoDart for ($($T),+,) {
#[allow(non_snake_case)]
fn into_dart(self) -> DartAbi {
let ($($T),+,) = self;
vec![$($T.into_dart()),+].into_dart()
}
}
impl<$($T: IntoDart),+> IntoDartExceptPrimitive for ($($T),+,) {}
)*};
}
impl_into_dart_for_tuple! {
(A)
(A B)
(A B C)
(A B C D)
(A B C D E)
(A B C D E F)
(A B C D E F G)
(A B C D E F G H)
(A B C D E F G H I)
(A B C D E F G H I J)
}
impl IntoDart for ZeroCopyBuffer<Vec<i64>> {
#[inline]
fn into_dart(self) -> DartAbi {
self.0.into_dart()
}
}
impl IntoDart for ZeroCopyBuffer<Vec<u64>> {
#[inline]
fn into_dart(self) -> DartAbi {
self.0.into_dart()
}
}
#[derive(Clone)]
pub struct Channel {
port: MessagePort,
}
impl Channel {
pub fn new(port: MessagePort) -> Self {
Self { port }
}
pub fn post(&self, msg: impl IntoDart) -> bool {
self.port
.post_message(&msg.into_dart())
.map_err(|err| {
crate::console_error!("post: {:?}", err);
})
.is_ok()
}
pub(crate) fn broadcast_name(&self) -> Option<String> {
self.port
.dyn_ref::<BroadcastChannel>()
.map(|channel| channel.name())
}
}
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console, js_name = "error")]
pub fn error(msg: &str);
}
type RawClosure<T> = Box<dyn FnOnce(&[T]) + Send + 'static>;
pub struct TransferClosure<T> {
pub(crate) data: Vec<T>,
pub(crate) transfer: Vec<T>,
pub(crate) closure: RawClosure<T>,
}
pub struct TransferClosurePayload<T> {
pub(crate) func: RawClosure<T>,
}
impl TransferClosure<JsValue> {
pub fn new(
data: Vec<JsValue>,
transfer: Vec<JsValue>,
closure: impl FnOnce(&[JsValue]) + Send + 'static,
) -> Self {
let closure = Box::new(closure);
Self {
data,
transfer,
closure,
}
}
}
#[derive(Debug)]
pub struct ZeroCopyBuffer<T>(pub T);
impl<T> ZeroCopyBuffer<Vec<T>> {
#[inline]
pub fn as_slice(&self) -> &[T] {
self.0.as_slice()
}
}
/// Internal implementations for transferables on WASM platforms.
pub trait Transfer {
/// Recover the self value from a [JsValue].
fn deserialize(value: &JsValue) -> Self;
/// Transform the self value into a [JsValue].
fn serialize(self) -> JsValue;
/// Extract items that are valid to be passed as the "transfer" argument.
fn transferables(&self) -> Vec<JsValue>;
}
impl<T: Transfer> Transfer for Option<T> {
fn deserialize(value: &JsValue) -> Self {
(!value.is_undefined() && !value.is_null()).then(|| T::deserialize(value))
}
fn serialize(self) -> JsValue {
self.map(T::serialize).unwrap_or_default()
}
fn transferables(&self) -> Vec<JsValue> {
self.as_ref().map(T::transferables).unwrap_or_default()
}
}
impl Transfer for PortLike {
fn deserialize(value: &JsValue) -> Self {
if let Some(name) = value.as_string() {
BroadcastChannel::new(&name).unwrap().unchecked_into()
} else if value.dyn_ref::<web_sys::MessagePort>().is_some() {
value.unchecked_ref::<Self>().clone()
} else {
panic!("Not a PortLike: {:?}", value)
}
}
fn serialize(self) -> JsValue {
if let Some(channel) = self.dyn_ref::<BroadcastChannel>() {
channel.name().into()
} else {
self.into()
}
}
fn transferables(&self) -> Vec<JsValue> {
if let Some(port) = self.dyn_ref::<web_sys::MessagePort>() {
vec![port.clone().into()]
} else {
vec![]
}
}
}
impl Transfer for ArrayBuffer {
fn deserialize(value: &JsValue) -> Self {
value.dyn_ref().cloned().unwrap()
}
fn serialize(self) -> JsValue {
self.into()
}
fn transferables(&self) -> Vec<JsValue> {
vec![self.into()]
}
}
#[wasm_bindgen]
extern "C" {
/// Objects implementing the interface of [`web_sys::MessagePort`].
///
/// Attempts to coerce [`JsValue`]s into this interface using [`dyn_into`][JsCast::dyn_into]
/// or [`dyn_ref`][JsCast::dyn_ref] will fail at runtime.
#[derive(Clone)]
pub type PortLike;
#[wasm_bindgen(method, catch, js_name = "postMessage")]
pub fn post_message(this: &PortLike, value: &JsValue) -> Result<(), JsValue>;
#[wasm_bindgen(method, catch)]
pub fn close(this: &PortLike) -> Result<(), JsValue>;
}
impl PortLike {
/// Create a [`BroadcastChannel`] with the specified name.
pub fn broadcast(name: &str) -> Self {
BroadcastChannel::new(name)
.expect("Failed to create broadcast channel")
.unchecked_into()
}
}
/// Copied from https://github.com/chemicstry/wasm_thread/blob/main/src/script_path.js
pub fn script_path() -> Option<String> {
js_sys::eval(
r"
(() => {
try {
throw new Error();
} catch (e) {
let parts = e.stack.match(/(?:\(|@)(\S+):\d+:\d+/);
return parts[1];
}
})()",
)
.ok()?
.as_string()
}
/// # Safety
///
/// TODO: need doc
#[wasm_bindgen]
pub unsafe fn get_dart_object(ptr: usize) -> JsValue {
*support::box_from_leak_ptr(ptr as _)
}
/// # Safety
///
/// TODO: need doc
#[wasm_bindgen]
pub unsafe fn drop_dart_object(ptr: usize) {
drop(support::box_from_leak_ptr::<JsValue>(ptr as _));
}
#[derive(Debug)]
pub struct DartOpaqueBase {
inner: Box<JsValue>,
drop_port: Option<String>,
}
impl DartOpaqueBase {
pub fn new(handle: JsValue, port: Option<JsValue>) -> Self {
Self {
inner: Box::new(handle),
drop_port: port.map(|p| p.dyn_ref::<BroadcastChannel>().unwrap().name()),
}
}
pub fn unwrap(self) -> JsValue {
*self.inner
}
pub fn into_raw(self) -> *mut JsValue {
Box::into_raw(self.inner)
}
pub fn channel(&self) -> Option<Channel> {
Some(Channel::new(PortLike::broadcast(self.drop_port.as_ref()?)))
}
}

View file

@ -1,316 +0,0 @@
//! Wrappers and executors for Rust functions.
use std::any::Any;
use std::panic;
use std::panic::{RefUnwindSafe, UnwindSafe};
use crate::bridge::bridge_engine::ffi::{IntoDart, MessagePort};
use crate::bridge::bridge_engine::rust2dart::{IntoIntoDart, Rust2Dart, TaskCallback};
use crate::bridge::bridge_engine::support::WireSyncReturn;
use crate::bridge::bridge_engine::SyncReturn;
use crate::spawn_bridge_task;
/// The types of return values for a particular Rust function.
#[derive(Copy, Clone)]
pub enum FfiCallMode {
/// The default mode, returns a Dart `Future<T>`.
Normal,
/// Used by `SyncReturn<T>` to skip spawning workers.
Sync,
/// Returns a Dart `Stream<T>`.
Stream,
}
/// Supporting information to identify a function's operating mode.
#[derive(Clone)]
pub struct WrapInfo {
/// A Dart `SendPort`. [None] if the mode is [FfiCallMode::Sync].
pub port: Option<MessagePort>,
/// Usually the name of the function.
pub debug_name: &'static str,
/// The call mode of this function.
pub mode: FfiCallMode,
}
/// Provide your own handler to customize how to execute your function calls, etc.
pub trait Handler {
/// Prepares the arguments, executes a Rust function and sets up its return value.
///
/// Why separate `PrepareFn` and `TaskFn`: because some things cannot be [`Send`] (e.g. raw
/// pointers), so those can be done in `PrepareFn`, while the real work is done in `TaskFn` with [`Send`].
///
/// The generated code depends on the fact that `PrepareFn` is synchronous to maintain
/// correctness, therefore implementors of [`Handler`] must also uphold this property.
///
/// If a Rust function returns [`SyncReturn`], it must be called with
/// [`wrap_sync`](Handler::wrap_sync) instead.
fn wrap<PrepareFn, TaskFn, TaskRet, D>(&self, wrap_info: WrapInfo, prepare: PrepareFn)
where
PrepareFn: FnOnce() -> TaskFn + UnwindSafe,
TaskFn: FnOnce(TaskCallback) -> Result<TaskRet, BridgeError> + Send + UnwindSafe + 'static,
TaskRet: IntoIntoDart<D>,
D: IntoDart;
/// Same as [`wrap`][Handler::wrap], but the Rust function must return a [SyncReturn] and
/// need not implement [Send].
fn wrap_sync<SyncTaskFn, TaskRet>(
&self,
wrap_info: WrapInfo,
sync_task: SyncTaskFn,
) -> WireSyncReturn
where
SyncTaskFn: FnOnce() -> Result<SyncReturn<TaskRet>, BridgeError> + UnwindSafe,
TaskRet: IntoDart;
}
/// The simple handler uses a simple thread pool to execute tasks.
pub struct SimpleHandler<E: Executor, EH: ErrorHandler> {
executor: E,
error_handler: EH,
}
impl<E: Executor, H: ErrorHandler> SimpleHandler<E, H> {
/// Create a new default handler.
pub fn new(executor: E, error_handler: H) -> Self {
SimpleHandler {
executor,
error_handler,
}
}
}
/// The default handler used by the generated code.
pub type DefaultHandler =
SimpleHandler<BridgeTaskExecutor<ReportDartErrorHandler>, ReportDartErrorHandler>;
impl Default for DefaultHandler {
fn default() -> Self {
Self::new(
BridgeTaskExecutor::new(ReportDartErrorHandler),
ReportDartErrorHandler,
)
}
}
impl<E: Executor, EH: ErrorHandler> Handler for SimpleHandler<E, EH> {
fn wrap<PrepareFn, TaskFn, TaskRet, D>(&self, wrap_info: WrapInfo, prepare: PrepareFn)
where
PrepareFn: FnOnce() -> TaskFn + UnwindSafe,
TaskFn: FnOnce(TaskCallback) -> Result<TaskRet, BridgeError> + Send + UnwindSafe + 'static,
TaskRet: IntoIntoDart<D>,
D: IntoDart,
{
// NOTE This extra [catch_unwind] **SHOULD** be put outside **ALL** code!
// Why do this: As nomicon says, unwind across languages is undefined behavior (UB).
// Therefore, we should wrap a [catch_unwind] outside of *each and every* line of code
// that can cause panic. Otherwise we may touch UB.
// Why do not report error or something like that if this outer [catch_unwind] really
// catches something: Because if we report error, that line of code itself can cause panic
// as well. Then that new panic will go across language boundary and cause UB.
// ref https://doc.rust-lang.org/nomicon/unwinding.html
let _ = panic::catch_unwind(move || {
let wrap_info2 = wrap_info.clone();
if let Err(error) = panic::catch_unwind(move || {
let task = prepare();
self.executor.execute(wrap_info2, task);
}) {
self.error_handler
.handle_error(wrap_info.port.unwrap(), BridgeError::Panic(error));
}
});
}
fn wrap_sync<SyncTaskFn, TaskRet>(
&self,
wrap_info: WrapInfo,
sync_task: SyncTaskFn,
) -> WireSyncReturn
where
TaskRet: IntoDart,
SyncTaskFn: FnOnce() -> Result<SyncReturn<TaskRet>, BridgeError> + UnwindSafe,
{
// NOTE This extra [catch_unwind] **SHOULD** be put outside **ALL** code!
// For reason, see comments in [wrap]
panic::catch_unwind(move || {
let catch_unwind_result = panic::catch_unwind(move || {
match self.executor.execute_sync(wrap_info, sync_task) {
Ok(data) => wire_sync_from_data(data.0, true),
Err(_err) => self
.error_handler
.handle_error_sync(BridgeError::ResultError),
}
});
catch_unwind_result.unwrap_or_else(|error| {
self.error_handler
.handle_error_sync(BridgeError::Panic(error))
})
})
.unwrap_or_else(|_| wire_sync_from_data(None::<()>, false))
}
}
/// An executor model for Rust functions.
///
/// For example, the default model is [ThreadPoolExecutor]
/// which runs each function in a separate thread.
pub trait Executor: RefUnwindSafe {
/// Executes a Rust function and transforms its return value into a Dart-compatible
/// value, i.e. types that implement [`IntoDart`].
fn execute<TaskFn, TaskRet, D>(&self, wrap_info: WrapInfo, task: TaskFn)
where
TaskFn: FnOnce(TaskCallback) -> Result<TaskRet, BridgeError> + Send + UnwindSafe + 'static,
TaskRet: IntoIntoDart<D>,
D: IntoDart;
/// Executes a Rust function that returns a [SyncReturn].
fn execute_sync<SyncTaskFn, TaskRet>(
&self,
wrap_info: WrapInfo,
sync_task: SyncTaskFn,
) -> Result<SyncReturn<TaskRet>, BridgeError>
where
SyncTaskFn: FnOnce() -> Result<SyncReturn<TaskRet>, BridgeError> + UnwindSafe,
TaskRet: IntoDart;
}
/// The default executor used.
pub struct BridgeTaskExecutor<EH: ErrorHandler> {
error_handler: EH,
}
impl<EH: ErrorHandler> BridgeTaskExecutor<EH> {
pub fn new(error_handler: EH) -> Self {
BridgeTaskExecutor { error_handler }
}
}
impl<EH: ErrorHandler> Executor for BridgeTaskExecutor<EH> {
fn execute<TaskFn, TaskRet, D>(&self, wrap_info: WrapInfo, task: TaskFn)
where
TaskFn: FnOnce(TaskCallback) -> Result<TaskRet, BridgeError> + Send + UnwindSafe + 'static,
TaskRet: IntoIntoDart<D>,
D: IntoDart,
{
let eh = self.error_handler;
let eh2 = self.error_handler;
let WrapInfo { port, mode, .. } = wrap_info;
spawn_bridge_task!(|port: Option<MessagePort>| {
let port2 = port.as_ref().cloned();
let thread_result = panic::catch_unwind(move || {
let port2 = port2.expect("(worker) thread");
#[allow(clippy::clone_on_copy)]
let rust2dart = Rust2Dart::new(port2.clone());
let ret = task(TaskCallback::new(rust2dart.clone()))
.map(|e| e.into_into_dart().into_dart());
match ret {
Ok(result) => {
match mode {
FfiCallMode::Normal => {
rust2dart.success(result);
}
FfiCallMode::Stream => {
// nothing - ignore the return value of a Stream-typed function
}
FfiCallMode::Sync => {
panic!("FfiCallMode::Sync should not call execute, please call execute_sync instead")
}
}
}
Err(_error) => {
eh2.handle_error(port2, BridgeError::ResultError);
}
};
});
if let Err(error) = thread_result {
eh.handle_error(port.expect("(worker) eh"), BridgeError::Panic(error));
}
});
}
fn execute_sync<SyncTaskFn, TaskRet>(
&self,
_wrap_info: WrapInfo,
sync_task: SyncTaskFn,
) -> Result<SyncReturn<TaskRet>, BridgeError>
where
SyncTaskFn: FnOnce() -> Result<SyncReturn<TaskRet>, BridgeError> + UnwindSafe,
TaskRet: IntoDart,
{
sync_task()
}
}
/// Errors that occur from normal code execution.
#[derive(Debug)]
pub enum BridgeError {
ResultError,
/// Exceptional errors from panicking.
Panic(Box<dyn Any + Send>),
}
impl BridgeError {
/// The identifier of the type of error.
pub fn code(&self) -> &'static str {
match self {
BridgeError::ResultError => "RESULT_ERROR",
BridgeError::Panic(_) => "PANIC_ERROR",
}
}
/// The message of the error.
pub fn message(&self) -> String {
match self {
BridgeError::ResultError => "There was a result error inside the bridge".into(),
BridgeError::Panic(panic_err) => match panic_err.downcast_ref::<&'static str>() {
Some(s) => *s,
None => match panic_err.downcast_ref::<String>() {
Some(s) => &s[..],
None => "Box<dyn Any>",
},
}
.to_string(),
}
}
}
/// A handler model that sends back the error to a Dart `SendPort`.
///
/// For example, instead of using the default [`ReportDartErrorHandler`],
/// you could implement your own handler that logs each error to stderr,
/// or to an external logging service.
pub trait ErrorHandler: UnwindSafe + RefUnwindSafe + Copy + Send + 'static {
/// The default error handler.
fn handle_error(&self, port: MessagePort, error: BridgeError);
/// Special handler only used for synchronous code.
fn handle_error_sync(&self, error: BridgeError) -> WireSyncReturn;
}
/// The default error handler used by generated code.
#[derive(Clone, Copy)]
pub struct ReportDartErrorHandler;
impl ErrorHandler for ReportDartErrorHandler {
fn handle_error(&self, port: MessagePort, error: BridgeError) {
Rust2Dart::new(port).error(error.code().to_string(), error.message());
}
fn handle_error_sync(&self, error: BridgeError) -> WireSyncReturn {
wire_sync_from_data(format!("{}: {}", error.code(), error.message()), false)
}
}
fn wire_sync_from_data<T: IntoDart>(data: T, success: bool) -> WireSyncReturn {
let sync_return = vec![data.into_dart(), success.into_dart()].into_dart();
#[cfg(not(target_family = "wasm"))]
return crate::bridge::bridge_engine::support::new_leak_box_ptr(sync_return);
#[cfg(target_family = "wasm")]
return sync_return;
}

View file

@ -1,179 +0,0 @@
use crate::bridge::bridge_engine::{ffi::*, DartSafe};
/// Basically the Into trait.
/// We need this separate trait because we need to implement it for Vec<T> etc.
/// These blanket implementations allow us to accept external types in various places.
/// The initial reason for this was to allow mirrored types in StreamSink<>.
pub trait IntoIntoDart<D: IntoDart> {
fn into_into_dart(self) -> D;
}
impl<T, D> IntoIntoDart<Vec<D>> for Vec<T>
where
T: IntoIntoDart<D>,
Vec<D>: IntoDart,
D: IntoDart,
{
fn into_into_dart(self) -> Vec<D> {
self.into_iter().map(|e| e.into_into_dart()).collect()
}
}
impl<T, D> IntoIntoDart<Option<D>> for Option<T>
where
T: IntoIntoDart<D>,
D: IntoDart,
{
fn into_into_dart(self) -> Option<D> {
self.map(|e| e.into_into_dart())
}
}
impl<T> IntoIntoDart<RustOpaque<T>> for RustOpaque<T>
where
T: DartSafe,
{
fn into_into_dart(self) -> RustOpaque<T> {
self
}
}
impl<T, D> IntoIntoDart<ZeroCopyBuffer<D>> for ZeroCopyBuffer<T>
where
T: IntoIntoDart<D>,
D: IntoDart,
ZeroCopyBuffer<D>: IntoDart,
{
fn into_into_dart(self) -> ZeroCopyBuffer<D> {
ZeroCopyBuffer(self.0.into_into_dart())
}
}
impl<T, const C: usize> IntoIntoDart<[T; C]> for [T; C]
where
T: IntoDart,
[T; C]: IntoDart,
{
fn into_into_dart(self) -> [T; C] {
self
}
}
impl<T> IntoIntoDart<T> for Box<T>
where
T: IntoDart,
{
fn into_into_dart(self) -> T {
*self
}
}
// These tuple impls should probably be a macro,
// but that is not easily possible with macro_rules because of the field access.
impl<A, AD, B, BD> IntoIntoDart<(AD, BD)> for (A, B)
where
A: IntoIntoDart<AD>,
AD: IntoDart,
B: IntoIntoDart<BD>,
BD: IntoDart,
{
fn into_into_dart(self) -> (AD, BD) {
(self.0.into_into_dart(), self.1.into_into_dart())
}
}
impl<A, AD, B, BD, C, CD> IntoIntoDart<(AD, BD, CD)> for (A, B, C)
where
A: IntoIntoDart<AD>,
AD: IntoDart,
B: IntoIntoDart<BD>,
BD: IntoDart,
C: IntoIntoDart<CD>,
CD: IntoDart,
{
fn into_into_dart(self) -> (AD, BD, CD) {
(
self.0.into_into_dart(),
self.1.into_into_dart(),
self.2.into_into_dart(),
)
}
}
impl<A, AD, B, BD, C, CD, D, DD> IntoIntoDart<(AD, BD, CD, DD)> for (A, B, C, D)
where
A: IntoIntoDart<AD>,
AD: IntoDart,
B: IntoIntoDart<BD>,
BD: IntoDart,
C: IntoIntoDart<CD>,
CD: IntoDart,
D: IntoIntoDart<DD>,
DD: IntoDart,
{
fn into_into_dart(self) -> (AD, BD, CD, DD) {
(
self.0.into_into_dart(),
self.1.into_into_dart(),
self.2.into_into_dart(),
self.3.into_into_dart(),
)
}
}
impl<A, AD, B, BD, C, CD, D, DD, E, ED> IntoIntoDart<(AD, BD, CD, DD, ED)> for (A, B, C, D, E)
where
A: IntoIntoDart<AD>,
AD: IntoDart,
B: IntoIntoDart<BD>,
BD: IntoDart,
C: IntoIntoDart<CD>,
CD: IntoDart,
D: IntoIntoDart<DD>,
DD: IntoDart,
E: IntoIntoDart<ED>,
ED: IntoDart,
{
fn into_into_dart(self) -> (AD, BD, CD, DD, ED) {
(
self.0.into_into_dart(),
self.1.into_into_dart(),
self.2.into_into_dart(),
self.3.into_into_dart(),
self.4.into_into_dart(),
)
}
}
// more generic impls do not work because they crate possibly conflicting trait impls
// this is why here are some more specific impls
// Implementations for simple types
macro_rules! impl_into_into_dart {
($t:ty) => {
impl IntoIntoDart<$t> for $t {
fn into_into_dart(self) -> $t {
self
}
}
};
}
// Impls for primitive types are taken from the IntoDart trait
impl_into_into_dart!(u8);
impl_into_into_dart!(i8);
impl_into_into_dart!(u16);
impl_into_into_dart!(i16);
impl_into_into_dart!(u32);
impl_into_into_dart!(i32);
impl_into_into_dart!(u64);
impl_into_into_dart!(i64);
impl_into_into_dart!(f32);
impl_into_into_dart!(f64);
impl_into_into_dart!(bool);
impl_into_into_dart!(());
impl_into_into_dart!(usize);
impl_into_into_dart!(String);
impl_into_into_dart!(DartOpaque);
#[cfg(not(target_family = "wasm"))]
impl_into_into_dart!(allo_isolate::ffi::DartCObject);
#[cfg(target_family = "wasm")]
impl_into_into_dart!(wasm_bindgen::JsValue);

View file

@ -1,73 +0,0 @@
#[macro_export]
macro_rules! spawn_bridge_task {
($($tt:tt)*) => {{
let bridge_task = $crate::transfer!($($tt)*);
#[cfg(not(target_family = "wasm"))]
{
bridge_task();
}
#[cfg(target_family = "wasm")]
{
$crate::bridge::bridge_engine::wasm_bindgen_src::worker::WEB_WORKER.with(|worker| {
let _ = bridge_task.apply(worker);
});
}
}};
}
/// On WASM, [JsValue][wasm_bindgen::JsValue]s cannot be shared between scopes
/// but instead can be ["transferred"].
/// Rust however is not aware of transferables and therefore cannot capture these values.
/// This macro wraps a closure and returns a [TransferClosure][crate::ffi::TransferClosure]
/// on WASM platforms which will capture these special values,
/// or a normal [FnOnce] on other platforms.
/// Note that the parameter names must match available variables/bindings from the outer scope.
///
/// ["transferred"]: https://developer.mozilla.org/en-US/docs/Glossary/Transferable_objects
#[macro_export]
macro_rules! transfer {
(|| $block:block) => {{
#[cfg(not(target_family = "wasm"))]
{ move || $block }
#[cfg(target_family = "wasm")]
{
$crate::ffi::TransferClosure::new(vec![], vec![], move |_: &[JsValue]| $block)
}
}};
(|$($param:ident: $ty:ty),*| $block:block) => {{
#[cfg(not(target_family = "wasm"))]
{
move || $block
}
#[cfg(target_family = "wasm")]
{
use wasm_bindgen::JsValue;
use $crate::bridge::bridge_engine::ffi::Transfer;
#[allow(unused_variables)]
let worker = move |transfer: &[JsValue]| {
let idx = 0;
$(
let $param = <$ty>::deserialize(&transfer[idx]);
let idx = idx + 1;
)*
$block
};
let transferables = [$($param.transferables()),*].concat();
$crate::bridge::bridge_engine::ffi::TransferClosure::new(
vec![$($param.serialize()),*],
transferables,
worker,
)
}
}};
}
#[macro_export]
macro_rules! console_error {
($lit:literal) => {
$crate::error($lit)
};
($($tt:tt)*) => {
$crate::bridge::bridge_engine::error(&format!($($tt)*))
};
}

View file

@ -1,24 +0,0 @@
use std::panic::{RefUnwindSafe, UnwindSafe};
pub use handler::{FfiCallMode, Handler, WrapInfo};
pub use rust2dart::StreamSink;
pub mod ffi;
pub use ffi::*;
pub mod handler;
mod into_into_dart;
mod macros;
pub mod rust2dart;
pub mod support;
#[cfg(target_family = "wasm")]
pub mod wasm_bindgen_src;
/// Use this struct in return type of your function, in order to tell the code generator
/// the function should return synchronously. Otherwise, it is by default asynchronously.
pub struct SyncReturn<T>(pub T);
/// Marker trait for types that are safe to share with Dart and can be dropped
/// safely in case of a panic.
pub trait DartSafe: UnwindSafe + RefUnwindSafe {}
impl<T: UnwindSafe + RefUnwindSafe> DartSafe for T {}

View file

@ -1,150 +0,0 @@
//! Manages receiving and sending values across the FFI boundary.
use std::marker::PhantomData;
/// The representation of a Dart object outside of the Dart heap.
///
/// Its implementation lies with the Dart language and therefore should not be
/// depended on to be stable.
pub use crate::bridge::bridge_engine::ffi::*;
pub use crate::bridge::bridge_engine::into_into_dart::IntoIntoDart;
/// A wrapper around a Dart [`Isolate`].
#[derive(Clone)]
pub struct Rust2Dart {
pub(crate) channel: Channel,
}
const RUST2DART_ACTION_SUCCESS: i32 = 0;
const RUST2DART_ACTION_ERROR: i32 = 1;
const RUST2DART_ACTION_CLOSE_STREAM: i32 = 2;
// API signatures is similar to Flutter Android's callback
// https://api.flutter.dev/javadoc/io/flutter/plugin/common/MethodChannel.Result.html
impl Rust2Dart {
/// Create a new wrapper from a raw port.
pub fn new(port: MessagePort) -> Self {
Rust2Dart {
channel: Channel::new(port),
}
}
/// Send a success message back to the specified port.
pub fn success(&self, result: impl IntoDart) -> bool {
self.channel.post(vec![
RUST2DART_ACTION_SUCCESS.into_dart(),
result.into_dart(),
])
}
/// Send an error back to the specified port.
pub fn error(&self, error_code: String, error_message: String) -> bool {
self.error_full(error_code, error_message, ())
}
/// Send a detailed error back to the specified port.
pub fn error_full(
&self,
error_code: String,
error_message: String,
error_details: impl IntoDart,
) -> bool {
self.channel.post(vec![
RUST2DART_ACTION_ERROR.into_dart(),
error_code.into_dart(),
error_message.into_dart(),
error_details.into_dart(),
])
}
/// Close the stream and ignore further messages.
pub fn close_stream(&self) -> bool {
self.channel
.post(vec![RUST2DART_ACTION_CLOSE_STREAM.into_dart()])
}
}
/// A callback that receives the return value of Rust functions.
pub struct TaskCallback {
rust2dart: Rust2Dart,
}
impl TaskCallback {
/// Create a new callback from a port wrapper.
pub fn new(rust2dart: Rust2Dart) -> Self {
Self { rust2dart }
}
/// Create a new [StreamSink] of the specified type.
pub fn stream_sink<T, D>(&self) -> StreamSink<T>
where
T: IntoIntoDart<D>,
D: IntoDart,
{
StreamSink::new(self.rust2dart.clone())
}
}
/// A handle to a [`web_sys::BroadcastChannel`].
#[derive(Clone)]
pub struct ChannelHandle(pub String);
impl ChannelHandle {
#[cfg(target_family = "wasm")]
pub fn port(&self) -> MessagePort {
PortLike::broadcast(&self.0)
}
}
/// A sink to send asynchronous data back to Dart.
/// Represented as a Dart
/// [`Stream`](https://api.dart.dev/stable/dart-async/Stream-class.html).
#[derive(Clone)]
pub struct StreamSink<T> {
#[cfg(not(target_family = "wasm"))]
rust2dart: Rust2Dart,
#[cfg(target_family = "wasm")]
handle: ChannelHandle,
_phantom_data: PhantomData<T>,
}
impl<T> StreamSink<T> {
/// Create a new sink from a port wrapper.
pub fn new(rust2dart: Rust2Dart) -> Self {
#[cfg(target_family = "wasm")]
let name = rust2dart
.channel
.broadcast_name()
.expect("Not a BroadcastChannel");
Self {
#[cfg(not(target_family = "wasm"))]
rust2dart,
#[cfg(target_family = "wasm")]
handle: ChannelHandle(name),
_phantom_data: PhantomData,
}
}
fn rust2dart(&self) -> Rust2Dart {
#[cfg(not(target_family = "wasm"))]
return self.rust2dart.clone();
#[cfg(target_family = "wasm")]
Rust2Dart::new(self.handle.port())
}
/// Add data to the stream. Returns false when data could not be sent,
/// or the stream has been closed.
pub fn add<D: IntoDart>(&self, value: T) -> bool
where
T: IntoIntoDart<D>,
{
self.rust2dart().success(value.into_into_dart().into_dart())
}
/// Close the stream and ignore further messages. Returns false when
/// the stream could not be closed, or when it has already been closed.
pub fn close(&self) -> bool {
self.rust2dart().close_stream()
}
}

View file

@ -1,75 +0,0 @@
//! Functions that support auto-generated Rust code.
//! These functions are *not* meant to be used by humans directly.
#![doc(hidden)]
use std::mem;
pub use crate::bridge::bridge_engine::ffi::*;
pub use lazy_static::lazy_static;
pub use crate::bridge::bridge_engine::handler::DefaultHandler;
// ref https://stackoverflow.com/questions/39224904/how-to-expose-a-rust-vect-to-ffi
pub fn new_leak_vec_ptr<T: Clone>(fill: T, length: i32) -> *mut T {
into_leak_vec_ptr(vec![fill; length as usize]).0
}
pub fn into_leak_vec_ptr<T: Clone>(mut v: Vec<T>) -> (*mut T, i32) {
v.shrink_to_fit();
assert!(v.len() == v.capacity());
let ptr = v.as_mut_ptr();
let len = v.len() as i32;
mem::forget(v);
(ptr, len)
}
/// # Safety
/// Use it in pair with [new_leak_vec_ptr].
pub unsafe fn vec_from_leak_ptr<T>(ptr: *mut T, len: i32) -> Vec<T> {
Vec::from_raw_parts(ptr, len as usize, len as usize)
}
/// Convert [Vec<T>] to array length `N`.
///
/// # Panics
///
/// Panics if length of [Vec<T>] != `N`.
pub fn from_vec_to_array<T, const N: usize>(v: Vec<T>) -> [T; N] {
core::convert::TryInto::try_into(v)
.unwrap_or_else(|v: Vec<T>| panic!("Expected a Vec of length {} but it was {}", N, v.len()))
}
// ref: doc of [Box::into_raw]
pub fn new_leak_box_ptr<T>(t: T) -> *mut T {
let x: Box<T> = Box::new(t);
Box::into_raw(x)
}
/// # Safety
/// Use it in pair with [new_leak_box_ptr].
pub unsafe fn box_from_leak_ptr<T>(ptr: *mut T) -> Box<T> {
Box::from_raw(ptr)
}
/// Cast a byte buffer into a boxed slice of the target type without making any copies.
/// Panics if the cast fails.
pub fn slice_from_byte_buffer<T: bytemuck::Pod>(buffer: Vec<u8>) -> Box<[T]> {
let buf = Box::leak(buffer.into_boxed_slice());
match bytemuck::try_cast_slice_mut(buf) {
Ok(buf) => unsafe { Box::from_raw(buf) },
Err(err) => {
// clean up before panicking
unsafe { core::ptr::drop_in_place(buf) }
panic!("cast error: {}", err);
}
}
}
#[cfg(not(target_family = "wasm"))]
use allo_isolate::ffi::DartCObject;
#[cfg(not(target_family = "wasm"))]
pub type WireSyncReturn = *mut DartCObject;
#[cfg(target_family = "wasm")]
pub type WireSyncReturn = wasm_bindgen::JsValue;

View file

@ -1,4 +0,0 @@
//! Code originally sourced from wasm-bindgen's repository.
pub mod transfer;
pub mod worker;

View file

@ -1,46 +0,0 @@
use crate::bridge::bridge_engine::ffi::web::*;
use js_sys::{global, Array};
use std::iter::FromIterator;
use web_sys::{DedicatedWorkerGlobalScope, Worker};
impl TransferClosure<JsValue> {
/// Posts a <code>[*mut [TransferClosurePayload], ...[JsValue]]</code> message to this worker.
///
/// The worker's `onmessage` should run the corresponding [`receive_transfer_closure`]
/// to receive the message.
pub fn apply(self, worker: &Worker) -> Result<(), JsValue> {
let transfer = self.transfer.into_iter().filter(|value| value.is_truthy());
let transfer = Array::from_iter(transfer);
let data = Array::from_iter(self.data);
// The worker is responsible for cleaning up the leak here.
let payload = Box::into_raw(Box::new(TransferClosurePayload { func: self.closure }));
data.unshift(&JsValue::from(payload as i32));
worker
.post_message_with_transfer(&data, &transfer)
.map_err(|err| {
// post message failed, ownership remains with us.
drop(unsafe { Box::from_raw(payload) });
err
})
}
}
/// ## Safety
/// This function reclaims a raw pointer created by [`TransferClosure`], and therefore
/// should **only** be used in conjunction with it.
/// Furthermore, the WASM module in the worker must have been initialized with the shared
/// memory from the host JS scope.
// wasm_bindgen cannot work with unsafe functions, hence the clippy ignore.
#[wasm_bindgen]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn receive_transfer_closure(
payload: *mut TransferClosurePayload<JsValue>,
transfer: Box<[JsValue]>,
) -> Result<(), JsValue> {
let closure = unsafe { Box::from_raw(payload) };
(closure.func)(&transfer);
// Once we're done here, notify the host scope so that it can reclaim this worker.
global()
.unchecked_into::<DedicatedWorkerGlobalScope>()
.post_message(&JsValue::UNDEFINED)
}

View file

@ -1,50 +0,0 @@
use crate::bridge::bridge_engine::script_path;
use js_sys::Array;
use wasm_bindgen::prelude::*;
use web_sys::{Blob, BlobPropertyBag, Url, Worker};
thread_local! {
pub static WEB_WORKER: Worker = create_worker();
}
fn create_worker() -> Worker {
let script = format!(
"
importScripts('{}');
onmessage = event => {{
let init = wasm_bindgen(...event.data).catch(err => {{
setTimeout(() => {{ throw err }})
throw err
}})
onmessage = async event => {{
await init
let [payload, ...transfer] = event.data
try {{
wasm_bindgen.receive_transfer_closure(payload, transfer)
}} catch (err) {{
if (transfer[0] && typeof transfer[0].postMessage === 'function') {{
transfer[0].postMessage([1, 'ABORT', err.toString(), err.stack])
}}
setTimeout(() => {{ throw err }})
postMessage(null)
throw err
}}
}}
}}
",
script_path().unwrap()
);
let blob = Blob::new_with_blob_sequence_and_options(
&Array::from_iter([JsValue::from(script)]).into(),
BlobPropertyBag::new().type_("text/javascript"),
)
.unwrap();
let url = Url::create_object_url_with_blob(&blob).unwrap();
let worker = Worker::new(&url).unwrap();
let module = wasm_bindgen::module();
let memory = wasm_bindgen::memory();
worker
.post_message(&Array::from_iter([module, memory]))
.unwrap();
worker
}

View file

@ -9,12 +9,12 @@
clippy::too_many_arguments
)]
// AUTO GENERATED FILE, DO NOT EDIT.
// Generated by flutter_rust_bridge_codegen@ 1.80.1.
// Generated by flutter_rust_bridge_codegen@ 1.79.0.
use crate::bridge::api::*;
use crate::bridge::bridge_engine::rust2dart::IntoIntoDart;
use crate::bridge::bridge_engine::*;
use crate::bridge::interface::*;
use core::panic::UnwindSafe;
use rinf::engine::rust2dart::IntoIntoDart;
use rinf::engine::*;
use std::ffi::c_void;
use std::sync::Arc;
@ -233,13 +233,13 @@ support::lazy_static! {
/// cbindgen:ignore
#[cfg(target_family = "wasm")]
#[path = "bridge_generated.web.rs"]
#[path = "generated.web.rs"]
mod web;
#[cfg(target_family = "wasm")]
pub use web::*;
#[cfg(not(target_family = "wasm"))]
#[path = "bridge_generated.io.rs"]
#[path = "generated.io.rs"]
mod io;
#[cfg(not(target_family = "wasm"))]
pub use io::*;

View file

@ -115,6 +115,8 @@ impl Wire2Api<u8> for JsValue {
}
impl Wire2Api<Vec<u8>> for JsValue {
fn wire2api(self) -> Vec<u8> {
self.unchecked_into::<js_sys::Uint8Array>().to_vec().into()
self.unchecked_into::<rinf::externs::js_sys::Uint8Array>()
.to_vec()
.into()
}
}

View file

@ -1,13 +1,14 @@
#![allow(dead_code)]
use crate::bridge::bridge_engine::StreamSink;
use lazy_static::lazy_static;
use rinf::engine::StreamSink;
use rinf::externs::lazy_static::lazy_static;
use std::cell::RefCell;
use std::sync::Arc;
use std::sync::Mutex;
use tokio::sync::mpsc::channel;
use tokio::sync::mpsc::Receiver;
use tokio::sync::mpsc::Sender;
use tokio_with_wasm::tokio;
/// Available operations that a `RustRequest` object can hold.
/// There are 4 options, `Create`,`Read`,`Update`, and `Delete`.
@ -104,8 +105,8 @@ lazy_static! {
#[cfg(not(target_family = "wasm"))]
lazy_static! {
pub static ref TOKIO_RUNTIME: os_thread_local::ThreadLocal<Cell<tokio::runtime::Runtime>> =
os_thread_local::ThreadLocal::new(|| RefCell::new(None));
pub static ref TOKIO_RUNTIME: rinf::externs::os_thread_local::ThreadLocal<Cell<tokio::runtime::Runtime>> =
rinf::externs::os_thread_local::ThreadLocal::new(|| RefCell::new(None));
}
#[cfg(target_family = "wasm")]
@ -167,6 +168,7 @@ pub fn check_rust_streams() -> bool {
pub fn start_rust_logic() {
#[cfg(not(target_family = "wasm"))]
{
use rinf::externs::backtrace;
#[cfg(debug_assertions)]
std::panic::set_hook(Box::new(|panic_info| {
let mut frames_filtered = Vec::new();
@ -213,12 +215,12 @@ pub fn start_rust_logic() {
{
#[cfg(debug_assertions)]
std::panic::set_hook(Box::new(|panic_info| {
crate::debug_print!("A panic occurred in Rust.\n{}", panic_info);
crate::debug_print!("A panic occurred in Rust.\n{panic_info}");
}));
IS_MAIN_STARTED.with(move |ref_cell| {
let is_started = *ref_cell.borrow();
if !is_started {
wasm_bindgen_futures::spawn_local(crate::main());
tokio::spawn(crate::main());
ref_cell.replace(true);
}
});

View file

@ -5,18 +5,17 @@
#![allow(dead_code)]
use api::RustResponseUnique;
use api::RustSignal;
pub use interface::*;
use tokio::sync::mpsc::Receiver;
use tokio_with_wasm::tokio;
pub mod api;
pub mod bridge_engine;
mod bridge_generated;
mod generated;
mod interface;
/// This function is expected to be used only once
/// during the initialization of the Rust logic.
pub fn get_request_receiver() -> Receiver<api::RustRequestUnique> {
let cell = api::REQUST_RECEIVER_SHARED.lock().unwrap();
pub fn get_request_receiver() -> Receiver<RustRequestUnique> {
let cell = REQUST_RECEIVER_SHARED.lock().unwrap();
let option = cell.replace(None);
option.unwrap()
}
@ -25,13 +24,13 @@ pub fn get_request_receiver() -> Receiver<api::RustRequestUnique> {
/// and trigger the rebuild.
/// No memory copy is involved as the bytes are moved directly to Dart.
pub fn send_rust_signal(rust_signal: RustSignal) {
api::SIGNAL_STREAM.with(|inner| {
SIGNAL_STREAM.with(|inner| {
let mut borrowed = inner.borrow_mut();
let option = borrowed.as_ref();
if let Some(stream) = option {
stream.add(rust_signal);
} else {
let cell = api::SIGNAL_STREAM_SHARED.lock().unwrap();
let cell = SIGNAL_STREAM_SHARED.lock().unwrap();
let stream = cell.borrow().as_ref().unwrap().clone();
stream.add(rust_signal);
borrowed.replace(stream);
@ -43,13 +42,13 @@ pub fn send_rust_signal(rust_signal: RustSignal) {
/// to remember which request that response corresponds to.
/// No memory copy is involved as the bytes are moved directly to Dart.
pub fn respond_to_dart(response_unique: RustResponseUnique) {
api::RESPONSE_STREAM.with(|inner| {
RESPONSE_STREAM.with(|inner| {
let mut borrowed = inner.borrow_mut();
let option = borrowed.as_ref();
if let Some(stream) = option {
stream.add(response_unique);
} else {
let cell = api::RESPONSE_STREAM_SHARED.lock().unwrap();
let cell = RESPONSE_STREAM_SHARED.lock().unwrap();
let stream = cell.borrow().as_ref().unwrap().clone();
stream.add(response_unique);
borrowed.replace(stream);
@ -79,13 +78,13 @@ macro_rules! debug_print {
/// Use `debug_print!` macro instead.
#[cfg(debug_assertions)]
pub fn send_rust_report(rust_report: String) {
api::REPORT_STREAM.with(|inner| {
REPORT_STREAM.with(|inner| {
let mut borrowed = inner.borrow_mut();
let option = borrowed.as_ref();
if let Some(stream) = option {
stream.add(rust_report);
} else {
let cell = api::REPORT_STREAM_SHARED.lock().unwrap();
let cell = REPORT_STREAM_SHARED.lock().unwrap();
let stream = cell.borrow().as_ref().unwrap().clone();
stream.add(rust_report);
borrowed.replace(stream);

View file

@ -19,7 +19,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.*/
use crate::bridge::api::{RustOperation, RustRequest, RustResponse};
use crate::bridge::{RustOperation, RustRequest, RustResponse};
use image::{DynamicImage, GenericImageView, ImageOutputFormat, ImageResult, Rgba};
use prost::Message;
use std::io::Cursor;

View file

@ -1,11 +1,10 @@
use bridge::respond_to_dart;
use web_alias::*;
use with_request::handle_request;
use tokio_with_wasm::tokio;
mod bridge;
mod imagecrop;
mod messages;
mod web_alias;
mod with_request;
/// This `hub` crate is the entry point for the Rust logic.
@ -16,7 +15,7 @@ async fn main() {
// Repeat `crate::spawn` anywhere in your code
// if more concurrent tasks are needed.
while let Some(request_unique) = request_receiver.recv().await {
crate::spawn(async {
tokio::spawn(async {
let response_unique = handle_request(request_unique).await;
respond_to_dart(response_unique);
});

View file

@ -1,115 +0,0 @@
//! The web has many restrictions due to its sandboxed environment
//! which prevents the use of
//! threads, atomics, time, file IO, network IO,
//! and many other native functionalities.
//! Consequently, certain features are missing from various crates
//! including Rust's `std` due to these limitations.
//!
//! To address this issue, this module offers various imports
//! with the **same names** as the original native ones,
//! providing workarounds for these constraints.
//!
//! You might encounter situations
//! where you cannot use native Rust code directly on the web.
//! Add more custom web aliases here if needed.
//! Refer to the links below to understand how to interact with JavaScript.
//! - https://rustwasm.github.io/wasm-bindgen/reference/attributes/on-js-imports/js_name.html
//! - https://rustwasm.github.io/wasm-bindgen/reference/attributes/on-js-imports/js_namespace.html
//!
//! Rust code is executed in a **web worker**.
//! Therefore, you cannot access the global `window` JavaScript object
//! just like when you work in the main thread of JavaScript.
//! Refer to the link below to check which web APIs are available in a web worker.
//! You'll be surprised by various capabilities that modern JavaScript has.
//! - https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Functions_and_classes_available_to_workers
//!
//! Also, there are many crates at `crates.io`
//! that mimic native functionalities on the web.
//! Use them if you do not want to write code that interacts with JavaScript yourself.
//!
//! If your app is not targeting web, you can simply remove this module.
#![allow(dead_code, unused_imports, unused_macros)]
// On native platforms,`tokio`'s multicore async runtime
// allows millions of concurrent tasks to run at the same time.
// On the web, concurrent tasks are executed
// in JavaScript's single-threaded event loop.
// Crate `wasm_bindgen_futures` has the ability
// to convert Rust `Future`s into JavaScript `Promise`s.
#[cfg(not(target_family = "wasm"))]
pub(crate) fn spawn<F, T>(future: F) -> tokio::task::JoinHandle<T>
where
F: std::future::Future<Output = T> + Send + 'static,
T: Send + 'static,
{
tokio::task::spawn(future)
}
#[cfg(target_family = "wasm")]
pub(crate) fn spawn<F, T>(future: F) -> async_wasm_task::JoinHandle<T>
where
F: std::future::Future<Output = T> + 'static,
T: 'static,
{
async_wasm_task::spawn(future)
}
// Sometimes, running CPU-intensive blocking tasks is necessary.
// It is better to spawn them
// in a totally separate thread pool for parallelization.
// On the web, `async_wasm_task` crate does this job
// by interacting with JavaScript and web workers.
#[cfg(not(target_family = "wasm"))]
pub(crate) fn spawn_blocking<C, T>(callable: C) -> tokio::task::JoinHandle<T>
where
C: FnOnce() -> T + Send + 'static,
T: Send + 'static,
{
tokio::task::spawn_blocking(callable)
}
#[cfg(target_family = "wasm")]
pub(crate) fn spawn_blocking<C, T>(callable: C) -> async_wasm_task::JoinHandle<T>
where
C: FnOnce() -> T + Send + 'static,
T: Send + 'static,
{
async_wasm_task::spawn_blocking(callable)
}
// To avoid blocking inside a long-running function,
// you have to yield to the async event loop regularly.
// On the web, `async_wasm_task` crate does this job
// by interacting with JavaScript.
#[cfg(not(target_family = "wasm"))]
pub async fn yield_now() {
tokio::task::yield_now().await;
}
#[cfg(target_family = "wasm")]
pub async fn yield_now() {
async_wasm_task::yield_now().await;
}
// On the web, `tokio` cannot access the system to check the passed time.
// The JavaScript function `setTimeout()` performs this task.
#[cfg(not(target_family = "wasm"))]
pub async fn sleep(duration: std::time::Duration) {
tokio::time::sleep(duration).await;
}
#[cfg(target_family = "wasm")]
pub async fn sleep(duration: std::time::Duration) {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_name = setTimeout)]
fn set_timeout(callback: &js_sys::Function, milliseconds: f64);
}
let milliseconds = duration.as_millis() as f64;
let promise = js_sys::Promise::new(&mut |resolve, _reject| {
set_timeout(&resolve, milliseconds);
});
let _ = wasm_bindgen_futures::JsFuture::from(promise).await;
}

View file

@ -2,7 +2,7 @@
//! when a `RustRequest` was received from Dart
//! and returns `RustResponse`.
use crate::bridge::api::{RustRequestUnique, RustResponse, RustResponseUnique};
use crate::bridge::{RustRequestUnique, RustResponse, RustResponseUnique};
use crate::imagecrop;
use crate::messages;

View file

@ -1,12 +0,0 @@
[package]
name = "sample_crate"
version = "0.1.0"
edition = "2021"
[target.'cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))'.dependencies]
machineid-rs = "1.2.4"
[dependencies]
num = "0.4"
image = "0.24.3"
chrono = { version = "0.4.31", features = ["wasmbind"] }

View file

@ -1,35 +0,0 @@
//! This crate is only for demonstration purposes.
//! You might want to remove this crate in production.
pub use mandelbrot::{mandelbrot, Point, Size};
mod mandelbrot;
// This is just a simple Rust function.
pub fn add_seven(before: i32) -> i32 {
before + 7
}
// `machineid_rs` only supports desktop platforms.
#[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
pub fn get_hardward_id() -> Option<String> {
let mut builder = machineid_rs::IdBuilder::new(machineid_rs::Encryption::MD5);
builder
.add_component(machineid_rs::HWIDComponent::SystemID)
.add_component(machineid_rs::HWIDComponent::CPUCores);
let hwid = builder.build("mykey").unwrap();
Some(hwid)
}
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
pub fn get_hardward_id() -> Option<String> {
None
}
// `chrono` supports all platforms when `wasmbind` feature is enabled.
use chrono::{offset, DateTime};
pub fn get_current_time() -> DateTime<offset::Local> {
offset::Local::now()
}

View file

@ -1,172 +0,0 @@
//! Mandelbrot is copied and modified from
//! https://github.com/ProgrammingRust/mandelbrot/blob/task-queue/src/main.rs and
//! https://github.com/Ducolnd/rust-mandelbrot/blob/master/src/main.rs
use image::codecs::png::PngEncoder;
use image::*;
use num::Complex;
#[derive(Debug, Clone)]
pub struct Size {
pub width: i32,
pub height: i32,
}
#[derive(Debug, Clone)]
pub struct Point {
pub x: f64,
pub y: f64,
}
/// Try to determine if `c` is in the Mandelbrot set, using at most `limit`
/// iterations to decide.
///
/// If `c` is not a member, return `Some(i)`, where `i` is the number of
/// iterations it took for `c` to leave the circle of radius two centered on the
/// origin. If `c` seems to be a member (more precisely, if we reached the
/// iteration limit without being able to prove that `c` is not a member),
/// return `None`.
fn escape_time(c: Complex<f64>, limit: usize) -> Option<usize> {
let mut z = Complex { re: 0.0, im: 0.0 };
for i in 0..limit {
if z.norm_sqr() > 4.0 {
return Some(i);
}
z = z * z + c;
}
None
}
/// Given the row and column of a pixel in the output image, return the
/// corresponding point on the complex plane.
///
/// `bounds` is a pair giving the width and height of the image in pixels.
/// `pixel` is a (column, row) pair indicating a particular pixel in that image.
/// The `upper_left` and `lower_right` parameters are points on the complex
/// plane designating the area our image covers.
fn pixel_to_point(
bounds: (usize, usize),
pixel: (usize, usize),
upper_left: Complex<f64>,
lower_right: Complex<f64>,
) -> Complex<f64> {
let (width, height) = (
lower_right.re - upper_left.re,
upper_left.im - lower_right.im,
);
Complex {
re: upper_left.re + pixel.0 as f64 * width / bounds.0 as f64,
im: upper_left.im - pixel.1 as f64 * height / bounds.1 as f64,
// Why subtraction here? pixel.1 increases as we go down,
// but the imaginary component increases as we go up.
}
}
#[test]
fn test_pixel_to_point() {
assert_eq!(
pixel_to_point(
(100, 200),
(25, 175),
Complex { re: -1.0, im: 1.0 },
Complex { re: 1.0, im: -1.0 },
),
Complex {
re: -0.5,
im: -0.75,
}
);
}
/// Render a rectangle of the Mandelbrot set into a buffer of pixels.
///
/// The `bounds` argument gives the width and height of the buffer `pixels`,
/// which holds one grayscale pixel per byte. The `upper_left` and `lower_right`
/// arguments specify points on the complex plane corresponding to the upper-
/// left and lower-right corners of the pixel buffer.
fn render(
pixels: &mut [u8],
bounds: (usize, usize),
upper_left: Complex<f64>,
lower_right: Complex<f64>,
) {
assert_eq!(pixels.len(), bounds.0 * bounds.1);
for row in 0..bounds.1 {
for column in 0..bounds.0 {
let point = pixel_to_point(bounds, (column, row), upper_left, lower_right);
pixels[row * bounds.0 + column] = match escape_time(point, 255) {
None => 0,
Some(count) => 255 - count as u8,
};
}
}
}
fn colorize(grey_pixels: &[u8]) -> Vec<u8> {
let mut ans = vec![0u8; grey_pixels.len() * 3];
for i in 0..grey_pixels.len() {
let (r, g, b) = colorize_pixel(grey_pixels[i]);
ans[i * 3] = r;
ans[i * 3 + 1] = g;
ans[i * 3 + 2] = b;
}
ans
}
const A: f64 = 1.0 * (1.0 / std::f64::consts::LOG2_10);
const B: f64 = (1.0 / (3.0 * std::f64::consts::SQRT_2)) * (1.0 / std::f64::consts::LOG2_10);
pub fn colorize_pixel(it: u8) -> (u8, u8, u8) {
if it == 0 {
return (0, 0, 0);
}
let it = it as f64;
let c: f64 = (1.0_f64 / ((7.0 * 3.0_f64).powf(1.0 / 8.0))) * (1.0 / std::f64::consts::LOG2_10);
let r = 255.0 * ((1.0 - (A * it).cos()) / 2.0);
let g = 255.0 * ((1.0 - (B * it).cos()) / 2.0);
let b = 255.0 * ((1.0 - (c * it).cos()) / 2.0);
// print!(" {:?} ", [r, g, b]);
(r as u8, b as u8, g as u8)
}
/// Write the buffer `pixels`, whose dimensions are given by `bounds`, to the
/// file named `filename`.
fn write_image(pixels: &[u8], bounds: (usize, usize)) -> Option<Vec<u8>> {
let mut buf = Vec::new();
let encoder = PngEncoder::new(&mut buf);
#[allow(deprecated)]
let result = encoder.encode(pixels, bounds.0 as u32, bounds.1 as u32, ColorType::Rgb8);
match result {
Ok(_) => Some(buf),
Err(_) => None,
}
}
pub fn mandelbrot(image_size: Size, zoom_point: Point, scale: f64) -> Option<Vec<u8>> {
let bounds = (image_size.width as usize, image_size.height as usize);
let upper_left = Complex::new(zoom_point.x - scale, zoom_point.y - scale);
let lower_right = Complex::new(zoom_point.x + scale, zoom_point.y + scale);
let mut pixels = vec![0; bounds.0 * bounds.1];
let bands = pixels.chunks_mut(bounds.0 * bounds.1).enumerate();
for (i, band) in bands {
let top = bounds.1 * i;
let height = band.len() / bounds.0;
let band_bounds = (bounds.0, height);
let band_upper_left = pixel_to_point(bounds, (0, top), upper_left, lower_right);
let band_lower_right =
pixel_to_point(bounds, (bounds.0, top + height), upper_left, lower_right);
render(band, band_bounds, band_upper_left, band_lower_right);
}
write_image(&colorize(&pixels), bounds)
}

View file

@ -1106,10 +1106,10 @@ packages:
dependency: "direct main"
description:
name: rinf
sha256: "71162fe4f4619cddf8eac869d56ceca50fe6e9d0ae249f3ce1bbf1f5457844ec"
sha256: "6de297929aa4e7d4820e646974acc5048fc946bea2a4bd41c6fd4ac79a63a17d"
url: "https://pub.dev"
source: hosted
version: "4.13.1"
version: "4.16.3"
riverpod:
dependency: transitive
description:

View file

@ -61,7 +61,7 @@ dependencies:
ref: e01d534
media_kit_libs_video: ^1.0.4
crypto: ^3.0.3
rinf: ^4.13.1
rinf: ^4.16.3
protobuf: ^3.1.0
cupertino_icons: ^1.0.2