handle logs with some broken nulls

This commit is contained in:
Robin Appelman 2024-02-10 12:53:50 +01:00
commit ff82fc9eb8
14 changed files with 13621 additions and 112 deletions

488
Cargo.lock generated
View file

@ -22,6 +22,21 @@ dependencies = [
"memchr", "memchr",
] ]
[[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]] [[package]]
name = "ansi_term" name = "ansi_term"
version = "0.12.1" version = "0.12.1"
@ -31,6 +46,12 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "anyhow"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
[[package]] [[package]]
name = "atoi" name = "atoi"
version = "1.0.0" version = "1.0.0"
@ -52,6 +73,12 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "base64"
version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
@ -87,9 +114,12 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.73" version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -99,18 +129,37 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.19" version = "0.4.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb"
dependencies = [ dependencies = [
"libc", "android-tzdata",
"num-integer", "iana-time-zone",
"js-sys",
"num-traits 0.2.15", "num-traits 0.2.15",
"serde", "serde",
"time", "wasm-bindgen",
"winapi", "windows-targets",
] ]
[[package]]
name = "console"
version = "0.15.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]] [[package]]
name = "cpufeatures" name = "cpufeatures"
version = "0.2.2" version = "0.2.2"
@ -150,6 +199,51 @@ dependencies = [
"typenum", "typenum",
] ]
[[package]]
name = "darling"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc5d6b04b3fd0ba9926f945895de7d806260a2d7431ba82e7edaecb043c4c6b8"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04e48a959bcd5c761246f5d090ebc2fbf7b9cd527a492b07a67510c108f1e7e3"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 2.0.48",
]
[[package]]
name = "darling_macro"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d1545d67a2149e1d93b7e5c7752dce5a7426eb5d1357ddcfd89336b94444f77"
dependencies = [
"darling_core",
"quote",
"syn 2.0.48",
]
[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
"serde",
]
[[package]] [[package]]
name = "digest" name = "digest"
version = "0.10.3" version = "0.10.3"
@ -196,6 +290,12 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]] [[package]]
name = "enum_primitive" name = "enum_primitive"
version = "0.1.1" version = "0.1.1"
@ -205,12 +305,24 @@ dependencies = [
"num-traits 0.1.43", "num-traits 0.1.43",
] ]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]] [[package]]
name = "event-listener" name = "event-listener"
version = "2.5.2" version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71"
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]] [[package]]
name = "form_urlencoded" name = "form_urlencoded"
version = "1.0.1" version = "1.0.1"
@ -309,6 +421,12 @@ dependencies = [
"ahash", "ahash",
] ]
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]] [[package]]
name = "hashlink" name = "hashlink"
version = "0.8.0" version = "0.8.0"
@ -360,6 +478,35 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "iana-time-zone"
version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
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]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "idna" name = "idna"
version = "0.2.3" version = "0.2.3"
@ -379,6 +526,33 @@ checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"hashbrown 0.11.2", "hashbrown 0.11.2",
"serde",
]
[[package]]
name = "indexmap"
version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520"
dependencies = [
"equivalent",
"hashbrown 0.14.3",
"serde",
]
[[package]]
name = "insta"
version = "1.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d64600be34b2fcfc267740a243fa7744441bb4947a619ac4e5bb6507f35fbfc"
dependencies = [
"console",
"lazy_static",
"linked-hash-map",
"ron",
"serde",
"similar",
"yaml-rust",
] ]
[[package]] [[package]]
@ -426,6 +600,12 @@ version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.7" version = "0.4.7"
@ -449,11 +629,14 @@ dependencies = [
name = "log-analyser" name = "log-analyser"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow",
"chrono", "chrono",
"dotenv", "dotenv",
"insta",
"main_error", "main_error",
"serde", "serde",
"serde_json", "serde_json",
"serde_with",
"sqlx", "sqlx",
"steamid-ng", "steamid-ng",
"test-case", "test-case",
@ -504,7 +687,7 @@ dependencies = [
"libc", "libc",
"log", "log",
"wasi 0.11.0+wasi-snapshot-preview1", "wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys", "windows-sys 0.36.1",
] ]
[[package]] [[package]]
@ -551,6 +734,12 @@ dependencies = [
"num-traits 0.2.15", "num-traits 0.2.15",
] ]
[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.45" version = "0.1.45"
@ -667,50 +856,32 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.16" version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[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]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.39" version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.18" version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -797,6 +968,17 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "ron"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
dependencies = [
"base64 0.13.0",
"bitflags",
"serde",
]
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.20.6" version = "0.20.6"
@ -815,7 +997,7 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9"
dependencies = [ dependencies = [
"base64", "base64 0.13.0",
] ]
[[package]] [[package]]
@ -842,22 +1024,22 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.140" version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03" checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.140" version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da" checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -871,6 +1053,36 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_with"
version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270"
dependencies = [
"base64 0.21.7",
"chrono",
"hex",
"indexmap 1.8.2",
"indexmap 2.2.2",
"serde",
"serde_derive",
"serde_json",
"serde_with_macros",
"time",
]
[[package]]
name = "serde_with_macros"
version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "865f9743393e638991566a8b7a479043c2c8da94a33e0a31f18214c9cae0a64d"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]] [[package]]
name = "sha-1" name = "sha-1"
version = "0.10.0" version = "0.10.0"
@ -902,6 +1114,12 @@ dependencies = [
"lazy_static", "lazy_static",
] ]
[[package]]
name = "similar"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21"
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.8.0" version = "1.8.0"
@ -953,7 +1171,7 @@ checksum = "6b69bf218860335ddda60d6ce85ee39f6cf6e5630e300e19757d1de15886a093"
dependencies = [ dependencies = [
"ahash", "ahash",
"atoi", "atoi",
"base64", "base64 0.13.0",
"bitflags", "bitflags",
"byteorder", "byteorder",
"bytes", "bytes",
@ -970,7 +1188,7 @@ dependencies = [
"hex", "hex",
"hkdf", "hkdf",
"hmac", "hmac",
"indexmap", "indexmap 1.8.2",
"itoa", "itoa",
"libc", "libc",
"log", "log",
@ -1015,7 +1233,7 @@ dependencies = [
"sha2", "sha2",
"sqlx-core", "sqlx-core",
"sqlx-rt", "sqlx-rt",
"syn", "syn 1.0.96",
"url", "url",
] ]
@ -1055,6 +1273,12 @@ dependencies = [
"unicode-normalization", "unicode-normalization",
] ]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "subtle" name = "subtle"
version = "2.4.1" version = "2.4.1"
@ -1073,25 +1297,47 @@ dependencies = [
] ]
[[package]] [[package]]
name = "test-case" name = "syn"
version = "2.2.1" version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07aea929e9488998b64adc414c29fe5620398f01c2e3f58164122b17e567a6d5" checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "test-case"
version = "3.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8"
dependencies = [ dependencies = [
"test-case-macros", "test-case-macros",
] ]
[[package]] [[package]]
name = "test-case-macros" name = "test-case-core"
version = "2.2.1" version = "3.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c95968eedc6fc4f5c21920e0f4264f78ec5e4c56bb394f319becc1a5830b3e54" checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"proc-macro-error",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.48",
]
[[package]]
name = "test-case-macros"
version = "3.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"test-case-core",
] ]
[[package]] [[package]]
@ -1111,7 +1357,7 @@ checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.96",
] ]
[[package]] [[package]]
@ -1125,13 +1371,33 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.1.44" version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
dependencies = [ dependencies = [
"libc", "deranged",
"wasi 0.10.0+wasi-snapshot-preview1", "itoa",
"winapi", "num-conv",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
dependencies = [
"num-conv",
"time-core",
] ]
[[package]] [[package]]
@ -1176,7 +1442,7 @@ checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.96",
] ]
[[package]] [[package]]
@ -1221,7 +1487,7 @@ checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.96",
] ]
[[package]] [[package]]
@ -1361,7 +1627,7 @@ dependencies = [
"log", "log",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.96",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -1383,7 +1649,7 @@ checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.96",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -1455,45 +1721,129 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.36.1" version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [ dependencies = [
"windows_aarch64_msvc", "windows_aarch64_msvc 0.36.1",
"windows_i686_gnu", "windows_i686_gnu 0.36.1",
"windows_i686_msvc", "windows_i686_msvc 0.36.1",
"windows_x86_64_gnu", "windows_x86_64_gnu 0.36.1",
"windows_x86_64_msvc", "windows_x86_64_msvc 0.36.1",
] ]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc 0.52.0",
"windows_i686_gnu 0.52.0",
"windows_i686_msvc 0.52.0",
"windows_x86_64_gnu 0.52.0",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc 0.52.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.36.1" version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.36.1" version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.36.1" version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_i686_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.36.1" version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.36.1" version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]]
name = "yaml-rust"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [
"linked-hash-map",
]

View file

@ -14,9 +14,14 @@ dotenv = "0.15.0"
main_error = "0.1.2" main_error = "0.1.2"
tokio = { version = "1.20.0", features = ["macros", "time"] } tokio = { version = "1.20.0", features = ["macros", "time"] }
serde = { version = "1.0.140", features = ["derive"] } serde = { version = "1.0.140", features = ["derive"] }
serde_with = "3.6.1"
serde_json = "1.0.82" serde_json = "1.0.82"
chrono = { version = "0.4.19", features = ["serde"] } chrono = { version = "0.4.19", features = ["serde"] }
steamid-ng = "1.0.0" steamid-ng = "1.0.0"
test-case = "2.2.1"
tracing = "0.1.35" tracing = "0.1.35"
tracing-subscriber = "0.3.15" tracing-subscriber = "0.3.15"
anyhow = "1.0.79"
[dev-dependencies]
insta = { version = "1.34.0", features = ["ron"] }
test-case = "3.3.1"

11
flake.lock generated
View file

@ -47,13 +47,16 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 0, "lastModified": 1707514827,
"narHash": "sha256-WbZKCf6g4+dljZ6Z866SGZzNA+WWjXt4Lc7td4zsRkw=", "narHash": "sha256-Y+wqFkvikpE1epCx57PsGw+M1hX5aY5q/xgk+ebDwxI=",
"path": "/nix/store/vavqvhqw8x42kqb1m3wkcys65jvvnl5i-source", "owner": "NixOS",
"type": "path" "repo": "nixpkgs",
"rev": "20f65b86b6485decb43c5498780c223571dd56ef",
"type": "github"
}, },
"original": { "original": {
"id": "nixpkgs", "id": "nixpkgs",
"ref": "release-23.11",
"type": "indirect" "type": "indirect"
} }
}, },

View file

@ -1,5 +1,6 @@
{ {
inputs = { inputs = {
nixpkgs.url = "nixpkgs/release-23.11";
flake-utils.url = "github:numtide/flake-utils"; flake-utils.url = "github:numtide/flake-utils";
naersk.url = "github:nix-community/naersk"; naersk.url = "github:nix-community/naersk";
}; };
@ -27,7 +28,7 @@
# `nix develop` # `nix develop`
devShell = pkgs.mkShell { devShell = pkgs.mkShell {
nativeBuildInputs = with pkgs; [rustc cargo bacon cargo-edit cargo-outdated]; nativeBuildInputs = with pkgs; [rustc cargo bacon cargo-edit cargo-outdated cargo-insta];
}; };
} }
) )

View file

@ -1,6 +1,6 @@
use serde::Deserialize; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Eq, PartialEq)] #[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Serialize, Eq, PartialEq)]
#[sqlx(type_name = "team")] #[sqlx(type_name = "team")]
#[sqlx(rename_all = "lowercase")] #[sqlx(rename_all = "lowercase")]
pub enum TeamId { pub enum TeamId {
@ -16,7 +16,7 @@ impl Default for TeamId {
} }
} }
#[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Eq, PartialEq)] #[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Serialize, Eq, PartialEq)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
#[sqlx(rename_all = "lowercase")] #[sqlx(rename_all = "lowercase")]
#[sqlx(type_name = "class_type")] #[sqlx(type_name = "class_type")]
@ -51,7 +51,7 @@ pub enum GameMode {
Other, Other,
} }
#[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Eq, PartialEq)] #[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Serialize, Eq, PartialEq)]
pub enum EventType { pub enum EventType {
Charge, Charge,
PointCap, PointCap,
@ -61,7 +61,7 @@ pub enum EventType {
Other, Other,
} }
#[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Hash, Eq, PartialEq)] #[derive(Debug, Clone, Copy, sqlx::Type, Deserialize, Serialize, Hash, Eq, PartialEq)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
#[sqlx(rename_all = "lowercase")] #[sqlx(rename_all = "lowercase")]
pub enum Medigun { pub enum Medigun {

View file

@ -1,10 +1,11 @@
mod data; mod data;
mod database; mod database;
mod normalized; mod normalized;
mod raw; pub mod raw;
use crate::database::{store_log, upgrade}; use crate::database::{store_log, upgrade};
use crate::normalized::NormalizedLog; use crate::normalized::NormalizedLog;
use anyhow::{Context, Error};
use main_error::MainError; use main_error::MainError;
use sqlx::pool::PoolOptions; use sqlx::pool::PoolOptions;
use sqlx::PgPool; use sqlx::PgPool;
@ -26,19 +27,27 @@ async fn main() -> Result<(), MainError> {
} }
} }
async fn normalize(database_url: &str, raw_database_url: &str) -> Result<(), MainError> { async fn normalize(database_url: &str, raw_database_url: &str) -> Result<(), Error> {
let pool = PoolOptions::new() let pool = PoolOptions::new()
.max_connections(2) .max_connections(2)
.connect(database_url) .connect(database_url)
.await?; .await
.context("Failed to connect to log database")?;
let raw_pool = PoolOptions::new() let raw_pool = PoolOptions::new()
.max_connections(2) .max_connections(2)
.connect(raw_database_url) .connect(raw_database_url)
.await?; .await
.context("Failed to connect to raw log database")?;
let max = get_max_log(&raw_pool).await?; let max = get_max_log(&raw_pool)
let old = get_min_old_stored_log(&pool, VERSION).await?; .await
let from = get_max_stored_log(&pool).await?; .context("Failed to get max raw log")?;
let old = get_min_old_stored_log(&pool, VERSION)
.await
.context("Failed to get min processed old log")?;
let from = get_max_stored_log(&pool)
.await
.context("Failed to get min processed log")?;
if let Some(old) = old { if let Some(old) = old {
for id in old..=from { for id in old..=from {
@ -63,7 +72,7 @@ async fn normalize(database_url: &str, raw_database_url: &str) -> Result<(), Mai
Ok(()) Ok(())
} }
async fn get_min_old_stored_log(pool: &PgPool, version: i16) -> Result<Option<i32>, MainError> { async fn get_min_old_stored_log(pool: &PgPool, version: i16) -> Result<Option<i32>, Error> {
Ok(sqlx::query!( Ok(sqlx::query!(
r#"SELECT MIN(id) as "id" from logs WHERE version < $1"#, r#"SELECT MIN(id) as "id" from logs WHERE version < $1"#,
version version
@ -73,7 +82,7 @@ async fn get_min_old_stored_log(pool: &PgPool, version: i16) -> Result<Option<i3
.and_then(|row| row.id)) .and_then(|row| row.id))
} }
async fn get_max_stored_log(pool: &PgPool) -> Result<i32, MainError> { async fn get_max_stored_log(pool: &PgPool) -> Result<i32, Error> {
Ok(sqlx::query!(r#"SELECT MAX(id) as id from logs"#) Ok(sqlx::query!(r#"SELECT MAX(id) as id from logs"#)
.fetch_one(pool) .fetch_one(pool)
.await? .await?
@ -81,7 +90,7 @@ async fn get_max_stored_log(pool: &PgPool) -> Result<i32, MainError> {
.unwrap_or_default()) .unwrap_or_default())
} }
async fn get_max_log(pool: &PgPool) -> Result<i32, MainError> { async fn get_max_log(pool: &PgPool) -> Result<i32, Error> {
let row: (i32,) = sqlx::query_as(r#"SELECT MAX(id) as id from logs_raw"#) let row: (i32,) = sqlx::query_as(r#"SELECT MAX(id) as id from logs_raw"#)
.fetch_one(pool) .fetch_one(pool)
.await?; .await?;
@ -89,12 +98,13 @@ async fn get_max_log(pool: &PgPool) -> Result<i32, MainError> {
} }
#[instrument(skip(pool))] #[instrument(skip(pool))]
async fn get_log(pool: &PgPool, id: i32) -> Result<Option<NormalizedLog>, MainError> { async fn get_log(pool: &PgPool, id: i32) -> Result<Option<NormalizedLog>, Error> {
let row: (serde_json::Value,) = let row: (serde_json::Value,) =
sqlx::query_as(r#"SELECT json as id from logs_raw where id = $1"#) sqlx::query_as(r#"SELECT json as id from logs_raw where id = $1"#)
.bind(id) .bind(id)
.fetch_one(pool) .fetch_one(pool)
.await?; .await
.context("failed to get raw log")?;
if is_valid(&row.0) { if is_valid(&row.0) {
match serde_json::from_value(row.0) { match serde_json::from_value(row.0) {
@ -114,7 +124,7 @@ async fn get_log(pool: &PgPool, id: i32) -> Result<Option<NormalizedLog>, MainEr
if formatted_err.starts_with("invalid type: floating point") { if formatted_err.starts_with("invalid type: floating point") {
return Ok(None); return Ok(None);
} }
Err(err.into()) Err(err).context("failed parse raw log")
} }
} }
} else { } else {

View file

@ -1,10 +1,11 @@
use crate::data::{Class, Medigun, TeamId}; use crate::data::{Class, Medigun, TeamId};
use serde::Deserialize; use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DefaultOnNull};
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use steamid_ng::SteamID; use steamid_ng::SteamID;
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RawLog { pub struct RawLog {
#[serde(default)] #[serde(default)]
pub version: u8, pub version: u8,
@ -28,71 +29,100 @@ pub struct RawLog {
pub kill_streaks: Option<Vec<KillStreak>>, pub kill_streaks: Option<Vec<KillStreak>>,
} }
#[derive(Debug, Clone, Deserialize, Default)] #[derive(Debug, Clone, Deserialize, Serialize, Default)]
#[serde(rename_all = "PascalCase")] #[serde(rename_all = "PascalCase")]
pub struct Teams { pub struct Teams {
pub red: Team, pub red: Team,
pub blue: Team, pub blue: Team,
} }
#[derive(Debug, Clone, Deserialize, Default)] #[serde_as]
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct Team { pub struct Team {
#[serde_as(deserialize_as = "DefaultOnNull")]
pub score: u32, pub score: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub kills: u32, pub kills: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub deaths: u32, pub deaths: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub dmg: u32, pub dmg: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub charges: u32, pub charges: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub drops: u32, pub drops: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub firstcaps: u32, pub firstcaps: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub caps: u32, pub caps: u32,
} }
#[derive(Debug, Clone, Deserialize)] #[serde_as]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Player { pub struct Player {
pub class_stats: Vec<ClassStat>, pub class_stats: Vec<ClassStat>,
pub team: Option<TeamId>, pub team: Option<TeamId>,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub kills: u16, pub kills: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub deaths: u16, pub deaths: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub assists: u16, pub assists: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub suicides: u16, pub suicides: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub dmg: u32, pub dmg: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub dmg_real: u32, pub dmg_real: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub dt: u32, pub dt: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub dt_real: u32, pub dt_real: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub hr: u16, pub hr: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub lks: u16, pub lks: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub ubers: u32, pub ubers: u32,
#[serde(default)] #[serde(default)]
pub ubertypes: HashMap<Medigun, u32>, pub ubertypes: HashMap<Medigun, u32>,
pub drops: u32, pub drops: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub medkits: u32, pub medkits: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub medkits_hp: u16, pub medkits_hp: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub backstabs: u32, pub backstabs: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub headshots: u32, pub headshots: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub headshots_hit: u32, pub headshots_hit: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub heal: u32, pub heal: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub cpc: u32, pub cpc: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub ic: u32, pub ic: u32,
pub medicstat: Option<MedicStats>, pub medicstat: Option<MedicStats>,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct MedicStats { pub struct MedicStats {
pub advantages_lost: u32, pub advantages_lost: u32,
pub biggest_advantage_list: u16, pub biggest_advantage_list: u16,
@ -104,34 +134,47 @@ pub struct MedicStats {
pub avg_uber_length: f32, pub avg_uber_length: f32,
} }
#[derive(Debug, Clone, Deserialize)] #[serde_as]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ClassStat { pub struct ClassStat {
#[serde(rename = "type")] #[serde(rename = "type")]
pub class: Class, pub class: Class,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub kills: u16, pub kills: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub assists: u16, pub assists: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub deaths: u16, pub deaths: u16,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub dmg: u32, pub dmg: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub total_time: u32, pub total_time: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
pub weapon: HashMap<String, WeaponStat>, pub weapon: HashMap<String, WeaponStat>,
} }
#[derive(Debug, Clone, Deserialize)] #[serde_as]
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)] #[serde(untagged)]
pub enum RawWeaponStats { pub enum RawWeaponStats {
Kills(u32), Kills(u32),
Stats { Stats {
#[serde_as(deserialize_as = "DefaultOnNull")]
kills: u32, kills: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
dmg: i64, dmg: i64,
#[serde_as(deserialize_as = "DefaultOnNull")]
#[serde(default)] #[serde(default)]
avg_dmg: f32, avg_dmg: f32,
#[serde_as(deserialize_as = "DefaultOnNull")]
shots: u32, shots: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
hits: u32, hits: u32,
}, },
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(from = "RawWeaponStats")] #[serde(from = "RawWeaponStats")]
pub struct WeaponStat { pub struct WeaponStat {
pub kills: u32, pub kills: u32,
@ -176,7 +219,7 @@ impl From<RawWeaponStats> for WeaponStat {
} }
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Round { pub struct Round {
#[serde(default)] #[serde(default)]
pub start_time: u64, pub start_time: u64,
@ -191,13 +234,16 @@ pub struct Round {
pub events: Vec<Event>, pub events: Vec<Event>,
} }
#[derive(Debug, Clone, Deserialize)] #[serde_as]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RoundPlayer { pub struct RoundPlayer {
#[serde_as(deserialize_as = "DefaultOnNull")]
pub kills: u32, pub kills: u32,
#[serde_as(deserialize_as = "DefaultOnNull")]
pub dmg: u32, pub dmg: u32,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(tag = "type")] #[serde(tag = "type")]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum Event { pub enum Event {
@ -246,7 +292,7 @@ impl Event {
} }
} }
#[derive(Debug, Clone, Deserialize, Default)] #[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct ClassNumbers { pub struct ClassNumbers {
#[serde(default)] #[serde(default)]
pub scout: u32, pub scout: u32,
@ -268,14 +314,14 @@ pub struct ClassNumbers {
pub spy: u32, pub spy: u32,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ChatMessage { pub struct ChatMessage {
pub steamid: ChatFrom, pub steamid: ChatFrom,
pub name: String, pub name: String,
pub msg: String, pub msg: String,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)] #[serde(untagged)]
#[serde(try_from = "String")] #[serde(try_from = "String")]
pub enum ChatFrom { pub enum ChatFrom {
@ -295,7 +341,7 @@ impl TryFrom<String> for ChatFrom {
} }
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Info { pub struct Info {
pub map: String, pub map: String,
pub total_length: u32, pub total_length: u32,
@ -340,14 +386,14 @@ pub struct Info {
pub teams: Option<Teams>, pub teams: Option<Teams>,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Uploader { pub struct Uploader {
pub id: SteamID, pub id: SteamID,
pub name: String, pub name: String,
pub info: Option<String>, pub info: Option<String>,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct KillStreak { pub struct KillStreak {
pub steamid: SteamID, pub steamid: SteamID,
pub streak: i32, pub streak: i32,
@ -364,14 +410,24 @@ mod tests {
#[test_case("134389.json")] #[test_case("134389.json")]
#[test_case("550237.json")] #[test_case("550237.json")]
#[test_case("2522305.json")] #[test_case("2522305.json")]
#[test_case("3578739.json")]
fn test_parse(file: &str) { fn test_parse(file: &str) {
let content = fs::read_to_string(format!("tests/data/{}", file)).unwrap(); let content = fs::read_to_string(format!("tests/data/{}", file)).unwrap();
let parsed: RawLog = serde_json::from_str(&content).unwrap(); let parsed: RawLog = serde_json::from_str(&content).unwrap();
assert!(parsed.teams.is_some() || parsed.info.teams.is_some()); assert!(parsed.teams.is_some() || parsed.info.teams.is_some());
assert!(parsed.rounds.is_some() || parsed.info.rounds.is_some()); assert!(parsed.rounds.is_some() || parsed.info.rounds.is_some());
for round in parsed.rounds.or(parsed.info.rounds).unwrap() { for round in parsed
.rounds
.as_ref()
.or(parsed.info.rounds.as_ref())
.unwrap()
{
assert!(round.flat_team.is_some() || round.team.is_some()); assert!(round.flat_team.is_some() || round.team.is_some());
} }
insta::with_settings!({sort_maps => true, snapshot_path => "../tests/data/snapshots"}, {
insta::assert_ron_snapshot!(file, parsed);
});
} }
} }

1806
tests/data/3578739.json Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file