mod error; use geo::{algorithm::haversine_destination::HaversineDestination, Point}; mod parser; use abi_stable::{ export_root_module, prefix_type::PrefixTypeTrait, sabi_extern_fn, sabi_trait::prelude::TD_Opaque, std_types::{ RNone, ROk, ROption::RSome, RResult::{self, RErr}, RStr, RString, RVec, }, }; use parser::{Record, ValueResult}; use radarg_plugin_interface::{ DataLoaderPlugin, DataLoaderPlugin_TO, Error, GridDataInfo, LoadedData, PluginId, PluginMod, PluginMod_Ref, PluginType, ProbeDataType, RadarGridData, VecResult, }; macro_rules! data_rvec { ($data:ident, $({$parsed_vec:tt => $abi_stable_rvec:tt}),+) => { match $data { $( ValueResult::$parsed_vec(data) => VecResult::$abi_stable_rvec(RVec::from(data)), )+ } }; } macro_rules! data_type { ($datetype:ident, $({ $($name:literal)|+ => $type:tt }),+) => { match $datetype { $( $($name)|+ => ProbeDataType::$type, )+ _ => ProbeDataType::Unknown } }; } #[export_root_module] fn instantiate_root_module() -> PluginMod_Ref { PluginMod { new }.leak_into_prefix() } struct ETWSLoader { id: PluginId, } impl DataLoaderPlugin for ETWSLoader { fn plugin_id(&self) -> &PluginId { &self.id } fn load(&self, path: RStr<'_>) -> RResult, Error> where { if let Ok(record) = Record::parse_from_path(path.to_string()) { let result = record .blocks .into_iter() .map(|b| { let data = b.data; let converted_data = data_rvec!( data, {I16 => I16}, {F32 => F32}, {F64 => F64}, {I32 => I32}, {U32 => U32}, {I64 => I64}, {U64 => U64}, {I8 => I8}, {U8 => U8} ); let dimension_values = convert_nested_vec_to_rvec(b.info.dimension_values); let dimension_size = convert_vec_to_rvec( b.info .dimension_size .into_iter() .map(|p| p as usize) .collect::>(), ); let dimension_names = convert_vec_to_rvec( b.info .dimension_des .into_iter() .map(RString::from) .collect::>(), ); let fill_value = b.info.fill_value; let value_name = RString::from(b.info.value_name); let value_description = RString::from(b.info.value_des); let datetime = record.filetime.timestamp(); let value_key = value_name.as_str(); let data_type = data_type!( value_key, { "ET" => ET }, { "DBZ" | "CR" | "FR" | "R" => DBZ}, { "VIL" => VIL}, { "EB" => EB}, { "V" => V}, { "ZDR" => ZDR}, { "PHIDP" => PHIDP}, { "KDP" => KDP}, { "CC" =>CC}, { "HCA" => HCA}, { "QPE" => QPE}, { "QPF" => QPF} ); let grid_info = GridDataInfo { shape: dimension_size, dimensions: dimension_values, dimension_names, fill_value, datetime: RSome(datetime), value_description: RSome(value_description), maybe_probe_data_type: RSome(data_type), value_name, dimension_description: "Wrong".into(), }; LoadedData::RadarGridData(RadarGridData { data: converted_data, info: grid_info, }) }) .collect::>(); ROk(result) } else { RErr(Error::UnsupportedFormat) } } fn plugin_info(&self) -> radarg_plugin_interface::PluginInfo where { radarg_plugin_interface::PluginInfo { plugin_type: "DataLoader".into(), name: "ETWS_Loader".into(), version: "0.1.0".into(), author: "Tsuki".into(), description: RSome("ETWS Loader".into()), url: RSome("https://keitsuki.club".into()), } } } fn convert_iter_to_rvec(raw: impl Iterator) -> RVec { RVec::from(raw.collect::>()) } fn convert_vec_to_rvec(raw: Vec) -> RVec { RVec::from(raw) } fn convert_nested_vec_to_rvec(raw: Vec>) -> RVec> { RVec::from(raw.into_iter().map(RVec::from).collect::>()) } #[sabi_extern_fn] pub fn new(plugin_id: PluginId) -> RResult { let this = ETWSLoader { id: plugin_id }; ROk(DataLoaderPlugin_TO::from_value(this, TD_Opaque)) } // 测试模块 #[cfg(test)] mod tests { // 导入外部作用域中的所有项 use super::*; // 一个简单的测试 #[test] fn test() { let result = Record::parse_from_path("/Volumes/data2/RadarArray/ShaoXing/radarData/OutputProducts/RadarProducts/BasicProductsX/20230627/20230627163400/ZJSXAA_20230627163400_VIL.dat.gz") .unwrap(); } }