Compare commits

...

No commits in common. "deploy" and "main" have entirely different histories.
deploy ... main

15 changed files with 1071 additions and 735 deletions

6
.gitignore vendored
View file

@ -1,2 +1,6 @@
/target
**/*.rs.bk
bin/
dist/
target/
pkg/
wasm-pack.log

View file

View file

648
Cargo.lock generated Normal file
View file

@ -0,0 +1,648 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
[[package]]
name = "assert_approx_eq"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c07dab4369547dbe5114677b33fbbf724971019f3818172d59a97a61c774ffd"
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "backtrace"
version = "0.3.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2baad346b2d4e94a24347adeee9c7a93f412ee94b9cc26e5b59dea23848e9f28"
dependencies = [
"addr2line",
"cfg-if 1.0.0",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "boolinator"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9"
[[package]]
name = "bumpalo"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
"libc",
"num-integer",
"num-traits",
"time",
"winapi",
]
[[package]]
name = "console_error_panic_hook"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211"
dependencies = [
"cfg-if 0.1.10",
"wasm-bindgen",
]
[[package]]
name = "error-chain"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
dependencies = [
"backtrace",
]
[[package]]
name = "geo-types"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "866e8f6dbd2218b05ea8a25daa1bfac32b0515fe7e0a37cb6a7b9ed0ed82a07e"
dependencies = [
"num-traits",
]
[[package]]
name = "gimli"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
[[package]]
name = "gloo"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23947965eee55e3e97a5cd142dd4c10631cc349b48cecca0ed230fd296f568cd"
dependencies = [
"gloo-console",
"gloo-dialogs",
"gloo-events",
"gloo-file",
"gloo-render",
"gloo-storage",
"gloo-timers",
"gloo-utils",
]
[[package]]
name = "gloo-console"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3907f786f65bbb4f419e918b0c5674175ef1c231ecda93b2dbd65fd1e8882637"
dependencies = [
"js-sys",
"serde",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-dialogs"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ffb557a2ea2ed283f1334423d303a336fad55fb8572d51ae488f828b1464b40"
dependencies = [
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-events"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "088514ec8ef284891c762c88a66b639b3a730134714692ee31829765c5bc814f"
dependencies = [
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-file"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d31ba1f51868ae10a0b665c6dccd5ed967486e7c17055d1c889596ee983be493"
dependencies = [
"gloo-events",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-render"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b4cda6e149df3bb4a3c6a343873903e5bcc2448a9877d61bb8274806ad67f6e"
dependencies = [
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-storage"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b5057761927af1b1929d02b1f49cf83553dd347a473ee7c8bb08420f2673ffc"
dependencies = [
"gloo-utils",
"js-sys",
"serde",
"serde_json",
"thiserror",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-timers"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f"
dependencies = [
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-utils"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d77d28d9a6f7c384d9e40293fa11f05558bf928a993208e12528ee6633cb415"
dependencies = [
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gpx"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d96f48f1635cee5d19d368d8142fb38b3ca5a6ae8b805f0cf42590751f3b33be"
dependencies = [
"assert_approx_eq",
"chrono",
"error-chain",
"geo-types",
"xml-rs",
]
[[package]]
name = "gpx-web-utils"
version = "0.0.1"
dependencies = [
"console_error_panic_hook",
"gloo-file",
"gpx",
"js-sys",
"wasm-bindgen",
"web-sys",
"wee_alloc",
"yew",
]
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "indexmap"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "itoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "js-sys"
version = "0.3.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
[[package]]
name = "log"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
dependencies = [
"cfg-if 0.1.10",
]
[[package]]
name = "memory_units"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
[[package]]
name = "miniz_oxide"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
dependencies = [
"adler",
"autocfg",
]
[[package]]
name = "num-integer"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "object"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustc-demangle"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "scoped-tls-hkt"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2e9d7eaddb227e8fbaaa71136ae0e1e913ca159b86c7da82f3e8f0044ad3a63"
[[package]]
name = "serde"
version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "slab"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
[[package]]
name = "syn"
version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "thiserror"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "time"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc",
"wasi",
"winapi",
]
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "version_check"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wasm-bindgen"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42"
dependencies = [
"cfg-if 0.1.10",
"serde",
"serde_json",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da"
dependencies = [
"cfg-if 0.1.10",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307"
[[package]]
name = "web-sys"
version = "0.3.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "wee_alloc"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e"
dependencies = [
"cfg-if 0.1.10",
"libc",
"memory_units",
"winapi",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "xml-rs"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a"
[[package]]
name = "yew"
version = "0.18.0"
source = "git+https://github.com/yewstack/yew.git#996bf5b41ac30d7ada14fdc2f419de7659e94613"
dependencies = [
"console_error_panic_hook",
"gloo",
"gloo-utils",
"indexmap",
"js-sys",
"scoped-tls-hkt",
"slab",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"yew-macro",
]
[[package]]
name = "yew-macro"
version = "0.18.0"
source = "git+https://github.com/yewstack/yew.git#996bf5b41ac30d7ada14fdc2f419de7659e94613"
dependencies = [
"boolinator",
"lazy_static",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]

28
Cargo.toml Normal file
View file

@ -0,0 +1,28 @@
[package]
name = "gpx-web-utils"
version = "0.0.1"
authors = ["Matthew Dillon <matthewrdillon@gmail.com>"]
edition = "2018"
description = "just some gpx-related tools that i want to use"
repository = "git://pingo.thermokar.st/gpx-web-utils"
license = "MIT"
[dependencies]
wasm-bindgen = "0.2"
js-sys = "0.3"
gpx = "0.8.1"
# TODO: still waiting on a public release
# yew = "0.19"
yew = { git = "https://github.com/yewstack/yew.git" }
gloo-file = "0.2"
wee_alloc = "0.4"
console_error_panic_hook = { version = "0.1.6", optional = true }
[profile.release]
opt-level = 3
lto = true
[dependencies.web-sys]
version = "0.3"
features = ["File", "Blob", "Element", "MouseEvent", "EventTarget", "Url", "Event"]

25
LICENSE Normal file
View file

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

21
README.md Normal file
View file

@ -0,0 +1,21 @@
# gpx-web-utils
## development
```bash
cargo install --locked trunk
cargo install wasm-bindgen-cli
rustup target add wasm32-unknown-unknown
trunk serve
```
## deployment
```bash
trunk build --release
git switch deploy
rm index-*
cp dist/* .
git commit -am 'foo'
git push <DOKKU INSTANCE> deploy
```

View file

@ -1,33 +0,0 @@
worker_processes 1;
error_log stderr;
pid nginx.pid;
daemon off;
events {
worker_connections 768;
}
http {
types_hash_max_size 2048;
include mime.types;
types {
application/wasm wasm;
}
charset UTF-8;
server {
listen {{ $.PORT }};
server_name _;
{{ if ne $.NGINX_ROOT "" }}
root /app/www/{{ $.NGINX_ROOT }};
{{ else }}
root /app/www;
{{ end }}
index index.html;
port_in_redirect off;
location / {
try_files $uri $uri/ /index.html;
}
}
}

View file

@ -1,693 +0,0 @@
let wasm;
const heap = new Array(32).fill(undefined);
heap.push(undefined, null, true, false);
function getObject(idx) { return heap[idx]; }
let heap_next = heap.length;
function dropObject(idx) {
if (idx < 36) return;
heap[idx] = heap_next;
heap_next = idx;
}
function takeObject(idx) {
const ret = getObject(idx);
dropObject(idx);
return ret;
}
function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
heap_next = heap[idx];
heap[idx] = obj;
return idx;
}
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
cachedTextDecoder.decode();
let cachegetUint8Memory0 = null;
function getUint8Memory0() {
if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.memory.buffer) {
cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer);
}
return cachegetUint8Memory0;
}
function getStringFromWasm0(ptr, len) {
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
let WASM_VECTOR_LEN = 0;
let cachedTextEncoder = new TextEncoder('utf-8');
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
? function (arg, view) {
return cachedTextEncoder.encodeInto(arg, view);
}
: function (arg, view) {
const buf = cachedTextEncoder.encode(arg);
view.set(buf);
return {
read: arg.length,
written: buf.length
};
});
function passStringToWasm0(arg, malloc, realloc) {
if (realloc === undefined) {
const buf = cachedTextEncoder.encode(arg);
const ptr = malloc(buf.length);
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
WASM_VECTOR_LEN = buf.length;
return ptr;
}
let len = arg.length;
let ptr = malloc(len);
const mem = getUint8Memory0();
let offset = 0;
for (; offset < len; offset++) {
const code = arg.charCodeAt(offset);
if (code > 0x7F) break;
mem[ptr + offset] = code;
}
if (offset !== len) {
if (offset !== 0) {
arg = arg.slice(offset);
}
ptr = realloc(ptr, len, len = offset + arg.length * 3);
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
const ret = encodeString(arg, view);
offset += ret.written;
}
WASM_VECTOR_LEN = offset;
return ptr;
}
function isLikeNone(x) {
return x === undefined || x === null;
}
let cachegetInt32Memory0 = null;
function getInt32Memory0() {
if (cachegetInt32Memory0 === null || cachegetInt32Memory0.buffer !== wasm.memory.buffer) {
cachegetInt32Memory0 = new Int32Array(wasm.memory.buffer);
}
return cachegetInt32Memory0;
}
function debugString(val) {
// primitive types
const type = typeof val;
if (type == 'number' || type == 'boolean' || val == null) {
return `${val}`;
}
if (type == 'string') {
return `"${val}"`;
}
if (type == 'symbol') {
const description = val.description;
if (description == null) {
return 'Symbol';
} else {
return `Symbol(${description})`;
}
}
if (type == 'function') {
const name = val.name;
if (typeof name == 'string' && name.length > 0) {
return `Function(${name})`;
} else {
return 'Function';
}
}
// objects
if (Array.isArray(val)) {
const length = val.length;
let debug = '[';
if (length > 0) {
debug += debugString(val[0]);
}
for(let i = 1; i < length; i++) {
debug += ', ' + debugString(val[i]);
}
debug += ']';
return debug;
}
// Test for built-in
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
let className;
if (builtInMatches.length > 1) {
className = builtInMatches[1];
} else {
// Failed to match the standard '[object ClassName]'
return toString.call(val);
}
if (className == 'Object') {
// we're a user defined class or Object
// JSON.stringify avoids problems with cycles, and is generally much
// easier than looping through ownProperties of `val`.
try {
return 'Object(' + JSON.stringify(val) + ')';
} catch (_) {
return 'Object';
}
}
// errors
if (val instanceof Error) {
return `${val.name}: ${val.message}\n${val.stack}`;
}
// TODO we could test for more things here, like `Set`s and `Map`s.
return className;
}
let cachegetFloat64Memory0 = null;
function getFloat64Memory0() {
if (cachegetFloat64Memory0 === null || cachegetFloat64Memory0.buffer !== wasm.memory.buffer) {
cachegetFloat64Memory0 = new Float64Array(wasm.memory.buffer);
}
return cachegetFloat64Memory0;
}
function makeMutClosure(arg0, arg1, dtor, f) {
const state = { a: arg0, b: arg1, cnt: 1, dtor };
const real = (...args) => {
// First up with a closure we increment the internal reference
// count. This ensures that the Rust closure environment won't
// be deallocated while we're invoking it.
state.cnt++;
const a = state.a;
state.a = 0;
try {
return f(a, state.b, ...args);
} finally {
if (--state.cnt === 0) {
wasm.__wbindgen_export_2.get(state.dtor)(a, state.b);
} else {
state.a = a;
}
}
};
real.original = state;
return real;
}
let stack_pointer = 32;
function addBorrowedObject(obj) {
if (stack_pointer == 1) throw new Error('out of js stack');
heap[--stack_pointer] = obj;
return stack_pointer;
}
function __wbg_adapter_28(arg0, arg1, arg2) {
try {
wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h207a40868e3ce597(arg0, arg1, addBorrowedObject(arg2));
} finally {
heap[stack_pointer++] = undefined;
}
}
function makeClosure(arg0, arg1, dtor, f) {
const state = { a: arg0, b: arg1, cnt: 1, dtor };
const real = (...args) => {
// First up with a closure we increment the internal reference
// count. This ensures that the Rust closure environment won't
// be deallocated while we're invoking it.
state.cnt++;
try {
return f(state.a, state.b, ...args);
} finally {
if (--state.cnt === 0) {
wasm.__wbindgen_export_2.get(state.dtor)(state.a, state.b);
state.a = 0;
}
}
};
real.original = state;
return real;
}
function __wbg_adapter_31(arg0, arg1, arg2) {
wasm._dyn_core__ops__function__Fn__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h2619a812962a2c7d(arg0, arg1, addHeapObject(arg2));
}
let cachegetUint32Memory0 = null;
function getUint32Memory0() {
if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) {
cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer);
}
return cachegetUint32Memory0;
}
function getArrayJsValueFromWasm0(ptr, len) {
const mem = getUint32Memory0();
const slice = mem.subarray(ptr / 4, ptr / 4 + len);
const result = [];
for (let i = 0; i < slice.length; i++) {
result.push(takeObject(slice[i]));
}
return result;
}
function handleError(f) {
return function () {
try {
return f.apply(this, arguments);
} catch (e) {
wasm.__wbindgen_exn_store(addHeapObject(e));
}
};
}
async function load(module, imports) {
if (typeof Response === 'function' && module instanceof Response) {
if (typeof WebAssembly.instantiateStreaming === 'function') {
try {
return await WebAssembly.instantiateStreaming(module, imports);
} catch (e) {
if (module.headers.get('Content-Type') != 'application/wasm') {
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
} else {
throw e;
}
}
}
const bytes = await module.arrayBuffer();
return await WebAssembly.instantiate(bytes, imports);
} else {
const instance = await WebAssembly.instantiate(module, imports);
if (instance instanceof WebAssembly.Instance) {
return { instance, module };
} else {
return instance;
}
}
}
async function init(input) {
if (typeof input === 'undefined') {
input = import.meta.url.replace(/\.js$/, '_bg.wasm');
}
const imports = {};
imports.wbg = {};
imports.wbg.__wbg_document_6cc8d0b87c0a99b9 = function(arg0) {
var ret = getObject(arg0).document;
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
takeObject(arg0);
};
imports.wbg.__wbg_createTextNode_b3c9e3cb02f83ab5 = function(arg0, arg1, arg2) {
var ret = getObject(arg0).createTextNode(getStringFromWasm0(arg1, arg2));
return addHeapObject(ret);
};
imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
var ret = getObject(arg0);
return addHeapObject(ret);
};
imports.wbg.__wbg_removeEventListener_9ffcd175e0916270 = handleError(function(arg0, arg1, arg2, arg3, arg4) {
getObject(arg0).removeEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), arg4 !== 0);
});
imports.wbg.__wbindgen_cb_drop = function(arg0) {
const obj = takeObject(arg0).original;
if (obj.cnt-- == 1) {
obj.a = 0;
return true;
}
var ret = false;
return ret;
};
imports.wbg.__wbg_readyState_96d1af7059614bb2 = function(arg0) {
var ret = getObject(arg0).readyState;
return ret;
};
imports.wbg.__wbg_abort_551ff9881e7f5157 = function(arg0) {
getObject(arg0).abort();
};
imports.wbg.__wbg_createElement_5bdf88a5af9f17c5 = handleError(function(arg0, arg1, arg2) {
var ret = getObject(arg0).createElement(getStringFromWasm0(arg1, arg2));
return addHeapObject(ret);
});
imports.wbg.__wbg_createObjectURL_356d0e93fee8a070 = handleError(function(arg0, arg1) {
var ret = URL.createObjectURL(getObject(arg1));
var ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
});
imports.wbg.__wbg_setAttribute_727bdb9763037624 = handleError(function(arg0, arg1, arg2, arg3, arg4) {
getObject(arg0).setAttribute(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4));
});
imports.wbg.__wbg_alert_4ad63c9979edd105 = function(arg0, arg1) {
alert(getStringFromWasm0(arg0, arg1));
};
imports.wbg.__wbg_name_846e8e23519fbe3d = function(arg0, arg1) {
var ret = getObject(arg1).name;
var ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbg_new_ba500001a5c5b152 = handleError(function() {
var ret = new FileReader();
return addHeapObject(ret);
});
imports.wbg.__wbg_readAsText_acc57fc7677de33a = handleError(function(arg0, arg1) {
getObject(arg0).readAsText(getObject(arg1));
});
imports.wbg.__wbg_new_59cb74e423758ede = function() {
var ret = new Error();
return addHeapObject(ret);
};
imports.wbg.__wbg_stack_558ba5917b466edd = function(arg0, arg1) {
var ret = getObject(arg1).stack;
var ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbg_error_4bb6c2a97407129a = function(arg0, arg1) {
try {
console.error(getStringFromWasm0(arg0, arg1));
} finally {
wasm.__wbindgen_free(arg0, arg1);
}
};
imports.wbg.__wbg_target_02b2c4e71f788cc6 = function(arg0) {
var ret = getObject(arg0).target;
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_files_ecbda252a7b3abd7 = function(arg0) {
var ret = getObject(arg0).files;
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_iterator_09191f8878ea9877 = function() {
var ret = Symbol.iterator;
return addHeapObject(ret);
};
imports.wbg.__wbg_get_0e3f2950cdf758ae = handleError(function(arg0, arg1) {
var ret = Reflect.get(getObject(arg0), getObject(arg1));
return addHeapObject(ret);
});
imports.wbg.__wbindgen_is_function = function(arg0) {
var ret = typeof(getObject(arg0)) === 'function';
return ret;
};
imports.wbg.__wbg_call_8e95613cc6524977 = handleError(function(arg0, arg1) {
var ret = getObject(arg0).call(getObject(arg1));
return addHeapObject(ret);
});
imports.wbg.__wbindgen_is_object = function(arg0) {
const val = getObject(arg0);
var ret = typeof(val) === 'object' && val !== null;
return ret;
};
imports.wbg.__wbg_next_edda7e0003e5daf9 = function(arg0) {
var ret = getObject(arg0).next;
return addHeapObject(ret);
};
imports.wbg.__wbg_next_2966fa909601a075 = handleError(function(arg0) {
var ret = getObject(arg0).next();
return addHeapObject(ret);
});
imports.wbg.__wbg_done_037d0a173aef1834 = function(arg0) {
var ret = getObject(arg0).done;
return ret;
};
imports.wbg.__wbg_value_e60bbfb7d52af62f = function(arg0) {
var ret = getObject(arg0).value;
return addHeapObject(ret);
};
imports.wbg.__wbindgen_memory = function() {
var ret = wasm.memory;
return addHeapObject(ret);
};
imports.wbg.__wbg_buffer_49131c283a06686f = function(arg0) {
var ret = getObject(arg0).buffer;
return addHeapObject(ret);
};
imports.wbg.__wbg_newwithbyteoffsetandlength_c0f38401daad5a22 = function(arg0, arg1, arg2) {
var ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_new_9b295d24cf1d706f = function(arg0) {
var ret = new Uint8Array(getObject(arg0));
return addHeapObject(ret);
};
imports.wbg.__wbg_new_e13110f81ae347cf = function() {
var ret = new Array();
return addHeapObject(ret);
};
imports.wbg.__wbg_buffer_3d4c28111c30d143 = function(arg0) {
var ret = getObject(arg0).buffer;
return addHeapObject(ret);
};
imports.wbg.__wbg_push_b46eeec52d2b03bb = function(arg0, arg1) {
var ret = getObject(arg0).push(getObject(arg1));
return ret;
};
imports.wbg.__wbg_newwithu8arraysequence_7aefb42249871bf2 = handleError(function(arg0) {
var ret = new Blob(getObject(arg0));
return addHeapObject(ret);
});
imports.wbg.__wbg_body_8c888fe47d81765f = function(arg0) {
var ret = getObject(arg0).body;
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_lastChild_4a41600911ce94c7 = function(arg0) {
var ret = getObject(arg0).lastChild;
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_removeChild_f4829fcd2e376e1b = handleError(function(arg0, arg1) {
var ret = getObject(arg0).removeChild(getObject(arg1));
return addHeapObject(ret);
});
imports.wbg.__wbg_addEventListener_f0baf69c9c7425c9 = handleError(function(arg0, arg1, arg2, arg3, arg4) {
getObject(arg0).addEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), getObject(arg4));
});
imports.wbg.__wbg_error_25001b5a07976ffc = function(arg0) {
var ret = getObject(arg0).error;
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_name_0c9e77d5ede395cb = function(arg0, arg1) {
var ret = getObject(arg1).name;
var ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbg_message_be852274e4513376 = function(arg0, arg1) {
var ret = getObject(arg1).message;
var ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbg_new_3e06d4f36713e4cb = function() {
var ret = new Object();
return addHeapObject(ret);
};
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
var ret = getStringFromWasm0(arg0, arg1);
return addHeapObject(ret);
};
imports.wbg.__wbg_set_304f2ec1a3ab3b79 = handleError(function(arg0, arg1, arg2) {
var ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2));
return ret;
});
imports.wbg.__wbg_result_4ced5ba81ed2dcf2 = handleError(function(arg0) {
var ret = getObject(arg0).result;
return addHeapObject(ret);
});
imports.wbg.__wbg_setinnerHTML_4ff235db1a3cb4d8 = function(arg0, arg1, arg2) {
getObject(arg0).innerHTML = getStringFromWasm0(arg1, arg2);
};
imports.wbg.__wbg_self_07b2f89e82ceb76d = handleError(function() {
var ret = self.self;
return addHeapObject(ret);
});
imports.wbg.__wbg_window_ba85d88572adc0dc = handleError(function() {
var ret = window.window;
return addHeapObject(ret);
});
imports.wbg.__wbg_globalThis_b9277fc37e201fe5 = handleError(function() {
var ret = globalThis.globalThis;
return addHeapObject(ret);
});
imports.wbg.__wbg_global_e16303fe83e1d57f = handleError(function() {
var ret = global.global;
return addHeapObject(ret);
});
imports.wbg.__wbindgen_is_undefined = function(arg0) {
var ret = getObject(arg0) === undefined;
return ret;
};
imports.wbg.__wbg_newnoargs_f3b8a801d5d4b079 = function(arg0, arg1) {
var ret = new Function(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
const obj = getObject(arg1);
var ret = typeof(obj) === 'string' ? obj : undefined;
var ptr0 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
var ret = debugString(getObject(arg1));
var ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
throw new Error(getStringFromWasm0(arg0, arg1));
};
imports.wbg.__wbg_dispatchEvent_aca3da6ff77b010c = handleError(function(arg0, arg1) {
var ret = getObject(arg0).dispatchEvent(getObject(arg1));
return ret;
});
imports.wbg.__wbg_instanceof_Window_adf3196bdc02b386 = function(arg0) {
var ret = getObject(arg0) instanceof Window;
return ret;
};
imports.wbg.__wbg_new_26d01414f47d4ceb = handleError(function(arg0, arg1) {
var ret = new MouseEvent(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
});
imports.wbg.__wbg_value_91d41b8dbd0b2f0b = function(arg0, arg1) {
var ret = getObject(arg1).value;
var ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbg_setchecked_1a89c058f5ac906a = function(arg0, arg1) {
getObject(arg0).checked = arg1 !== 0;
};
imports.wbg.__wbg_setvalue_839acf17e43a847f = function(arg0, arg1, arg2) {
getObject(arg0).value = getStringFromWasm0(arg1, arg2);
};
imports.wbg.__wbg_value_bff6f7ef104e077a = function(arg0, arg1) {
var ret = getObject(arg1).value;
var ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbg_namespaceURI_a4d52538ca0c6bae = function(arg0, arg1) {
var ret = getObject(arg1).namespaceURI;
var ptr0 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbg_createElementNS_ea14cb45a87a0719 = handleError(function(arg0, arg1, arg2, arg3, arg4) {
var ret = getObject(arg0).createElementNS(arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4));
return addHeapObject(ret);
});
imports.wbg.__wbg_warn_2aa0e7178e1d35f6 = function(arg0, arg1) {
var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice();
wasm.__wbindgen_free(arg0, arg1 * 4);
console.warn(...v0);
};
imports.wbg.__wbg_setvalue_1012134a2989f3ee = function(arg0, arg1, arg2) {
getObject(arg0).value = getStringFromWasm0(arg1, arg2);
};
imports.wbg.__wbg_setnodeValue_ec452cd3716fee72 = function(arg0, arg1, arg2) {
getObject(arg0).nodeValue = arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2);
};
imports.wbg.__wbg_is_333329c4a02916de = function(arg0, arg1) {
var ret = Object.is(getObject(arg0), getObject(arg1));
return ret;
};
imports.wbg.__wbg_removeAttribute_a705c6de4bb158c4 = handleError(function(arg0, arg1, arg2) {
getObject(arg0).removeAttribute(getStringFromWasm0(arg1, arg2));
});
imports.wbg.__wbg_appendChild_77215fd672b162c5 = handleError(function(arg0, arg1) {
var ret = getObject(arg0).appendChild(getObject(arg1));
return addHeapObject(ret);
});
imports.wbg.__wbg_insertBefore_ea385f1d7ec76e50 = handleError(function(arg0, arg1, arg2) {
var ret = getObject(arg0).insertBefore(getObject(arg1), getObject(arg2));
return addHeapObject(ret);
});
imports.wbg.__wbg_instanceof_Element_fa1f2e86d1bc5f26 = function(arg0) {
var ret = getObject(arg0) instanceof Element;
return ret;
};
imports.wbg.__wbg_cancelBubble_ba020b9735aa529e = function(arg0) {
var ret = getObject(arg0).cancelBubble;
return ret;
};
imports.wbg.__wbg_parentElement_41bda1ad58a631b1 = function(arg0) {
var ret = getObject(arg0).parentElement;
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbindgen_number_get = function(arg0, arg1) {
const obj = getObject(arg1);
var ret = typeof(obj) === 'number' ? obj : undefined;
getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret;
getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret);
};
imports.wbg.__wbg_valueOf_f6d2b0994b83b882 = function(arg0) {
var ret = getObject(arg0).valueOf();
return ret;
};
imports.wbg.__wbindgen_number_new = function(arg0) {
var ret = arg0;
return addHeapObject(ret);
};
imports.wbg.__wbindgen_closure_wrapper184 = function(arg0, arg1, arg2) {
var ret = makeMutClosure(arg0, arg1, 32, __wbg_adapter_28);
return addHeapObject(ret);
};
imports.wbg.__wbindgen_closure_wrapper1625 = function(arg0, arg1, arg2) {
var ret = makeClosure(arg0, arg1, 32, __wbg_adapter_31);
return addHeapObject(ret);
};
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
input = fetch(input);
}
const { instance, module } = await load(await input, imports);
wasm = instance.exports;
init.__wbindgen_wasm_module = module;
wasm.__wbindgen_start();
return wasm;
}
export default init;

View file

@ -1,5 +1,7 @@
<!DOCTYPE html><html><head>
<meta charset="utf-8">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>gpx.thermokar.st</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
@ -11,9 +13,7 @@
font-size: large;
}
</style>
<link rel="preload" href="/gpx-web-utils-bf09a17967dc63a6_bg.wasm" as="fetch" type="application/wasm" crossorigin="">
<link rel="modulepreload" href="/gpx-web-utils-bf09a17967dc63a6.js"></head>
</head>
<body>
<noscript>
<mark>
@ -21,6 +21,5 @@
javascript in your browser to use this tool.
</mark>
</noscript>
<script type="module">import init from '/gpx-web-utils-bf09a17967dc63a6.js';init('/gpx-web-utils-bf09a17967dc63a6_bg.wasm');</script></body></html>
</body>
</html>

81
src/app.rs Normal file
View file

@ -0,0 +1,81 @@
use super::loader::Loader;
use web_sys::Node;
use yew::virtual_dom::VNode;
use yew::{function_component, html, Html};
#[function_component(App)]
pub fn app() -> Html {
html! {
<>
<h1>
<a href="/">
{ "gpx.thermokar.st" }
</a>
</h1>
<p>
{ "a client-side tool for merging " }
<a href="https://www.topografix.com/gpx.asp">
{ "gpx files" }
</a>
</p>
<Loader />
<hr/>
<Footer />
</>
}
}
#[function_component(Footer)]
fn footer() -> Html {
let notes = Vec::from([
// note 1
"this has only been tested on GPX files produced by \
<a href=\"https://strava.com\" target=\"_blank\">strava</a> and \
<a href=\"https://garmin.com\" target=\"_blank\">garmin</a>",
// note 2
"all third-party extension info \
<a href=\"https://github.com/georust/gpx/issues/8\" target=\"_blank\">\
is stripped</a>",
// note 3
"if the app breaks, try refreshing the page",
"source (public access): git://pingo.thermokar.st/gpx-web-utils",
// note 4
"source (mirror): \
<a href=\"https://github.com/thermokarst/gpx-web-utils\" target=\"_blank\">\
https://github.com/thermokarst/gpx-web-utils</a>",
]);
html! {
<div>
<ul>
{ for notes.iter().map(|n| inner_html_enabled_li(n)) }
</ul>
<span>
<small>
{ "\u{000A9} matthew ryan dillon, 2022" }
</small>
</span>
</div>
}
}
fn inner_html_enabled_li(data: &str) -> Html {
let li = web_sys::window()
.unwrap()
.document()
.unwrap()
.create_element("li")
.unwrap();
li.set_inner_html(data);
let node = Node::from(li);
VNode::VRef(node)
}

88
src/gpx.rs Normal file
View file

@ -0,0 +1,88 @@
use std::error::Error;
use wasm_bindgen::prelude::*;
use web_sys::{Blob, MouseEvent, Url};
fn join_gpx_files(files: &[String]) -> Result<gpx::Gpx, Box<dyn Error>> {
let mut merged_gpx: gpx::Gpx = Default::default();
let mut merged_track: gpx::Track = gpx::Track::new();
for file in files.iter() {
let buffer = std::io::BufReader::new(file.as_bytes());
let mut parsed_gpx: gpx::Gpx = gpx::read(buffer)?;
// consolidate all track segements into one single track.
for track in parsed_gpx.tracks {
for segment in track.segments {
merged_track.segments.push(segment);
}
}
merged_gpx.waypoints.append(&mut parsed_gpx.waypoints);
}
merged_gpx.tracks.push(merged_track);
let link = gpx::Link {
href: String::from("https://gpx.thermokar.st"),
..Default::default()
};
let author = gpx::Person {
link: Some(link),
..Default::default()
};
let metadata = gpx::Metadata {
name: Some(String::from("merged")),
author: Some(author),
..Default::default()
};
merged_gpx.metadata = Some(metadata);
merged_gpx.version = gpx::GpxVersion::Gpx11;
Ok(merged_gpx)
}
fn write_gpx_to_buffer(gpx: gpx::Gpx) -> Result<js_sys::Array, Box<dyn Error>> {
let mut buffer = Vec::new();
gpx::write(&gpx, &mut buffer)?;
let uint8arr = js_sys::Uint8Array::new(&unsafe { js_sys::Uint8Array::view(&buffer) }.into());
let array = js_sys::Array::new();
array.push(&uint8arr.buffer());
Ok(array)
}
pub fn merge(files: &[String]) -> Result<Blob, Box<dyn Error>> {
let merged: gpx::Gpx = join_gpx_files(files)?;
let out_vec = write_gpx_to_buffer(merged)?;
let result = Blob::new_with_u8_array_sequence(&out_vec).map_err(|e| e.as_string().unwrap())?;
Ok(result)
}
pub fn download(merged: Blob) -> Result<(), Box<dyn Error>> {
let window = web_sys::window().ok_or("no global `window` exists")?;
let document = window
.document()
.ok_or("should have a document on window")?;
let err_handler = |e: JsValue| e.as_string().unwrap();
let anchor_element = document.create_element("a").map_err(err_handler)?;
let url = Url::create_object_url_with_blob(&merged).map_err(err_handler)?;
anchor_element
.set_attribute("href", &url)
.map_err(err_handler)?;
anchor_element
.set_attribute("download", "merged.gpx")
.map_err(err_handler)?;
let event = MouseEvent::new("click").map_err(err_handler)?;
anchor_element.dispatch_event(&event).map_err(err_handler)?;
Ok(())
}
#[wasm_bindgen]
extern "C" {
pub fn alert(s: &str);
}

155
src/loader.rs Normal file
View file

@ -0,0 +1,155 @@
use std::collections::HashMap;
use gloo_file::callbacks::FileReader;
use gloo_file::File;
use web_sys::{Blob, Event, HtmlInputElement};
use yew::{html, html::TargetCast, Component, Context, Html};
use super::gpx;
pub enum Msg {
FileLoaded(String, String),
StartLoad(Vec<File>),
FilesLoaded,
Download(Blob),
Reset,
}
pub struct Loader {
readers: HashMap<String, FileReader>,
files: Vec<String>,
count: usize,
is_loading: bool,
// This field is to handle resetting the native HTML widget's state on error
field_value: &'static str,
}
impl Component for Loader {
type Message = Msg;
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self {
readers: HashMap::default(),
files: vec![],
count: 0,
is_loading: false,
field_value: "",
}
}
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::FileLoaded(filename, data) => {
self.files.push(data);
self.readers.remove(&filename);
if self.files.len() == self.count {
ctx.link().send_message(Msg::FilesLoaded);
}
true
}
Msg::StartLoad(files) => {
self.count = files.len();
if self.count < 2 {
gpx::alert("must load two or more files");
ctx.link().send_message(Msg::Reset);
return true;
}
self.is_loading = true;
for file in files.into_iter() {
let file_name = file.name();
let task = {
let file_name = file_name.clone();
let link = ctx.link().clone();
gloo_file::callbacks::read_as_text(&file, move |res| {
link.send_message(Msg::FileLoaded(
file_name,
res.unwrap_or_else(|e| e.to_string()),
))
})
};
self.readers.insert(file_name, task);
}
true
}
Msg::FilesLoaded => {
let link = ctx.link();
let merged = match gpx::merge(&self.files) {
Ok(result) => result,
Err(err) => {
gpx::alert(&err.to_string());
link.send_message(Msg::Reset);
return true;
}
};
link.send_message(Msg::Download(merged));
true
}
Msg::Download(merged) => {
let link = ctx.link();
match gpx::download(merged) {
Ok(_) => (),
Err(err) => {
gpx::alert(&err.to_string());
link.send_message(Msg::Reset);
return true;
}
}
link.send_message(Msg::Reset);
true
}
Msg::Reset => {
self.readers = HashMap::default();
self.files = vec![];
self.count = 0;
self.is_loading = false;
self.field_value = "";
true
}
}
}
fn view(&self, ctx: &Context<Self>) -> Html {
let cb = move |e: Event| {
let mut result = Vec::new();
let input: HtmlInputElement = e.target_unchecked_into();
if let Some(files) = input.files() {
let files = js_sys::try_iter(&files)
.unwrap()
.unwrap()
.map(|v| web_sys::File::from(v.unwrap()))
.map(File::from);
result.extend(files);
}
Msg::StartLoad(result)
};
html! {
if self.is_loading {
<span><strong>{"processing..."}</strong></span>
} else {
<input
type="file"
value={self.field_value}
multiple=true
onchange={ctx.link().callback(cb)}
/>
}
}
}
}

13
src/main.rs Normal file
View file

@ -0,0 +1,13 @@
extern crate wee_alloc;
mod app;
mod gpx;
mod loader;
// Use `wee_alloc` as the global allocator.
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
fn main() {
yew::start_app::<app::App>();
}