mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-04-20 23:22:07 +00:00
Upgrade Rinf
This commit is contained in:
parent
fa29bc9d24
commit
f9820d2215
41 changed files with 135 additions and 8071 deletions
637
Cargo.lock
generated
637
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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}}" ]
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
|
@ -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_
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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_
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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_
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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?))
|
||||
}
|
||||
}
|
||||
|
|
@ -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))
|
||||
};
|
||||
}
|
||||
|
|
@ -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()?)))
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
@ -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)*))
|
||||
};
|
||||
}
|
||||
|
|
@ -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 {}
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
//! Code originally sourced from wasm-bindgen's repository.
|
||||
|
||||
pub mod transfer;
|
||||
pub mod worker;
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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::*;
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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"] }
|
||||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue