forgot to commit this for 7 months...

This commit is contained in:
Robin Appelman 2023-11-24 22:07:44 +01:00
commit 6d568799a7
11 changed files with 77 additions and 31 deletions

784
wasm/Cargo.lock generated Normal file
View file

@ -0,0 +1,784 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
dependencies = [
"memchr",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitbuffer"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a9c93bd4423a7740feae26d6daf52b7d53451cba0b2d6bed59b836c32e15c"
dependencies = [
"bitbuffer_derive",
"err-derive",
"memchr",
"num-traits 0.2.15",
"serde",
]
[[package]]
name = "bitbuffer_derive"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4090254bfbc71442ff4a426ddba663346e26fd14b55b259281f763e350d7f621"
dependencies = [
"proc-macro2 1.0.43",
"quote 1.0.21",
"syn",
"syn_util",
]
[[package]]
name = "bumpalo"
version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
[[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 = "console_error_panic_hook"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen",
]
[[package]]
name = "either"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
name = "enum_primitive"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
dependencies = [
"num-traits 0.1.43",
]
[[package]]
name = "enumflags2"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb"
dependencies = [
"enumflags2_derive",
"serde",
]
[[package]]
name = "enumflags2_derive"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae"
dependencies = [
"proc-macro2 1.0.43",
"quote 1.0.21",
"syn",
]
[[package]]
name = "err-derive"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c34a887c8df3ed90498c1c437ce21f211c8e27672921a8ffa293cb8d6d4caa9e"
dependencies = [
"proc-macro-error",
"proc-macro2 1.0.43",
"quote 1.0.21",
"rustversion",
"syn",
"synstructure",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "futures"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678"
[[package]]
name = "itertools"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8bf247779e67a9082a4790b45e71ac7cfd1321331a5c856a74a9faebdab78d0"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
[[package]]
name = "js-sys"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
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.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "main_error"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "155db5e86c6e45ee456bf32fad5a290ee1f7151c2faca27ea27097568da67d1a"
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memory_units"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
[[package]]
name = "num"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
dependencies = [
"num-bigint",
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits 0.2.15",
]
[[package]]
name = "num-bigint"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3"
dependencies = [
"autocfg",
"num-integer",
"num-traits 0.2.15",
]
[[package]]
name = "num-complex"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
dependencies = [
"num-traits 0.2.15",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits 0.2.15",
]
[[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 0.2.15",
]
[[package]]
name = "num-rational"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
dependencies = [
"autocfg",
"num-bigint",
"num-integer",
"num-traits 0.2.15",
]
[[package]]
name = "num-traits"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
dependencies = [
"num-traits 0.2.15",
]
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]]
name = "num_enum"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9"
dependencies = [
"num_enum_derive",
]
[[package]]
name = "num_enum_derive"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce"
dependencies = [
"proc-macro-crate",
"proc-macro2 1.0.43",
"quote 1.0.21",
"syn",
]
[[package]]
name = "once_cell"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
[[package]]
name = "parse-display"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "813e91c6232dbeb2e9deba0eb0dc5c967bd6f380676fd34419f9ddd71411faa7"
dependencies = [
"once_cell",
"parse-display-derive",
"regex",
]
[[package]]
name = "parse-display-derive"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "007ed61a69cf7d9b95cc5dc18489dbb4f70d4adb0a0c100e2dd46f0be241711a"
dependencies = [
"once_cell",
"proc-macro2 1.0.43",
"quote 1.0.21",
"regex",
"regex-syntax",
"structmeta",
"syn",
]
[[package]]
name = "proc-macro-crate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9"
dependencies = [
"once_cell",
"thiserror",
"toml",
]
[[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 1.0.43",
"quote 1.0.21",
"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 1.0.43",
"quote 1.0.21",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
dependencies = [
"unicode-xid 0.1.0",
]
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
dependencies = [
"proc-macro2 0.4.30",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2 1.0.43",
]
[[package]]
name = "regex"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "rustversion"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
[[package]]
name = "ryu"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "scoped-tls"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
[[package]]
name = "serde"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
dependencies = [
"proc-macro2 1.0.43",
"quote 1.0.21",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_repr"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca"
dependencies = [
"proc-macro2 1.0.43",
"quote 1.0.21",
"syn",
]
[[package]]
name = "snap"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45456094d1983e2ee2a18fdfebce3189fa451699d0502cb8e3b49dba5ba41451"
[[package]]
name = "steamid-ng"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb049f8faa2cba570c5366dbaf88ee5849725b16edb771848639fac92e33673"
dependencies = [
"enum_primitive",
"lazy_static",
"num",
"regex",
"serde",
"serde_derive",
"thiserror",
]
[[package]]
name = "structmeta"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bd9c2155aa89fb2c2cb87d99a610c689e7c47099b3e9f1c8a8f53faf4e3d2e3"
dependencies = [
"proc-macro2 1.0.43",
"quote 1.0.21",
"structmeta-derive",
"syn",
]
[[package]]
name = "structmeta-derive"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bafede0d0a2f21910f36d47b1558caae3076ed80f6f3ad0fc85a91e6ba7e5938"
dependencies = [
"proc-macro2 1.0.43",
"quote 1.0.21",
"syn",
]
[[package]]
name = "syn"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
dependencies = [
"proc-macro2 1.0.43",
"quote 1.0.21",
"unicode-ident",
]
[[package]]
name = "syn_util"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6754c4559b79657554e9d8a0d56e65e490c76d382b9c23108364ec4125dea23c"
dependencies = [
"proc-macro2 1.0.43",
"quote 1.0.21",
"syn",
]
[[package]]
name = "synstructure"
version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
"proc-macro2 1.0.43",
"quote 1.0.21",
"syn",
"unicode-xid 0.2.4",
]
[[package]]
name = "tf-demo-parser"
version = "0.4.0"
source = "git+https://github.com/demostf/parser#9e3f008e510a0b69cefd48e606adccb7669e700c"
dependencies = [
"bitbuffer",
"enumflags2",
"err-derive",
"fnv",
"itertools",
"main_error",
"num-traits 0.2.15",
"num_enum",
"parse-display",
"serde",
"serde_json",
"serde_repr",
"snap",
"steamid-ng",
]
[[package]]
name = "tf-demos-viewer"
version = "0.1.0"
dependencies = [
"futures",
"js-sys",
"tf-demo-parser",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-test",
"web-sys",
"wee_alloc",
]
[[package]]
name = "thiserror"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783"
dependencies = [
"proc-macro2 1.0.43",
"quote 1.0.21",
"syn",
]
[[package]]
name = "toml"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
dependencies = [
"serde",
]
[[package]]
name = "unicode-ident"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasm-bindgen"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2 1.0.43",
"quote 1.0.21",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83420b37346c311b9ed822af41ec2e82839bfe99867ec6c54e2da43b7538771c"
dependencies = [
"cfg-if 0.1.10",
"futures",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
dependencies = [
"quote 1.0.21",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [
"proc-macro2 1.0.43",
"quote 1.0.21",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
[[package]]
name = "wasm-bindgen-test"
version = "0.2.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2d9693b63a742d481c7f80587e057920e568317b2806988c59cd71618bc26c1"
dependencies = [
"console_error_panic_hook",
"futures",
"js-sys",
"scoped-tls",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-test-macro",
]
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.2.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0789dac148a8840bbcf9efe13905463b733fa96543bfbf263790535c11af7ba5"
dependencies = [
"proc-macro2 0.4.30",
"quote 0.6.13",
]
[[package]]
name = "web-sys"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
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"

37
wasm/Cargo.toml Normal file
View file

@ -0,0 +1,37 @@
[package]
name = "tf-demos-viewer"
description = "JS bindings for demo parser"
version = "0.1.1"
authors = ["Robin Appelman <robin@icewind.nl>"]
categories = ["wasm"]
readme = "README.md"
edition = "2018"
[lib]
crate-type = ["cdylib"]
[profile.dev]
opt-level = 3 # demo parsing is slow
[profile.release]
lto = true
[package.metadata.wasm-pack.profile.release]
wasm-opt = true
#wasm-opt = ["-Oz", "--enable-mutable-globals"]
[features]
[dependencies]
wasm-bindgen = "0.2.45"
wee_alloc = { version = "0.4.2", optional = true }
web-sys = { version = "0.3.22", features = ["console"] }
js-sys = "0.3.22"
tf-demo-parser = { version = "0.4", git = "https://github.com/demostf/parser" }
#tf-demo-parser = { version = "0.4", path = "../tf-demo-parser" }
[dev-dependencies]
wasm-bindgen-test = "0.2.45"
futures = "0.1.27"
js-sys = "0.3.22"
wasm-bindgen-futures = "0.3.22"

210
wasm/src/lib.rs Normal file
View file

@ -0,0 +1,210 @@
#![macro_use]
use crate::state::ParsedDemo;
use js_sys::Function;
use tf_demo_parser::demo::header::Header;
use tf_demo_parser::demo::parser::analyser::UserInfo;
use tf_demo_parser::demo::parser::gamestateanalyser::{GameStateAnalyser, World};
use tf_demo_parser::demo::vector::Vector;
use tf_demo_parser::{Demo, DemoParser, ParseError};
use wasm_bindgen::prelude::*;
mod state;
#[wasm_bindgen]
#[derive(Debug, Clone, Copy)]
pub struct XY {
pub x: f32,
pub y: f32,
}
impl From<Vector> for XY {
fn from(vec: Vector) -> Self {
XY { x: vec.x, y: vec.y }
}
}
#[wasm_bindgen]
#[derive(Debug, Clone, Copy)]
pub struct WorldBoundaries {
pub boundary_min: XY,
pub boundary_max: XY,
}
impl From<World> for WorldBoundaries {
fn from(world: World) -> Self {
WorldBoundaries {
boundary_min: world.boundary_min.into(),
boundary_max: world.boundary_max.into(),
}
}
}
#[wasm_bindgen]
pub struct FlatState {
pub player_count: usize,
pub building_count: usize,
pub boundaries: WorldBoundaries,
pub interval_per_tick: f32,
pub tick_count: u32,
kill_ticks: Box<[u32]>,
attackers: Box<[u8]>,
assisters: Box<[u8]>,
victims: Box<[u8]>,
weapons: Vec<String>,
player_info: Vec<UserInfo>,
data: Box<[u8]>,
header: Header,
}
impl FlatState {
pub fn new(parsed: ParsedDemo, world: World) -> Self {
let ParsedDemo {
players,
header,
buildings,
max_building_count,
tick,
..
} = parsed;
let player_count = players.len();
let building_count = max_building_count;
let flat: Vec<_> = players
.into_iter()
.chain(buildings.into_iter())
.flat_map(|data| data.into_iter())
.collect();
FlatState {
player_count,
building_count,
tick_count: tick as u32,
boundaries: world.into(),
interval_per_tick: header.duration / (header.ticks as f32),
data: flat.into_boxed_slice(),
kill_ticks: parsed.kills.iter().map(|kill| kill.tick.into()).collect(),
attackers: parsed
.kills
.iter()
.map(|kill| kill.attacker_id as u8)
.collect(),
assisters: parsed
.kills
.iter()
.map(|kill| kill.assister_id as u8)
.collect(),
victims: parsed
.kills
.iter()
.map(|kill| kill.victim_id as u8)
.collect(),
weapons: parsed.kills.into_iter().map(|kill| kill.weapon).collect(),
player_info: parsed.player_info,
header,
}
}
}
#[wasm_bindgen]
pub fn parse_demo(buffer: Box<[u8]>, progress: &Function) -> Result<FlatState, JsValue> {
let (parsed, world) =
parse_demo_inner(&buffer, progress).map_err(|e| JsValue::from(e.to_string()))?;
let world = world.ok_or_else(|| JsValue::from_str("No world defined in demo"))?;
Ok(FlatState::new(parsed, world))
}
#[wasm_bindgen]
pub fn get_data(state: FlatState) -> Box<[u8]> {
state.data
}
#[wasm_bindgen]
pub fn get_map(state: &FlatState) -> String {
state.header.map.clone()
}
#[wasm_bindgen]
pub fn get_kill_ticks(state: &FlatState) -> Box<[u32]> {
state.kill_ticks.clone()
}
#[wasm_bindgen]
pub fn get_attacker_ids(state: &FlatState) -> Box<[u8]> {
state.attackers.clone()
}
#[wasm_bindgen]
pub fn get_assister_ids(state: &FlatState) -> Box<[u8]> {
state.assisters.clone()
}
#[wasm_bindgen]
pub fn get_victim_ids(state: &FlatState) -> Box<[u8]> {
state.victims.clone()
}
#[wasm_bindgen]
pub fn get_weapon(state: &FlatState, kill_id: usize) -> String {
state.weapons[kill_id].clone()
}
#[wasm_bindgen]
pub fn get_player_name(state: &FlatState, player_id: usize) -> String {
state.player_info[player_id].name.clone()
}
#[wasm_bindgen]
pub fn get_player_entity_id(state: &FlatState, player_id: usize) -> u32 {
state.player_info[player_id].entity_id.into()
}
#[wasm_bindgen]
pub fn get_player_user_id(state: &FlatState, player_id: usize) -> u8 {
state.player_info[player_id].user_id.into()
}
#[wasm_bindgen]
pub fn get_player_steam_id(state: &FlatState, player_id: usize) -> String {
state.player_info[player_id].steam_id.clone()
}
pub fn parse_demo_inner(
buffer: &[u8],
progress: &Function,
) -> Result<(ParsedDemo, Option<World>), ParseError> {
let demo = Demo::new(buffer);
let parser = DemoParser::new_with_analyser(demo.get_stream(), GameStateAnalyser::default());
let (header, mut ticker) = parser.ticker()?;
let total_ticks = header.ticks;
let mut last_progress = 0.0;
let mut parsed_demo = ParsedDemo::new(header);
while ticker.tick()? {
parsed_demo.push_state(ticker.state());
let new_progress =
((u32::from(ticker.state().tick) as f32 / total_ticks as f32) * 100.0).floor();
if new_progress > last_progress {
last_progress = new_progress;
let _ = progress.call1(&JsValue::null(), &last_progress.into());
}
}
parsed_demo.finish();
let state = ticker.into_state();
parsed_demo.kills = state.kills;
Ok((parsed_demo, state.world))
}
// This is like the `main` function, except for JavaScript.
#[wasm_bindgen(start)]
pub fn main_js() -> Result<(), JsValue> {
Ok(())
}

447
wasm/src/state.rs Normal file
View file

@ -0,0 +1,447 @@
use tf_demo_parser::demo::data::DemoTick;
use tf_demo_parser::demo::header::Header;
use tf_demo_parser::demo::parser::analyser::UserInfo;
use tf_demo_parser::demo::parser::gamestateanalyser::{
Building, Class, Dispenser, GameState, Kill, PlayerState as PlayerAliveState, Sentry, Team,
Teleporter, World,
};
use tf_demo_parser::demo::vector::VectorXY;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct Angle(u8);
impl From<f32> for Angle {
fn from(val: f32) -> Self {
let ratio = val.rem_euclid(360.0) / 360.0;
Angle((ratio * u8::max_value() as f32) as u8)
}
}
impl From<Angle> for f32 {
fn from(val: Angle) -> Self {
let ratio = val.0 as f32 / u8::max_value() as f32;
ratio * 360.0
}
}
#[derive(Debug)]
pub struct ParsedDemo {
last_tick: DemoTick,
pub tick: usize,
pub players: Vec<Vec<u8>>,
pub buildings: Vec<Vec<u8>>,
pub kills: Vec<Kill>,
pub header: Header,
pub player_info: Vec<UserInfo>,
pub max_building_count: usize,
}
impl ParsedDemo {
pub fn new(header: Header) -> Self {
ParsedDemo {
last_tick: DemoTick::default(),
tick: 0,
players: Vec::new(),
buildings: Vec::new(),
kills: Vec::new(),
player_info: Vec::new(),
max_building_count: 0,
header,
}
}
pub fn push_state(&mut self, game_state: &GameState) {
if let Some(world) = game_state.world.as_ref() {
for _tick in u32::from(self.last_tick)..u32::from(game_state.tick) {
for (index, player) in game_state.players.iter().enumerate() {
let state = PlayerState {
position: player.position.into(),
angle: Angle::from(player.view_angle),
health: if player.state == PlayerAliveState::Alive {
player.health
} else {
0
},
team: player.team,
class: player.class,
charge: player.charge,
};
if let None = self.players.get(index) {
let mut new_player = Vec::with_capacity(
self.header.ticks as usize * PlayerState::PACKET_SIZE,
);
// backfill with defaults
new_player.resize(self.tick * PlayerState::PACKET_SIZE, 0);
self.players.push(new_player);
};
match (self.player_info.get(index), player.info.as_ref()) {
(None, Some(info)) => self.player_info.push(info.clone()),
_ => {}
}
let parsed_player = &mut self.players[index];
parsed_player.extend_from_slice(&state.pack(world));
}
self.max_building_count = self.max_building_count.max(game_state.buildings.len());
for (index, building) in game_state.buildings.values().enumerate() {
let state = BuildingState::new(building);
if let None = self.buildings.get(index) {
let new_building = Vec::with_capacity(
self.header.ticks as usize * BuildingState::PACKET_SIZE,
);
self.buildings.push(new_building);
};
let parsed_building = &mut self.buildings[index];
parsed_building.resize(self.tick * BuildingState::PACKET_SIZE, 0);
parsed_building.extend_from_slice(&state.pack(world));
}
self.tick += 1;
}
self.last_tick = game_state.tick;
}
}
pub fn finish(&mut self) {
for parsed_building in self.buildings.iter_mut() {
parsed_building.resize(self.tick * BuildingState::PACKET_SIZE, 0);
}
}
pub fn size(&self) -> usize {
self.players
.iter()
.fold(0, |size, player| size + player.len())
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct PlayerState {
position: VectorXY,
angle: Angle,
health: u16,
team: Team,
class: Class,
charge: u8,
}
impl PlayerState {
const PACKET_SIZE: usize = 8;
pub fn pack(&self, world: &World) -> [u8; Self::PACKET_SIZE] {
// for the purpose of viewing the demo in the browser we dont really need high accuracy for
// position or angle, so we save a bunch of space by truncating those down to half the number
// of bits
fn pack_f32(val: f32, min: f32, max: f32) -> u16 {
let ratio = (val - min) / (max - min);
(ratio * u16::max_value() as f32) as u16
}
let x = pack_f32(self.position.x, world.boundary_min.x, world.boundary_max.x).to_le_bytes();
let y = pack_f32(self.position.y, world.boundary_min.y, world.boundary_max.y).to_le_bytes();
// 2 bits for team
// 4 bits for class
// 10 bits for health
let team_class_health =
((self.team as u16) << 14) + ((self.class as u16) << 10) + self.health;
let combined_bytes = team_class_health.to_le_bytes();
[
x[0],
x[1],
y[0],
y[1],
combined_bytes[0],
combined_bytes[1],
self.angle.0,
self.charge,
]
}
#[allow(dead_code)]
pub fn unpack(bytes: [u8; 8], world: &World) -> Self {
fn unpack_f32(val: u16, min: f32, max: f32) -> f32 {
let ratio = val as f32 / (u16::max_value() as f32);
ratio * (max - min) + min
}
let x = unpack_f32(
u16::from_le_bytes([bytes[0], bytes[1]]),
world.boundary_min.x,
world.boundary_max.x,
);
let y = unpack_f32(
u16::from_le_bytes([bytes[2], bytes[3]]),
world.boundary_min.y,
world.boundary_max.y,
);
let team_class_health = u16::from_le_bytes([bytes[4], bytes[5]]);
let health = team_class_health & 1023;
let angle = Angle(bytes[6]);
let team = Team::new(team_class_health >> 14);
let class = Class::new((team_class_health >> 10) & 15);
let charge = bytes[7];
PlayerState {
position: VectorXY { x, y },
angle,
health,
team,
class,
charge,
}
}
}
#[test]
fn test_player_packing() {
use tf_demo_parser::demo::vector::Vector;
let world = World {
boundary_max: Vector {
x: 10000.0,
y: 10000.0,
z: 100.0,
},
boundary_min: Vector {
x: -10000.0,
y: -10000.0,
z: -100.0,
},
};
let input = PlayerState {
position: VectorXY {
x: 100.0,
y: -5000.0,
},
angle: Angle::from(213.0),
health: 250,
team: Team::Blue,
class: Class::Demoman,
charge: 7,
};
let bytes = input.pack(&world);
let unpacked = PlayerState::unpack(bytes, &world);
assert_eq!(input.angle, unpacked.angle);
assert_eq!(input.health, unpacked.health);
assert_eq!(input.class, unpacked.class);
assert_eq!(input.team, unpacked.team);
assert_eq!(input.charge, unpacked.charge);
assert!(f32::abs(input.position.x - unpacked.position.x) < 0.5);
assert!(f32::abs(input.position.y - unpacked.position.y) < 0.5);
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(u8)]
pub enum BuildingType {
TeleporterEntrance = 0,
TeleporterExit = 1,
Dispenser = 2,
Level1Sentry = 3,
Level2Sentry = 4,
Level3Sentry = 5,
MiniSentry = 6,
Unknown = 7,
}
impl Default for BuildingType {
fn default() -> Self {
BuildingType::Unknown
}
}
impl BuildingType {
pub fn new(raw: u8) -> BuildingType {
match raw {
0 => Self::TeleporterEntrance,
1 => Self::TeleporterExit,
2 => Self::Dispenser,
3 => Self::Level1Sentry,
4 => Self::Level2Sentry,
5 => Self::Level3Sentry,
6 => Self::MiniSentry,
_ => Self::Unknown,
}
}
pub fn from_building(building: &Building) -> Self {
match building {
Building::Sentry(Sentry { is_mini: true, .. }) => BuildingType::MiniSentry,
Building::Sentry(Sentry {
is_mini: false,
level: 1,
..
}) => BuildingType::Level1Sentry,
Building::Sentry(Sentry {
is_mini: false,
level: 2,
..
}) => BuildingType::Level2Sentry,
Building::Sentry(Sentry {
is_mini: false,
level: 3,
..
}) => BuildingType::Level3Sentry,
Building::Dispenser(Dispenser { .. }) => BuildingType::Dispenser,
Building::Teleporter(Teleporter {
is_entrance: true, ..
}) => BuildingType::TeleporterEntrance,
Building::Teleporter(Teleporter {
is_entrance: false, ..
}) => BuildingType::TeleporterExit,
_ => BuildingType::Unknown,
}
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct BuildingState {
position: VectorXY,
angle: Angle,
health: u16,
team: Team,
ty: BuildingType,
level: u8,
}
impl BuildingState {
const PACKET_SIZE: usize = 7;
pub fn new(building: &Building) -> Self {
let position = building.position();
BuildingState {
position: VectorXY {
x: position.x,
y: position.y,
},
angle: Angle::from(building.angle()),
health: building.health(),
team: building.team(),
ty: BuildingType::from_building(building),
level: building.level(),
}
}
pub fn pack(&self, world: &World) -> [u8; 7] {
// for the purpose of viewing the demo in the browser we dont really need high accuracy for
// position or angle, so we save a bunch of space by truncating those down to half the number
// of bits
fn pack_f32(val: f32, min: f32, max: f32) -> u16 {
let ratio = (val - min) / (max - min);
(ratio * u16::max_value() as f32) as u16
}
let x = pack_f32(self.position.x, world.boundary_min.x, world.boundary_max.x).to_le_bytes();
let y = pack_f32(self.position.y, world.boundary_min.y, world.boundary_max.y).to_le_bytes();
// 2 bits level
// 1 bit team
// 3 bits for type
// 10 bits for health
let team = if self.team == Team::Blue { 0 } else { 1 };
let team_type_health = ((self.level as u16) << 14)
+ ((team as u16) << 13)
+ ((self.ty as u16) << 10)
+ self.health;
let combined_bytes = team_type_health.to_le_bytes();
[
x[0],
x[1],
y[0],
y[1],
combined_bytes[0],
combined_bytes[1],
self.angle.0,
]
}
#[allow(dead_code)]
pub fn unpack(bytes: [u8; 7], world: &World) -> Self {
fn unpack_f32(val: u16, min: f32, max: f32) -> f32 {
let ratio = val as f32 / (u16::max_value() as f32);
ratio * (max - min) + min
}
let x = unpack_f32(
u16::from_le_bytes([bytes[0], bytes[1]]),
world.boundary_min.x,
world.boundary_max.x,
);
let y = unpack_f32(
u16::from_le_bytes([bytes[2], bytes[3]]),
world.boundary_min.y,
world.boundary_max.y,
);
let team_type_health = u16::from_le_bytes([bytes[4], bytes[5]]);
let health = team_type_health & 1023;
let angle = Angle(bytes[6]);
let packed_team = (team_type_health >> 13) & 1;
let team = if packed_team == 0 {
Team::Blue
} else {
Team::Red
};
let ty = BuildingType::new((team_type_health >> 10) as u8 & 7);
let level = (team_type_health >> 14) as u8;
BuildingState {
position: VectorXY { x, y },
angle,
health,
team,
ty,
level,
}
}
}
#[test]
fn test_building_packing() {
use tf_demo_parser::demo::vector::Vector;
let world = World {
boundary_max: Vector {
x: 10000.0,
y: 10000.0,
z: 100.0,
},
boundary_min: Vector {
x: -10000.0,
y: -10000.0,
z: -100.0,
},
};
let input = BuildingState {
position: VectorXY {
x: 100.0,
y: -5000.0,
},
angle: Angle::from(213.0),
health: 250,
team: Team::Blue,
level: 3,
ty: BuildingType::Level1Sentry,
};
let bytes = input.pack(&world);
let unpacked = BuildingState::unpack(bytes, &world);
assert_eq!(input.angle, unpacked.angle);
assert_eq!(input.health, unpacked.health);
assert_eq!(input.ty, unpacked.ty);
assert_eq!(input.team, unpacked.team);
assert_eq!(input.level, unpacked.level);
assert!(f32::abs(input.position.x - unpacked.position.x) < 0.5);
assert!(f32::abs(input.position.y - unpacked.position.y) < 0.5);
}

35
wasm/tests/app.rs Normal file
View file

@ -0,0 +1,35 @@
use wasm_bindgen_test::{wasm_bindgen_test_configure, wasm_bindgen_test};
use futures::prelude::*;
use wasm_bindgen::JsValue;
use wasm_bindgen_futures::JsFuture;
wasm_bindgen_test_configure!(run_in_browser);
// This runs a unit test in native Rust, so it can only use Rust APIs.
#[test]
fn rust_test() {
assert_eq!(1, 1);
}
// This runs a unit test in the browser, so it can use browser APIs.
#[wasm_bindgen_test]
fn web_test() {
assert_eq!(1, 1);
}
// This runs a unit test in the browser, and in addition it supports asynchronous Future APIs.
#[wasm_bindgen_test(async)]
fn async_test() -> impl Future<Item = (), Error = JsValue> {
// Creates a JavaScript Promise which will asynchronously resolve with the value 42.
let promise = js_sys::Promise::resolve(&JsValue::from(42));
// Converts that Promise into a Future.
// The unit test will wait for the Future to resolve.
JsFuture::from(promise)
.map(|x| {
assert_eq!(x, 42);
})
}