From 8c70077e4a22228100b340facfd46ef6770c348d Mon Sep 17 00:00:00 2001 From: Celeo Date: Thu, 16 Jan 2025 16:46:59 -0800 Subject: [PATCH 1/2] Rewrite WIP --- Cargo.lock | 778 ++++++++++++++++++++++++++++--------------------- Cargo.toml | 24 +- faa/Cargo.toml | 7 - faa/src/lib.rs | 113 ------- src/faa.rs | 113 +++++++ src/main.rs | 304 +++++++++---------- src/models.rs | 45 +++ 7 files changed, 758 insertions(+), 626 deletions(-) delete mode 100644 faa/Cargo.toml delete mode 100644 faa/src/lib.rs create mode 100644 src/faa.rs create mode 100644 src/models.rs diff --git a/Cargo.lock b/Cargo.lock index 30087b6..2243fba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -18,16 +18,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] -name = "ahash" -version = "0.8.7" +name = "aho-corasick" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ - "cfg-if", - "getrandom", - "once_cell", - "version_check", - "zerocopy", + "memchr", ] [[package]] @@ -53,9 +49,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "atoi" @@ -67,14 +63,10 @@ dependencies = [ ] [[package]] -name = "atomic-write-file" -version = "0.1.2" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edcdbedc2236483ab103a53415653d6b4442ea6141baf1ffa85df29635e88436" -dependencies = [ - "nix", - "rand", -] +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" @@ -99,9 +91,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.21.7" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" @@ -147,9 +139,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" @@ -173,8 +165,9 @@ dependencies = [ "anyhow", "chrono", "dotenv", - "faa", - "futures", + "itertools", + "log", + "pretty_env_logger", "reqwest", "serde", "serde-xml-rs", @@ -184,16 +177,25 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.33" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", ] [[package]] @@ -320,6 +322,19 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -328,9 +343,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", "windows-sys 0.52.0", @@ -349,22 +364,20 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.3" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "faa" -version = "0.1.0" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" dependencies = [ - "chrono", + "concurrent-queue", + "parking", + "pin-project-lite", ] [[package]] name = "fastrand" -version = "2.0.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "finl_unicode" @@ -389,6 +402,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + [[package]] name = "foreign-types" version = "0.3.2" @@ -413,21 +432,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - [[package]] name = "futures-channel" version = "0.3.30" @@ -472,17 +476,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "futures-sink" version = "0.3.30" @@ -501,10 +494,8 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ - "futures-channel", "futures-core", "futures-io", - "futures-macro", "futures-sink", "futures-task", "memchr", @@ -525,9 +516,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -542,15 +533,15 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "h2" -version = "0.3.24" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", "http", "indexmap", "slab", @@ -564,28 +555,38 @@ name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ - "ahash", "allocator-api2", + "equivalent", + "foldhash", ] [[package]] name = "hashlink" -version = "0.8.4" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown", + "hashbrown 0.15.2", ] [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -dependencies = [ - "unicode-segmentation", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "hex" @@ -622,9 +623,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -633,12 +634,24 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.6" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", + "futures-util", "http", + "http-body", "pin-project-lite", ] @@ -649,46 +662,81 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] -name = "httpdate" -version = "1.0.3" +name = "humantime" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ "bytes", "futures-channel", - "futures-core", "futures-util", "h2", "http", "http-body", "httparse", - "httpdate", "itoa", "pin-project-lite", - "socket2", + "smallvec", "tokio", - "tower-service", - "tracing", "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + [[package]] name = "hyper-tls" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", + "http-body-util", "hyper", + "hyper-util", "native-tls", "tokio", "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", ] [[package]] @@ -731,7 +779,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.3", ] [[package]] @@ -740,11 +788,22 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "itertools" -version = "0.12.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] @@ -775,9 +834,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.153" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libm" @@ -787,20 +846,19 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libsqlite3-sys" -version = "0.27.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" dependencies = [ - "cc", "pkg-config", "vcpkg", ] [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "lock_api" @@ -814,9 +872,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "md-5" @@ -840,12 +898,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.7.2" @@ -857,13 +909,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -884,27 +936,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "nix" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" -dependencies = [ - "bitflags 2.4.2", - "cfg-if", - "libc", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "num-bigint-dig" version = "0.8.4" @@ -991,7 +1022,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn", ] [[package]] @@ -1012,6 +1043,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.1" @@ -1035,12 +1072,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "paste" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" - [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -1101,11 +1132,21 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "pretty_env_logger" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" +dependencies = [ + "env_logger", + "log", +] + [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -1158,11 +1199,40 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + [[package]] name = "reqwest" -version = "0.11.24" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" +checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" dependencies = [ "base64", "bytes", @@ -1172,8 +1242,11 @@ dependencies = [ "h2", "http", "http-body", + "http-body-util", "hyper", + "hyper-rustls", "hyper-tls", + "hyper-util", "ipnet", "js-sys", "log", @@ -1190,12 +1263,13 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", + "tower", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg", + "windows-registry", ] [[package]] @@ -1240,9 +1314,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ "bitflags 2.4.2", "errno", @@ -1253,31 +1327,41 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.23.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" dependencies = [ + "once_cell", "ring", + "rustls-pki-types", "rustls-webpki", - "sct", + "subtle", + "zeroize", ] [[package]] name = "rustls-pemfile" -version = "1.0.4" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64", + "rustls-pki-types", ] +[[package]] +name = "rustls-pki-types" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" + [[package]] name = "rustls-webpki" -version = "0.101.7" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", + "rustls-pki-types", "untrusted", ] @@ -1302,16 +1386,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "security-framework" version = "2.9.2" @@ -1337,9 +1411,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.196" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] @@ -1352,19 +1426,19 @@ checksum = "fb3aa78ecda1ebc9ec9847d5d3aba7d618823446a049ba2491940506da6e2782" dependencies = [ "log", "serde", - "thiserror", + "thiserror 1.0.56", "xml-rs", ] [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn", ] [[package]] @@ -1412,6 +1486,15 @@ dependencies = [ "digest", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "signature" version = "2.2.0" @@ -1436,6 +1519,9 @@ name = "smallvec" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +dependencies = [ + "serde", +] [[package]] name = "socket2" @@ -1472,22 +1558,11 @@ dependencies = [ "der", ] -[[package]] -name = "sqlformat" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" -dependencies = [ - "itertools", - "nom", - "unicode_categories", -] - [[package]] name = "sqlx" -version = "0.7.3" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba03c279da73694ef99763320dea58b51095dfe87d001b1d4b5fe78ba8763cf" +checksum = "4410e73b3c0d8442c5f99b425d7a435b5ee0ae4167b3196771dd3f7a01be745f" dependencies = [ "sqlx-core", "sqlx-macros", @@ -1498,31 +1573,25 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.7.3" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d84b0a3c3739e220d94b3239fd69fb1f74bc36e16643423bd99de3b43c21bfbd" +checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0" dependencies = [ - "ahash", - "atoi", - "byteorder", "bytes", "crc", "crossbeam-queue", - "dotenvy", "either", "event-listener", - "futures-channel", "futures-core", "futures-intrusive", "futures-io", "futures-util", + "hashbrown 0.15.2", "hashlink", - "hex", "indexmap", "log", "memchr", "once_cell", - "paste", "percent-encoding", "rustls", "rustls-pemfile", @@ -1530,8 +1599,7 @@ dependencies = [ "serde_json", "sha2", "smallvec", - "sqlformat", - "thiserror", + "thiserror 2.0.11", "tokio", "tokio-stream", "tracing", @@ -1541,24 +1609,23 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.7.3" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89961c00dc4d7dffb7aee214964b065072bff69e36ddb9e2c107541f75e4f2a5" +checksum = "3112e2ad78643fef903618d78cf0aec1cb3134b019730edb039b69eaf531f310" dependencies = [ "proc-macro2", "quote", "sqlx-core", "sqlx-macros-core", - "syn 1.0.109", + "syn", ] [[package]] name = "sqlx-macros-core" -version = "0.7.3" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0bd4519486723648186a08785143599760f7cc81c52334a55d6a83ea1e20841" +checksum = "4e9f90acc5ab146a99bf5061a7eb4976b573f560bc898ef3bf8435448dd5e7ad" dependencies = [ - "atomic-write-file", "dotenvy", "either", "heck", @@ -1571,8 +1638,9 @@ dependencies = [ "sha2", "sqlx-core", "sqlx-mysql", + "sqlx-postgres", "sqlx-sqlite", - "syn 1.0.109", + "syn", "tempfile", "tokio", "url", @@ -1580,9 +1648,9 @@ dependencies = [ [[package]] name = "sqlx-mysql" -version = "0.7.3" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" +checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233" dependencies = [ "atoi", "base64", @@ -1615,16 +1683,16 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror", + "thiserror 2.0.11", "tracing", "whoami", ] [[package]] name = "sqlx-postgres" -version = "0.7.3" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" +checksum = "c5b98a57f363ed6764d5b3a12bfedf62f07aa16e1856a7ddc2a0bb190a959613" dependencies = [ "atoi", "base64", @@ -1635,7 +1703,6 @@ dependencies = [ "etcetera", "futures-channel", "futures-core", - "futures-io", "futures-util", "hex", "hkdf", @@ -1649,21 +1716,20 @@ dependencies = [ "rand", "serde", "serde_json", - "sha1", "sha2", "smallvec", "sqlx-core", "stringprep", - "thiserror", + "thiserror 2.0.11", "tracing", "whoami", ] [[package]] name = "sqlx-sqlite" -version = "0.7.3" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490" +checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540" dependencies = [ "atoi", "flume", @@ -1676,10 +1742,10 @@ dependencies = [ "log", "percent-encoding", "serde", + "serde_urlencoded", "sqlx-core", "tracing", "url", - "urlencoding", ] [[package]] @@ -1701,9 +1767,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -1711,38 +1777,30 @@ dependencies = [ ] [[package]] -name = "syn" -version = "2.0.48" +name = "sync_wrapper" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "futures-core", ] -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - [[package]] name = "system-configuration" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.2", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ "core-foundation-sys", "libc", @@ -1750,24 +1808,43 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.9.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", + "getrandom", + "once_cell", "rustix", "windows-sys 0.52.0", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.56", +] + +[[package]] +name = "thiserror" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +dependencies = [ + "thiserror-impl 2.0.11", ] [[package]] @@ -1778,7 +1855,18 @@ checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1798,29 +1886,31 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.36.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", "libc", "mio", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn", ] [[package]] @@ -1833,6 +1923,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.14" @@ -1858,11 +1958,32 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -1884,7 +2005,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn", ] [[package]] @@ -1929,18 +2050,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode_categories" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" - [[package]] name = "untrusted" version = "0.9.0" @@ -1958,12 +2067,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - [[package]] name = "vcpkg" version = "0.2.15" @@ -2012,7 +2115,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn", "wasm-bindgen-shared", ] @@ -2046,7 +2149,7 @@ checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2069,9 +2172,12 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.4" +version = "0.26.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" +dependencies = [ + "rustls-pki-types", +] [[package]] name = "whoami" @@ -2079,13 +2185,52 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "windows-core" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", ] [[package]] @@ -2103,7 +2248,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", ] [[package]] @@ -2123,17 +2268,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "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 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -2144,9 +2290,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -2156,9 +2302,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -2168,9 +2314,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -2180,9 +2332,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -2192,9 +2344,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -2204,9 +2356,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -2216,19 +2368,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "xml-rs" @@ -2236,26 +2378,6 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" -[[package]] -name = "zerocopy" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "zeroize" version = "1.7.0" diff --git a/Cargo.toml b/Cargo.toml index 50f8943..f1afab4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,19 +3,15 @@ name = "chart-parser" version = "2.0.0" edition = "2021" -[workspace] -members = [ - "faa" -] - [dependencies] -anyhow = "1.0" -chrono = "0.4" +anyhow = "1.0.95" +chrono = "0.4.39" dotenv = "0.15.0" -faa = { path = "faa" } -futures = "0.3" -reqwest = { version = "0.11" } -serde = {version = "1.0.152", features = ["derive"]} -serde-xml-rs = "0.6" -sqlx = { version = "0.7", features = [ "mysql", "runtime-tokio", "tls-rustls" ] } -tokio = { version = "1.20.0", features = ["rt", "macros"]} +itertools = "0.14.0" +log = "0.4.25" +pretty_env_logger = "0.5.0" +reqwest = "0.12.12" +serde = {version = "1.0.207", features = ["derive"] } +serde-xml-rs = "0.6.0" +sqlx = { version = "0.8.3", features = [ "mysql", "runtime-tokio", "tls-rustls" ] } +tokio = { version = "1.43.0", features = ["full"] } diff --git a/faa/Cargo.toml b/faa/Cargo.toml deleted file mode 100644 index f6d33f6..0000000 --- a/faa/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "faa" -version = "0.1.0" -edition = "2021" - -[dependencies] -chrono = "0.4" \ No newline at end of file diff --git a/faa/src/lib.rs b/faa/src/lib.rs deleted file mode 100644 index adc7742..0000000 --- a/faa/src/lib.rs +++ /dev/null @@ -1,113 +0,0 @@ -use std::cmp::Ordering; - -// Find if provided date is a an interval of 28 days from 2023-01-26 -pub fn is_cycle_date(date: &str) -> bool { - let known_cycle_date = "2023-01-26"; - let date = date.parse::().unwrap(); - let known_cycle_date = known_cycle_date.parse::().unwrap(); - let diff = date.signed_duration_since(known_cycle_date).num_days(); - diff % 28 == 0 -} - -pub fn first_cycle_of_year(year: i64) -> String { - let mut new_date = chrono::NaiveDate::from_ymd_opt(i32::try_from(year).unwrap(), 1, 1).unwrap(); - while !is_cycle_date(new_date.to_string().as_str()) { - new_date += chrono::Duration::days(1); - } - new_date.to_string() -} - -pub fn number_of_cycles_in_year(year: i64) -> i64 { - let first_cycle = first_cycle_of_year(year); - let next_year_first_cycle = first_cycle_of_year(year + 1); - - return cycles_between_dates(first_cycle.as_str(), next_year_first_cycle.as_str()); -} - -pub fn cycles_between_dates(date1: &str, date2: &str) -> i64 { - let date1 = date1.parse::().unwrap(); - let date2 = date2.parse::().unwrap(); - let diff = date2.signed_duration_since(date1).num_days(); - diff / 28 + 1 -} - -fn split_year(year: &i64) -> i32 { - let year = year.to_string(); - let year = year.split_at(2); - year.1.parse::().unwrap() -} - -pub fn calculate_cycle(date: &str) -> Option { - // Find out if date is before get_first_cytcle_of_year - // Extract year from date - let year = date.split('-').collect::>()[0].parse::(); - if year.is_err() { - return None; - } - let year = year.unwrap(); - - match date.cmp(first_cycle_of_year(year).as_str()) { - Ordering::Less => { - let year = year - 1; - Some(format!( - "{:02}{:02}", - split_year(&year), - number_of_cycles_in_year(year) - )) - } - Ordering::Equal => Some(format!("{:02}{:02}", split_year(&year), 1)), - Ordering::Greater => Some(format!( - "{:02}{:02}", - split_year(&year), - cycles_between_dates(first_cycle_of_year(year).as_str(), date) - )), - } -} - -pub fn calculate_cycle_dates(cycle: &str) -> (String, String) { - let year = format!("20{}", &cycle[0..2]); - let cycle_num = &cycle[2..4]; - - let mut new_date = chrono::NaiveDate::from_ymd_opt(year.parse::().unwrap(), 1, 1).unwrap(); - while !is_cycle_date(new_date.to_string().as_str()) { - new_date = new_date.succ_opt().unwrap(); - } - - let cycle_num = cycle_num.parse::().unwrap(); - new_date += chrono::Duration::days((cycle_num - 1) * 28); - let cycle_end = new_date + chrono::Duration::days(27); - - (new_date.to_string(), cycle_end.to_string()) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn tests() { - assert_eq!(is_cycle_date("2023-12-28"), true); - assert_ne!(is_cycle_date("2023-12-27"), true); - - assert_eq!(first_cycle_of_year(2023), "2023-01-26"); - - assert_eq!(number_of_cycles_in_year(2023), 13); - assert_eq!(number_of_cycles_in_year(2020), 14); - - assert_eq!(cycles_between_dates("2023-01-26", "2023-02-22"), 1); - assert_eq!(cycles_between_dates("2023-01-26", "2023-02-23"), 2); // technically, 2023-02-23 is the start of cycle 2 - - let year = 2023; - assert_eq!(split_year(&year), 23); - - assert_eq!(calculate_cycle("2023-01-26").unwrap(), "2301"); - assert_eq!(calculate_cycle("2023-01-01").unwrap(), "2213"); - assert_eq!(calculate_cycle("invaliddate"), None); - - let cycle = "2301".to_string(); - assert_eq!( - calculate_cycle_dates(&cycle), - ("2023-01-26".to_string(), "2023-02-22".to_string()) - ); - } -} diff --git a/src/faa.rs b/src/faa.rs new file mode 100644 index 0000000..1c5f9e3 --- /dev/null +++ b/src/faa.rs @@ -0,0 +1,113 @@ +//! Aviation-related code. + +use chrono::NaiveDate; +use itertools::Itertools; +use log::error; +use std::sync::LazyLock; + +pub const DATE_FORMAT: &str = "%Y-%m-%d"; + +#[derive(Debug, Clone)] +pub struct Airac { + pub code: u16, + pub start: NaiveDate, +} + +impl Airac { + fn new(code: u16, start: &str) -> Self { + Self { + code, + start: NaiveDate::parse_from_str(start, DATE_FORMAT).unwrap(), + } + } +} + +// TODO I guess I'll have to calculate end dates for these +// or put the end dates into the struct itself? + +/// Static collection of AIRAC cycle info. +/// +/// Sourced from [Wikipedia]. +/// +/// [Wikipedia]: https://en.wikipedia.org/wiki/Aeronautical_Information_Publication +static AIRAC_DATES: LazyLock> = LazyLock::new(|| { + vec![ + // 2024 + Airac::new(2401, "2024-01-25"), + Airac::new(2402, "2024-02-22"), + Airac::new(2403, "2024-03-21"), + Airac::new(2404, "2024-04-18"), + Airac::new(2405, "2024-05-16"), + Airac::new(2406, "2024-06-13"), + Airac::new(2407, "2024-07-11"), + Airac::new(2408, "2024-08-08"), + Airac::new(2409, "2024-09-05"), + Airac::new(2410, "2024-10-03"), + Airac::new(2411, "2024-10-31"), + Airac::new(2412, "2024-11-28"), + Airac::new(2413, "2024-12-26"), + // 2025 + Airac::new(2501, "2025-01-23"), + Airac::new(2502, "2025-02-20"), + Airac::new(2503, "2025-03-20"), + Airac::new(2504, "2025-04-17"), + Airac::new(2505, "2025-05-15"), + Airac::new(2506, "2025-06-12"), + Airac::new(2507, "2025-07-12"), + Airac::new(2508, "2025-08-07"), + Airac::new(2509, "2025-09-04"), + Airac::new(2510, "2025-10-02"), + Airac::new(2511, "2025-10-30"), + Airac::new(2512, "2025-11-27"), + Airac::new(2513, "2025-12-25"), + // 2026 + Airac::new(2601, "2026-01-22"), + Airac::new(2602, "2026-02-19"), + Airac::new(2603, "2026-03-19"), + Airac::new(2604, "2026-04-16"), + Airac::new(2605, "2026-05-14"), + Airac::new(2606, "2026-06-11"), + Airac::new(2607, "2026-07-09"), + Airac::new(2608, "2026-08-06"), + Airac::new(2609, "2026-09-03"), + Airac::new(2610, "2026-10-01"), + Airac::new(2611, "2026-10-29"), + Airac::new(2612, "2026-11-26"), + Airac::new(2613, "2026-12-24"), + ] +}); + +/// Return `true` if the passed date is exactly +/// an AIRAC cycle update date. +pub fn is_cycle_date(date: &str) -> bool { + AIRAC_DATES + .iter() + .any(|airac| airac.start.format(DATE_FORMAT).to_string() == date) +} + +/// Get the cycle code for the supplied date. +/// +/// `None` is returned if the date falls outside the bounds +/// of the static data. +pub fn get_cycle_for(date: &str) -> Option { + // parse the String into a date for use in comparison + let dt = match NaiveDate::parse_from_str(date, DATE_FORMAT) { + Ok(dt) => dt, + Err(e) => { + error!("Error parsing date string \"{date}\": {e}"); + return None; + } + }; + /* + The code that should be returned, if any, is the code for the AIRAC + date that the supplied date is after, but only just. Using tuples + (i.e. iter windows), the supplied date should be after the first + tuple item but before the second. + */ + for (a, b) in AIRAC_DATES.iter().tuples() { + if a.start <= dt && dt <= b.start { + return Some(a.to_owned()); + } + } + None +} diff --git a/src/main.rs b/src/main.rs index 20b12b7..44edf37 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,99 +1,67 @@ -extern crate serde; -extern crate serde_xml_rs; - +use anyhow::Result; +use chrono::NaiveDate; use dotenv::dotenv; -use serde::{Deserialize, Serialize}; -use std::fs::File; - -#[derive(Debug, Deserialize, Serialize, PartialEq)] -struct Airport { - #[serde(rename = "ID")] - id: String, - #[serde(rename = "apt_ident")] - apt_ident: Option, - #[serde(rename = "record")] - records: Option>, -} - -#[derive(Debug, Deserialize, Serialize, PartialEq)] -struct Chart { - #[serde(rename = "chart_code")] - chart_code: String, - #[serde(rename = "chart_name")] - chart_name: String, - #[serde(rename = "pdf_name")] - pdf_name: String, -} - -#[derive(Debug, Deserialize, Serialize, PartialEq)] -struct City { - #[serde(rename = "ID")] - id: String, - #[serde(rename = "airport_name")] - airports: Vec, -} - -#[derive(Debug, Deserialize, Serialize, PartialEq)] -struct State { - #[serde(rename = "ID")] - id: String, - #[serde(rename = "city_name")] - city_names: Vec, -} - -#[derive(Debug, Deserialize, Serialize, PartialEq)] -struct DigitalTpp { - #[serde(rename = "state_code")] - state_codes: Vec, -} - -#[tokio::main(flavor = "current_thread")] -async fn main() -> anyhow::Result<()> { - dotenv().ok(); +use faa::DATE_FORMAT; +use log::{debug, error, info, warn}; +use models::DigitalTpp; +use sqlx::mysql::MySqlPool; +use std::{env, fs, process}; + +mod faa; +mod models; + +/// Downloaded FAA file name. +const DOWNLOAD_FILE_NAME: &str = "d-tpp.xml"; + +#[tokio::main] +async fn main() { + // env load and logger setup + if let Err(e) = dotenv() { + eprintln!("Could not load .env file: {e}"); + process::exit(1); + } + if env::var("RUST_LOG").is_err() { + env::set_var("RUST_LOG", "info"); + } + pretty_env_logger::init(); + // basic info let today = chrono::Local::now().format("%Y-%m-%d").to_string(); - - println!("ADH Chart Parser v2"); - println!("Today is {}", today); - println!( - "Is today a cylce day? {}", - faa::is_cycle_date(today.as_str()) - ); - if !faa::is_cycle_date(today.as_str()) { - // Check if the FORCE environment variable is set - if std::env::var("FORCE").is_err() { - println!("Today is not a cycle day and FORCE is not set. Exiting."); - std::process::exit(0); - } - - println!("Today is not a cycle day but FORCE is set. Continuing."); + info!("ADH Chart Parser v2"); + info!("Today is {}", today); + + let today_is = faa::is_cycle_date(&today); + info!("Is today a cycle day? {}", today_is); + if !today_is && env::var("FORCE").is_err() { + warn!("Today is not a cycle day and FORCE is not set. Exiting."); + return; } - let table = if let Ok(db_table) = std::env::var("DB_TABLE") { - db_table - } else { - "airport_charts".to_string() + let table = match env::var("DB_TABLE") { + Ok(t) => t, + Err(_) => String::from("airport_charts"), }; - - if std::env::var("STATES").is_err() { - println!("STATES environment variable not set. Exiting."); - std::process::exit(1); - } - let states: Vec = std::env::var("STATES") - .unwrap() + let states: Vec = env::var("STATES") + .expect("Missing \"STATES\" env var") .split(',') .map(|s| s.to_string()) .collect(); - println!("States: {:?}", states); - - let cycle = faa::calculate_cycle(&today).unwrap(); - println!("Cycle: {}", cycle); + info!("States: {:?}", states); - let (start_date, end_date) = faa::calculate_cycle_dates(&cycle); - println!("Cycle start date: {}", start_date); - println!("Cycle end date: {}", end_date); + let cycle = match faa::get_cycle_for(&today) { + Some(c) => c, + None => { + error!("Could not determine cycle for \"{today}\""); + process::exit(1); + } + }; + info!( + "Cycle start date is {}, code {}", + cycle.start.to_string(), + cycle.code + ); - println!("Connecting to database..."); + info!("Connecting to database..."); let login = format!( "mysql://{}:{}@{}:{}/{}", std::env::var("DB_USER").unwrap(), @@ -102,103 +70,113 @@ async fn main() -> anyhow::Result<()> { std::env::var("DB_PORT").unwrap(), std::env::var("DB_DATABASE").unwrap() ); - let pool = sqlx::mysql::MySqlPool::connect(login.as_str()).await?; - println!("Connected to database."); - - println!("Getting d-tpp.xml"); - let body: String; - // Check if file d-tpp.xml exists first - if std::fs::metadata("d-tpp.xml").is_err() { - let response = reqwest::get(format!( + let pool = match sqlx::mysql::MySqlPool::connect(login.as_str()).await { + Ok(p) => p, + Err(e) => { + error!("Could not connect to the database: {e}"); + process::exit(1); + } + }; + info!("Connected to database."); + + info!("Getting {DOWNLOAD_FILE_NAME}"); + if fs::metadata("d-tpp.xml").is_err() { + let resp = reqwest::get(format!( "https://aeronav.faa.gov/d-tpp/{}/xml_data/d-tpp_Metafile.xml", - cycle + cycle.code )) - .await?; - if response.status() != 200 { - println!("Failed to get d-tpp.xml"); - std::process::exit(1); + .await + .expect("Could not send request"); + if !resp.status().is_success() { + error!("Got status code {} from FAA site", resp.status().as_u16()); + process::exit(1); + } + let body = match resp.text().await { + Ok(b) => b, + Err(e) => { + error!("Could not read response body: {e}"); + process::exit(1) + } + }; + if let Err(e) = fs::write(DOWNLOAD_FILE_NAME, body) { + error!("Error writing response body to file: {e}"); + process::exit(1); } - body = response.text().await?; - // write body to d-tpp.xml - std::fs::write("d-tpp.xml", body).unwrap(); + } else { + debug!("{DOWNLOAD_FILE_NAME} already exists; not re-downloading"); } - println!("Parsing d-tpp.xml"); - parse_data( - "d-tpp.xml", - &states, - &cycle, - &start_date, - &end_date, - &pool, - &table, - ) - .await; - - println!("Cleaning up old charts"); - sqlx::query(format!("DELETE FROM {} WHERE cycle != ?", table).as_str()) - .bind(&cycle) - .execute(&pool) - .await?; + info!("Parsing {DOWNLOAD_FILE_NAME}"); + // TODO parse the file, looks like, and pass in the DB connection + if let Err(e) = parse_data(&states, cycle.code, &cycle.start, "TODO???", &pool, &table).await { + error!("Could not parse the document: {e}"); + process::exit(1); + } - println!("Done"); + info!("Cleaning up old charts"); + if let Err(e) = sqlx::query(&format!("DELETE FROM {} WHERE cycle != ?", table)) + .bind(cycle.code) + .execute(&pool) + .await + { + error!("Could not execute SQL to clean up old charts: {e}"); + process::exit(1); + } - Ok(()) + info!("Done"); } +/// Load the downloaded file, parse, and update the database. async fn parse_data( - file_path: &str, states: &[String], - cycle: &str, - start_date: &str, + cycle: u16, + start_date: &NaiveDate, end_date: &str, - pool: &sqlx::mysql::MySqlPool, + pool: &MySqlPool, table: &str, -) { - let file = File::open(file_path).expect("Failed to open XML file"); - let digital_tpp: DigitalTpp = serde_xml_rs::from_reader(file).expect("Failed to parse XML"); - let all: String = "ALL".to_string(); +) -> Result<()> { + let file_content = fs::read_to_string(DOWNLOAD_FILE_NAME)?; + let digital_tpp: DigitalTpp = serde_xml_rs::from_str(&file_content)?; + let all = String::from("ALL"); - let mut chart_count = 0; - let mut airport_count = 0; + let mut chart_count = 0usize; + let mut airport_count = 0usize; for state in digital_tpp.state_codes { for city in state.city_names { if states.contains(&state.id) || states.contains(&all) { for airport in city.airports { - // Check if airport has an apt_ident if airport.apt_ident.is_none() { - println!("Airport has no apt_ident: {:?}", airport); - continue; - } - - if airport.records.is_none() { - println!("Airport has no records: {:?}", airport); + warn!("Airport {} has no apt_ident", airport.id); continue; } - + let records = match airport.records { + Some(r) => r, + None => { + warn!("Airport {} has no records", airport.id); + continue; + } + }; airport_count += 1; - for chart in airport.records.unwrap() { + for chart in records { let chart_type = match chart.chart_code.as_str() { "DP" | "STAR" | "IAP" => chart.chart_code.clone(), - _ => "OTHER".to_string(), + _ => String::from("OTHER"), }; - - let apt_ident = airport.apt_ident.clone().unwrap(); - + let apt_ident = airport.apt_ident.as_ref().unwrap().clone(); update_chart( &format!("FAA-{}-{}-{}", apt_ident, chart_type, chart.chart_name), &apt_ident, cycle, - start_date, + &start_date.format(DATE_FORMAT).to_string(), end_date, &chart_type, &chart.chart_name, &format!("https://aeronav.faa.gov/d-tpp/{}/{}", cycle, chart.pdf_name), pool, - &table, + table, ) - .await; + .await?; chart_count += 1; } } @@ -206,25 +184,23 @@ async fn parse_data( } } - println!( - "Processed {} charts for {} airports", - chart_count, airport_count - ); + todo!() } +/// Update the chart in the database. #[allow(clippy::too_many_arguments)] async fn update_chart( chart_id: &str, apt_ident: &str, - cycle: &str, + cycle: u16, start_date: &str, end_date: &str, chart_type: &str, chart_name: &str, pdf_url: &str, - pool: &sqlx::mysql::MySqlPool, + pool: &MySqlPool, table: &str, -) { +) -> Result<()> { sqlx::query(&format!( "INSERT INTO {} (id, airport_id, cycle, from_date, to_date, chart_code, chart_name, chart_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?) @@ -237,15 +213,15 @@ async fn update_chart( chart_url = VALUES(chart_url)", table )) - .bind(chart_id) - .bind(apt_ident) - .bind(cycle) - .bind(start_date) - .bind(end_date) - .bind(chart_type) - .bind(chart_name) - .bind(pdf_url) - .execute(pool) - .await - .expect("Failed to update chart"); + .bind(chart_id) + .bind(apt_ident) + .bind(cycle) + .bind(start_date) + .bind(end_date) + .bind(chart_type) + .bind(chart_name) + .bind(pdf_url) + .execute(pool) + .await?; + Ok(()) } diff --git a/src/models.rs b/src/models.rs new file mode 100644 index 0000000..afcad35 --- /dev/null +++ b/src/models.rs @@ -0,0 +1,45 @@ +//! Models for (de)serialization. + +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize, PartialEq)] +pub struct Chart { + #[serde(rename = "chart_code")] + pub chart_code: String, + #[serde(rename = "chart_name")] + pub chart_name: String, + #[serde(rename = "pdf_name")] + pub pdf_name: String, +} + +#[derive(Debug, Deserialize, Serialize, PartialEq)] +pub struct Airport { + #[serde(rename = "ID")] + pub id: String, + #[serde(rename = "apt_ident")] + pub apt_ident: Option, + #[serde(rename = "record")] + pub records: Option>, +} + +#[derive(Debug, Deserialize, Serialize, PartialEq)] +pub struct City { + #[serde(rename = "ID")] + pub id: String, + #[serde(rename = "airport_name")] + pub airports: Vec, +} + +#[derive(Debug, Deserialize, Serialize, PartialEq)] +pub struct State { + #[serde(rename = "ID")] + pub id: String, + #[serde(rename = "city_name")] + pub city_names: Vec, +} + +#[derive(Debug, Deserialize, Serialize, PartialEq)] +pub struct DigitalTpp { + #[serde(rename = "state_code")] + pub state_codes: Vec, +} From 1479ebbf7f3602897c2d3b2af32b1b22f2c5066e Mon Sep 17 00:00:00 2001 From: Celeo Date: Fri, 17 Jan 2025 14:29:08 -0800 Subject: [PATCH 2/2] Got it working (I think) --- src/faa.rs | 44 ++++++++++++++++++++++++++++++++++++++++---- src/main.rs | 10 +++++----- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/faa.rs b/src/faa.rs index 1c5f9e3..4723962 100644 --- a/src/faa.rs +++ b/src/faa.rs @@ -22,8 +22,22 @@ impl Airac { } } -// TODO I guess I'll have to calculate end dates for these -// or put the end dates into the struct itself? +#[derive(Debug, Clone)] +pub struct AiracWithEnd { + pub code: u16, + pub start: NaiveDate, + pub end: NaiveDate, +} + +impl From<(Airac, NaiveDate)> for AiracWithEnd { + fn from(pair: (Airac, NaiveDate)) -> Self { + Self { + code: pair.0.code, + start: pair.0.start, + end: pair.1, + } + } +} /// Static collection of AIRAC cycle info. /// @@ -89,7 +103,7 @@ pub fn is_cycle_date(date: &str) -> bool { /// /// `None` is returned if the date falls outside the bounds /// of the static data. -pub fn get_cycle_for(date: &str) -> Option { +pub fn get_cycle_for(date: &str) -> Option { // parse the String into a date for use in comparison let dt = match NaiveDate::parse_from_str(date, DATE_FORMAT) { Ok(dt) => dt, @@ -106,8 +120,30 @@ pub fn get_cycle_for(date: &str) -> Option { */ for (a, b) in AIRAC_DATES.iter().tuples() { if a.start <= dt && dt <= b.start { - return Some(a.to_owned()); + let end = b.start.checked_sub_days(chrono::Days::new(1)).unwrap(); + return Some((a.to_owned(), end).into()); } } None } + +#[cfg(test)] +mod tests { + use super::{get_cycle_for, is_cycle_date}; + + #[test] + fn test_is_cycle_date() { + assert!(is_cycle_date("2024-01-25")); + assert!(is_cycle_date("2025-01-23")); + assert!(!is_cycle_date("2025-01-24")); + assert!(!is_cycle_date("2025-06-13")); + } + + #[test] + fn test_get_cycle_for() { + let cycle = get_cycle_for("2024-02-20").unwrap(); + assert_eq!(cycle.code, 2401); + assert_eq!(cycle.start.format("%Y-%m-%d").to_string(), "2024-01-25"); + assert_eq!(cycle.end.format("%Y-%m-%d").to_string(), "2024-02-21"); + } +} diff --git a/src/main.rs b/src/main.rs index 44edf37..5fa929a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -107,8 +107,7 @@ async fn main() { } info!("Parsing {DOWNLOAD_FILE_NAME}"); - // TODO parse the file, looks like, and pass in the DB connection - if let Err(e) = parse_data(&states, cycle.code, &cycle.start, "TODO???", &pool, &table).await { + if let Err(e) = parse_data(&states, cycle.code, &cycle.start, &cycle.end, &pool, &table).await { error!("Could not parse the document: {e}"); process::exit(1); } @@ -131,7 +130,7 @@ async fn parse_data( states: &[String], cycle: u16, start_date: &NaiveDate, - end_date: &str, + end_date: &NaiveDate, pool: &MySqlPool, table: &str, ) -> Result<()> { @@ -169,7 +168,7 @@ async fn parse_data( &apt_ident, cycle, &start_date.format(DATE_FORMAT).to_string(), - end_date, + &end_date.format(DATE_FORMAT).to_string(), &chart_type, &chart.chart_name, &format!("https://aeronav.faa.gov/d-tpp/{}/{}", cycle, chart.pdf_name), @@ -184,7 +183,8 @@ async fn parse_data( } } - todo!() + info!("Processed {chart_count} chartts for {airport_count} airports"); + Ok(()) } /// Update the chart in the database.