diff --git a/Cargo.lock b/Cargo.lock index 746c6ae..8775120 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,7 +7,11 @@ name = "CINRad" version = "0.1.0" dependencies = [ "bzip2", + "chrono", "flate2", + "nom", + "num-integer", + "num-traits", "thiserror", ] @@ -17,6 +21,27 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bumpalo" +version = "3.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" + [[package]] name = "bzip2" version = "0.4.4" @@ -50,6 +75,37 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "time", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + [[package]] name = "crc32fast" version = "1.3.2" @@ -59,6 +115,50 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "cxx" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn 2.0.15", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.15", +] + [[package]] name = "flate2" version = "1.0.25" @@ -69,12 +169,75 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "iana-time-zone" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "libc" version = "0.2.142" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.6.2" @@ -84,6 +247,41 @@ dependencies = [ "adler", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + [[package]] name = "pkg-config" version = "0.3.26" @@ -108,6 +306,23 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "scratch" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.15" @@ -119,6 +334,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.40" @@ -136,7 +360,18 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", +] + +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi", + "winapi", ] [[package]] @@ -144,3 +379,166 @@ name = "unicode-ident" version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 1.0.109", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +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.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/Cargo.toml b/Cargo.toml index 511fad9..34ea1a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +num-traits = "0.2.15" +num-integer = "0.1.45" flate2 = "1.0.25" thiserror = "1.0.40" bzip2 = "0.4.4" +nom = "7.1.3" +chrono = "0.4.24" diff --git a/src/error.rs b/src/error.rs index 3855bf7..5d6563c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,3 +1,4 @@ +use nom::error::Error; use std::{error, io}; use thiserror::Error; @@ -12,4 +13,7 @@ pub enum UnexpectedError { #[error("")] UnknownFormat, + + #[error("")] + DataParseError, } diff --git a/src/product.rs b/src/product.rs index 8034321..31f9033 100644 --- a/src/product.rs +++ b/src/product.rs @@ -1,11 +1,10 @@ use crate::error::UnexpectedError; -use bzip2::{read::BzDecoder, Decompress}; +use bzip2::read::BzDecoder; use flate2::read::GzDecoder; -use std::{ - fs, - io::{Read, Seek}, - path::Path, -}; +use nom::multi::{count, many0}; +use nom::IResult; +use nom::{bytes::complete::take, sequence::tuple}; +use std::{fs, io::Read, path::Path}; pub trait DataBound {} @@ -31,10 +30,202 @@ struct ProductLoader<'a>(&'a Path); // } // } -trait RadarType {} +trait RadarData {} + +enum RadarType { + SC, + CD, + CC, + Other(String), +} trait RecordParseStrategy { - fn parse>(raw:T) -> Box; + fn parse>(&self, raw: T) -> Result, UnexpectedError>; +} + +struct SimpleRecordStrategy(); + +struct Header { + spare: [u16; 7], + a: u16, + res: [u16; 6], +} + +use std::convert::TryInto; + +fn vec2array(v: Vec) -> [T; N] { + v.try_into() + .unwrap_or_else(|v: Vec| panic!("Expected a Vec of length {} but it was {}", N, v.len())) +} + +impl Header { + fn parse(data: &[u8]) -> IResult<&[u8], Self> { + use nom::number::complete as c; + let (next, header) = tuple(( + count(c::le_u16, 6usize), + c::le_u16, + count(c::le_u16, 6usize), + ))(data)?; + + Ok(( + next, + Self { + spare: vec2array(header.0), + a: header.1, + res: vec2array(header.2), + }, + )) + } +} + +struct Info { + time: u32, + day: u16, + unambiguous_distance: u16, + azimuth: f32, + radial_num: u16, + radial_state: u16, + elevation: f32, + el_num: u16, + first_gate_r: u16, + first_gate_v: u16, + gate_length_r: u16, + gate_length_v: u16, + gate_num_r: u16, + gate_num_v: u16, + sector_num: u16, + system_coff: u32, + r_pointer: u16, + v_pointer: u16, + w_pointer: u16, + v_reso: u16, + vcp_mode: u16, + r_pointer_2: u16, + v_pointer_2: u16, + w_pointer_2: u16, + nyquist_vel: u16, +} + +impl Info { + #[inline] + fn angle(raw: u16) -> f32 { + const con: f32 = (180.0 / 4096.0) * 0.125; + raw as f32 * con + } + + fn parse(data: &[u8]) -> IResult<&[u8], Self> { + use chrono::prelude::*; + use nom::number::complete as c; + + let (next, info) = tuple(( + c::le_u32, + count(c::le_u16, 14), + c::le_u32, + count(c::le_u16, 5), + count(c::le_u16, 4), + count(c::le_u16, 4), + ))(data)?; + + let gate_len_r = info.1[9]; + let gate_len_v = info.1[10]; + + let radial_num = info.1[3]; + + let azimuth = Info::angle(info.1[2]); + + let v_reso = info.3[3]; + let nyquist_vel = info.5[3]; + + let ele = Info::angle(info.1[5]); + + Ok(( + next, + Self { + time: info.0, + day: info.1[0], + unambiguous_distance: info.1[1], + azimuth, + radial_num, + radial_state: info.1[4], + elevation: ele, + el_num: info.1[6], + first_gate_r: info.1[7], + first_gate_v: info.1[8], + gate_length_r: gate_len_r, + gate_length_v: gate_len_v, + gate_num_r: info.1[11], + gate_num_v: info.1[12], + sector_num: info.1[13], + system_coff: info.2, + r_pointer: info.3[0], + v_pointer: info.3[1], + w_pointer: info.3[2], + v_reso, + vcp_mode: info.3[4], + r_pointer_2: info.5[0], + v_pointer_2: info.5[1], + w_pointer_2: info.5[2], + nyquist_vel, + }, + )) + } +} + +struct SABData<'a> { + r: &'a [u8], + u1: &'a [u8], + w: &'a [u8], +} + +impl<'a> SABData<'a> { + fn parse(data: &'a [u8]) -> IResult<&[u8], Self> { + let (next, (r, u1, w, _)) = + tuple((take(460usize), take(920usize), take(920usize), take(2usize)))(data)?; + Ok((next, Self { r, u1, w })) + } +} +struct SAB {} + +impl RadarData for SAB {} + +impl SimpleRecordStrategy { + #[inline] + fn radar_type<'a>(&self, data: &'a [u8]) -> IResult<&'a [u8], RadarType> { + let _m = &data[100..]; + + let zip_method_result = take(9usize)(_m)?; + + return Ok(( + zip_method_result.0, + match zip_method_result.1 { + b"CINRAD/SC" => RadarType::SC, + b"CINRAD/CD" => RadarType::CD, + b"CINRAD/CC" => RadarType::CC, + _ => RadarType::Other(format!("hi")), + }, + )); + } + + fn sab(&self, data: &[u8]) -> Result { + let (_, value) = many0(tuple(( + Header::parse, + Info::parse, + take(38usize), + SABData::parse, + )))(data) + .map_err(|_x| UnexpectedError::DataParseError)?; + + Ok(SAB {}) + } +} + +impl RecordParseStrategy for SimpleRecordStrategy { + fn parse>(&self, raw: T) -> Result, UnexpectedError> { + Ok(Box::new(match self.radar_type(raw.as_ref()).unwrap() { + (_, RadarType::SC) => self.sab(raw.as_ref())?, + _ => self.sab(raw.as_ref())?, + })) + } } struct DataLoader<'a, T: RecordParseStrategy>(&'a Path, T); @@ -61,27 +252,6 @@ impl<'a, T: RecordParseStrategy> DataLoader<'a, T> { pub fn parse(&self) { let _prepard_value = self.prepare().unwrap(); - self.1.parse(_prepard_value); - + (&self.1).parse(_prepard_value); } } - -// impl<'a, T: RecordParseStrategy> Loader for DataLoader<'a, T> { -// type T = Record; - -// fn load(&self) -> Result { -// let _p = self.0; -// if !_p.is_file() { -// return Err(std::io::ErrorKind::AddrInUse); -// } -// } -// } - -// impl<'a> Loader for ProductLoader<'a> { -// type T = Product; -// fn load(&self) -> std::io::Result { -// let _path = self.0; -// let _paths = fs::read_dir(_path)?; -// _paths.filter(|x| x.is_ok_and(|v| !v.path().isdir()))?; -// } -// }