From 7b790830f490795e9f5cf41eaff30136b9407a21 Mon Sep 17 00:00:00 2001 From: sleptworld Date: Thu, 19 Jan 2023 19:18:17 +0800 Subject: [PATCH] finished all part --- Cargo.lock | 356 ++++++++++- Cargo.toml | 11 + pyproject.toml | 12 + src/gds.rs | 85 --- src/grib/bds.rs | 83 +++ src/grib/bms.rs | 100 +++ src/grib/gds.rs | 402 ++++++++++++ src/grib/is.rs | 28 + src/grib/mod.rs | 7 + src/{ => grib}/parm_tables/dwdtable_002.rs | 0 src/{ => grib}/parm_tables/dwdtable_201.rs | 0 src/{ => grib}/parm_tables/dwdtable_202.rs | 0 src/{ => grib}/parm_tables/dwdtable_203.rs | 0 src/{ => grib}/parm_tables/dwdtable_204.rs | 0 src/{ => grib}/parm_tables/dwdtable_205.rs | 0 src/{ => grib}/parm_tables/ectable_128.rs | 0 src/{ => grib}/parm_tables/ectable_129.rs | 0 src/{ => grib}/parm_tables/ectable_130.rs | 0 src/{ => grib}/parm_tables/ectable_131.rs | 0 src/{ => grib}/parm_tables/ectable_132.rs | 0 src/{ => grib}/parm_tables/ectable_133.rs | 0 src/{ => grib}/parm_tables/ectable_140.rs | 0 src/{ => grib}/parm_tables/ectable_150.rs | 0 src/{ => grib}/parm_tables/ectable_151.rs | 0 src/{ => grib}/parm_tables/ectable_160.rs | 0 src/{ => grib}/parm_tables/ectable_162.rs | 0 src/{ => grib}/parm_tables/ectable_170.rs | 0 src/{ => grib}/parm_tables/ectable_171.rs | 0 src/{ => grib}/parm_tables/ectable_172.rs | 0 src/{ => grib}/parm_tables/ectable_173.rs | 0 src/{ => grib}/parm_tables/ectable_174.rs | 0 src/{ => grib}/parm_tables/ectable_180.rs | 0 src/{ => grib}/parm_tables/ectable_190.rs | 0 src/{ => grib}/parm_tables/ectable_200.rs | 0 src/{ => grib}/parm_tables/ectable_210.rs | 0 src/{ => grib}/parm_tables/ectable_211.rs | 0 src/{ => grib}/parm_tables/ectable_228.rs | 0 src/{ => grib}/parm_tables/mod.rs | 2 +- src/{ => grib}/parm_tables/nceptab_128.rs | 0 src/{ => grib}/parm_tables/nceptab_129.rs | 0 src/{ => grib}/parm_tables/nceptab_130.rs | 0 src/{ => grib}/parm_tables/nceptab_131.rs | 0 src/{ => grib}/parm_tables/nceptab_133.rs | 0 src/{ => grib}/parm_tables/nceptab_140.rs | 0 src/{ => grib}/parm_tables/nceptab_141.rs | 0 src/{ => grib}/parm_tables/nceptable_mdl.rs | 0 src/{ => grib}/parm_tables/nceptable_opn.rs | 0 .../parm_tables/nceptable_reanal.rs | 0 src/{ => grib}/pds.rs | 36 +- src/lib.rs | 51 ++ src/libs.rs | 576 ------------------ src/main.rs | 5 - 52 files changed, 1059 insertions(+), 695 deletions(-) create mode 100644 pyproject.toml delete mode 100644 src/gds.rs create mode 100644 src/grib/bds.rs create mode 100644 src/grib/bms.rs create mode 100644 src/grib/gds.rs create mode 100644 src/grib/is.rs create mode 100644 src/grib/mod.rs rename src/{ => grib}/parm_tables/dwdtable_002.rs (100%) rename src/{ => grib}/parm_tables/dwdtable_201.rs (100%) rename src/{ => grib}/parm_tables/dwdtable_202.rs (100%) rename src/{ => grib}/parm_tables/dwdtable_203.rs (100%) rename src/{ => grib}/parm_tables/dwdtable_204.rs (100%) rename src/{ => grib}/parm_tables/dwdtable_205.rs (100%) rename src/{ => grib}/parm_tables/ectable_128.rs (100%) rename src/{ => grib}/parm_tables/ectable_129.rs (100%) rename src/{ => grib}/parm_tables/ectable_130.rs (100%) rename src/{ => grib}/parm_tables/ectable_131.rs (100%) rename src/{ => grib}/parm_tables/ectable_132.rs (100%) rename src/{ => grib}/parm_tables/ectable_133.rs (100%) rename src/{ => grib}/parm_tables/ectable_140.rs (100%) rename src/{ => grib}/parm_tables/ectable_150.rs (100%) rename src/{ => grib}/parm_tables/ectable_151.rs (100%) rename src/{ => grib}/parm_tables/ectable_160.rs (100%) rename src/{ => grib}/parm_tables/ectable_162.rs (100%) rename src/{ => grib}/parm_tables/ectable_170.rs (100%) rename src/{ => grib}/parm_tables/ectable_171.rs (100%) rename src/{ => grib}/parm_tables/ectable_172.rs (100%) rename src/{ => grib}/parm_tables/ectable_173.rs (100%) rename src/{ => grib}/parm_tables/ectable_174.rs (100%) rename src/{ => grib}/parm_tables/ectable_180.rs (100%) rename src/{ => grib}/parm_tables/ectable_190.rs (100%) rename src/{ => grib}/parm_tables/ectable_200.rs (100%) rename src/{ => grib}/parm_tables/ectable_210.rs (100%) rename src/{ => grib}/parm_tables/ectable_211.rs (100%) rename src/{ => grib}/parm_tables/ectable_228.rs (100%) rename src/{ => grib}/parm_tables/mod.rs (96%) rename src/{ => grib}/parm_tables/nceptab_128.rs (100%) rename src/{ => grib}/parm_tables/nceptab_129.rs (100%) rename src/{ => grib}/parm_tables/nceptab_130.rs (100%) rename src/{ => grib}/parm_tables/nceptab_131.rs (100%) rename src/{ => grib}/parm_tables/nceptab_133.rs (100%) rename src/{ => grib}/parm_tables/nceptab_140.rs (100%) rename src/{ => grib}/parm_tables/nceptab_141.rs (100%) rename src/{ => grib}/parm_tables/nceptable_mdl.rs (100%) rename src/{ => grib}/parm_tables/nceptable_opn.rs (100%) rename src/{ => grib}/parm_tables/nceptable_reanal.rs (100%) rename src/{ => grib}/pds.rs (96%) create mode 100644 src/lib.rs delete mode 100644 src/libs.rs diff --git a/Cargo.lock b/Cargo.lock index 7da0511..a842f02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,35 @@ # It is not intended for manual editing. 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]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "chrono" version = "0.4.19" @@ -21,24 +44,94 @@ dependencies = [ "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]] name = "libc" version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "nom" version = "7.1.1" @@ -49,6 +142,15 @@ dependencies = [ "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]] name = "num-integer" version = "0.1.45" @@ -68,14 +170,185 @@ dependencies = [ "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]] name = "ripgrib" version = "0.1.0" dependencies = [ + "bitflags", "chrono", + "ibmfloat", + "lazy_static", "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]] name = "time" version = "0.1.44" @@ -83,16 +356,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", - "wasi", + "wasi 0.10.0+wasi-snapshot-preview1", "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]] 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 = "winapi" version = "0.3.9" @@ -114,3 +411,60 @@ 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-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" diff --git a/Cargo.toml b/Cargo.toml index b18580d..e019f08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,18 @@ version = "0.1.0" edition = "2021" # 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] nom = "7.1.1" 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" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..d010ffb --- /dev/null +++ b/pyproject.toml @@ -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", +] diff --git a/src/gds.rs b/src/gds.rs deleted file mode 100644 index df648d8..0000000 --- a/src/gds.rs +++ /dev/null @@ -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; -} diff --git a/src/grib/bds.rs b/src/grib/bds.rs new file mode 100644 index 0000000..7b01d1a --- /dev/null +++ b/src/grib/bds.rs @@ -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 {} + // } + // } +} diff --git a/src/grib/bms.rs b/src/grib/bms.rs new file mode 100644 index 0000000..20f0f97 --- /dev/null +++ b/src/grib/bms.rs @@ -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>, +} + +impl<'a> Iterator for BMS<'a> { + type Item = bool; + fn next(&mut self) -> Option { + 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 { + 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 = 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, + }, + )) +} diff --git a/src/grib/gds.rs b/src/grib/gds.rs new file mode 100644 index 0000000..e25479a --- /dev/null +++ b/src/grib/gds.rs @@ -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 IResult<&[u8], DataRepresentation> + Sync>>, +} + +impl Default for DP { + fn default() -> Self { + let mut events: HashMap< + u8, + Box 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), + }, + )); + } +} diff --git a/src/grib/is.rs b/src/grib/is.rs new file mode 100644 index 0000000..84dd519 --- /dev/null +++ b/src/grib/is.rs @@ -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, + }, + )) +} diff --git a/src/grib/mod.rs b/src/grib/mod.rs new file mode 100644 index 0000000..60473c1 --- /dev/null +++ b/src/grib/mod.rs @@ -0,0 +1,7 @@ +pub mod bds; +pub mod bms; +pub mod gds; +pub mod is; +pub mod pds; + +mod parm_tables; diff --git a/src/parm_tables/dwdtable_002.rs b/src/grib/parm_tables/dwdtable_002.rs similarity index 100% rename from src/parm_tables/dwdtable_002.rs rename to src/grib/parm_tables/dwdtable_002.rs diff --git a/src/parm_tables/dwdtable_201.rs b/src/grib/parm_tables/dwdtable_201.rs similarity index 100% rename from src/parm_tables/dwdtable_201.rs rename to src/grib/parm_tables/dwdtable_201.rs diff --git a/src/parm_tables/dwdtable_202.rs b/src/grib/parm_tables/dwdtable_202.rs similarity index 100% rename from src/parm_tables/dwdtable_202.rs rename to src/grib/parm_tables/dwdtable_202.rs diff --git a/src/parm_tables/dwdtable_203.rs b/src/grib/parm_tables/dwdtable_203.rs similarity index 100% rename from src/parm_tables/dwdtable_203.rs rename to src/grib/parm_tables/dwdtable_203.rs diff --git a/src/parm_tables/dwdtable_204.rs b/src/grib/parm_tables/dwdtable_204.rs similarity index 100% rename from src/parm_tables/dwdtable_204.rs rename to src/grib/parm_tables/dwdtable_204.rs diff --git a/src/parm_tables/dwdtable_205.rs b/src/grib/parm_tables/dwdtable_205.rs similarity index 100% rename from src/parm_tables/dwdtable_205.rs rename to src/grib/parm_tables/dwdtable_205.rs diff --git a/src/parm_tables/ectable_128.rs b/src/grib/parm_tables/ectable_128.rs similarity index 100% rename from src/parm_tables/ectable_128.rs rename to src/grib/parm_tables/ectable_128.rs diff --git a/src/parm_tables/ectable_129.rs b/src/grib/parm_tables/ectable_129.rs similarity index 100% rename from src/parm_tables/ectable_129.rs rename to src/grib/parm_tables/ectable_129.rs diff --git a/src/parm_tables/ectable_130.rs b/src/grib/parm_tables/ectable_130.rs similarity index 100% rename from src/parm_tables/ectable_130.rs rename to src/grib/parm_tables/ectable_130.rs diff --git a/src/parm_tables/ectable_131.rs b/src/grib/parm_tables/ectable_131.rs similarity index 100% rename from src/parm_tables/ectable_131.rs rename to src/grib/parm_tables/ectable_131.rs diff --git a/src/parm_tables/ectable_132.rs b/src/grib/parm_tables/ectable_132.rs similarity index 100% rename from src/parm_tables/ectable_132.rs rename to src/grib/parm_tables/ectable_132.rs diff --git a/src/parm_tables/ectable_133.rs b/src/grib/parm_tables/ectable_133.rs similarity index 100% rename from src/parm_tables/ectable_133.rs rename to src/grib/parm_tables/ectable_133.rs diff --git a/src/parm_tables/ectable_140.rs b/src/grib/parm_tables/ectable_140.rs similarity index 100% rename from src/parm_tables/ectable_140.rs rename to src/grib/parm_tables/ectable_140.rs diff --git a/src/parm_tables/ectable_150.rs b/src/grib/parm_tables/ectable_150.rs similarity index 100% rename from src/parm_tables/ectable_150.rs rename to src/grib/parm_tables/ectable_150.rs diff --git a/src/parm_tables/ectable_151.rs b/src/grib/parm_tables/ectable_151.rs similarity index 100% rename from src/parm_tables/ectable_151.rs rename to src/grib/parm_tables/ectable_151.rs diff --git a/src/parm_tables/ectable_160.rs b/src/grib/parm_tables/ectable_160.rs similarity index 100% rename from src/parm_tables/ectable_160.rs rename to src/grib/parm_tables/ectable_160.rs diff --git a/src/parm_tables/ectable_162.rs b/src/grib/parm_tables/ectable_162.rs similarity index 100% rename from src/parm_tables/ectable_162.rs rename to src/grib/parm_tables/ectable_162.rs diff --git a/src/parm_tables/ectable_170.rs b/src/grib/parm_tables/ectable_170.rs similarity index 100% rename from src/parm_tables/ectable_170.rs rename to src/grib/parm_tables/ectable_170.rs diff --git a/src/parm_tables/ectable_171.rs b/src/grib/parm_tables/ectable_171.rs similarity index 100% rename from src/parm_tables/ectable_171.rs rename to src/grib/parm_tables/ectable_171.rs diff --git a/src/parm_tables/ectable_172.rs b/src/grib/parm_tables/ectable_172.rs similarity index 100% rename from src/parm_tables/ectable_172.rs rename to src/grib/parm_tables/ectable_172.rs diff --git a/src/parm_tables/ectable_173.rs b/src/grib/parm_tables/ectable_173.rs similarity index 100% rename from src/parm_tables/ectable_173.rs rename to src/grib/parm_tables/ectable_173.rs diff --git a/src/parm_tables/ectable_174.rs b/src/grib/parm_tables/ectable_174.rs similarity index 100% rename from src/parm_tables/ectable_174.rs rename to src/grib/parm_tables/ectable_174.rs diff --git a/src/parm_tables/ectable_180.rs b/src/grib/parm_tables/ectable_180.rs similarity index 100% rename from src/parm_tables/ectable_180.rs rename to src/grib/parm_tables/ectable_180.rs diff --git a/src/parm_tables/ectable_190.rs b/src/grib/parm_tables/ectable_190.rs similarity index 100% rename from src/parm_tables/ectable_190.rs rename to src/grib/parm_tables/ectable_190.rs diff --git a/src/parm_tables/ectable_200.rs b/src/grib/parm_tables/ectable_200.rs similarity index 100% rename from src/parm_tables/ectable_200.rs rename to src/grib/parm_tables/ectable_200.rs diff --git a/src/parm_tables/ectable_210.rs b/src/grib/parm_tables/ectable_210.rs similarity index 100% rename from src/parm_tables/ectable_210.rs rename to src/grib/parm_tables/ectable_210.rs diff --git a/src/parm_tables/ectable_211.rs b/src/grib/parm_tables/ectable_211.rs similarity index 100% rename from src/parm_tables/ectable_211.rs rename to src/grib/parm_tables/ectable_211.rs diff --git a/src/parm_tables/ectable_228.rs b/src/grib/parm_tables/ectable_228.rs similarity index 100% rename from src/parm_tables/ectable_228.rs rename to src/grib/parm_tables/ectable_228.rs diff --git a/src/parm_tables/mod.rs b/src/grib/parm_tables/mod.rs similarity index 96% rename from src/parm_tables/mod.rs rename to src/grib/parm_tables/mod.rs index 823bacf..ef438dd 100644 --- a/src/parm_tables/mod.rs +++ b/src/grib/parm_tables/mod.rs @@ -39,5 +39,5 @@ pub mod dwdtable_202; pub mod dwdtable_203; pub mod dwdtable_204; pub mod dwdtable_205; -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub struct Parm(&'static str, &'static str); diff --git a/src/parm_tables/nceptab_128.rs b/src/grib/parm_tables/nceptab_128.rs similarity index 100% rename from src/parm_tables/nceptab_128.rs rename to src/grib/parm_tables/nceptab_128.rs diff --git a/src/parm_tables/nceptab_129.rs b/src/grib/parm_tables/nceptab_129.rs similarity index 100% rename from src/parm_tables/nceptab_129.rs rename to src/grib/parm_tables/nceptab_129.rs diff --git a/src/parm_tables/nceptab_130.rs b/src/grib/parm_tables/nceptab_130.rs similarity index 100% rename from src/parm_tables/nceptab_130.rs rename to src/grib/parm_tables/nceptab_130.rs diff --git a/src/parm_tables/nceptab_131.rs b/src/grib/parm_tables/nceptab_131.rs similarity index 100% rename from src/parm_tables/nceptab_131.rs rename to src/grib/parm_tables/nceptab_131.rs diff --git a/src/parm_tables/nceptab_133.rs b/src/grib/parm_tables/nceptab_133.rs similarity index 100% rename from src/parm_tables/nceptab_133.rs rename to src/grib/parm_tables/nceptab_133.rs diff --git a/src/parm_tables/nceptab_140.rs b/src/grib/parm_tables/nceptab_140.rs similarity index 100% rename from src/parm_tables/nceptab_140.rs rename to src/grib/parm_tables/nceptab_140.rs diff --git a/src/parm_tables/nceptab_141.rs b/src/grib/parm_tables/nceptab_141.rs similarity index 100% rename from src/parm_tables/nceptab_141.rs rename to src/grib/parm_tables/nceptab_141.rs diff --git a/src/parm_tables/nceptable_mdl.rs b/src/grib/parm_tables/nceptable_mdl.rs similarity index 100% rename from src/parm_tables/nceptable_mdl.rs rename to src/grib/parm_tables/nceptable_mdl.rs diff --git a/src/parm_tables/nceptable_opn.rs b/src/grib/parm_tables/nceptable_opn.rs similarity index 100% rename from src/parm_tables/nceptable_opn.rs rename to src/grib/parm_tables/nceptable_opn.rs diff --git a/src/parm_tables/nceptable_reanal.rs b/src/grib/parm_tables/nceptable_reanal.rs similarity index 100% rename from src/parm_tables/nceptable_reanal.rs rename to src/grib/parm_tables/nceptable_reanal.rs diff --git a/src/pds.rs b/src/grib/pds.rs similarity index 96% rename from src/pds.rs rename to src/grib/pds.rs index aef5625..c55f74e 100644 --- a/src/pds.rs +++ b/src/grib/pds.rs @@ -1,38 +1,20 @@ -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::sequence::{preceded, tuple, 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; +use super::parm_tables; +use super::parm_tables::Parm; - 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 { +#[derive(Debug)] +pub struct PDS { center_identification: Center, generating_process_id: u8, grid_identification: u8, - gds_or_bms: (bool, bool), + pub gds_or_bms: (bool, bool), unit: Parm, level_type_and_value: String, datetime: DateTime, @@ -43,7 +25,7 @@ struct PDS { missing: u8, } -#[derive(Clone)] +#[derive(Clone, Debug)] enum Center { WMC(u8), RSMC(u8), @@ -54,7 +36,7 @@ enum Center { Other(u8), } -#[derive(Clone)] +#[derive(Clone, Debug)] enum SubCenter { NCEPReAnalysis, NCEPEnsemble, @@ -493,7 +475,7 @@ fn decimal_scale_parser(input: &[u8]) -> IResult<&[u8], i32> { 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 length = u24(Little); diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..7be1ccc --- /dev/null +++ b/src/lib.rs @@ -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>, + bms: Option>, + 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 = None; + let mut bms: Option = 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, + }, + )) +} diff --git a/src/libs.rs b/src/libs.rs deleted file mode 100644 index 2dc7c83..0000000 --- a/src/libs.rs +++ /dev/null @@ -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, - 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 { - 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, -} diff --git a/src/main.rs b/src/main.rs index f58c5ee..e7a11a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,3 @@ -pub mod gds; -pub mod libs; -pub mod parm_tables; -pub mod pds; - fn main() { println!("Hello, world!"); }