diff --git a/gen/src/fr/btable.rs b/gen/src/fr/btable.rs index f3d4dec..5c77e88 100644 --- a/gen/src/fr/btable.rs +++ b/gen/src/fr/btable.rs @@ -1,7 +1,11 @@ -use crate::{FXY, TableEntry, TableEntryLoader}; -use rkyv::Archive; +use super::EntryLoader; +use crate::{ + FXY, + tables::{BTable, BTableEntry}, +}; -pub struct BTableCsvLoader; +#[derive(Default)] +pub struct BTableLoader; #[derive(Debug)] pub struct RawBTableEntry { @@ -10,145 +14,62 @@ pub struct RawBTableEntry { pub y: u16, } -// Helper function to deserialize empty strings as None -fn deserialize_optional_string<'de, D>(deserializer: D) -> Result, D::Error> -where - D: serde::Deserializer<'de>, -{ - let s: String = serde::Deserialize::deserialize(deserializer)?; - if s.is_empty() { Ok(None) } else { Ok(Some(s)) } -} +impl EntryLoader for BTableLoader { + type Output = BTableEntry; + type TableType = BTable; -// Helper function to deserialize empty strings as None for u32 -fn deserialize_optional_u32<'de, D>(deserializer: D) -> Result, D::Error> -where - D: serde::Deserializer<'de>, -{ - let s: String = serde::Deserialize::deserialize(deserializer)?; - if s.is_empty() { - Ok(None) - } else { - s.parse::().map(Some).map_err(serde::de::Error::custom) - } -} + fn process_entry(&mut self, raw: csv::StringRecord) -> anyhow::Result> { + let f = raw + .get(0) + .ok_or_else(|| anyhow::anyhow!("Missing F field"))? + .parse()?; -#[derive( - Debug, Clone, serde::Deserialize, serde::Serialize, Archive, rkyv::Serialize, rkyv::Deserialize, -)] -#[rkyv(compare(PartialEq), derive(Debug))] -pub struct BTableEntry { - fxy: FXY, - class_name_en: String, - element_name_en: String, - bufr_unit: String, - bufr_scale: i32, - bufr_reference_value: i32, - bufr_datawidth_bits: u32, - note_en: Option, - note_ids: Option, - status: String, -} + let x = raw + .get(1) + .ok_or_else(|| anyhow::anyhow!("Missing X field"))? + .parse()?; -impl BTableEntry { - pub fn fxy(&self) -> FXY { - self.fxy - } + let y = raw + .get(2) + .ok_or_else(|| anyhow::anyhow!("Missing Y field"))? + .parse()?; - pub fn class_name_en(&self) -> &str { - &self.class_name_en - } + let fxy = FXY::new(f, x, y); - pub fn element_name_en(&self) -> &str { - &self.element_name_en - } - - pub fn bufr_unit(&self) -> &str { - &self.bufr_unit - } - - pub fn bufr_scale(&self) -> i32 { - self.bufr_scale - } - - pub fn bufr_reference_value(&self) -> i32 { - self.bufr_reference_value - } - - pub fn bufr_datawidth_bits(&self) -> u32 { - self.bufr_datawidth_bits - } - - pub fn note_en(&self) -> Option<&str> { - self.note_en.as_deref() - } - - pub fn note_ids(&self) -> Option<&str> { - self.note_ids.as_deref() - } - - pub fn status(&self) -> &str { - &self.status - } -} - -impl std::fmt::Display for BTableEntry { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let element_name = if self.element_name_en.len() > 40 { - format!("{}...", &self.element_name_en[..37]) - } else { - self.element_name_en.clone() - }; - - let unit = if self.bufr_unit.len() > 15 { - format!("{}...", &self.bufr_unit[..12]) - } else { - self.bufr_unit.clone() - }; - - write!( - f, - "{:02}{:02}{:03} | {:<40} | {:<15} | {:>5} | {:>8} | {:>8} | {}", - self.fxy.f, - self.fxy.x, - self.fxy.y, - element_name, - unit, - self.bufr_scale, - self.bufr_reference_value, - self.bufr_datawidth_bits, - self.status - ) - } -} - -impl TableEntryLoader for BTableCsvLoader { - type RawEntry = RawBTableEntry; - type TableEntry = BTableEntry; - const TABLE_TYPE: crate::TableType = crate::TableType::B; - - fn process_entry(&mut self, raw: Self::RawEntry) -> anyhow::Result> { - // Parse FXY string (e.g., "001001") to u32 - let fxy = FXY::from_str(&raw.fxy)?; + let class_name_en = raw + .get(3) + .ok_or_else(|| anyhow::anyhow!("Missing Class Name EN"))? + .to_string(); + let bufr_unit = raw + .get(4) + .ok_or_else(|| anyhow::anyhow!("Missing BUFR Unit"))? + .to_string(); + let bufr_scale = raw + .get(5) + .ok_or_else(|| anyhow::anyhow!("Missing Scaling Field"))? + .parse()?; + let bufr_reference_value = raw + .get(6) + .ok_or_else(|| anyhow::anyhow!("Missing Reference Value Field"))? + .parse()?; + let bufr_datawidth_bits = raw + .get(7) + .ok_or_else(|| anyhow::anyhow!("Missing Datawidth Bits Field"))? + .parse()?; let entry = BTableEntry { fxy, - class_name_en: raw.class_name_en, - element_name_en: raw.element_name_en, - bufr_unit: raw.bufr_unit, - bufr_scale: raw.bufr_scale, - bufr_reference_value: raw.bufr_reference_value, - bufr_datawidth_bits: raw.bufr_datawidth_bits, - note_en: raw.note_en, - note_ids: raw.note_ids, - status: raw.status, + class_name_en: class_name_en.clone(), + element_name_en: class_name_en, + bufr_unit, + bufr_scale, + bufr_reference_value, + bufr_datawidth_bits, + note_en: None, + note_ids: None, + status: None, }; Ok(Some(entry)) } } - -impl TableEntry for BTableEntry { - fn fxy(&self) -> FXY { - self.fxy - } -} diff --git a/gen/src/fr/dtable.rs b/gen/src/fr/dtable.rs index 10f6489..80ba369 100644 --- a/gen/src/fr/dtable.rs +++ b/gen/src/fr/dtable.rs @@ -1,34 +1,67 @@ -use super::TableEntryLoader; +use super::EntryLoader; +use crate::{ + FXY, + tables::{DTable, DTableEntry}, +}; use csv::StringRecord; -use rkyv::Archive; -#[derive(Debug, Clone, Default)] -pub struct DTableCsvLoader { +#[derive(Default)] +pub struct FRDTableLoader { current_chain: Option, } -impl TableEntryLoader for DTableCsvLoader { - type TableEntry = DTableEntry; - const TABLE_TYPE: crate::TableType = crate::TableType::D; +impl EntryLoader for FRDTableLoader { + type Output = DTableEntry; + type TableType = DTable; - fn process_entry(&mut self, raw: &StringRecord) -> anyhow::Result> { + fn process_entry(&mut self, raw: StringRecord) -> anyhow::Result> { + let f = raw + .get(0) + .ok_or_else(|| anyhow::anyhow!("Missing F field"))? + .parse::()?; + + let x = raw + .get(1) + .ok_or_else(|| anyhow::anyhow!("Missing X field"))? + .parse::()?; + + let y = raw + .get(2) + .ok_or_else(|| anyhow::anyhow!("Missing Y field"))? + .parse::()?; + + let f1 = raw + .get(3) + .ok_or_else(|| anyhow::anyhow!("Missing F1 field"))?; + + let x1 = raw + .get(4) + .ok_or_else(|| anyhow::anyhow!("Missing X1 field"))?; + + let y1 = raw + .get(5) + .ok_or_else(|| anyhow::anyhow!("Missing Y1 field"))?; + + let fxy1 = FXY::new(f1.parse()?, x1.parse()?, y1.parse()?); + + let fxy = FXY::new(f, x, y); // Process the raw entry as needed if self.current_chain.is_none() { let entry = DTableEntry { - fxy: FXY::from_str(&raw.fxy1)?, - fxy_chain: vec![FXY::from_str(&raw.fxy2)?], - category: raw.category, - category_of_sequences_en: raw.category_of_sequences_en, - title_en: raw.title_en, - subtitle_en: raw.subtitle_en, - note_en: raw.note_en, - note_ids: raw.note_ids, - status: raw.status, + fxy, + fxy_chain: vec![fxy1], + category: None, + category_of_sequences_en: None, + title_en: None, + subtitle_en: None, + note_en: None, + note_ids: None, + status: None, }; self.current_chain = Some(entry); return Ok(None); } else { - let fxy = FXY::from_str(&raw.fxy1)?; + let fxy = FXY::new(f, x, y); if self.current_chain.as_ref().unwrap().fxy != fxy { // First take out the old completed chain let finished = self.current_chain.take(); @@ -36,116 +69,26 @@ impl TableEntryLoader for DTableCsvLoader { // Then create and save the new chain let entry = DTableEntry { fxy, - fxy_chain: vec![FXY::from_str(&raw.fxy2)?], - category: raw.category, - category_of_sequences_en: raw.category_of_sequences_en, - title_en: raw.title_en, - subtitle_en: raw.subtitle_en, - note_en: raw.note_en, - note_ids: raw.note_ids, - status: raw.status, + fxy_chain: vec![fxy1], + category: None, + category_of_sequences_en: None, + title_en: None, + subtitle_en: None, + note_en: None, + note_ids: None, + status: None, }; self.current_chain = Some(entry); - // Return the old completed chain return Ok(finished); } else { - self.current_chain - .as_mut() - .unwrap() - .fxy_chain - .push(FXY::from_str(&raw.fxy2)?); - + self.current_chain.as_mut().unwrap().fxy_chain.push(fxy1); return Ok(None); } } } - fn finish(&mut self) -> anyhow::Result> { + fn finish(&mut self) -> anyhow::Result> { Ok(self.current_chain.take()) } } - -#[derive( - Debug, Clone, serde::Deserialize, serde::Serialize, Archive, rkyv::Serialize, rkyv::Deserialize, -)] -#[rkyv(compare(PartialEq), derive(Debug))] -pub struct DTableEntry { - fxy: FXY, - fxy_chain: Vec, - category: String, - category_of_sequences_en: String, - title_en: Option, - subtitle_en: Option, - note_en: Option, - note_ids: String, - status: String, -} - -impl DTableEntry { - pub fn fxy(&self) -> FXY { - self.fxy - } - - pub fn fxy_chain(&self) -> &[FXY] { - &self.fxy_chain - } - - pub fn category(&self) -> &str { - &self.category - } - - pub fn category_of_sequences_en(&self) -> &str { - &self.category_of_sequences_en - } - - pub fn title_en(&self) -> Option<&str> { - self.title_en.as_deref() - } - - pub fn subtitle_en(&self) -> Option<&str> { - self.subtitle_en.as_deref() - } - - pub fn note_en(&self) -> Option<&str> { - self.note_en.as_deref() - } - - pub fn note_ids(&self) -> &str { - &self.note_ids - } - - pub fn status(&self) -> &str { - &self.status - } -} - -impl std::fmt::Display for DTableEntry { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let fxy_chain_str: String = self - .fxy_chain - .iter() - .map(|fxy| format!("{:02}{:02}{:03}", fxy.f, fxy.x, fxy.y)) - .collect::>() - .join(", "); - - let title = self.title_en.as_deref().unwrap_or("N/A"); - let truncated_title = if title.len() > 50 { - format!("{}...", &title[..47]) - } else { - title.to_string() - }; - - write!( - f, - "{:02}{:02}{:03} | {:<50} | {:<12} | [{}]", - self.fxy.f, self.fxy.x, self.fxy.y, truncated_title, self.status, fxy_chain_str - ) - } -} - -impl TableEntry for DTableEntry { - fn fxy(&self) -> FXY { - self.fxy - } -} diff --git a/gen/src/fr/mod.rs b/gen/src/fr/mod.rs index 57c0dd6..85b901e 100644 --- a/gen/src/fr/mod.rs +++ b/gen/src/fr/mod.rs @@ -1,24 +1,34 @@ +use crate::{ + TableConverter, + tables::{TableEntry, TableEntryFull, TableTypeTrait}, +}; use csv::{ReaderBuilder, StringRecord}; -use std::path::Path; pub mod btable; pub mod dtable; -pub struct TableLoader; +pub type FRDTableLoader = TableLoader; +pub type FRBTableLoader = TableLoader; -impl TableLoader { - pub fn load_table, T: TableEntryLoader>( +#[derive(Default)] +pub struct TableLoader { + _marker: std::marker::PhantomData, +} + +impl TableLoader { + pub fn load_table>( &self, path: P, - loader: &mut T, - ) -> anyhow::Result> { + loader: &mut C, + ) -> anyhow::Result> { + let path = path.as_ref(); let mut entries = vec![]; let mut rdr = ReaderBuilder::new() .has_headers(false) .delimiter(b';') - .flexible(false) // Allow variable number of fields - .from_path(path.as_ref())?; + .flexible(false) + .from_path(path)?; - let mut line_num = 1; // Start at 1 for header + let mut line_num = 1; for result in rdr.records() { line_num += 1; match result { @@ -28,11 +38,10 @@ impl TableLoader { } } Err(e) => { - // Log the error but continue processing eprintln!( "Warning: Skipping line {} in {}: {}", line_num, - path.as_ref().display(), + path.display(), e ); } @@ -47,15 +56,25 @@ impl TableLoader { } } -pub trait TableEntryLoader: Sized { - type TableEntry: TableEntry; +pub trait EntryLoader: Default { + type Output: TableEntryFull; + type TableType: TableTypeTrait; - const TABLE_TYPE: TableType; - - /// Process a single entry from the CSV file - fn process_entry(&mut self, raw: &StringRecord) -> anyhow::Result>; - - fn finish(&mut self) -> anyhow::Result> { + fn process_entry(&mut self, raw: StringRecord) -> anyhow::Result>; + fn finish(&mut self) -> anyhow::Result> { Ok(None) } } + +impl TableConverter for TableLoader { + type OutputEntry = T::Output; + type TableType = T::TableType; + + fn convert>( + &self, + path: P, + ) -> anyhow::Result> { + let mut loader = T::default(); + self.load_table(path, &mut loader) + } +} diff --git a/gen/src/lib.rs b/gen/src/lib.rs index ad68205..50591e7 100644 --- a/gen/src/lib.rs +++ b/gen/src/lib.rs @@ -1,117 +1,44 @@ -// pub mod fr; +pub mod fr; pub mod prelude; +pub mod tables; mod utils; pub mod wmo; use anyhow::Context; use memmap2::Mmap; use ph::fmph::GOFunction; use rkyv::Archive; -use rkyv::api::high::{HighDeserializer, HighSerializer}; use rkyv::rancor::Error; -use serde::de::DeserializeOwned; use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize}; use std::fmt::Debug; use std::io::Write; use std::path::Path; -use csv::ReaderBuilder; +use crate::tables::{TableEntryFull, TableTypeTrait}; -pub struct TableLoader; +pub trait TableConverter { + type OutputEntry: TableEntryFull; + type TableType: TableTypeTrait; + fn convert>(&self, path: P) -> anyhow::Result>; -impl TableLoader { - pub fn load_table, T: TableEntryLoader>( - &self, - path: P, - loader: &mut T, - ) -> anyhow::Result> { - let mut entries = vec![]; - let mut rdr = ReaderBuilder::new() - .has_headers(true) - .delimiter(b',') - .flexible(true) // Allow variable number of fields - .from_path(path.as_ref())?; - - let mut line_num = 1; // Start at 1 for header - for result in rdr.deserialize() { - line_num += 1; - match result { - Ok(record) => { - let record: T::RawEntry = record; - if let Some(processed_entry) = loader.process_entry(record)? { - entries.push(processed_entry); - } - } - Err(e) => { - // Log the error but continue processing - eprintln!( - "Warning: Skipping line {} in {}: {}", - line_num, - path.as_ref().display(), - e - ); - } - } - } - - if let Some(processed_entry) = loader.finish()? { - entries.push(processed_entry); - } - - Ok(entries) + fn table_type(&self) -> crate::TableType { + Self::TableType::TABLE_TYPE } } -pub trait TableEntryLoader: Sized -where - Self::TableEntry: for<'a> rkyv::Serialize< - HighSerializer, Error>, - >, - ::Archived: - rkyv::Deserialize>, -{ - /// The raw CSV entry type that will be deserialized - type RawEntry: for<'de> serde::Deserialize<'de> + Debug; - - type TableEntry: TableEntry; - - const TABLE_TYPE: TableType; - - /// Process a single entry from the CSV file - fn process_entry(&mut self, raw: Self::RawEntry) -> anyhow::Result>; - - fn finish(&mut self) -> anyhow::Result> { - Ok(None) - } -} - -pub trait TableEntry: SerdeSerialize + DeserializeOwned + Debug + Clone + Archive { - fn fxy(&self) -> FXY; -} - -struct BufrTableMph { +struct BufrTableMph { mphf: GOFunction, offsets: Vec, mmap: Mmap, _marker: std::marker::PhantomData, } -struct BUFRTableM { - mphf: GOFunction, -} - -impl BufrTableMph -where - for<'a> T::TableEntry: rkyv::Serialize< - HighSerializer, Error>, - >, - ::Archived: rkyv::Deserialize>, -{ - fn build(entries: Vec, output_path: &str) -> std::io::Result { +impl BufrTableMph { + fn build(entries: Vec, output_path: &str) -> std::io::Result { println!("Building MPH table with {} entries...", entries.len()); let keys: Vec = entries.iter().map(|e| e.fxy()).collect(); let mphf = GOFunction::from_slice(&keys); - let mut sorted_entries: Vec<(usize, T::TableEntry)> = entries + let mut sorted_entries: Vec<(usize, T)> = entries .into_iter() .map(|e| (mphf.get(&(e.fxy())).unwrap() as usize, e)) .collect(); @@ -212,7 +139,7 @@ where } /// 获取拥有的版本 - fn get(&self, fxy: FXY) -> Option { + fn get(&self, fxy: FXY) -> Option { let hash = self.mphf.get(&fxy)? as usize; let offset = *self.offsets.get(hash)? as usize; @@ -221,13 +148,12 @@ where let data = self.mmap.get(offset + 4..offset + 4 + len)?; - let archived = - unsafe { rkyv::access_unchecked::<::Archived>(data) }; - rkyv::deserialize::(archived).ok() + let archived = unsafe { rkyv::access_unchecked::<::Archived>(data) }; + rkyv::deserialize::(archived).ok() } /// 获取所有条目 - fn get_all(&self) -> Vec { + fn get_all(&self) -> Vec { let mut entries = Vec::new(); for offset in &self.offsets { let offset = *offset as usize; @@ -236,9 +162,9 @@ where let len = u32::from_le_bytes(len_bytes_array) as usize; if let Some(data) = self.mmap.get(offset + 4..offset + 4 + len) { let archived = unsafe { - rkyv::access_unchecked::<::Archived>(data) + rkyv::access_unchecked::<::Archived>(data) }; - if let Ok(entry) = rkyv::deserialize::(archived) { + if let Ok(entry) = rkyv::deserialize::(archived) { entries.push(entry); } } @@ -269,15 +195,6 @@ pub struct FXY { pub y: u16, } -// // Custom Hash implementation to work around boomphf's overflow bug -// // We implement Hash by converting to u32 first -// impl std::hash::Hash for FXY { -// fn hash(&self, state: &mut H) { -// // Convert FXY to a simple u32 value to avoid complex hashing -// self.to_u32().hash(state); -// } -// } - impl FXY { pub fn new(f: u16, x: u16, y: u16) -> Self { FXY { f, x, y } @@ -319,32 +236,37 @@ impl FXY { } } -pub struct BUFRTableMPH { - inner: BufrTableMph, +pub struct BUFRTableMPH { + inner: BufrTableMph, } -impl BUFRTableMPH { - pub fn build_from_csv>( - mut loader: T, - csv_path: P, +impl BUFRTableMPH { + pub fn build_from_csv, L: TableConverter>( + loader: L, + path: P, output_path: P, - ) -> anyhow::Result { - let entries = TableLoader.load_table(csv_path, &mut loader)?; - let bhm = BufrTableMph::::build(entries, output_path.as_ref().to_str().unwrap())?; + ) -> anyhow::Result + where + L: TableConverter, + L: TableConverter, + { + let entries = loader.convert(path)?; + let bhm = + BufrTableMph::::build(entries, output_path.as_ref().to_str().unwrap())?; Ok(BUFRTableMPH { inner: bhm }) } pub fn load_from_disk>(path: P) -> anyhow::Result { - let bhm: BufrTableMph = BufrTableMph::load(path)?; + let bhm: BufrTableMph = BufrTableMph::load(path)?; Ok(BUFRTableMPH { inner: bhm }) } - pub fn lookup(&self, fxy: FXY) -> anyhow::Result> { + pub fn lookup(&self, fxy: FXY) -> anyhow::Result> { Ok(self.inner.get(fxy)) } - pub fn get_all_entries(&self) -> Vec { + pub fn get_all_entries(&self) -> Vec { self.inner.get_all() } } @@ -358,16 +280,7 @@ pub enum TableType { #[cfg(test)] mod test { - use crate::{BUFRTableMPH, dtable::DTableCsvLoader}; #[test] - fn test() { - let d_loader = DTableCsvLoader::default(); - BUFRTableMPH::build_from_csv( - d_loader, - "/Users/xiang.li1/projects/rbufr/BUFR4/BUFR_TableD_en_00.csv", - "test_table_d", - ) - .unwrap(); - } + fn test() {} } diff --git a/gen/src/main.rs b/gen/src/main.rs index dd3d079..7986153 100644 --- a/gen/src/main.rs +++ b/gen/src/main.rs @@ -1,6 +1,9 @@ -use anyhow::{Context, Result}; +use anyhow::{Context, Result, anyhow}; use clap::{Parser, Subcommand}; -use genlib::{BUFRTableMPH, btable::BTableCsvLoader, dtable::DTableCsvLoader}; +use genlib::{ + TableType, + prelude::{BUFRTableB, BUFRTableD}, +}; use std::path::{Path, PathBuf}; #[derive(Parser)] @@ -196,16 +199,63 @@ fn convert_single_file(input_path: &Path, output_path: &Path, table_type: &str) Ok(()) } +type BuildFn = fn(&Path, &Path) -> Result<()>; + +fn run_with_fallbacks( + kind: TableType, + input_path: &Path, + output_path: &Path, + attempts: &[(&str, BuildFn)], +) -> Result<()> { + let mut errors = Vec::new(); + for (label, build_fn) in attempts { + match build_fn(input_path, output_path) { + Ok(()) => return Ok(()), + Err(err) => errors.push(format!("{label} failed: {err:#}")), + } + } + + Err(anyhow!( + "all {:?} loaders failed:\n{}", + kind, + errors.join("\n---\n") + )) +} + +fn build_wmo_d(input_path: &Path, output_path: &Path) -> Result<()> { + let loader = genlib::wmo::TableLoader::::default(); + BUFRTableD::build_from_csv(loader, input_path, output_path).map(|_| ()) +} + +fn build_fr_d(input_path: &Path, output_path: &Path) -> Result<()> { + let loader = genlib::fr::FRDTableLoader::default(); + BUFRTableD::build_from_csv(loader, input_path, output_path).map(|_| ()) +} + fn convert_table_d(input_path: &Path, output_path: &Path) -> Result<()> { - let loader = DTableCsvLoader::default(); - BUFRTableMPH::build_from_csv(loader, input_path, output_path)?; - Ok(()) + const ATTEMPTS: &[(&str, BuildFn)] = &[ + ("WMO Table D loader", build_wmo_d), + ("FR Table D loader", build_fr_d), + ]; + run_with_fallbacks(TableType::D, input_path, output_path, ATTEMPTS) +} + +fn build_wmo_b(input_path: &Path, output_path: &Path) -> Result<()> { + let loader = genlib::wmo::TableLoader::::default(); + BUFRTableB::build_from_csv(loader, input_path, output_path).map(|_| ()) +} + +fn build_fr_b(input_path: &Path, output_path: &Path) -> Result<()> { + let loader = genlib::fr::FRBTableLoader::default(); + BUFRTableB::build_from_csv(loader, input_path, output_path).map(|_| ()) } fn convert_table_b(input_path: &Path, output_path: &Path) -> Result<()> { - let loader = BTableCsvLoader; - BUFRTableMPH::build_from_csv(loader, input_path, output_path)?; - Ok(()) + const ATTEMPTS: &[(&str, BuildFn)] = &[ + ("WMO Table B loader", build_wmo_b), + ("FR Table B loader", build_fr_b), + ]; + run_with_fallbacks(TableType::B, input_path, output_path, ATTEMPTS) } fn print_table(input_path: &Path, table_type: &str, limit: Option) -> Result<()> { @@ -219,11 +269,9 @@ fn print_table(input_path: &Path, table_type: &str, limit: Option) -> Res } fn print_table_d(input_path: &Path, limit: Option) -> Result<()> { - use genlib::dtable::DTableEntry; - println!("Loading Table D from: {}", input_path.display()); - let table: BUFRTableMPH = BUFRTableMPH::load_from_disk(input_path)?; + let table: BUFRTableD = BUFRTableD::load_from_disk(input_path)?; let entries = table.get_all_entries(); println!("\nTable D Entries (Total: {})", entries.len()); @@ -254,11 +302,9 @@ fn print_table_d(input_path: &Path, limit: Option) -> Result<()> { } fn print_table_b(input_path: &Path, limit: Option) -> Result<()> { - use genlib::btable::BTableEntry; - println!("Loading Table B from: {}", input_path.display()); - let table: BUFRTableMPH = BUFRTableMPH::load_from_disk(input_path)?; + let table: BUFRTableB = BUFRTableB::load_from_disk(input_path)?; let entries = table.get_all_entries(); println!("\nTable B Entries (Total: {})", entries.len()); diff --git a/gen/src/prelude.rs b/gen/src/prelude.rs index 7cdc85f..9aaa2b8 100644 --- a/gen/src/prelude.rs +++ b/gen/src/prelude.rs @@ -1,6 +1,8 @@ +use crate::tables::BTable; +use crate::tables::DTable; pub use crate::wmo; -// pub type BUFRTableD = crate::BUFRTableMPH; -// pub type BUFRTableB = crate::BUFRTableMPH; +pub type BUFRTableD = crate::BUFRTableMPH; +pub type BUFRTableB = crate::BUFRTableMPH; pub use crate::BUFRTableMPH; pub use crate::FXY; pub use crate::TableType; diff --git a/gen/src/tables.rs b/gen/src/tables.rs new file mode 100644 index 0000000..d6719c8 --- /dev/null +++ b/gen/src/tables.rs @@ -0,0 +1,238 @@ +use crate::FXY; +use rkyv::Archive; +use rkyv::api::high::{HighDeserializer, HighSerializer}; +use rkyv::de::Pool; +use rkyv::rancor::{Error, Strategy}; +use serde::Serialize as SerdeSerialize; +use serde::de::DeserializeOwned; +use std::fmt::Debug; + +pub struct BTable; +pub struct DTable; + +pub trait TableTypeTrait { + type EntryType: TableEntryFull; + const TABLE_TYPE: crate::TableType; +} + +impl TableTypeTrait for BTable { + type EntryType = crate::tables::BTableEntry; + const TABLE_TYPE: crate::TableType = crate::TableType::B; +} +impl TableTypeTrait for DTable { + type EntryType = crate::tables::DTableEntry; + const TABLE_TYPE: crate::TableType = crate::TableType::D; +} + +pub trait TableEntry: + SerdeSerialize + + DeserializeOwned + + Debug + + Clone + + Sized + + Archive + + for<'a> rkyv::Serialize< + HighSerializer, Error>, + > +{ + fn fxy(&self) -> FXY; +} + +pub trait TableEntryFull: TableEntry { + type Archived: for<'a> rkyv::Deserialize> + + rkyv::Deserialize> + + rkyv::Portable; +} + +impl TableEntryFull for T +where + T: TableEntry, + ::Archived: for<'a> rkyv::Deserialize> + + rkyv::Deserialize>, +{ + type Archived = ::Archived; +} + +#[derive( + Debug, Clone, serde::Deserialize, serde::Serialize, Archive, rkyv::Serialize, rkyv::Deserialize, +)] +#[rkyv(compare(PartialEq), derive(Debug))] +pub struct BTableEntry { + pub fxy: FXY, + pub class_name_en: String, + pub element_name_en: String, + pub bufr_unit: String, + pub bufr_scale: i32, + pub bufr_reference_value: i32, + pub bufr_datawidth_bits: u32, + pub note_en: Option, + pub note_ids: Option, + pub status: Option, +} + +impl BTableEntry { + pub fn fxy(&self) -> FXY { + self.fxy + } + + pub fn class_name_en(&self) -> &str { + &self.class_name_en + } + + pub fn element_name_en(&self) -> &str { + &self.element_name_en + } + + pub fn bufr_unit(&self) -> &str { + &self.bufr_unit + } + + pub fn bufr_scale(&self) -> i32 { + self.bufr_scale + } + + pub fn bufr_reference_value(&self) -> i32 { + self.bufr_reference_value + } + + pub fn bufr_datawidth_bits(&self) -> u32 { + self.bufr_datawidth_bits + } + + pub fn note_en(&self) -> Option<&str> { + self.note_en.as_deref() + } + + pub fn note_ids(&self) -> Option<&str> { + self.note_ids.as_deref() + } + + pub fn status(&self) -> Option<&str> { + self.status.as_deref() + } +} + +impl std::fmt::Display for BTableEntry { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let element_name = if self.element_name_en.len() > 40 { + format!("{}...", &self.element_name_en[..37]) + } else { + self.element_name_en.clone() + }; + + let unit = if self.bufr_unit.len() > 15 { + format!("{}...", &self.bufr_unit[..12]) + } else { + self.bufr_unit.clone() + }; + + write!( + f, + "{:02}{:02}{:03} | {:<40} | {:<15} | {:>5} | {:>8} | {:>8} | {}", + self.fxy.f, + self.fxy.x, + self.fxy.y, + element_name, + unit, + self.bufr_scale, + self.bufr_reference_value, + self.bufr_datawidth_bits, + self.status().unwrap_or("N/A") + ) + } +} + +#[derive( + Debug, Clone, serde::Deserialize, serde::Serialize, Archive, rkyv::Serialize, rkyv::Deserialize, +)] +#[rkyv(compare(PartialEq), derive(Debug))] +pub struct DTableEntry { + pub fxy: FXY, + pub fxy_chain: Vec, + pub category: Option, + pub category_of_sequences_en: Option, + pub title_en: Option, + pub subtitle_en: Option, + pub note_en: Option, + pub note_ids: Option, + pub status: Option, +} + +impl DTableEntry { + pub fn fxy(&self) -> FXY { + self.fxy + } + + pub fn fxy_chain(&self) -> &[FXY] { + &self.fxy_chain + } + + pub fn category(&self) -> Option<&str> { + self.category.as_deref() + } + + pub fn category_of_sequences_en(&self) -> Option<&str> { + self.category_of_sequences_en.as_deref() + } + + pub fn title_en(&self) -> Option<&str> { + self.title_en.as_deref() + } + + pub fn subtitle_en(&self) -> Option<&str> { + self.subtitle_en.as_deref() + } + + pub fn note_en(&self) -> Option<&str> { + self.note_en.as_deref() + } + + pub fn note_ids(&self) -> Option<&str> { + self.note_ids.as_deref() + } + + pub fn status(&self) -> Option<&str> { + self.status.as_deref() + } +} + +impl std::fmt::Display for DTableEntry { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let fxy_chain_str: String = self + .fxy_chain + .iter() + .map(|fxy| format!("{:02}{:02}{:03}", fxy.f, fxy.x, fxy.y)) + .collect::>() + .join(", "); + + let title = self.title_en.as_deref().unwrap_or("N/A"); + let truncated_title = if title.len() > 50 { + format!("{}...", &title[..47]) + } else { + title.to_string() + }; + + write!( + f, + "{:02}{:02}{:03} | {:<50} | {:<12} | [{}]", + self.fxy.f, + self.fxy.x, + self.fxy.y, + truncated_title, + self.status().unwrap_or("N/A"), + fxy_chain_str + ) + } +} + +impl TableEntry for DTableEntry { + fn fxy(&self) -> FXY { + self.fxy + } +} + +impl TableEntry for BTableEntry { + fn fxy(&self) -> FXY { + self.fxy + } +} diff --git a/gen/src/wmo/btable.rs b/gen/src/wmo/btable.rs index 701e7b4..87a2970 100644 --- a/gen/src/wmo/btable.rs +++ b/gen/src/wmo/btable.rs @@ -1,6 +1,10 @@ -use crate::{FXY, TableEntry, TableEntryLoader}; -use rkyv::Archive; +use super::EntryLoader; +use crate::{ + FXY, + tables::{BTable, BTableEntry}, +}; +#[derive(Default)] pub struct BTableCsvLoader; #[derive(Debug, serde::Deserialize)] @@ -32,7 +36,7 @@ pub struct RawBTableEntry { #[serde(rename = "noteIDs")] pub note_ids: Option, #[serde(rename = "Status")] - pub status: String, + pub status: Option, } // Helper function to deserialize empty strings as None @@ -57,102 +61,12 @@ where } } -#[derive( - Debug, Clone, serde::Deserialize, serde::Serialize, Archive, rkyv::Serialize, rkyv::Deserialize, -)] -#[rkyv(compare(PartialEq), derive(Debug))] -pub struct BTableEntry { - fxy: FXY, - class_name_en: String, - element_name_en: String, - bufr_unit: String, - bufr_scale: i32, - bufr_reference_value: i32, - bufr_datawidth_bits: u32, - note_en: Option, - note_ids: Option, - status: String, -} - -impl BTableEntry { - pub fn fxy(&self) -> FXY { - self.fxy - } - - pub fn class_name_en(&self) -> &str { - &self.class_name_en - } - - pub fn element_name_en(&self) -> &str { - &self.element_name_en - } - - pub fn bufr_unit(&self) -> &str { - &self.bufr_unit - } - - pub fn bufr_scale(&self) -> i32 { - self.bufr_scale - } - - pub fn bufr_reference_value(&self) -> i32 { - self.bufr_reference_value - } - - pub fn bufr_datawidth_bits(&self) -> u32 { - self.bufr_datawidth_bits - } - - pub fn note_en(&self) -> Option<&str> { - self.note_en.as_deref() - } - - pub fn note_ids(&self) -> Option<&str> { - self.note_ids.as_deref() - } - - pub fn status(&self) -> &str { - &self.status - } -} - -impl std::fmt::Display for BTableEntry { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let element_name = if self.element_name_en.len() > 40 { - format!("{}...", &self.element_name_en[..37]) - } else { - self.element_name_en.clone() - }; - - let unit = if self.bufr_unit.len() > 15 { - format!("{}...", &self.bufr_unit[..12]) - } else { - self.bufr_unit.clone() - }; - - write!( - f, - "{:02}{:02}{:03} | {:<40} | {:<15} | {:>5} | {:>8} | {:>8} | {}", - self.fxy.f, - self.fxy.x, - self.fxy.y, - element_name, - unit, - self.bufr_scale, - self.bufr_reference_value, - self.bufr_datawidth_bits, - self.status - ) - } -} - -impl TableEntryLoader for BTableCsvLoader { +impl EntryLoader for BTableCsvLoader { type RawEntry = RawBTableEntry; - type TableEntry = BTableEntry; - const TABLE_TYPE: crate::TableType = crate::TableType::B; + type Output = BTableEntry; + type TableType = BTable; - fn process_entry(&mut self, raw: Self::RawEntry) -> anyhow::Result> { - // Parse FXY string (e.g., "001001") to u32 + fn process_entry(&mut self, raw: Self::RawEntry) -> anyhow::Result> { let fxy = FXY::from_str(&raw.fxy)?; let entry = BTableEntry { @@ -171,9 +85,3 @@ impl TableEntryLoader for BTableCsvLoader { Ok(Some(entry)) } } - -impl TableEntry for BTableEntry { - fn fxy(&self) -> FXY { - self.fxy - } -} diff --git a/gen/src/wmo/dtable.rs b/gen/src/wmo/dtable.rs index d9af9f8..65c3de0 100644 --- a/gen/src/wmo/dtable.rs +++ b/gen/src/wmo/dtable.rs @@ -1,5 +1,8 @@ -use crate::{FXY, TableEntry, TableEntryLoader}; -use rkyv::Archive; +use super::EntryLoader; +use crate::{ + FXY, + tables::{DTable, DTableEntry}, +}; #[derive(Debug, Clone, Default)] pub struct DTableCsvLoader { @@ -9,9 +12,9 @@ pub struct DTableCsvLoader { #[derive(Debug, serde::Deserialize)] pub struct RawDTableEntry { #[serde(rename = "Category")] - pub category: String, + pub category: Option, #[serde(rename = "CategoryOfSequences_en")] - pub category_of_sequences_en: String, + pub category_of_sequences_en: Option, #[serde(rename = "FXY1")] pub fxy1: String, #[serde(rename = "Title_en")] @@ -27,17 +30,17 @@ pub struct RawDTableEntry { #[serde(rename = "Note_en")] pub note_en: Option, #[serde(rename = "noteIDs")] - pub note_ids: String, + pub note_ids: Option, #[serde(rename = "Status")] - pub status: String, + pub status: Option, } -impl TableEntryLoader for DTableCsvLoader { +impl EntryLoader for DTableCsvLoader { type RawEntry = RawDTableEntry; - type TableEntry = DTableEntry; - const TABLE_TYPE: crate::TableType = crate::TableType::D; + type Output = DTableEntry; + type TableType = DTable; - fn process_entry(&mut self, raw: Self::RawEntry) -> anyhow::Result> { + fn process_entry(&mut self, raw: Self::RawEntry) -> anyhow::Result> { // Process the raw entry as needed if self.current_chain.is_none() { let entry = DTableEntry { @@ -87,91 +90,7 @@ impl TableEntryLoader for DTableCsvLoader { } } - fn finish(&mut self) -> anyhow::Result> { + fn finish(&mut self) -> anyhow::Result> { Ok(self.current_chain.take()) } } - -#[derive( - Debug, Clone, serde::Deserialize, serde::Serialize, Archive, rkyv::Serialize, rkyv::Deserialize, -)] -#[rkyv(compare(PartialEq), derive(Debug))] -pub struct DTableEntry { - fxy: FXY, - fxy_chain: Vec, - category: String, - category_of_sequences_en: String, - title_en: Option, - subtitle_en: Option, - note_en: Option, - note_ids: String, - status: String, -} - -impl DTableEntry { - pub fn fxy(&self) -> FXY { - self.fxy - } - - pub fn fxy_chain(&self) -> &[FXY] { - &self.fxy_chain - } - - pub fn category(&self) -> &str { - &self.category - } - - pub fn category_of_sequences_en(&self) -> &str { - &self.category_of_sequences_en - } - - pub fn title_en(&self) -> Option<&str> { - self.title_en.as_deref() - } - - pub fn subtitle_en(&self) -> Option<&str> { - self.subtitle_en.as_deref() - } - - pub fn note_en(&self) -> Option<&str> { - self.note_en.as_deref() - } - - pub fn note_ids(&self) -> &str { - &self.note_ids - } - - pub fn status(&self) -> &str { - &self.status - } -} - -impl std::fmt::Display for DTableEntry { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let fxy_chain_str: String = self - .fxy_chain - .iter() - .map(|fxy| format!("{:02}{:02}{:03}", fxy.f, fxy.x, fxy.y)) - .collect::>() - .join(", "); - - let title = self.title_en.as_deref().unwrap_or("N/A"); - let truncated_title = if title.len() > 50 { - format!("{}...", &title[..47]) - } else { - title.to_string() - }; - - write!( - f, - "{:02}{:02}{:03} | {:<50} | {:<12} | [{}]", - self.fxy.f, self.fxy.x, self.fxy.y, truncated_title, self.status, fxy_chain_str - ) - } -} - -impl TableEntry for DTableEntry { - fn fxy(&self) -> FXY { - self.fxy - } -} diff --git a/gen/src/wmo/mod.rs b/gen/src/wmo/mod.rs index 2b2c7b1..f829fc6 100644 --- a/gen/src/wmo/mod.rs +++ b/gen/src/wmo/mod.rs @@ -1,2 +1,82 @@ pub mod btable; pub mod dtable; +use crate::{ + TableConverter, + tables::{TableEntryFull, TableTypeTrait}, +}; +pub use btable::BTableCsvLoader as WMOBTableLoader; +use csv::ReaderBuilder; +pub use dtable::DTableCsvLoader as WMODTableLoader; +use std::fmt::Debug; + +#[derive(Default)] +pub struct TableLoader { + _marker: std::marker::PhantomData, +} + +impl TableLoader { + pub fn load_table>( + &self, + path: P, + loader: &mut C, + ) -> anyhow::Result> { + let mut entries = vec![]; + let mut rdr = ReaderBuilder::new() + .has_headers(true) + .delimiter(b',') + .flexible(true) // Allow variable number of fields + .from_path(path.as_ref())?; + + let mut line_num = 1; // Start at 1 for header + for result in rdr.deserialize() { + line_num += 1; + match result { + Ok(record) => { + let record: C::RawEntry = record; + if let Some(processed_entry) = loader.process_entry(record)? { + entries.push(processed_entry); + } + } + Err(e) => { + // Log the error but continue processing + eprintln!( + "Warning: Skipping line {} in {}: {}", + line_num, + path.as_ref().display(), + e + ); + } + } + } + + if let Some(processed_entry) = loader.finish()? { + entries.push(processed_entry); + } + Ok(entries) + } +} + +pub trait EntryLoader: Default { + type Output: TableEntryFull; + type RawEntry: for<'de> serde::Deserialize<'de> + Debug; + type TableType: TableTypeTrait; + + fn process_entry(&mut self, raw: Self::RawEntry) -> anyhow::Result>; + + fn finish(&mut self) -> anyhow::Result> { + Ok(None) + } +} + +impl TableConverter for TableLoader { + type OutputEntry = T::Output; + type TableType = T::TableType; + + fn convert>( + &self, + path: P, + ) -> anyhow::Result> { + let mut loader = T::default(); + self.load_table(path, &mut loader) + } +} diff --git a/rbufr/src/block.rs b/rbufr/src/block.rs index 02c13db..1da4386 100644 --- a/rbufr/src/block.rs +++ b/rbufr/src/block.rs @@ -1,4 +1,5 @@ -use genlib::{BUFRTableMPH, TableEntryLoader}; +use genlib::BUFRTableMPH; +use genlib::tables::TableTypeTrait; use crate::errors::Result; use crate::structs::versions::BUFRMessage; @@ -44,7 +45,7 @@ impl MessageBlock { // master_b_table.load_table(TT::Standard); } - fn load_first_validable_table( + fn load_first_validable_table( &self, table_version: u8, ) -> Result> { diff --git a/rbufr/src/tables.rs b/rbufr/src/tables.rs index 6489f5b..33bf68f 100644 --- a/rbufr/src/tables.rs +++ b/rbufr/src/tables.rs @@ -1,6 +1,6 @@ use crate::errors::Result; pub use genlib::prelude::{BUFRTableB, BUFRTableD, TableType}; -use genlib::{TableEntryLoader, prelude::*}; +use genlib::{prelude::*, tables::TableTypeTrait}; use std::path::PathBuf; pub trait TableTrait { @@ -94,7 +94,7 @@ pub struct TableLoader; impl TableLoader { pub fn load_table(&self, table_type: impl TableTrait) -> Result> where - T: TableEntryLoader, + T: TableTypeTrait, { let path = table_type.file_path(T::TABLE_TYPE); BUFRTableMPH::::load_from_disk(path).map_err(|e| e.into()) diff --git a/tables/master/BUFR_TableB_en_00.bufrtbl b/tables/master/BUFR_TableB_en_00.bufrtbl index babfa11..8b586bc 100644 Binary files a/tables/master/BUFR_TableB_en_00.bufrtbl and b/tables/master/BUFR_TableB_en_00.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_01.bufrtbl b/tables/master/BUFR_TableB_en_01.bufrtbl index a4755b8..0197c6f 100644 Binary files a/tables/master/BUFR_TableB_en_01.bufrtbl and b/tables/master/BUFR_TableB_en_01.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_02.bufrtbl b/tables/master/BUFR_TableB_en_02.bufrtbl index bb156f2..7cc9e84 100644 Binary files a/tables/master/BUFR_TableB_en_02.bufrtbl and b/tables/master/BUFR_TableB_en_02.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_03.bufrtbl b/tables/master/BUFR_TableB_en_03.bufrtbl index 14bee96..d2319bf 100644 Binary files a/tables/master/BUFR_TableB_en_03.bufrtbl and b/tables/master/BUFR_TableB_en_03.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_04.bufrtbl b/tables/master/BUFR_TableB_en_04.bufrtbl index 8989c53..197b213 100644 Binary files a/tables/master/BUFR_TableB_en_04.bufrtbl and b/tables/master/BUFR_TableB_en_04.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_05.bufrtbl b/tables/master/BUFR_TableB_en_05.bufrtbl index 080a03c..400b7aa 100644 Binary files a/tables/master/BUFR_TableB_en_05.bufrtbl and b/tables/master/BUFR_TableB_en_05.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_06.bufrtbl b/tables/master/BUFR_TableB_en_06.bufrtbl index ffaeda8..66ccb91 100644 Binary files a/tables/master/BUFR_TableB_en_06.bufrtbl and b/tables/master/BUFR_TableB_en_06.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_07.bufrtbl b/tables/master/BUFR_TableB_en_07.bufrtbl index 3324fed..2be778b 100644 Binary files a/tables/master/BUFR_TableB_en_07.bufrtbl and b/tables/master/BUFR_TableB_en_07.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_08.bufrtbl b/tables/master/BUFR_TableB_en_08.bufrtbl index 5e20f5c..c3ed6f7 100644 Binary files a/tables/master/BUFR_TableB_en_08.bufrtbl and b/tables/master/BUFR_TableB_en_08.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_10.bufrtbl b/tables/master/BUFR_TableB_en_10.bufrtbl index e3b0e4c..2a5e92d 100644 Binary files a/tables/master/BUFR_TableB_en_10.bufrtbl and b/tables/master/BUFR_TableB_en_10.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_11.bufrtbl b/tables/master/BUFR_TableB_en_11.bufrtbl index eb500a0..bbfa2cb 100644 Binary files a/tables/master/BUFR_TableB_en_11.bufrtbl and b/tables/master/BUFR_TableB_en_11.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_12.bufrtbl b/tables/master/BUFR_TableB_en_12.bufrtbl index 5fe1d6a..0e07415 100644 Binary files a/tables/master/BUFR_TableB_en_12.bufrtbl and b/tables/master/BUFR_TableB_en_12.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_13.bufrtbl b/tables/master/BUFR_TableB_en_13.bufrtbl index 0d52b9d..3acf0f4 100644 Binary files a/tables/master/BUFR_TableB_en_13.bufrtbl and b/tables/master/BUFR_TableB_en_13.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_14.bufrtbl b/tables/master/BUFR_TableB_en_14.bufrtbl index 704b366..329fadb 100644 Binary files a/tables/master/BUFR_TableB_en_14.bufrtbl and b/tables/master/BUFR_TableB_en_14.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_15.bufrtbl b/tables/master/BUFR_TableB_en_15.bufrtbl index f2975db..18d09b9 100644 Binary files a/tables/master/BUFR_TableB_en_15.bufrtbl and b/tables/master/BUFR_TableB_en_15.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_19.bufrtbl b/tables/master/BUFR_TableB_en_19.bufrtbl index fc3743c..433aaf1 100644 Binary files a/tables/master/BUFR_TableB_en_19.bufrtbl and b/tables/master/BUFR_TableB_en_19.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_20.bufrtbl b/tables/master/BUFR_TableB_en_20.bufrtbl index 48f53e6..0780657 100644 Binary files a/tables/master/BUFR_TableB_en_20.bufrtbl and b/tables/master/BUFR_TableB_en_20.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_21.bufrtbl b/tables/master/BUFR_TableB_en_21.bufrtbl index dfdf41a..179186f 100644 Binary files a/tables/master/BUFR_TableB_en_21.bufrtbl and b/tables/master/BUFR_TableB_en_21.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_22.bufrtbl b/tables/master/BUFR_TableB_en_22.bufrtbl index 96a240c..b76e1e8 100644 Binary files a/tables/master/BUFR_TableB_en_22.bufrtbl and b/tables/master/BUFR_TableB_en_22.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_23.bufrtbl b/tables/master/BUFR_TableB_en_23.bufrtbl index f2a2cfa..6e7604d 100644 Binary files a/tables/master/BUFR_TableB_en_23.bufrtbl and b/tables/master/BUFR_TableB_en_23.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_24.bufrtbl b/tables/master/BUFR_TableB_en_24.bufrtbl index e021675..287710c 100644 Binary files a/tables/master/BUFR_TableB_en_24.bufrtbl and b/tables/master/BUFR_TableB_en_24.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_25.bufrtbl b/tables/master/BUFR_TableB_en_25.bufrtbl index 67b16ab..b0119d8 100644 Binary files a/tables/master/BUFR_TableB_en_25.bufrtbl and b/tables/master/BUFR_TableB_en_25.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_26.bufrtbl b/tables/master/BUFR_TableB_en_26.bufrtbl index 27cb7b9..44ebfad 100644 Binary files a/tables/master/BUFR_TableB_en_26.bufrtbl and b/tables/master/BUFR_TableB_en_26.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_27.bufrtbl b/tables/master/BUFR_TableB_en_27.bufrtbl index 311b21f..22bec20 100644 Binary files a/tables/master/BUFR_TableB_en_27.bufrtbl and b/tables/master/BUFR_TableB_en_27.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_28.bufrtbl b/tables/master/BUFR_TableB_en_28.bufrtbl index 76b0a41..d05d3bc 100644 Binary files a/tables/master/BUFR_TableB_en_28.bufrtbl and b/tables/master/BUFR_TableB_en_28.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_29.bufrtbl b/tables/master/BUFR_TableB_en_29.bufrtbl index de678b4..0427fd5 100644 Binary files a/tables/master/BUFR_TableB_en_29.bufrtbl and b/tables/master/BUFR_TableB_en_29.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_30.bufrtbl b/tables/master/BUFR_TableB_en_30.bufrtbl index 3f8fad2..97afb43 100644 Binary files a/tables/master/BUFR_TableB_en_30.bufrtbl and b/tables/master/BUFR_TableB_en_30.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_31.bufrtbl b/tables/master/BUFR_TableB_en_31.bufrtbl index 1a289ce..786ea10 100644 Binary files a/tables/master/BUFR_TableB_en_31.bufrtbl and b/tables/master/BUFR_TableB_en_31.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_33.bufrtbl b/tables/master/BUFR_TableB_en_33.bufrtbl index e258bcb..d54694c 100644 Binary files a/tables/master/BUFR_TableB_en_33.bufrtbl and b/tables/master/BUFR_TableB_en_33.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_35.bufrtbl b/tables/master/BUFR_TableB_en_35.bufrtbl index dece8d2..e9bac08 100644 Binary files a/tables/master/BUFR_TableB_en_35.bufrtbl and b/tables/master/BUFR_TableB_en_35.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_40.bufrtbl b/tables/master/BUFR_TableB_en_40.bufrtbl index 236ecb2..5e3475f 100644 Binary files a/tables/master/BUFR_TableB_en_40.bufrtbl and b/tables/master/BUFR_TableB_en_40.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_41.bufrtbl b/tables/master/BUFR_TableB_en_41.bufrtbl index 1779d0a..9f08ee6 100644 Binary files a/tables/master/BUFR_TableB_en_41.bufrtbl and b/tables/master/BUFR_TableB_en_41.bufrtbl differ diff --git a/tables/master/BUFR_TableB_en_42.bufrtbl b/tables/master/BUFR_TableB_en_42.bufrtbl index fa2f762..649c101 100644 Binary files a/tables/master/BUFR_TableB_en_42.bufrtbl and b/tables/master/BUFR_TableB_en_42.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_00.bufrtbl b/tables/master/BUFR_TableD_en_00.bufrtbl index fef8285..744e559 100644 Binary files a/tables/master/BUFR_TableD_en_00.bufrtbl and b/tables/master/BUFR_TableD_en_00.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_01.bufrtbl b/tables/master/BUFR_TableD_en_01.bufrtbl index 9e195c1..e20871b 100644 Binary files a/tables/master/BUFR_TableD_en_01.bufrtbl and b/tables/master/BUFR_TableD_en_01.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_02.bufrtbl b/tables/master/BUFR_TableD_en_02.bufrtbl index b512e79..ec30d18 100644 Binary files a/tables/master/BUFR_TableD_en_02.bufrtbl and b/tables/master/BUFR_TableD_en_02.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_03.bufrtbl b/tables/master/BUFR_TableD_en_03.bufrtbl index 476b196..cd4207d 100644 Binary files a/tables/master/BUFR_TableD_en_03.bufrtbl and b/tables/master/BUFR_TableD_en_03.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_04.bufrtbl b/tables/master/BUFR_TableD_en_04.bufrtbl index 9a902d0..fef2f0a 100644 Binary files a/tables/master/BUFR_TableD_en_04.bufrtbl and b/tables/master/BUFR_TableD_en_04.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_05.bufrtbl b/tables/master/BUFR_TableD_en_05.bufrtbl index 6ea92d6..d2f822e 100644 Binary files a/tables/master/BUFR_TableD_en_05.bufrtbl and b/tables/master/BUFR_TableD_en_05.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_06.bufrtbl b/tables/master/BUFR_TableD_en_06.bufrtbl index 367e14e..ced2fc7 100644 Binary files a/tables/master/BUFR_TableD_en_06.bufrtbl and b/tables/master/BUFR_TableD_en_06.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_07.bufrtbl b/tables/master/BUFR_TableD_en_07.bufrtbl index af93874..11185e5 100644 Binary files a/tables/master/BUFR_TableD_en_07.bufrtbl and b/tables/master/BUFR_TableD_en_07.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_08.bufrtbl b/tables/master/BUFR_TableD_en_08.bufrtbl index 29960be..960141d 100644 Binary files a/tables/master/BUFR_TableD_en_08.bufrtbl and b/tables/master/BUFR_TableD_en_08.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_09.bufrtbl b/tables/master/BUFR_TableD_en_09.bufrtbl index a55ee89..bb5899c 100644 Binary files a/tables/master/BUFR_TableD_en_09.bufrtbl and b/tables/master/BUFR_TableD_en_09.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_10.bufrtbl b/tables/master/BUFR_TableD_en_10.bufrtbl index dfdfecf..3856e69 100644 Binary files a/tables/master/BUFR_TableD_en_10.bufrtbl and b/tables/master/BUFR_TableD_en_10.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_11.bufrtbl b/tables/master/BUFR_TableD_en_11.bufrtbl index 3318af6..7b0e7e5 100644 Binary files a/tables/master/BUFR_TableD_en_11.bufrtbl and b/tables/master/BUFR_TableD_en_11.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_12.bufrtbl b/tables/master/BUFR_TableD_en_12.bufrtbl index 6885259..1becd81 100644 Binary files a/tables/master/BUFR_TableD_en_12.bufrtbl and b/tables/master/BUFR_TableD_en_12.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_13.bufrtbl b/tables/master/BUFR_TableD_en_13.bufrtbl index ab58def..6aaa134 100644 Binary files a/tables/master/BUFR_TableD_en_13.bufrtbl and b/tables/master/BUFR_TableD_en_13.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_15.bufrtbl b/tables/master/BUFR_TableD_en_15.bufrtbl index f266c2e..b13ba08 100644 Binary files a/tables/master/BUFR_TableD_en_15.bufrtbl and b/tables/master/BUFR_TableD_en_15.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_16.bufrtbl b/tables/master/BUFR_TableD_en_16.bufrtbl index 6c4b93c..531dbae 100644 Binary files a/tables/master/BUFR_TableD_en_16.bufrtbl and b/tables/master/BUFR_TableD_en_16.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_18.bufrtbl b/tables/master/BUFR_TableD_en_18.bufrtbl index 8c14c00..cc2ce47 100644 Binary files a/tables/master/BUFR_TableD_en_18.bufrtbl and b/tables/master/BUFR_TableD_en_18.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_21.bufrtbl b/tables/master/BUFR_TableD_en_21.bufrtbl index e5b0090..68e10ad 100644 Binary files a/tables/master/BUFR_TableD_en_21.bufrtbl and b/tables/master/BUFR_TableD_en_21.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_22.bufrtbl b/tables/master/BUFR_TableD_en_22.bufrtbl index eb19ea4..da29ca2 100644 Binary files a/tables/master/BUFR_TableD_en_22.bufrtbl and b/tables/master/BUFR_TableD_en_22.bufrtbl differ diff --git a/tables/master/BUFR_TableD_en_40.bufrtbl b/tables/master/BUFR_TableD_en_40.bufrtbl index b6fbc6e..33d58d7 100644 Binary files a/tables/master/BUFR_TableD_en_40.bufrtbl and b/tables/master/BUFR_TableD_en_40.bufrtbl differ