use crate::errors::Result; use encoding_rs::WINDOWS_1252; use std::fs; use std::path::{Path, PathBuf}; mod btable; mod dtable; pub use btable::BTable; pub use dtable::DTable; #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum TableType { A, B, C, D, } pub struct BUFRTable; pub trait TableTrait { fn file_path(table_type: TableType, sub_center: Option, table_version: u8) -> PathBuf; } impl BUFRTable { pub fn file_path(table_type: TableType, table_version: u8) -> PathBuf { let base_dir = Path::new("tables/bufr"); let file_name = match table_type { TableType::A => format!("bufrtaba_{}.csv", table_version), TableType::B => format!("bufrtabb_{}.csv", table_version), TableType::C => format!("bufrtabc_{}.csv", table_version), TableType::D => format!("bufrtabd_{}.csv", table_version), }; base_dir.join(file_name) } } pub struct LocalTable; impl LocalTable { pub fn file_path(table_type: TableType, sub_center: u32, table_version: u8) -> PathBuf { let base_dir = Path::new("tables/local"); let file_name = match table_type { TableType::A => format!("loctaba_{}_{}.csv", sub_center * 256, table_version), TableType::B => format!("loctabb_{}_{}.csv", sub_center * 256, table_version), TableType::C => format!("loctabc_{}_{}.csv", sub_center * 256, table_version), TableType::D => format!("loctabd_{}_{}.csv", sub_center * 256, table_version), }; base_dir.join(file_name) } } impl TableTrait for BUFRTable { fn file_path(table_type: TableType, sub_center: Option, table_version: u8) -> PathBuf { BUFRTable::file_path(table_type, table_version) } } impl TableTrait for LocalTable { fn file_path(table_type: TableType, sub_center: Option, table_version: u8) -> PathBuf { let sub_center = sub_center.expect("Sub-center must be provided for LocalTable"); LocalTable::file_path(table_type, sub_center, table_version) } } #[derive(Debug, Clone)] pub struct TableLoader { sequences: Vec, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum TT { Localized(u32), // sub_center Standard, } impl TableLoader { pub fn new() -> Self { Self { sequences: Vec::new(), } } pub fn load_table(&mut self, table_type: TT, table_version: u8) -> Result> { let table_kind = T::table_type(); let local_table_path = match table_type { TT::Localized(sc) => LocalTable::file_path(table_kind, sc, table_version), TT::Standard => BUFRTable::file_path(table_kind, table_version), }; // Here you would add code to actually load and parse the table from the file at `path`. println!("Loading table from path: {:?}", local_table_path); let raw = fs::read(&local_table_path)?; let fixed = normalize_dashes(raw); let text = decode_tabd_text(fixed); let mut table = T::default(); for line in text.lines() { if let Some(seq) = table.parse_line(line) { self.sequences.push(seq); } } if let Some(seq) = table.finish() { self.sequences.push(seq); } let mut sequences = Vec::new(); std::mem::swap(&mut sequences, &mut self.sequences); Ok(sequences) } } fn normalize_dashes(mut bytes: Vec) -> Vec { for b in &mut bytes { match *b { 0x96 | 0x97 => *b = b'-', // EN / EM dash → '-' _ => {} } } bytes } fn decode_tabd_text(bytes: Vec) -> String { let (text, _, _) = WINDOWS_1252.decode(&bytes); text.into_owned() } pub trait TableT: Default { type Seq; fn table_type() -> TableType; fn parse_line(&mut self, line: &str) -> Option; fn finish(&mut self) -> Option { None } } #[derive(Debug, Clone)] pub struct Descriptor { pub f: i32, pub x: i32, pub y: i32, } #[cfg(test)] mod test { use crate::discriptor_table::{TableLoader, btable::BTable, dtable::DTable}; #[test] fn test_read_table() { // let mut bufr_table: super::Table = super::Table::new(); let mut bufr_table = TableLoader::::new(); bufr_table.load_table(super::TT::Standard, 11).unwrap(); println!("{:#?}", bufr_table.sequences); } }