finished all part
This commit is contained in:
parent
5f232ab664
commit
7b790830f4
356
Cargo.lock
generated
356
Cargo.lock
generated
@ -2,12 +2,35 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.19"
|
version = "0.4.19"
|
||||||
@ -21,24 +44,94 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ibmfloat"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "875843bb4493ed3d109a9c474814b30860b420f3f53932c26291623378f1c85d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indoc"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da2d6f23ffea9d7e76c53eee25dfb67bcd8fde7f1198b0855350698c9f07c780"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.126"
|
version = "0.2.126"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matrixmultiply"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "add85d4dd35074e6fedc608f8c8f513a3548619a9024b751949ef0e8e45a4d84"
|
||||||
|
dependencies = [
|
||||||
|
"rawpointer",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minimal-lexical"
|
name = "minimal-lexical"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ndarray"
|
||||||
|
version = "0.15.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32"
|
||||||
|
dependencies = [
|
||||||
|
"matrixmultiply",
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
"rawpointer",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "7.1.1"
|
version = "7.1.1"
|
||||||
@ -49,6 +142,15 @@ dependencies = [
|
|||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.45"
|
version = "0.1.45"
|
||||||
@ -68,14 +170,185 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "numpy"
|
||||||
|
version = "0.17.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a462c1af5ba1fddec1488c4646993a23ae7931f9e170ccba23e9c7c834277797"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"libc",
|
||||||
|
"ndarray",
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
"pyo3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||||
|
|
||||||
|
[[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.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.49"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyo3"
|
||||||
|
version = "0.17.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "268be0c73583c183f2b14052337465768c07726936a260f480f0857cb95ba543"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"indoc",
|
||||||
|
"libc",
|
||||||
|
"memoffset",
|
||||||
|
"parking_lot",
|
||||||
|
"pyo3-build-config",
|
||||||
|
"pyo3-ffi",
|
||||||
|
"pyo3-macros",
|
||||||
|
"unindent",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyo3-build-config"
|
||||||
|
version = "0.17.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "28fcd1e73f06ec85bf3280c48c67e731d8290ad3d730f8be9dc07946923005c8"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"target-lexicon",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyo3-ffi"
|
||||||
|
version = "0.17.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f6cb136e222e49115b3c51c32792886defbfb0adead26a688142b346a0b9ffc"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"pyo3-build-config",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyo3-macros"
|
||||||
|
version = "0.17.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94144a1266e236b1c932682136dc35a9dee8d3589728f68130c7c3861ef96b28"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"pyo3-macros-backend",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyo3-macros-backend"
|
||||||
|
version = "0.17.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c8df9be978a2d2f0cdebabb03206ed73b11314701a5bfe71b0d753b81997777f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rawpointer"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ripgrib"
|
name = "ripgrib"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"ibmfloat",
|
||||||
|
"lazy_static",
|
||||||
"nom",
|
"nom",
|
||||||
|
"numpy",
|
||||||
|
"pyo3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.107"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "target-lexicon"
|
||||||
|
version = "0.12.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.44"
|
version = "0.1.44"
|
||||||
@ -83,16 +356,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unindent"
|
||||||
|
version = "0.1.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.10.0+wasi-snapshot-preview1"
|
version = "0.10.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
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]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@ -114,3 +411,60 @@ name = "winapi-x86_64-pc-windows-gnu"
|
|||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.42.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||||
|
|||||||
11
Cargo.toml
11
Cargo.toml
@ -4,7 +4,18 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
#
|
||||||
|
[lib]
|
||||||
|
name = "pyo3_example"
|
||||||
|
|
||||||
|
# "cdylib" is necessary to produce a shared library for Python to import from.
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nom = "7.1.1"
|
nom = "7.1.1"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
|
bitflags = "1.3.2"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
pyo3 = { version = "0.17.3", features = ["extension-module"] }
|
||||||
|
numpy = "0.17"
|
||||||
|
ibmfloat = "0.1.1"
|
||||||
|
|||||||
12
pyproject.toml
Normal file
12
pyproject.toml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = ["maturin>=0.13,<0.14"]
|
||||||
|
build-backend = "maturin"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "pyo3_example"
|
||||||
|
requires-python = ">=3.7"
|
||||||
|
classifiers = [
|
||||||
|
"Programming Language :: Rust",
|
||||||
|
"Programming Language :: Python :: Implementation :: CPython",
|
||||||
|
"Programming Language :: Python :: Implementation :: PyPy",
|
||||||
|
]
|
||||||
85
src/gds.rs
85
src/gds.rs
@ -1,85 +0,0 @@
|
|||||||
use nom::{character::complete::u8, number::complete::u24, IResult};
|
|
||||||
|
|
||||||
struct GDS {
|
|
||||||
nv: usize,
|
|
||||||
pv_or_pl: usize,
|
|
||||||
representation: DataRepresentation,
|
|
||||||
ni: usize,
|
|
||||||
nj: usize,
|
|
||||||
pv: u8,
|
|
||||||
pl: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
type Lat = i32;
|
|
||||||
type Lon = i32;
|
|
||||||
|
|
||||||
type LatPair = (Lat, Lat);
|
|
||||||
type LonPair = (Lon, Lon);
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
enum DataRepresentation {
|
|
||||||
LatLon {
|
|
||||||
lat: LatPair,
|
|
||||||
lon_1: LonPair,
|
|
||||||
di: u32,
|
|
||||||
regular_grib: u32,
|
|
||||||
scan_mode: u8,
|
|
||||||
},
|
|
||||||
Mercator {
|
|
||||||
lon: LonPair,
|
|
||||||
lat: LatPair,
|
|
||||||
latin: u32,
|
|
||||||
di: u32,
|
|
||||||
dj: u32,
|
|
||||||
scan_mode: u8,
|
|
||||||
},
|
|
||||||
Gnomonic,
|
|
||||||
LambertConformal {
|
|
||||||
lat_1: Lat,
|
|
||||||
lon_1: Lon,
|
|
||||||
lov: u32,
|
|
||||||
dx: u32,
|
|
||||||
dy: u32,
|
|
||||||
projection_center: u32,
|
|
||||||
scan_mode: u32,
|
|
||||||
latin_1: u32,
|
|
||||||
latin_2: u32,
|
|
||||||
southern_pole_lon: u32,
|
|
||||||
southern_pole_lat: u32,
|
|
||||||
},
|
|
||||||
Gaussian {
|
|
||||||
lat: LatPair,
|
|
||||||
lon_1: LonPair,
|
|
||||||
di: u32,
|
|
||||||
gaussian_grid: u32,
|
|
||||||
scan_mode: u8,
|
|
||||||
},
|
|
||||||
PolarStereographic {
|
|
||||||
lat_1: Lat,
|
|
||||||
lon_1: Lon,
|
|
||||||
lov: u32,
|
|
||||||
dx: u32,
|
|
||||||
dy: u32,
|
|
||||||
projection_center: u32,
|
|
||||||
scan_mode: u32,
|
|
||||||
},
|
|
||||||
|
|
||||||
// NCEP
|
|
||||||
SemiStaggered {
|
|
||||||
lat: LatPair,
|
|
||||||
lon: LonPair,
|
|
||||||
di: u32,
|
|
||||||
dj: u32,
|
|
||||||
scan_mode: u8,
|
|
||||||
},
|
|
||||||
FilledStaggered,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gds_parser(input: &[u8]) -> IResult<&[u8], GDS> {
|
|
||||||
let (next, gds_length) = u24(nom::number::Endianness::Little)(input)?;
|
|
||||||
|
|
||||||
let nv_p = u8;
|
|
||||||
let pv_or_pl_p = u8;
|
|
||||||
|
|
||||||
let r_type_p = u8;
|
|
||||||
}
|
|
||||||
83
src/grib/bds.rs
Normal file
83
src/grib/bds.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
use bitflags::bitflags;
|
||||||
|
use nom::{
|
||||||
|
bytes::complete::take,
|
||||||
|
number::complete::{le_f32, le_i16, le_u24, u8},
|
||||||
|
sequence::tuple,
|
||||||
|
IResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{bms::BMS, gds::GDS};
|
||||||
|
const UNDIFINED: u32 = 0;
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
|
||||||
|
pub struct BdsFlag:u8{
|
||||||
|
const SPHERICAL_HARMONIC = 0b10000000;
|
||||||
|
const COMPLEX_PACKING = 0b01000000;
|
||||||
|
const INTEGER_NUMBERIC = 0b00100000;
|
||||||
|
const ADDITIONAL_FLAG = 0b00010000;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BDS<'a> {
|
||||||
|
length: usize,
|
||||||
|
flag: BdsFlag,
|
||||||
|
scale: i16,
|
||||||
|
refrence_value: f32,
|
||||||
|
// Number of bits into which a datum point is packed.
|
||||||
|
bit_number: usize,
|
||||||
|
data: PackedData<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum PackedData<'a> {
|
||||||
|
Simple(&'a [u8]),
|
||||||
|
Complex {
|
||||||
|
n1: u16,
|
||||||
|
extension_flag: u8,
|
||||||
|
n2: u16,
|
||||||
|
p1: u16,
|
||||||
|
p2: u16,
|
||||||
|
width: &'a [u8],
|
||||||
|
secondary_bitmap: &'a [u8],
|
||||||
|
first_order_packed_values: &'a [u8],
|
||||||
|
second_order_packed_values: &'a [u8],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bds_parser<'a>(input: &'a [u8]) -> IResult<&'a [u8], BDS<'a>> {
|
||||||
|
let (next, (length, flag_bit, scale, refrence, number)) =
|
||||||
|
tuple((le_u24, u8, le_i16, le_f32, u8))(input)?;
|
||||||
|
let flags = BdsFlag::from_bits(flag_bit).unwrap();
|
||||||
|
|
||||||
|
if flags.contains(BdsFlag::COMPLEX_PACKING) {
|
||||||
|
panic!();
|
||||||
|
} else {
|
||||||
|
let (next, value) = take(length - 11)(next)?;
|
||||||
|
Ok((
|
||||||
|
next,
|
||||||
|
BDS {
|
||||||
|
length: length as usize,
|
||||||
|
flag: flags,
|
||||||
|
scale,
|
||||||
|
refrence_value: refrence,
|
||||||
|
bit_number: number as usize,
|
||||||
|
data: PackedData::Simple(value),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
// // Grid-point data - Simple packing
|
||||||
|
// let g_s = BdsFlag::DATA_TYPE | BdsFlag::PACKING_TYPE;
|
||||||
|
// let s_s = !BdsFlag::DATA_TYPE | BdsFlag::PACKING_TYPE;
|
||||||
|
// let g_c = BdsFlag::DATA_TYPE | !BdsFlag::PACKING_TYPE;
|
||||||
|
// // total length
|
||||||
|
// let total_length: usize = gds.representation.get_total();
|
||||||
|
|
||||||
|
// if flags.contains(g_s) {
|
||||||
|
// if let Some(b) = bms.as_ref() {
|
||||||
|
// for v in bms {}
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
100
src/grib/bms.rs
Normal file
100
src/grib/bms.rs
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
use nom::{
|
||||||
|
bytes::complete::take,
|
||||||
|
number::complete::{le_u16, le_u24, u8},
|
||||||
|
sequence::tuple,
|
||||||
|
IResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum BitmapType {
|
||||||
|
Follows,
|
||||||
|
Predefined(u16),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BMS<'a> {
|
||||||
|
length: usize,
|
||||||
|
pub map_type: BitmapType,
|
||||||
|
map: Option<BitMap<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for BMS<'a> {
|
||||||
|
type Item = bool;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if let Some(map) = self.map.as_mut() {
|
||||||
|
map.next()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
|
struct BitMap<'a> {
|
||||||
|
map: &'a [u8],
|
||||||
|
position: usize,
|
||||||
|
unused: usize,
|
||||||
|
length: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> std::ops::Deref for BitMap<'a> {
|
||||||
|
type Target = &'a [u8];
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.map
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> BitMap<'a> {
|
||||||
|
fn new(map: &'a [u8], unused: usize) -> Self {
|
||||||
|
BitMap {
|
||||||
|
map,
|
||||||
|
position: 0,
|
||||||
|
unused,
|
||||||
|
length: map.len() * 8 - unused,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_masked(&self, position: usize) -> bool {
|
||||||
|
(self.map[position / 7] >> (8 - (position & 7))) == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for BitMap<'a> {
|
||||||
|
type Item = bool;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.position < self.length {
|
||||||
|
self.position += 1;
|
||||||
|
Some(self.is_masked(self.position))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bms_parser(input: &[u8]) -> IResult<&[u8], BMS> {
|
||||||
|
let (mut next, (length, unused, b_type)) = tuple((le_u24, u8, le_u16))(input)?;
|
||||||
|
|
||||||
|
let map_type = if b_type == 0 {
|
||||||
|
BitmapType::Follows
|
||||||
|
} else {
|
||||||
|
BitmapType::Predefined(b_type)
|
||||||
|
};
|
||||||
|
|
||||||
|
let map: Option<BitMap> = if let BitmapType::Follows = map_type {
|
||||||
|
let (n, map_part) = take((length - 7) as usize)(next)?;
|
||||||
|
next = n;
|
||||||
|
let len = map_part.len();
|
||||||
|
Some(BitMap::new(&map_part, unused as usize))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
next,
|
||||||
|
BMS {
|
||||||
|
length: length as usize,
|
||||||
|
map_type,
|
||||||
|
map,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
402
src/grib/gds.rs
Normal file
402
src/grib/gds.rs
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
use nom::{
|
||||||
|
bytes::complete::take,
|
||||||
|
character::complete::u8,
|
||||||
|
multi::count,
|
||||||
|
number::complete::{be_u16, le_i16, le_i24, le_u24},
|
||||||
|
sequence::tuple,
|
||||||
|
IResult,
|
||||||
|
};
|
||||||
|
use std::{borrow::Borrow, collections::HashMap};
|
||||||
|
|
||||||
|
use bitflags::bitflags;
|
||||||
|
|
||||||
|
// Deal with data representation type and Projection
|
||||||
|
// ....
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref E: DP = DP::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type declare
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GDS<'a> {
|
||||||
|
pub nv: usize,
|
||||||
|
pub representation: DataRepresentation,
|
||||||
|
pv: Option<&'a [u8]>,
|
||||||
|
pl: Option<&'a [u8]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Lat = i32;
|
||||||
|
pub type Lon = i32;
|
||||||
|
|
||||||
|
pub type LatPair = (Lat, Lat);
|
||||||
|
pub type LonPair = (Lon, Lon);
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct DataRepresentation {
|
||||||
|
row_length: usize,
|
||||||
|
col_length: usize,
|
||||||
|
projection: Projection,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DataRepresentation {
|
||||||
|
pub fn get_total(&self) -> usize {
|
||||||
|
self.row_length * self.col_length
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_row_length(&self) -> usize {
|
||||||
|
self.row_length
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_col_length(&self) -> usize {
|
||||||
|
self.col_length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DataRepresentation {
|
||||||
|
fn default() -> Self {
|
||||||
|
DataRepresentation {
|
||||||
|
row_length: 0,
|
||||||
|
col_length: 0,
|
||||||
|
projection: Projection::FilledStaggered,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Projections
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum Projection {
|
||||||
|
// Plate Carree Projecion(including GAUSSIAN)
|
||||||
|
LatLon {
|
||||||
|
ni: usize,
|
||||||
|
nj: usize,
|
||||||
|
lat: LatPair,
|
||||||
|
lon: LonPair,
|
||||||
|
res_com_flag: ResComFlags,
|
||||||
|
di: i16,
|
||||||
|
regular_grib: i16,
|
||||||
|
scan_mode: ScanningFlags,
|
||||||
|
},
|
||||||
|
Mercator {
|
||||||
|
ni: usize,
|
||||||
|
nj: usize,
|
||||||
|
lon: LonPair,
|
||||||
|
lat: LatPair,
|
||||||
|
latin: u32,
|
||||||
|
di: i32,
|
||||||
|
dj: i32,
|
||||||
|
scan_mode: ScanningFlags,
|
||||||
|
},
|
||||||
|
Gnomonic,
|
||||||
|
LambertConformal {
|
||||||
|
nx: usize,
|
||||||
|
ny: usize,
|
||||||
|
lat_1: Lat,
|
||||||
|
lon_1: Lon,
|
||||||
|
|
||||||
|
resolution: ResComFlags,
|
||||||
|
lov: i32,
|
||||||
|
dx: i32,
|
||||||
|
dy: i32,
|
||||||
|
projection_center: u8,
|
||||||
|
scan_mode: ScanningFlags,
|
||||||
|
latin_1: i32,
|
||||||
|
latin_2: i32,
|
||||||
|
southern_pole_lon: i32,
|
||||||
|
southern_pole_lat: i32,
|
||||||
|
},
|
||||||
|
Gaussian {
|
||||||
|
lat: LatPair,
|
||||||
|
lon_1: LonPair,
|
||||||
|
di: u32,
|
||||||
|
gaussian_grid: u32,
|
||||||
|
scan_mode: u8,
|
||||||
|
},
|
||||||
|
PolarStereographic {
|
||||||
|
nx: usize,
|
||||||
|
ny: usize,
|
||||||
|
lat_1: Lat,
|
||||||
|
lon_1: Lon,
|
||||||
|
resolution: ResComFlags,
|
||||||
|
lov: i32,
|
||||||
|
dx: i32,
|
||||||
|
dy: i32,
|
||||||
|
projection_center: u8,
|
||||||
|
scan_mode: ScanningFlags,
|
||||||
|
},
|
||||||
|
|
||||||
|
// NCEP
|
||||||
|
SemiStaggered {
|
||||||
|
ni: usize,
|
||||||
|
nj: usize,
|
||||||
|
lat: LatPair,
|
||||||
|
lon: LonPair,
|
||||||
|
resolution: ResComFlags,
|
||||||
|
di: i32,
|
||||||
|
dj: i32,
|
||||||
|
scan_mode: ScanningFlags,
|
||||||
|
},
|
||||||
|
FilledStaggered,
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct ScanningFlags:u8 {
|
||||||
|
const IINCREASE = 0b10000000;
|
||||||
|
const JINCREASE = 0b01000000;
|
||||||
|
const FORTRAN_MODE = 0b00100000;
|
||||||
|
}
|
||||||
|
// Resolution and Component flags
|
||||||
|
// GDS Octet 17
|
||||||
|
pub struct ResComFlags:u8 {
|
||||||
|
const DIRE_INCRES = 0b10000000;
|
||||||
|
// If earth assumed spherical with radius = 6367.47km
|
||||||
|
const EARTH_RADIUS = 0b01000000;
|
||||||
|
// If u/v components of vector quantities resolved relative to easterly and northerly directions
|
||||||
|
const U_V_RESO = 0b00001000;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DP {
|
||||||
|
events: HashMap<u8, Box<dyn Fn(&[u8]) -> IResult<&[u8], DataRepresentation> + Sync>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DP {
|
||||||
|
fn default() -> Self {
|
||||||
|
let mut events: HashMap<
|
||||||
|
u8,
|
||||||
|
Box<dyn Fn(&[u8]) -> IResult<&[u8], DataRepresentation> + Sync>,
|
||||||
|
> = HashMap::new();
|
||||||
|
events.insert(
|
||||||
|
0,
|
||||||
|
Box::new(|next| {
|
||||||
|
let (next, ni) = be_u16(next)?;
|
||||||
|
let (next, nj) = be_u16(next)?;
|
||||||
|
let (next, (lat1, lon1, reso, lat2, lon2, di, dj, scan_mode, _)) =
|
||||||
|
tuple((
|
||||||
|
le_i24,
|
||||||
|
le_i24,
|
||||||
|
u8,
|
||||||
|
le_i24,
|
||||||
|
le_i24,
|
||||||
|
le_i16,
|
||||||
|
le_i16,
|
||||||
|
u8,
|
||||||
|
take(4usize),
|
||||||
|
))(next)?;
|
||||||
|
|
||||||
|
return Ok((
|
||||||
|
next,
|
||||||
|
DataRepresentation {
|
||||||
|
col_length: ni as usize,
|
||||||
|
row_length: nj as usize,
|
||||||
|
projection: Projection::LatLon {
|
||||||
|
ni: ni as usize,
|
||||||
|
nj: nj as usize,
|
||||||
|
lat: (lat1, lat2),
|
||||||
|
lon: (lon1, lon2),
|
||||||
|
res_com_flag: ResComFlags::from_bits(reso).unwrap(),
|
||||||
|
di,
|
||||||
|
regular_grib: dj,
|
||||||
|
scan_mode: ScanningFlags::from_bits(scan_mode).unwrap(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
events.insert(
|
||||||
|
1,
|
||||||
|
Box::new(|next| {
|
||||||
|
let (next, ni) = be_u16(next)?;
|
||||||
|
let (next, nj) = be_u16(next)?;
|
||||||
|
let (next, (lat1, lon1, reso, lat2, lon2, latin, _, scan_mode, dij, _)) =
|
||||||
|
tuple((
|
||||||
|
le_i24,
|
||||||
|
le_i24,
|
||||||
|
u8,
|
||||||
|
le_i24,
|
||||||
|
le_i24,
|
||||||
|
le_u24,
|
||||||
|
take(1usize),
|
||||||
|
u8,
|
||||||
|
count(le_i24, 2),
|
||||||
|
take(8usize),
|
||||||
|
))(next)?;
|
||||||
|
|
||||||
|
return Ok((
|
||||||
|
next,
|
||||||
|
DataRepresentation {
|
||||||
|
col_length: ni as usize,
|
||||||
|
row_length: nj as usize,
|
||||||
|
projection: Projection::Mercator {
|
||||||
|
ni: ni as usize,
|
||||||
|
nj: nj as usize,
|
||||||
|
lon: (lon1, lon2),
|
||||||
|
lat: (lat1, lat2),
|
||||||
|
latin: (latin),
|
||||||
|
di: (dij[0]),
|
||||||
|
dj: (dij[1]),
|
||||||
|
scan_mode: ScanningFlags::from_bits(scan_mode).unwrap(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
events.insert(
|
||||||
|
3,
|
||||||
|
Box::new(|next| {
|
||||||
|
let (next, nx) = be_u16(next)?;
|
||||||
|
let (next, ny) = be_u16(next)?;
|
||||||
|
let (next, (lat1, lon1, reso, lxy, center, scan, lls, _)) =
|
||||||
|
tuple((
|
||||||
|
le_i24,
|
||||||
|
le_i24,
|
||||||
|
u8,
|
||||||
|
count(le_i24, 3),
|
||||||
|
u8,
|
||||||
|
u8,
|
||||||
|
count(le_i24, 4),
|
||||||
|
take(2usize),
|
||||||
|
))(next)?;
|
||||||
|
|
||||||
|
return Ok((
|
||||||
|
next,
|
||||||
|
DataRepresentation {
|
||||||
|
col_length: nx as usize,
|
||||||
|
row_length: ny as usize,
|
||||||
|
projection: Projection::LambertConformal {
|
||||||
|
nx: nx as usize,
|
||||||
|
ny: ny as usize,
|
||||||
|
lat_1: lat1,
|
||||||
|
lon_1: lon1,
|
||||||
|
resolution: ResComFlags::from_bits(reso).unwrap(),
|
||||||
|
lov: lxy[0],
|
||||||
|
dx: lxy[1],
|
||||||
|
dy: lxy[2],
|
||||||
|
projection_center: center,
|
||||||
|
scan_mode: ScanningFlags::from_bits(scan).unwrap(),
|
||||||
|
latin_1: lls[0],
|
||||||
|
latin_2: lls[1],
|
||||||
|
southern_pole_lon: lls[2],
|
||||||
|
southern_pole_lat: lls[3],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
events.insert(
|
||||||
|
5,
|
||||||
|
Box::new(|next| {
|
||||||
|
let (next, nx) = be_u16(next)?;
|
||||||
|
let (next, ny) = be_u16(next)?;
|
||||||
|
|
||||||
|
let (next, (lat1, lon1, reso, lxy, center, scan, _)) =
|
||||||
|
tuple((le_i24, le_i24, u8, count(le_i24, 3), u8, u8, take(4usize)))(next)?;
|
||||||
|
|
||||||
|
return Ok((
|
||||||
|
next,
|
||||||
|
DataRepresentation {
|
||||||
|
col_length: nx as usize,
|
||||||
|
row_length: ny as usize,
|
||||||
|
projection: Projection::PolarStereographic {
|
||||||
|
nx: nx as usize,
|
||||||
|
ny: ny as usize,
|
||||||
|
lat_1: lat1,
|
||||||
|
lon_1: lon1,
|
||||||
|
resolution: ResComFlags::from_bits(reso).unwrap(),
|
||||||
|
lov: lxy[0],
|
||||||
|
dx: lxy[1],
|
||||||
|
dy: lxy[2],
|
||||||
|
projection_center: center,
|
||||||
|
scan_mode: ScanningFlags::from_bits(scan).unwrap(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
events.insert(
|
||||||
|
201,
|
||||||
|
Box::new(|next| {
|
||||||
|
let (next, ni) = be_u16(next)?;
|
||||||
|
let (next, nj) = be_u16(next)?;
|
||||||
|
|
||||||
|
let (next, (lat1, lon1, reso, lij, scan, _)) =
|
||||||
|
tuple((le_i24, le_i24, u8, count(le_i24, 4), u8, take(4usize)))(next)?;
|
||||||
|
|
||||||
|
return Ok((
|
||||||
|
next,
|
||||||
|
DataRepresentation {
|
||||||
|
col_length: ni as usize,
|
||||||
|
row_length: nj as usize,
|
||||||
|
projection: Projection::SemiStaggered {
|
||||||
|
ni: ni as usize,
|
||||||
|
nj: nj as usize,
|
||||||
|
lat: (lat1, lij[0]),
|
||||||
|
lon: (lon1, lij[1]),
|
||||||
|
resolution: ResComFlags::from_bits(reso).unwrap(),
|
||||||
|
di: lij[2],
|
||||||
|
dj: lij[3],
|
||||||
|
scan_mode: ScanningFlags::from_bits(scan).unwrap(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
DP { events }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DP {
|
||||||
|
fn run_event<'a>(&self, next: &'a [u8], e: u8) -> IResult<&'a [u8], DataRepresentation> {
|
||||||
|
if let Some(func) = self.events.get(&e).borrow() {
|
||||||
|
return func(next);
|
||||||
|
} else {
|
||||||
|
return Ok((next, DataRepresentation::default()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn representation_parser(input: &[u8]) -> IResult<&[u8], DataRepresentation> {
|
||||||
|
let (next, projection_type_mask) = u8(input)?;
|
||||||
|
return E.run_event(next, projection_type_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gds_parser(input: &[u8]) -> IResult<&[u8], GDS> {
|
||||||
|
let (next, gds_length) = le_u24(input)?;
|
||||||
|
let nv_p = u8;
|
||||||
|
let pv_or_pl_p = u8;
|
||||||
|
|
||||||
|
let (next, (nv, pv_pl, data_repr)) = tuple((nv_p, pv_or_pl_p, representation_parser))(next)?;
|
||||||
|
|
||||||
|
if nv == 0 {
|
||||||
|
assert!(pv_pl != 255);
|
||||||
|
let (next, pl_list) = take(data_repr.row_length * 2)(next)?;
|
||||||
|
return Ok((
|
||||||
|
next,
|
||||||
|
GDS {
|
||||||
|
nv: nv as usize,
|
||||||
|
representation: data_repr,
|
||||||
|
pv: None,
|
||||||
|
pl: Some(pl_list),
|
||||||
|
},
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
let (next, (pv_list, pl_list)) =
|
||||||
|
tuple((take(nv * 4), take(data_repr.row_length * 2)))(next)?;
|
||||||
|
return Ok((
|
||||||
|
next,
|
||||||
|
GDS {
|
||||||
|
nv: nv as usize,
|
||||||
|
representation: data_repr,
|
||||||
|
pv: Some(pv_list),
|
||||||
|
pl: Some(pl_list),
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/grib/is.rs
Normal file
28
src/grib/is.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
use nom::{
|
||||||
|
bytes::complete::tag,
|
||||||
|
number::{complete::le_u24, complete::u8},
|
||||||
|
sequence::{preceded, tuple},
|
||||||
|
IResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct IS {
|
||||||
|
total_length: usize,
|
||||||
|
version_number: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_parser(input: &[u8]) -> IResult<&[u8], IS> {
|
||||||
|
let grib = tag([]);
|
||||||
|
let total_length = le_u24;
|
||||||
|
let editon = u8;
|
||||||
|
|
||||||
|
let (input, (len, edition_number)) = preceded(grib, tuple((total_length, editon)))(input)?;
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
IS {
|
||||||
|
total_length: len as usize,
|
||||||
|
version_number: edition_number,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
7
src/grib/mod.rs
Normal file
7
src/grib/mod.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
pub mod bds;
|
||||||
|
pub mod bms;
|
||||||
|
pub mod gds;
|
||||||
|
pub mod is;
|
||||||
|
pub mod pds;
|
||||||
|
|
||||||
|
mod parm_tables;
|
||||||
@ -39,5 +39,5 @@ pub mod dwdtable_202;
|
|||||||
pub mod dwdtable_203;
|
pub mod dwdtable_203;
|
||||||
pub mod dwdtable_204;
|
pub mod dwdtable_204;
|
||||||
pub mod dwdtable_205;
|
pub mod dwdtable_205;
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Parm(&'static str, &'static str);
|
pub struct Parm(&'static str, &'static str);
|
||||||
@ -1,38 +1,20 @@
|
|||||||
use super::parm_tables::Parm;
|
|
||||||
use crate::parm_tables;
|
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use nom::bytes::complete::{tag, take};
|
use nom::bytes::complete::{tag, take};
|
||||||
use nom::multi::count;
|
use nom::multi::count;
|
||||||
use nom::number::complete::{i16, u16, u24, u8};
|
use nom::number::complete::{i16, u16, u24, u8};
|
||||||
use nom::number::Endianness::Little;
|
use nom::number::Endianness::Little;
|
||||||
use nom::sequence::{preceded, tuple};
|
use nom::sequence::{preceded, tuple, Tuple};
|
||||||
use nom::IResult;
|
use nom::IResult;
|
||||||
|
|
||||||
struct IS {
|
use super::parm_tables;
|
||||||
total_length: usize,
|
use super::parm_tables::Parm;
|
||||||
version_number: u8,
|
|
||||||
}
|
|
||||||
fn isParser(input: &[u8]) -> IResult<&[u8], IS> {
|
|
||||||
let grib = tag([]);
|
|
||||||
let total_length = u24(Little);
|
|
||||||
let editon = u8;
|
|
||||||
|
|
||||||
let (input, (len, edition_number)) = preceded(grib, tuple((total_length, editon)))(input)?;
|
#[derive(Debug)]
|
||||||
|
pub struct PDS {
|
||||||
Ok((
|
|
||||||
input,
|
|
||||||
IS {
|
|
||||||
total_length: len as usize,
|
|
||||||
version_number: edition_number,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PDS {
|
|
||||||
center_identification: Center,
|
center_identification: Center,
|
||||||
generating_process_id: u8,
|
generating_process_id: u8,
|
||||||
grid_identification: u8,
|
grid_identification: u8,
|
||||||
gds_or_bms: (bool, bool),
|
pub gds_or_bms: (bool, bool),
|
||||||
unit: Parm,
|
unit: Parm,
|
||||||
level_type_and_value: String,
|
level_type_and_value: String,
|
||||||
datetime: DateTime<Utc>,
|
datetime: DateTime<Utc>,
|
||||||
@ -43,7 +25,7 @@ struct PDS {
|
|||||||
missing: u8,
|
missing: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
enum Center {
|
enum Center {
|
||||||
WMC(u8),
|
WMC(u8),
|
||||||
RSMC(u8),
|
RSMC(u8),
|
||||||
@ -54,7 +36,7 @@ enum Center {
|
|||||||
Other(u8),
|
Other(u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
enum SubCenter {
|
enum SubCenter {
|
||||||
NCEPReAnalysis,
|
NCEPReAnalysis,
|
||||||
NCEPEnsemble,
|
NCEPEnsemble,
|
||||||
@ -493,7 +475,7 @@ fn decimal_scale_parser(input: &[u8]) -> IResult<&[u8], i32> {
|
|||||||
Ok((next, result))
|
Ok((next, result))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pds_parser(input: &[u8]) -> IResult<&[u8], PDS> {
|
pub fn pds_parser(input: &[u8]) -> IResult<&[u8], PDS> {
|
||||||
let date_time_parser = take(5usize);
|
let date_time_parser = take(5usize);
|
||||||
|
|
||||||
let length = u24(Little);
|
let length = u24(Little);
|
||||||
51
src/lib.rs
Normal file
51
src/lib.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
use grib::{
|
||||||
|
bds::{self, bds_parser, BDS},
|
||||||
|
bms::{bms_parser, BMS},
|
||||||
|
gds::{gds_parser, GDS},
|
||||||
|
is::{is_parser, IS},
|
||||||
|
pds::{pds_parser, PDS},
|
||||||
|
};
|
||||||
|
use nom::{sequence::tuple, IResult};
|
||||||
|
|
||||||
|
pub mod grib;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Project<'a> {
|
||||||
|
is: IS,
|
||||||
|
pds: PDS,
|
||||||
|
gds: Option<GDS<'a>>,
|
||||||
|
bms: Option<BMS<'a>>,
|
||||||
|
bds: BDS<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn test_mth<'a>(input: &'a [u8]) -> IResult<&'a [u8], Project<'a>> {
|
||||||
|
let (mut next, (is, pds)) = tuple((is_parser, pds_parser))(input)?;
|
||||||
|
|
||||||
|
let mut gds: Option<GDS> = None;
|
||||||
|
let mut bms: Option<BMS> = None;
|
||||||
|
|
||||||
|
if pds.gds_or_bms.0 {
|
||||||
|
let (n, g) = gds_parser(next)?;
|
||||||
|
next = n;
|
||||||
|
gds = Some(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
if pds.gds_or_bms.1 {
|
||||||
|
let (n, b) = bms_parser(next)?;
|
||||||
|
next = n;
|
||||||
|
bms = Some(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (next, bds) = bds_parser(next)?;
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
next,
|
||||||
|
Project {
|
||||||
|
is,
|
||||||
|
pds,
|
||||||
|
gds,
|
||||||
|
bms,
|
||||||
|
bds,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
576
src/libs.rs
576
src/libs.rs
@ -1,576 +0,0 @@
|
|||||||
use super::parm_tables::Parm;
|
|
||||||
use crate::parm_tables;
|
|
||||||
use chrono::prelude::*;
|
|
||||||
use nom::bytes::complete::{tag, take};
|
|
||||||
use nom::multi::count;
|
|
||||||
use nom::number::complete::{i16, u16, u24, u8};
|
|
||||||
use nom::number::Endianness::Little;
|
|
||||||
use nom::sequence::{preceded, tuple};
|
|
||||||
use nom::IResult;
|
|
||||||
|
|
||||||
struct IS {
|
|
||||||
total_length: usize,
|
|
||||||
version_number: u8,
|
|
||||||
}
|
|
||||||
fn isParser(input: &[u8]) -> IResult<&[u8], IS> {
|
|
||||||
let grib = tag([]);
|
|
||||||
let total_length = u24(Little);
|
|
||||||
let editon = u8;
|
|
||||||
|
|
||||||
let (input, (len, edition_number)) = preceded(grib, tuple((total_length, editon)))(input)?;
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
input,
|
|
||||||
IS {
|
|
||||||
total_length: len as usize,
|
|
||||||
version_number: edition_number,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PDS {
|
|
||||||
center_identification: Center,
|
|
||||||
generating_process_id: u8,
|
|
||||||
grid_identification: u8,
|
|
||||||
gds_or_bms: (bool, bool),
|
|
||||||
unit: Parm,
|
|
||||||
level_type_and_value: String,
|
|
||||||
datetime: DateTime<Utc>,
|
|
||||||
time_range: String,
|
|
||||||
average_or_missing_number: i16,
|
|
||||||
decimal_scale: i32,
|
|
||||||
sub_center: SubCenter,
|
|
||||||
missing: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
enum Center {
|
|
||||||
WMC(u8),
|
|
||||||
RSMC(u8),
|
|
||||||
RAFC(u8),
|
|
||||||
RsmcAndRafc(u8),
|
|
||||||
WAFC(u8),
|
|
||||||
NMC(u8),
|
|
||||||
Other(u8),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
enum SubCenter {
|
|
||||||
NCEPReAnalysis,
|
|
||||||
NCEPEnsemble,
|
|
||||||
NCEPCentral,
|
|
||||||
EnvModelingCenter,
|
|
||||||
WeatherPredictionCenter,
|
|
||||||
OceanPredictionCenter,
|
|
||||||
ClimatePredictionCenter,
|
|
||||||
AviationWeatherCenter,
|
|
||||||
StormPredictionCenter,
|
|
||||||
NationalHurricaneCenter,
|
|
||||||
NWSTechDevLab,
|
|
||||||
NESDIS,
|
|
||||||
FederalAviationAdministration,
|
|
||||||
NWSMeteorologialDevLab,
|
|
||||||
NorthAmericaRegionalRA,
|
|
||||||
SpaceWeather,
|
|
||||||
ESRLGlobalSystem,
|
|
||||||
Other,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum GridID {
|
|
||||||
Lambert,
|
|
||||||
Mocator,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn center_parser(input: &[u8]) -> IResult<&[u8], (Center, PreConfParaTable)> {
|
|
||||||
let (next, value) = u8(input)?;
|
|
||||||
match value {
|
|
||||||
// WMC
|
|
||||||
1..=6 => Ok((next, (Center::WMC(value), PreConfParaTable::NONE))),
|
|
||||||
7 => Ok((next, (Center::WMC(value), PreConfParaTable::NMC))),
|
|
||||||
8..=9 => Ok((next, (Center::WMC(value), PreConfParaTable::NONE))),
|
|
||||||
|
|
||||||
// RSMC/RAFC
|
|
||||||
10..=15 | 28 | 29 | 41..=44 | 51 | 69 | 70 => {
|
|
||||||
Ok((next, (Center::RsmcAndRafc(value), PreConfParaTable::NONE)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// RSMC
|
|
||||||
16..=19 | 21 | 24..=27 | 30..=35 | 38 | 39 | 53 | 65..=67 | 71 | 74 | 75 | 79..=81 => {
|
|
||||||
Ok((next, (Center::RSMC(value), PreConfParaTable::NONE)))
|
|
||||||
}
|
|
||||||
54 => Ok((next, (Center::RSMC(value), PreConfParaTable::CMC))),
|
|
||||||
78 => Ok((next, (Center::RSMC(value), PreConfParaTable::DWD))),
|
|
||||||
|
|
||||||
// NMC
|
|
||||||
23
|
|
||||||
| 47..=50
|
|
||||||
| 73
|
|
||||||
| 102..=109
|
|
||||||
| 111..=122
|
|
||||||
| 124..=136
|
|
||||||
| 140..=144
|
|
||||||
| 150..=153
|
|
||||||
| 156..=159
|
|
||||||
| 162..=165
|
|
||||||
| 167..=171
|
|
||||||
| 190..=198
|
|
||||||
| 201..=203
|
|
||||||
| 222..=232
|
|
||||||
| 234..=238
|
|
||||||
| 240
|
|
||||||
| 242..=246 => Ok((next, (Center::NMC(value), PreConfParaTable::NONE))),
|
|
||||||
200 => Ok((next, (Center::NMC(value), PreConfParaTable::LAMI))),
|
|
||||||
|
|
||||||
// WAFC
|
|
||||||
93 => Ok((next, (Center::WAFC(value), PreConfParaTable::NONE))),
|
|
||||||
|
|
||||||
// Other
|
|
||||||
146 => Ok((next, (Center::Other(value), PreConfParaTable::CHM))),
|
|
||||||
46 => Ok((next, (Center::Other(value), PreConfParaTable::CPTEC))),
|
|
||||||
20 | 92 => Ok((next, (Center::RAFC(value), PreConfParaTable::NONE))),
|
|
||||||
_ => Ok((next, (Center::Other(value), PreConfParaTable::NONE))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gds_or_bms_parser(input: &[u8]) -> IResult<&[u8], (bool, bool)> {
|
|
||||||
let (next, value) = u8(input)?;
|
|
||||||
let gds = if value & 128 != 0 { true } else { false };
|
|
||||||
let bms = if value & 64 != 0 { true } else { false };
|
|
||||||
|
|
||||||
Ok((next, (gds, bms)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn levels(layer_indicator: u8, center: &PreConfParaTable, key_value: u16) -> String {
|
|
||||||
let o11 = key_value / 256;
|
|
||||||
let o12 = key_value % 256;
|
|
||||||
|
|
||||||
return match layer_indicator {
|
|
||||||
1 => String::from("sfc"),
|
|
||||||
2 => String::from("cloud base"),
|
|
||||||
3 => String::from(String::from("cloud top")),
|
|
||||||
4 => String::from("0 deg isotherm"),
|
|
||||||
5 => String::from("cond level"),
|
|
||||||
6 => String::from("max wind level"),
|
|
||||||
7 => String::from("tropopause"),
|
|
||||||
8 => String::from("nominal top of atmosphere"),
|
|
||||||
9 => String::from("sea bottom"),
|
|
||||||
|
|
||||||
100 => format!("{} mb", key_value),
|
|
||||||
101 => format!("{}-{} mb", o11 + 10, o12 + 10),
|
|
||||||
102 => String::from("mean sea level (MSL)"),
|
|
||||||
103 => format!("{} m above MSL", key_value),
|
|
||||||
104 => format!("{}-{} m above MSL", o11 * 100, o12 * 100),
|
|
||||||
105 => format!("{} m above gnd", key_value),
|
|
||||||
106 => format!("{}-{} m above gnd", o11 * 100, o12 * 100),
|
|
||||||
107 => format!("sigma={:.4}", key_value as f32 / 10000.0),
|
|
||||||
108 => format!("sigma {:.2}-{:.2}", o11 as f32 / 100.0, o12 as f32 / 100.0),
|
|
||||||
109 => format!("hybrid level {}", key_value),
|
|
||||||
110 => format!("hybrid {}-{}", o11, o12),
|
|
||||||
111 => format!("{} cm down", key_value),
|
|
||||||
112 => format!("{}-{} cm down", o11, o12),
|
|
||||||
113 => format!("pot-temp={}K", key_value),
|
|
||||||
114 => format!("{}-{}K", 475 - o11, 475 - o12),
|
|
||||||
115 => format!("{} mb above gnd", key_value),
|
|
||||||
116 => format!("{}-{} mb above gnd", o11, o12),
|
|
||||||
117 => format!(
|
|
||||||
"{} pv units",
|
|
||||||
(1 - ((o11 & 0x80) >> 6) as u32) * ((o11 & 0x7f) << 8 + o12) as u32
|
|
||||||
),
|
|
||||||
119 => format!("{:.5} (ETA level)", key_value as f32 / 10000.0),
|
|
||||||
120 => format!(
|
|
||||||
"{:.2}-{:.2} (ETA levels)",
|
|
||||||
o11 as f32 / 100.0,
|
|
||||||
o12 as f32 / 100.0
|
|
||||||
),
|
|
||||||
121 => format!("{}-{} mb", 1100 - o11, 1100 - o12),
|
|
||||||
125 => format!("{} cm above gnd", key_value),
|
|
||||||
126 => match center {
|
|
||||||
PreConfParaTable::NMC => format!("{:.2} mb", key_value as f32 * 0.01),
|
|
||||||
_ => String::from("None"),
|
|
||||||
},
|
|
||||||
128 => format!(
|
|
||||||
"{:.3}-{:.3} (sigma)",
|
|
||||||
1.1 - o11 as f32 / 1000.0,
|
|
||||||
1.1 - o12 as f32 / 1000.0
|
|
||||||
),
|
|
||||||
141 => format!("{}-{} mb", o11 * 10, 1100 - o12),
|
|
||||||
160 => format!("{} m below sea level", key_value),
|
|
||||||
|
|
||||||
200 => String::from("atmos col"),
|
|
||||||
201 => String::from("ocean column"),
|
|
||||||
|
|
||||||
204 => String::from("high trop freezing lvl"),
|
|
||||||
206 => String::from("grid-scale cloud bottom"),
|
|
||||||
207 => String::from("grid-scale cloud top"),
|
|
||||||
209 => String::from("boundary layer cloud bottom"),
|
|
||||||
|
|
||||||
210 => match center {
|
|
||||||
PreConfParaTable::NMC => String::from("boundary-layer cloud top"),
|
|
||||||
_ => format!("{:.2} mb", key_value as f32 * 0.01),
|
|
||||||
},
|
|
||||||
|
|
||||||
211 => String::from("boundary layer cloud layer"),
|
|
||||||
212 => String::from("low cloud bottom"),
|
|
||||||
213 => String::from("low cloud top"),
|
|
||||||
214 => String::from("low cloud layer"),
|
|
||||||
215 => String::from("cloud ceiling"),
|
|
||||||
216 => String::from("Cb base"),
|
|
||||||
217 => String::from("Cb top"),
|
|
||||||
220 => String::from("planetary boundary layer(from Richardson no.)"),
|
|
||||||
|
|
||||||
222 => String::from("middle cloud bottom"),
|
|
||||||
223 => String::from("middle cloud top"),
|
|
||||||
224 => String::from("middle cloud layer"),
|
|
||||||
|
|
||||||
232 => String::from("high cloud bottom"),
|
|
||||||
233 => String::from("high cloud top"),
|
|
||||||
234 => String::from("high cloud layer"),
|
|
||||||
|
|
||||||
235 => {
|
|
||||||
if key_value % 10 == 0 {
|
|
||||||
format!("{}C ocean isotherm level", key_value / 10)
|
|
||||||
} else {
|
|
||||||
format!("{:.1}C ocean isotherm level", key_value as f32 / 10.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
236 => format!("{}-{}m ocean layer", o11 * 10, o12 * 10),
|
|
||||||
|
|
||||||
237 => String::from("ocean mixed layer bottom"),
|
|
||||||
238 => String::from("ocean isothermal layer bottom"),
|
|
||||||
239 => String::from("surface-26C ocean layer"),
|
|
||||||
240 => String::from("ocean mixed layer"),
|
|
||||||
241 => String::from("ordered sequence of data"),
|
|
||||||
242 => String::from("convect-cloud bottom"),
|
|
||||||
243 => String::from("convect-cloud top"),
|
|
||||||
244 => String::from("convect-cloud layer"),
|
|
||||||
245 => String::from("lowest level of wet bulb zero"),
|
|
||||||
246 => String::from("max e-pot-temp level"),
|
|
||||||
247 => String::from("equilibrium level"),
|
|
||||||
248 => String::from("shallow convect-cloud bottom"),
|
|
||||||
249 => String::from("shallow convect-cloud top"),
|
|
||||||
251 => String::from("deep convect-cloud bottom"),
|
|
||||||
252 => String::from("deep convect-cloud top"),
|
|
||||||
253 => String::from("lowest bottom level of supercooled liquid water layer"),
|
|
||||||
254 => String::from("highest top level of supercooled liquid water layer"),
|
|
||||||
_ => String::from(""),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
enum PreConfParaTable {
|
|
||||||
NMC,
|
|
||||||
ECMWF,
|
|
||||||
DWD,
|
|
||||||
CMC,
|
|
||||||
CPTEC,
|
|
||||||
CHM,
|
|
||||||
LAMI,
|
|
||||||
NONE,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unit_parser(
|
|
||||||
value: u8,
|
|
||||||
p_table: u8,
|
|
||||||
center: &PreConfParaTable,
|
|
||||||
sub_center: &SubCenter,
|
|
||||||
process: u8,
|
|
||||||
) -> Parm {
|
|
||||||
let mut para_table: &'static [Parm; 256] = &parm_tables::nceptable_opn::NCEP_OPN_PARM_TABLE;
|
|
||||||
|
|
||||||
match *center {
|
|
||||||
PreConfParaTable::NMC => {
|
|
||||||
if p_table <= 3 {
|
|
||||||
match sub_center {
|
|
||||||
SubCenter::NCEPReAnalysis => {
|
|
||||||
para_table = &parm_tables::nceptable_reanal::NCEP_REANAL_PARM_TABLE
|
|
||||||
}
|
|
||||||
|
|
||||||
SubCenter::NWSMeteorologialDevLab => {
|
|
||||||
para_table = &parm_tables::nceptable_mdl::NCEP_TABLE_MDL_PARM_TABLE
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process != 80 && process != 180) || (p_table != 1 && p_table != 2) {
|
|
||||||
para_table = &parm_tables::nceptable_opn::NCEP_OPN_PARM_TABLE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
match p_table {
|
|
||||||
128 => para_table = &parm_tables::nceptab_128::NCEP_128,
|
|
||||||
129 => para_table = &parm_tables::nceptab_129::NCEP_129,
|
|
||||||
130 => para_table = &parm_tables::nceptab_130::NCEP_130,
|
|
||||||
131 => para_table = &parm_tables::nceptab_131::NCEP_131,
|
|
||||||
133 => para_table = &parm_tables::nceptab_133::NCEP_133,
|
|
||||||
140 => para_table = &parm_tables::nceptab_140::NCEP_140,
|
|
||||||
141 => para_table = &parm_tables::nceptab_141::NCEP_141,
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PreConfParaTable::ECMWF => {}
|
|
||||||
|
|
||||||
PreConfParaTable::DWD | PreConfParaTable::CHM => {}
|
|
||||||
|
|
||||||
PreConfParaTable::CPTEC => {}
|
|
||||||
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
para_table[value as usize]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn time_unit(input: u8) -> String {
|
|
||||||
// MINUTE 0
|
|
||||||
// HOUR 1
|
|
||||||
// DAY 2
|
|
||||||
// MONTH 3
|
|
||||||
// YEAR 4
|
|
||||||
// DECADE 5
|
|
||||||
// NORMAL 6
|
|
||||||
// CENTURY 7
|
|
||||||
// HOURS3 10
|
|
||||||
// HOURS6 11
|
|
||||||
// HOURS12 12
|
|
||||||
// MINUTES15 13
|
|
||||||
// MINUTES30 14
|
|
||||||
// SECOND 254
|
|
||||||
match input {
|
|
||||||
0 => String::from("Minute"),
|
|
||||||
1 => String::from("Hour"),
|
|
||||||
2 => String::from("Day"),
|
|
||||||
3 => String::from("Month"),
|
|
||||||
4 => String::from("Year"),
|
|
||||||
5 => String::from("Decade"),
|
|
||||||
6 => String::from("Normal"),
|
|
||||||
7 => String::from("Century"),
|
|
||||||
10 => String::from("3 Hours"),
|
|
||||||
11 => String::from("6 Hours"),
|
|
||||||
12 => String::from("12 Hours"),
|
|
||||||
13 => String::from("15 Minutes"),
|
|
||||||
14 => String::from("30 Minutes"),
|
|
||||||
254 => String::from("Second"),
|
|
||||||
_ => String::from("Undefined"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn subcenter_parser(input: &[u8]) -> IResult<&[u8], SubCenter> {
|
|
||||||
let (next, value) = u8(input)?;
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
next,
|
|
||||||
match value {
|
|
||||||
1 => SubCenter::NCEPReAnalysis,
|
|
||||||
2 => SubCenter::NCEPEnsemble,
|
|
||||||
3 => SubCenter::NCEPCentral,
|
|
||||||
4 => SubCenter::EnvModelingCenter,
|
|
||||||
5 => SubCenter::WeatherPredictionCenter,
|
|
||||||
6 => SubCenter::OceanPredictionCenter,
|
|
||||||
7 => SubCenter::ClimatePredictionCenter,
|
|
||||||
8 => SubCenter::AviationWeatherCenter,
|
|
||||||
9 => SubCenter::StormPredictionCenter,
|
|
||||||
10 => SubCenter::NationalHurricaneCenter,
|
|
||||||
11 => SubCenter::NWSTechDevLab,
|
|
||||||
12 => SubCenter::NESDIS,
|
|
||||||
13 => SubCenter::FederalAviationAdministration,
|
|
||||||
14 => SubCenter::NWSMeteorologialDevLab,
|
|
||||||
15 => SubCenter::NorthAmericaRegionalRA,
|
|
||||||
16 => SubCenter::SpaceWeather,
|
|
||||||
17 => SubCenter::ESRLGlobalSystem,
|
|
||||||
_ => SubCenter::Other,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init_time(input: &[u8], century: u8) -> DateTime<Utc> {
|
|
||||||
let year = 100 * (century as i32 - 1) + input[0] as i32;
|
|
||||||
let month = input[1] as u32;
|
|
||||||
let day = input[2] as u32;
|
|
||||||
let hour = input[3] as u32;
|
|
||||||
|
|
||||||
let minute = input[4] as u32;
|
|
||||||
|
|
||||||
Utc.ymd(year, month, day).and_hms(hour, minute, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn time_range_parser(input: &[u8]) -> IResult<&[u8], String> {
|
|
||||||
let (next, value) = count(u8, 4)(input)?;
|
|
||||||
|
|
||||||
let unit = time_unit(value[0]);
|
|
||||||
|
|
||||||
let time_range = value[1];
|
|
||||||
let p1 = value[2];
|
|
||||||
let p2 = value[3];
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
next,
|
|
||||||
match time_range {
|
|
||||||
0 | 1 | 10 => format!(""),
|
|
||||||
2 => format!("valid {}-{}{}:", p1, p2, unit),
|
|
||||||
|
|
||||||
3 => format!("{}-{}{} ave:", p1, p2, unit),
|
|
||||||
|
|
||||||
4 => format!("{}-{}{} acc:", p1, p2, unit),
|
|
||||||
|
|
||||||
5 => format!("{}-{}{} diff:", p1, p2, unit),
|
|
||||||
|
|
||||||
6 => format!("-{} to -{} {} ave:", p1, p2, unit),
|
|
||||||
|
|
||||||
7 => format!("-{} to {} {} ave:", p1, p2, unit),
|
|
||||||
|
|
||||||
11 => {
|
|
||||||
if p1 > 0 {
|
|
||||||
format!("init fcst {}{}:", p1, unit)
|
|
||||||
} else {
|
|
||||||
format!("time?:")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
13 => format!("nudge ana {}{}:", p1, unit),
|
|
||||||
|
|
||||||
14 => format!("rel. fcst {}{}:", p1, unit),
|
|
||||||
|
|
||||||
51 => {
|
|
||||||
if p1 == 0 {
|
|
||||||
/* format!("clim {}{}:",p2,unit), */
|
|
||||||
format!("0-{}{} product:ave@1yr:", p2, unit)
|
|
||||||
} else if p1 == 1 {
|
|
||||||
/* format!("clim (diurnal) {}{}:",p2,unit), */
|
|
||||||
format!("0-{}{} product:same-hour,ave@1yr:", p2, unit)
|
|
||||||
} else {
|
|
||||||
format!("clim? p1={}? {}{}?:", p1, p2, unit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
113 | 123 => format!("ave@{}{}:", p2, unit),
|
|
||||||
|
|
||||||
114 | 124 => format!("acc@{}{}:", p2, unit),
|
|
||||||
|
|
||||||
115 => format!("ave of fcst:{} to {}{}:", p1, p2, unit),
|
|
||||||
|
|
||||||
116 => format!("acc of fcst:{} to {}{}:", p1, p2, unit),
|
|
||||||
|
|
||||||
118 => format!("var@{}{}:", p2, unit),
|
|
||||||
|
|
||||||
128 => format!("{}-{}{} fcst acc:ave@24hr:", p1, p2, unit),
|
|
||||||
|
|
||||||
129 => format!("{}-{}{} fcst acc:ave@{}{}:", p1, p2, unit, p2 - p1, unit),
|
|
||||||
|
|
||||||
130 => format!("{}-{}{} fcst ave:ave@24hr:", p1, p2, unit),
|
|
||||||
|
|
||||||
131 => format!("{}-{}{} fcst ave:ave@{}{}:", p1, p2, unit, p2 - p1, unit),
|
|
||||||
|
|
||||||
/* for CFS */
|
|
||||||
132 => format!("{}-{}{} anl:ave@1yr:", p1, p2, unit),
|
|
||||||
|
|
||||||
133 => format!("{}-{}{} fcst:ave@1yr:", p1, p2, unit),
|
|
||||||
|
|
||||||
134 => format!("{}-{}{} fcst-anl:rms@1yr:", p1, p2, unit),
|
|
||||||
|
|
||||||
135 => format!("{}-{}{} fcst-fcst_mean:rms@1yr:", p1, p2, unit),
|
|
||||||
|
|
||||||
136 => format!("{}-{}{} anl-anl_mean:rms@1yr:", p1, p2, unit),
|
|
||||||
|
|
||||||
137 => format!("{}-{}{} fcst acc:ave@6hr:", p1, p2, unit),
|
|
||||||
|
|
||||||
138 => format!("{}-{}{} fcst ave:ave@6hr:", p1, p2, unit),
|
|
||||||
|
|
||||||
139 => format!("{}-{}{} fcst acc:ave@12hr:", p1, p2, unit),
|
|
||||||
|
|
||||||
140 => format!("{}-{}{} fcst ave:ave@12hr:", p1, p2, unit),
|
|
||||||
|
|
||||||
_ => format!("time?:"),
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decimal_scale_parser(input: &[u8]) -> IResult<&[u8], i32> {
|
|
||||||
let (next, value) = take(2usize)(input)?;
|
|
||||||
|
|
||||||
let result = 1 - ((value[0] & 0x80) >> 6) as i32 * (((value[0] & 0x7f) << 8) + value[1]) as i32;
|
|
||||||
|
|
||||||
Ok((next, result))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pds_parser(input: &[u8]) -> IResult<&[u8], PDS> {
|
|
||||||
let date_time_parser = take(5usize);
|
|
||||||
|
|
||||||
let length = u24(Little);
|
|
||||||
|
|
||||||
let (
|
|
||||||
next,
|
|
||||||
(
|
|
||||||
ll,
|
|
||||||
p_table,
|
|
||||||
center_and_preconf,
|
|
||||||
process,
|
|
||||||
grid_id,
|
|
||||||
flag,
|
|
||||||
raw_unit,
|
|
||||||
level_type,
|
|
||||||
raw_level,
|
|
||||||
date_time,
|
|
||||||
time_range,
|
|
||||||
average_or_acc,
|
|
||||||
missing,
|
|
||||||
init_century,
|
|
||||||
subcenter,
|
|
||||||
decimal_factor,
|
|
||||||
),
|
|
||||||
) = tuple((
|
|
||||||
length,
|
|
||||||
u8,
|
|
||||||
center_parser,
|
|
||||||
u8,
|
|
||||||
u8,
|
|
||||||
gds_or_bms_parser,
|
|
||||||
u8,
|
|
||||||
u8,
|
|
||||||
u16(Little),
|
|
||||||
date_time_parser,
|
|
||||||
time_range_parser,
|
|
||||||
i16(Little),
|
|
||||||
u8,
|
|
||||||
u8,
|
|
||||||
subcenter_parser,
|
|
||||||
decimal_scale_parser,
|
|
||||||
))(input)?;
|
|
||||||
|
|
||||||
let unit = unit_parser(
|
|
||||||
raw_unit,
|
|
||||||
p_table,
|
|
||||||
¢er_and_preconf.1,
|
|
||||||
&subcenter,
|
|
||||||
process,
|
|
||||||
);
|
|
||||||
let levels = levels(level_type, ¢er_and_preconf.1, raw_level);
|
|
||||||
|
|
||||||
let init_time = init_time(date_time, init_century);
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
next,
|
|
||||||
PDS {
|
|
||||||
center_identification: center_and_preconf.0,
|
|
||||||
generating_process_id: process,
|
|
||||||
grid_identification: grid_id,
|
|
||||||
gds_or_bms: flag,
|
|
||||||
unit,
|
|
||||||
time_range,
|
|
||||||
level_type_and_value: levels,
|
|
||||||
datetime: init_time,
|
|
||||||
average_or_missing_number: average_or_acc,
|
|
||||||
decimal_scale: decimal_factor,
|
|
||||||
sub_center: subcenter,
|
|
||||||
missing,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
struct GDS {
|
|
||||||
length: usize,
|
|
||||||
nv: u8,
|
|
||||||
pv_or_pl: u8,
|
|
||||||
r_type: u8,
|
|
||||||
description: u8,
|
|
||||||
}
|
|
||||||
@ -1,8 +1,3 @@
|
|||||||
pub mod gds;
|
|
||||||
pub mod libs;
|
|
||||||
pub mod parm_tables;
|
|
||||||
pub mod pds;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Hello, world!");
|
println!("Hello, world!");
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user