radar-g/etws_loader/src/lib.rs
2024-08-26 20:50:55 +08:00

189 lines
5.8 KiB
Rust

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<RVec<LoadedData>, 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::<Vec<_>>(),
);
let dimension_names = convert_vec_to_rvec(
b.info
.dimension_des
.into_iter()
.map(RString::from)
.collect::<Vec<_>>(),
);
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::<RVec<_>>();
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<T>(raw: impl Iterator<Item = T>) -> RVec<T> {
RVec::from(raw.collect::<Vec<_>>())
}
fn convert_vec_to_rvec<T>(raw: Vec<T>) -> RVec<T> {
RVec::from(raw)
}
fn convert_nested_vec_to_rvec<T>(raw: Vec<Vec<T>>) -> RVec<RVec<T>> {
RVec::from(raw.into_iter().map(RVec::from).collect::<Vec<_>>())
}
#[sabi_extern_fn]
pub fn new(plugin_id: PluginId) -> RResult<PluginType, Error> {
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();
}
}