commit 44ef27b2b6b01b6d69ca097a17071c8b635ee855 Author: core Date: Wed Jun 14 23:02:44 2023 -0400 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..e3bc1e7 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vfsm.iml b/.idea/vfsm.iml new file mode 100644 index 0000000..c254557 --- /dev/null +++ b/.idea/vfsm.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..813f031 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1369 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "time 0.1.45", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "colored" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "h2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", +] + +[[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 = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.1", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "ipnet" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.146" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "openssl" +version = "0.10.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b3f656a17a6cbc115b5c7a40c616947d213ba182135b014d6051b73ab6f019" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2ce0f250f34a308dcfdbb351f511359857d4ed2134ba715a4eadd46e1ffd617" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.11.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "rustix" +version = "0.37.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[package]] +name = "schannel" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +dependencies = [ + "windows-sys 0.42.0", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "security-framework" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.164" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.164" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + +[[package]] +name = "serde_json" +version = "1.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "simple_logger" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2230cd5c29b815c9b699fb610b49a5ed65588f3509d9f0108be3a885da629333" +dependencies = [ + "colored", + "log", + "time 0.3.22", + "windows-sys 0.42.0", +] + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +dependencies = [ + "autocfg", + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "time" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +dependencies = [ + "itoa", + "libc", + "num_threads", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" + +[[package]] +name = "time-macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +dependencies = [ + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +dependencies = [ + "autocfg", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vfsm" +version = "0.1.0" +dependencies = [ + "chrono", + "log", + "rand", + "reqwest", + "serde", + "serde_json", + "simple_logger", + "tokio", + "url", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 1.0.109", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "web-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..31dc925 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "vfsm" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +log = "0.4.17" +simple_logger = "4.1.0" +url = { version = "2.3.1", features = ["serde"] } +serde = { version = "1", features = ["derive"] } +serde_json = "1.0.96" +chrono = { version = "0.4.24", features = ["serde"] } +reqwest = { version = "0.11.17", features = ["json"] } +tokio = { version = "1", features = ["full"]} +rand = "0.8.5" \ No newline at end of file diff --git a/src/fps.rs b/src/fps.rs new file mode 100644 index 0000000..9c02a5e --- /dev/null +++ b/src/fps.rs @@ -0,0 +1,119 @@ +use rand::Rng; +use crate::vatlink::data_v3::VatlinkDataV3FlightPlan; + +/* +┌┬┐ +│││ +├┼┤ +│││ +└┴┘ + +── + */ + +pub const BOTTOM_RIGHT: char = '┌'; +pub const LEFT_BOTTOM_RIGHT: char = '┬'; +pub const LEFT_BOTTOM: char = '┐'; + + +pub fn print_fps(fp: &VatlinkDataV3FlightPlan, callsign: &str) { + let ac_type = fp.aircraft_faa.clone(); + let flight_type = fp.flight_rules.clone(); + let blocks_leftmost = [callsign.len(), ac_type.len(), flight_type.len()]; + let longest_block_leftmost = blocks_leftmost.iter().max().unwrap(); + let ft_offset = longest_block_leftmost - 3; + let cid = rand::thread_rng().gen_range(0..999); + let leftmost_with_padding = longest_block_leftmost + 2; + + let squawk = fp.assigned_transponder.clone(); + let departure_time = format!("P{}", fp.deptime); + let cruise_alt = fp.altitude.clone(); + let blocks_2nd_leftmost = [squawk.len(), departure_time.len(), cruise_alt.len()]; + let longest_block_2nd_leftmost = blocks_2nd_leftmost.iter().max().unwrap(); + let tnd_leftmost_with_padding = longest_block_2nd_leftmost + 2; + + let departure = fp.departure.clone(); + let arrival = fp.arrival.clone(); + let alternate = fp.alternate.clone(); + + let MAIN_WRAP = 68; + + let mut route = fp.route.clone(); + + if fp.route.len() > 68 * 3 { + route = route[..68*3-3].to_string() + "..."; + } + + let route_chars: Vec = route.chars().collect(); + let mut route_split = &mut route_chars.chunks(MAIN_WRAP) + .map(|chunk| chunk.iter().collect::()) + .collect::>(); + route_split.push("".to_string()); + route_split.push("".to_string()); + route_split.push("".to_string()); + + let mut rem = fp.remarks.clone(); + + let room_for_remarks = if fp.route.len() < 68 { + 4 + } else if fp.route.len() < 68 * 2 { + 3 + } else { + 2 + }; + + if fp.remarks.len() > 68 * room_for_remarks { + rem = rem[..68*room_for_remarks-3].to_string() + "..."; + } + + let rem_chars: Vec = rem.chars().collect(); + let mut rem_split = &mut rem_chars.chunks(MAIN_WRAP) + .map(|chunk| chunk.iter().collect::()) + .collect::>(); + + + + let rem_01; + let rem_02; + let rem_03; + let rem_04; + + + + if rem_split.len() == 1 { + rem_01 = "".to_string(); + rem_02 = "".to_string(); + rem_03 = "".to_string(); + rem_04 = rem_split[0].clone(); + } else if rem_split.len() == 2 { + rem_01 = "".to_string(); + rem_02 = "".to_string(); + rem_03 = rem_split[0].clone(); + rem_04 = rem_split[1].clone(); + } else if rem_split.len() == 3 { + rem_01 = "".to_string(); + rem_02 = rem_split[0].clone(); + rem_03 = rem_split[1].clone(); + rem_04 = rem_split[2].clone(); + } else if rem_split.is_empty() { + rem_01 = "".to_string(); + rem_02 = "".to_string(); + rem_03 = "".to_string(); + rem_04 = "".to_string(); + } else { + rem_01 = rem_split[0].clone(); + rem_02 = rem_split[1].clone(); + rem_03 = rem_split[2].clone(); + rem_04 = rem_split[3].clone(); + } + + println!("--- FLIGHT PROGRESS STRIP READOUT FOR {} ---", callsign); + println!("┌{:─>leftmost_with_padding$}┬{:─>tnd_leftmost_with_padding$}┬──────┬──────────────────────────────────────────────────────────────────────┬──────┬──────┬──────┐", "", ""); + println!("│ {: >longest_block_leftmost$} │ {: >longest_block_2nd_leftmost$} │ {: >4} │ {: leftmost_with_padding$}├{:─>tnd_leftmost_with_padding$}┤ {: >4} │ {: longest_block_leftmost$} │ {: >longest_block_2nd_leftmost$} │ {: >4} │ {: leftmost_with_padding$}├{:─>tnd_leftmost_with_padding$}┤ │ {: 3}{: >ft_offset$} │ {: >longest_block_2nd_leftmost$} │ │ {: leftmost_with_padding$}┴{:─>tnd_leftmost_with_padding$}┴──────┴──────────────────────────────────────────────────────────────────────┴──────┴──────┴──────┘", "", ""); + println!("--- END FLIGHT PROGRESS STRIP READOUT FOR {} ---", callsign); +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..975da57 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,160 @@ +use std::error::Error; +use std::{io, thread}; +use std::io::Write; +use std::sync::Arc; +use std::time::Duration; + +use log::{debug, error, info, Level, warn}; +use tokio::select; +use tokio::sync::mpsc::{Receiver, channel}; +use tokio::sync::RwLock; +use tokio::time::{sleep, sleep_until}; +use crate::fps::print_fps; + +use crate::vatlink::{vatlink_init, VATLINK_STATUS_URL, VATLINK_VERSION}; +use crate::vatlink::data_v3::VATLINK_DATAV3_UPDATE_INTERVAL; +use crate::vatlink::data_v3_client::DataClientV3; + + +pub mod vatlink; +pub mod fps; + +pub const VFSM_VERSION: &str = "0.1.0"; + +#[tokio::main] +async fn main() -> Result<(), Box> { + simple_logger::init_with_level(Level::Debug).unwrap(); + + info!("VATSIM Flight System Manager - By coredoesdev - Version {}, built with vatlink {}", VFSM_VERSION, VATLINK_VERSION); + info!("Initializing vatlink..."); + + // pull vatlink server data + let vatlink_init_data = vatlink_init(VATLINK_STATUS_URL).await?; + + info!("Retrieved vatlink initialization data, connecting to servers..."); + + let mut datav3_client = DataClientV3::new(vatlink_init_data.data.v3).await?; + let mut client = Arc::new(RwLock::new(datav3_client)); + + { + debug!("connected: {} pilots online", client.read().await.last_saved_data().pilots.len()); + } + + let (update_shutdown_tx, update_shutdown_rx) = channel::<()>(128); + let update_client = client.clone(); + + let update_task = tokio::spawn(update_main(update_client, update_shutdown_rx)); + + let sector_lat: f64 = 0.0; + let sector_long: f64 = 0.0; + let sector_loaded: bool = false; + + loop { + let mut input = String::new(); + print!("vfsm> "); + + io::stdout().flush()?; + + /* + Commands: + s/callsign - Show a flight strip (i.e s/AF1) + p/callsign - Print a flight strip (i.e. p/AF1) + w/callsign - Watch a specific aircraft. Will show flight strip, print it, and add it to your watchlist, where changes will be automatically shown and printed. (i.e. w/AF1) + u/callsign - Unwatch a specific aircraft. + d/ - Download new vatlink data + :/sector - Load a sector file + c/lat/long/range/sector - Create and load a sector file + l/ - List aircraft in sector + h/ - Help + */ + + let _ = io::stdin().read_line(&mut input).is_ok(); + + let input = input.trim().to_string(); + + let input_split = input.split('/').collect::>(); + let command = input_split[0]; + + match command { + "s" => { + if input_split.len() != 2 { + error!("syntax s/"); + continue; + } + let callsign = input_split[1]; + + if !sector_loaded { + warn!("no sector loaded"); + } + + { + let client = client.read().await; + let maybe_pilot = client.last_saved_data().pilots.iter().find(|u| u.callsign == callsign); + match maybe_pilot { + Some(pilot) => { + if let Some(fp) = &pilot.flight_plan { + print_fps(fp, callsign); + } else { + error!("no active flight plan for '{}'", callsign); + } + }, + None => { + error!("no active pilot by callsign '{}'", callsign); + } + } + } + }, + "p" => todo!(), + "w" => todo!(), + "u" => todo!(), + "d" => todo!(), + ":" => todo!(), + "c" => todo!(), + "l" => todo!(), + "h" => { + info!("vfsm: Commands:"); + info!("s/callsign - Show a flight strip (s/AF1)"); + info!("p/callsign - Print a flight strip (p/AF1)"); + info!("w/callsign - Watch a specific aircraft. Will show flight strip, print it, and add it to your watchlist, where changes will be automatically shown and printed. (i.e. w/AF1)"); + info!("u/callsign - Unwatch a specific aircraft"); + info!("d/ - Download new vatlink data"); + info!(":/sector - Load a sector file"); + info!("c/lat/long/range/sector - Create and load a sector file"); + info!("l/ - List aircraft in sector"); + info!("h/ - Help"); + }, + _unknown => { + error!("unknown command '{}'", _unknown); + info!("vfsm: Commands:"); + info!("s/callsign - Show a flight strip (s/AF1)"); + info!("p/callsign - Print a flight strip (p/AF1)"); + info!("w/callsign - Watch a specific aircraft. Will show flight strip, print it, and add it to your watchlist, where changes will be automatically shown and printed. (i.e. w/AF1)"); + info!("u/callsign - Unwatch a specific aircraft"); + info!("d/ - Download new vatlink data"); + info!(":/sector - Load a sector file"); + info!("c/lat/long/range/sector - Create and load a sector file"); + info!("l/ - List aircraft in sector"); + info!("h/ - Help"); + } + } + } + + update_shutdown_tx.send(()).await?; + update_task.await?.unwrap(); + + Ok(()) +} + +async fn update_main(datav3_client: Arc>, mut rx: Receiver<()>) -> Result<(), Box> { + loop { + select! { + _ = sleep(Duration::from_secs(VATLINK_DATAV3_UPDATE_INTERVAL as u64)) => (), + x = rx.recv() => { + return Ok(()); // if anything happens (channel closed OR we recv a shutdown) we should exit + } + } + { + datav3_client.write().await.update().await?; + } + } +} \ No newline at end of file diff --git a/src/vatlink/data_v3.rs b/src/vatlink/data_v3.rs new file mode 100644 index 0000000..ef93133 --- /dev/null +++ b/src/vatlink/data_v3.rs @@ -0,0 +1,166 @@ +use chrono::{DateTime, Utc}; +use serde::{Serialize, Deserialize}; + +pub const VATLINK_DATAV3_UPDATE_INTERVAL: i32 = 15; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct VatlinkDataV3 { + pub general: VatlinkDataV3General, + pub pilots: Vec, + pub controllers: Vec, + pub atis: Vec, + pub servers: Vec, + pub prefiles: Vec, + pub facilities: Vec, + pub ratings: Vec, + pub pilot_ratings: Vec, + pub military_ratings: Vec +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct VatlinkDataV3General { + pub version: i32, // 3 + pub reload: i32, // Seemingly always 1 + #[serde(with = "vatlink_data_v3_timestamp_format_01")] + pub update: DateTime, //YYYYMMDDHHMMSS + pub update_timestamp: DateTime, //YYYY-MM-DDTHH:MM:SS.6fZ + pub connected_clients: i32, + pub unique_users: i32 +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct VatlinkDataV3Pilot { + pub cid: i32, + pub name: String, + pub callsign: String, + pub server: String, + pub pilot_rating: i32, + pub military_rating: i32, + pub latitude: f64, + pub longitude: f64, + pub altitude: i64, + pub groundspeed: i64, + pub transponder: String, + pub heading: i32, + pub qnh_i_hg: f32, + pub qnh_mb: i32, + pub flight_plan: Option, + pub logon_time: DateTime, // YYYY-MM-DDTHH:MM:SS.3fZ + pub last_updated: DateTime, // YYYY-MM-DDTHH:MM:SS.3fZ +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct VatlinkDataV3FlightPlan { + pub flight_rules: String, + pub aircraft: String, // ICAO aircraft code (i.e B789/H-SDE1E2E3FGHIJ2J3J4J5M1RWXY/LB1D1) + pub aircraft_faa: String, // FAA aircraft code (i.e H/B789/L) + pub aircraft_short: String, // FAA aircraft code middle (i.e B789), + pub departure: String, // ICAO airfield code (e.g. KCLT) + pub arrival: String, // ICAO airfield code (e.g. KATL) + pub alternate: String, // ICAO airfield code (e.g. KJQF) + pub cruise_tas: String, // Cruise KTAS, as a string though. + pub altitude: String, // Cruise altitude in ft, as a string though. + pub deptime: String, // Departure time, HHMM + pub enroute_time: String, // Enroute time, HHMM + pub fuel_time: String, // Fuel on board, HHMM + pub remarks: String, // Flight plan remarks + pub route: String, // Flight plan route + pub revision_id: i32, + pub assigned_transponder: String, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct VatlinkDataV3Controller { + pub cid: i32, + pub name: String, + pub callsign: String, + pub frequency: String, // frequency, ex: 121.900 + pub facility: i32, + pub rating: i32, + pub server: String, + pub visual_range: i32, + pub text_atis: Option>, + pub last_updated: DateTime, // YYYY-MM-DDTHH:MM:SS.3fZ + pub logon_time: DateTime, // YYYY-MM-DDTHH:MM:SS.3fZ +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct VatlinkDataV3Atis { + pub cid: i32, + pub name: String, + pub callsign: String, + pub frequency: String, // frequency, ex: 121.900 + pub facility: i32, + pub rating: i32, + pub server: String, + pub visual_range: i32, + pub atis_code: Option, + pub text_atis: Option>, + pub last_updated: DateTime, // YYYY-MM-DDTHH:MM:SS.3fZ + pub logon_time: DateTime // YYYY-MM-DDTHH:MM:SS.3fZ +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct VatlinkDataV3Server { + pub ident: String, + pub hostname_or_ip: String, + pub location: String, + pub name: String, + pub clients_connection_allowed: i32, + pub client_connections_allowed: bool, + pub is_sweatbox: bool +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct VatlinkDataV3Prefile { + pub cid: i32, + pub name: String, + pub callsign: String, + pub flight_plan: VatlinkDataV3FlightPlan, + pub last_updated: DateTime, // YYYY-MM-DDTHH:MM:SS.3fZ +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct VatlinkDataV3Facility { + pub id: i32, + pub short: String, + pub long: String +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct VatlinkDataV3Rating { + pub id: i32, + pub short: String, + pub long: String +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct VatlinkDataV3PilotRating { + pub id: i32, + pub short_name: String, + pub long_name: String +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct VatlinkDataV3MilitaryRating { + pub id: i32, + pub short_name: String, + pub long_name: String +} + +mod vatlink_data_v3_timestamp_format_01 { + use chrono::{DateTime, Utc, TimeZone}; + use serde::{self, Deserialize, Serializer, Deserializer}; + + const FORMAT: &'static str = "%Y%m%d%H%M%S"; + + pub fn serialize(date: &DateTime, serializer: S) -> Result where S: Serializer { + let s = format!("{}", date.format(FORMAT)); + serializer.serialize_str(&s) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de> { + let s = String::deserialize(deserializer)?; + Utc.datetime_from_str(&s, FORMAT).map_err(serde::de::Error::custom) + } +} \ No newline at end of file diff --git a/src/vatlink/data_v3_client.rs b/src/vatlink/data_v3_client.rs new file mode 100644 index 0000000..8c2bb22 --- /dev/null +++ b/src/vatlink/data_v3_client.rs @@ -0,0 +1,98 @@ +use std::error::Error; +use std::fmt::{Display, Formatter}; +use chrono::{DateTime, Duration, Utc}; +use log::{debug, trace}; +use reqwest::{Client, ClientBuilder, header}; +use tokio::sync::oneshot::channel; +use tokio::task::JoinHandle; +use tokio::time::sleep; +use url::Url; +use crate::vatlink::data_v3::VatlinkDataV3; +use crate::vatlink::{VATLINK_VERSION, VatlinkServer}; +use crate::VFSM_VERSION; + +pub struct DataClientV3 { + client: Client, + last_data: VatlinkDataV3, + last_data_update: DateTime, + next_data_update: DateTime, + data_v3_url: Url, +} +impl DataClientV3 { + pub async fn new(server: VatlinkServer) -> Result> { + if server.is_empty() { + return Err(DataClientV3Error::NoServerProvided { options: server }.into()); + } + + let server = server[0].clone(); + + let mut headers = header::HeaderMap::new(); + headers.insert("X-Legal-Contact", header::HeaderValue::from_static("email:core(at)e3t(dot)cc")); + headers.insert("X-Who-Is-This", header::HeaderValue::from_static("emailLcore(at)e3t(dot)cc")); + headers.insert("X-Whoami", header::HeaderValue::from_static("emailLcore(at)e3t(dot)cc")); + + let client = ClientBuilder::new().user_agent(format!("vatlink/{} vfsm/{}", VATLINK_VERSION, VFSM_VERSION)).default_headers(headers).build()?; + + let resp: VatlinkDataV3 = client.get(server.clone()).send().await?.json().await?; + + Ok(Self { + client, + last_data: resp.clone(), + last_data_update: resp.general.update_timestamp, + next_data_update: resp.general.update_timestamp + Duration::seconds(15), + data_v3_url: server.clone(), + }) + } + + pub fn last_saved_data(&self) -> &VatlinkDataV3 { + &self.last_data + } + + pub async fn current_data(&mut self) -> Result<&VatlinkDataV3, Box> { + let cur_time = Utc::now(); + let sleep_time = self.next_data_update - cur_time; + if sleep_time < Duration::milliseconds(500) { + debug!("fetch current data: current data expires in <500ms, delaying until new data is available"); + self.update().await?; + } + Ok(&self.last_data) + } + + pub async fn update(&mut self) -> Result<(), Box> { + trace!("updating stored data"); + let cur_time = Utc::now(); + let sleep_time = (self.next_data_update + Duration::seconds(1)) - cur_time; + if (self.next_data_update + Duration::seconds(1)) > cur_time { + trace!("delaying {} until next data is available", sleep_time); + sleep(sleep_time.to_std()?).await; + } + + let resp: VatlinkDataV3 = self.client.get(self.data_v3_url.clone()).send().await?.json().await?; + + self.last_data = resp.clone(); + self.last_data_update = resp.general.update_timestamp; + self.next_data_update = resp.general.update_timestamp + Duration::seconds(15); + + trace!("data updated to {}, next update available at {}", self.last_data_update, self.next_data_update); + + Ok(()) + } +} + +enum DataClientUpdateThreadMsg { + Shutdown, + UpdateNow +} + +#[derive(Debug)] +pub enum DataClientV3Error { + NoServerProvided { options: VatlinkServer } +} +impl Display for DataClientV3Error { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Self::NoServerProvided { options } => write!(f, "No valid server URL provided (from options {})", options.iter().map(|u| format!("'{}'", u.to_string())).collect::>().join(", ")) + } + } +} +impl Error for DataClientV3Error {} \ No newline at end of file diff --git a/src/vatlink/mod.rs b/src/vatlink/mod.rs new file mode 100644 index 0000000..d623448 --- /dev/null +++ b/src/vatlink/mod.rs @@ -0,0 +1,34 @@ +use std::error::Error; +use log::debug; +use url::Url; +use serde::{Serialize, Deserialize}; + +pub const VATLINK_VERSION: &str = "0.1.0"; + +pub mod data_v3; +pub mod data_v3_client; + +#[derive(Serialize, Deserialize, Debug)] +pub struct VatlinkStatus { + pub data: VatlinkStatusData, + pub user: VatlinkServer +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct VatlinkStatusData { + pub v3: VatlinkServer, + pub transceivers: VatlinkServer, + pub servers: VatlinkServer, + pub servers_sweatbox: VatlinkServer, + pub servers_all: VatlinkServer +} + +pub type VatlinkServer = Vec; + +pub const VATLINK_STATUS_URL: &str = "https://status.vatsim.net/status.json"; + +pub async fn vatlink_init(url: &str) -> Result> { + debug!("retrieving VATSIMv3 network status from {}", url); + let resp: VatlinkStatus = reqwest::get(url).await?.json().await?; + Ok(resp) +} \ No newline at end of file