diff --git a/.gitignore b/.gitignore index ea8c4bf..5ced689 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target + +/tmp-out \ No newline at end of file diff --git a/gen/src/fr/btable.rs b/gen/src/fr/btable.rs index a266904..c7776c9 100644 --- a/gen/src/fr/btable.rs +++ b/gen/src/fr/btable.rs @@ -23,7 +23,16 @@ impl EntryLoader for BTableLoader { raw.get(index) .map(|s| { let mut s = s.to_string(); - s.retain(|c| c.is_alphanumeric()); + s.retain(|c| { + c.is_alphanumeric() + || c == '-' + || c == '.' + || c == '+' + || c == 'e' + || c == 'E' + || c == '_' + || c == '/' + }); s }) .ok_or_else(|| anyhow::anyhow!("Missing field at index {}", index)) diff --git a/gen/src/lib.rs b/gen/src/lib.rs index 7bf5cf4..63cadf2 100644 --- a/gen/src/lib.rs +++ b/gen/src/lib.rs @@ -2,8 +2,6 @@ pub mod config; pub mod fr; #[cfg(feature = "opera")] pub mod opera; -#[cfg(feature = "opera")] -pub use opera::bitmap::OPERABitmap; pub mod pattern; pub mod prelude; pub mod tables; @@ -15,14 +13,13 @@ use ph::fmph::GOFunction; use rkyv::api::high::HighValidator; use rkyv::bytecheck::CheckBytes; use rkyv::rancor::Error; -use rkyv::{Archive, Archived, Deserialize, Serialize}; +use rkyv::{Archive, Deserialize, Serialize}; use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize}; -use std::fmt::{Debug, Display}; +use std::fmt::Debug; use std::io::{Cursor, Write}; use std::path::Path; -use crate::tables::{TableEntry, TableEntryFull, TableTypeTrait}; -use rkyv::{api::high::to_bytes_with_alloc, ser::allocator::Arena}; +use crate::tables::{TableEntryFull, TableTypeTrait}; pub trait TableConverter { type OutputEntry: TableEntryFull; @@ -159,13 +156,13 @@ where )] #[rkyv(compare(PartialEq), derive(Debug, Clone, Copy))] pub struct FXY { - pub f: u16, - pub x: u16, - pub y: u16, + pub f: i32, + pub x: i32, + pub y: i32, } impl FXY { - pub fn new(f: u16, x: u16, y: u16) -> Self { + pub fn new(f: i32, x: i32, y: i32) -> Self { FXY { f, x, y } } pub fn from_str(fxy_str: &str) -> anyhow::Result { @@ -176,14 +173,14 @@ impl FXY { } let f = fxy_str[0..2] - .parse::() + .parse::() .with_context(|| format!("Failed to parse F from FXY: {}", fxy_str))?; let x = fxy_str[2..4] - .parse::() + .parse::() .with_context(|| format!("Failed to parse X from FXY: {}", fxy_str))?; let y = fxy_str[4..6] - .parse::() + .parse::() .with_context(|| format!("Failed to parse Y from FXY: {}", fxy_str))?; Ok(FXY { f, x, y }) @@ -195,14 +192,13 @@ impl FXY { ((self.f as u32) << 14) | ((self.x as u32) << 8) | (self.y as u32) } - /// Convert u32 back to FXY - pub fn from_u32(value: u32) -> Self { - FXY { - f: ((value >> 14) & 0x3) as u16, - x: ((value >> 8) & 0x3F) as u16, - y: (value & 0xFF) as u16, - } - } + // pub fn from_u32(value: u32) -> Self { + // FXY { + // f: ((value >> 14) & 0x3) as u16, + // x: ((value >> 8) & 0x3F) as u16, + // y: (value & 0xFF) as u16, + // } + // } } pub struct BUFRTableMPH { @@ -248,14 +244,18 @@ where pub enum TableType { B, D, + BitMap, } #[cfg(test)] mod test { use crate::{ - BUFRTableMPH, BufrTableMph, FXY, + BUFRTableMPH, + BufrTableMph, + FXY, + // wmo::{TableLoader, btable::BTableCsvLoader}, + fr::{TableLoader, btable::BTableLoader as BTableCsvLoader}, prelude::{BUFRTableB, BUFRTableD}, - wmo::{TableLoader, btable::BTableCsvLoader}, }; #[test] @@ -263,7 +263,8 @@ mod test { let table_loader = TableLoader::::default(); BUFRTableB::build_from_csv( table_loader, - "/Users/xiang.li1/projects/rbufr/BUFR4/BUFRCREX_TableB_en_42.csv", + // "/Users/xiang.li1/projects/rbufr/BUFR4/BUFRCREX_TableB_en_42.csv", + "/Users/xiang.li1/Downloads/tables 2/bufrtabb_16.csv", "./test.bufrtbl", ) .unwrap(); diff --git a/gen/src/main.rs b/gen/src/main.rs index d97733d..355d09a 100644 --- a/gen/src/main.rs +++ b/gen/src/main.rs @@ -6,6 +6,8 @@ use genlib::{ pattern::{TableKind, TableScanner}, prelude::{BUFRTableB, BUFRTableD}, }; +#[cfg(feature = "opera")] +use genlib::{BUFRTableMPH, opera, tables::BitMap}; use std::path::{Path, PathBuf}; #[derive(Parser)] @@ -78,6 +80,28 @@ enum Commands { #[arg(short, long, default_value = "scan-config.toml")] output: PathBuf, }, + /// Convert Opera bitmap file to BUFR format + #[cfg(feature = "opera")] + ConvertOperaBitmap { + /// Input Opera bitmap CSV file + #[arg(short, long)] + input: PathBuf, + + /// Output path (without extension) + #[arg(short, long)] + output: PathBuf, + }, + /// Print Opera bitmap table + #[cfg(feature = "opera")] + PrintOperaBitmap { + /// Path to Opera bitmap .bufrtbl file (without extension) + #[arg(short, long)] + input: PathBuf, + + /// Maximum number of entries to print (optional) + #[arg(short, long)] + limit: Option, + }, } fn main() -> Result<()> { @@ -111,6 +135,14 @@ fn main() -> Result<()> { Commands::GenConfig { output } => { generate_config_file(&output)?; } + #[cfg(feature = "opera")] + Commands::ConvertOperaBitmap { input, output } => { + convert_opera_bitmap(&input, &output)?; + } + #[cfg(feature = "opera")] + Commands::PrintOperaBitmap { input, limit } => { + print_opera_bitmap(&input, limit)?; + } } Ok(()) @@ -477,3 +509,49 @@ fn generate_config_file(output_path: &Path) -> Result<()> { Ok(()) } + +#[cfg(feature = "opera")] +fn convert_opera_bitmap(input_path: &Path, output_path: &Path) -> Result<()> { + println!( + "Converting Opera bitmap from {} to {}", + input_path.display(), + output_path.display() + ); + + let loader = opera::TableLoader {}; + BUFRTableMPH::::build_from_csv(loader, input_path, output_path)?; + + println!("Conversion completed successfully!"); + Ok(()) +} + +#[cfg(feature = "opera")] +fn print_opera_bitmap(input_path: &Path, limit: Option) -> Result<()> { + println!("Loading Opera bitmap from: {}", input_path.display()); + + let table = BUFRTableMPH::::load_from_disk(input_path)?; + let entries = table.get_all_entries(); + + println!("\nOpera Bitmap Entries (Total: {})", entries.len()); + println!("{}", "=".repeat(60)); + println!("{:<10} | {}", "FXY", "Depth"); + println!("{}", "-".repeat(60)); + + let display_entries = if let Some(max) = limit { + &entries[..entries.len().min(max)] + } else { + &entries[..] + }; + + for entry in display_entries { + println!("{}", entry); + } + + if let Some(max) = limit { + if entries.len() > max { + println!("\n... ({} more entries omitted)", entries.len() - max); + } + } + + Ok(()) +} diff --git a/gen/src/opera/bitmap.rs b/gen/src/opera/bitmap.rs deleted file mode 100644 index d66ab40..0000000 --- a/gen/src/opera/bitmap.rs +++ /dev/null @@ -1,82 +0,0 @@ -use csv::ReaderBuilder; -use std::{fs::File, path::Path}; - -pub struct OPERABitmap { - bitmap: Vec, -} - -impl OPERABitmap { - pub fn load>(p: P) -> anyhow::Result { - let mut rdr = ReaderBuilder::new() - .has_headers(false) - .delimiter(b';') - .from_reader(File::open(p)?); - - let mut results = default_bitmap(); - let mut line: usize = 0; - - for result in rdr.records() { - let record = result?; - - let parse_field = |idx: usize| { - record - .get(idx) - .map(|s| s.trim().to_string()) - .ok_or_else(|| { - anyhow::anyhow!("Parse Opera Bitmap File failed at index {}", idx) - }) - }; - - let f = parse_field(0)?.parse()?; - let x = parse_field(1)?.parse()?; - let y = parse_field(2)?.parse()?; - let dw = parse_field(3)?.parse()?; - - let entry = OPERABitmapEntry { - f, - x, - y, - datawidth_bits: dw, - }; - if let Some(line) = results.get_mut(line) { - *line = entry; - } else { - results.push(entry); - } - - line += 1; - } - - Ok(OPERABitmap { bitmap: results }) - } -} - -pub struct OPERABitmapEntry { - pub f: u16, - pub x: u16, - pub y: u16, - pub datawidth_bits: u8, -} - -fn default_bitmap() -> Vec { - const VALUES: [(u16, u16, u16, u8); 8] = [ - (3, 21, 192, 1), - (3, 21, 193, 1), - (3, 21, 194, 1), - (3, 21, 195, 1), - (3, 21, 196, 1), - (3, 21, 197, 1), - (3, 21, 200, 2), - (3, 21, 202, 2), - ]; - - VALUES - .iter() - .map(|(f, x, y, dw)| OPERABitmapEntry { - f: *f, - x: *x, - y: *y, - datawidth_bits: *dw, - }) - .collect() -} diff --git a/gen/src/opera/mod.rs b/gen/src/opera/mod.rs index 163f896..ec25762 100644 --- a/gen/src/opera/mod.rs +++ b/gen/src/opera/mod.rs @@ -1 +1,51 @@ -pub mod bitmap; +use crate::{ + FXY, TableConverter, TableType, + tables::{BitMap, BitMapEntry}, +}; + +use csv::ReaderBuilder; + +pub struct TableLoader {} + +impl TableConverter for TableLoader { + type OutputEntry = BitMapEntry; + type TableType = BitMap; + + fn convert>( + &self, + path: P, + ) -> anyhow::Result> { + let mut rdr = ReaderBuilder::new() + .has_headers(false) + .delimiter(b';') + .flexible(true) // Allow variable number of fields + .from_path(path.as_ref())?; + + let mut entries = vec![]; + + for result in rdr.records() { + let record = result?; + + let parse_field = |idx: usize| { + record + .get(idx) + .map(|s| s.trim().to_string()) + .ok_or_else(|| { + anyhow::anyhow!("Parse Opera Bitmap File failed at index {}", idx) + }) + }; + + let f = parse_field(0)?.parse()?; + let x = parse_field(1)?.parse()?; + let y = parse_field(2)?.parse()?; + let dw = parse_field(3)?.parse()?; + + let entry = BitMapEntry { + fxy: FXY::new(f, x, y), + depth: dw, + }; + entries.push(entry); + } + Ok(entries) + } +} diff --git a/gen/src/prelude.rs b/gen/src/prelude.rs index 9aaa2b8..d36bcdd 100644 --- a/gen/src/prelude.rs +++ b/gen/src/prelude.rs @@ -3,6 +3,7 @@ use crate::tables::DTable; pub use crate::wmo; pub type BUFRTableD = crate::BUFRTableMPH; pub type BUFRTableB = crate::BUFRTableMPH; +pub type BUFRTableBitMap = 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 index a383cd8..e507613 100644 --- a/gen/src/tables.rs +++ b/gen/src/tables.rs @@ -7,10 +7,13 @@ use rkyv::rancor::{Error, Strategy}; use serde::Serialize as SerdeSerialize; use serde::de::DeserializeOwned; use std::fmt::{Debug, Display}; +use toml::Table; pub struct BTable; pub struct DTable; +pub struct BitMap; + pub trait TableTypeTrait where ::Archived: for<'a> CheckBytes>, @@ -28,6 +31,11 @@ impl TableTypeTrait for DTable { const TABLE_TYPE: crate::TableType = crate::TableType::D; } +impl TableTypeTrait for BitMap { + type EntryType = crate::tables::BitMapEntry; + const TABLE_TYPE: crate::TableType = crate::TableType::BitMap; +} + pub trait TableEntry: SerdeSerialize + DeserializeOwned @@ -295,6 +303,41 @@ impl Display for ArchivedDTableEntry { } } +#[derive( + Debug, Clone, serde::Deserialize, serde::Serialize, Archive, rkyv::Serialize, rkyv::Deserialize, +)] +#[rkyv(compare(PartialEq), derive(Debug))] +pub struct BitMapEntry { + pub fxy: FXY, + pub depth: u8, +} + +impl Display for BitMapEntry { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{:02}{:02}{:03} | Depth: {}", + self.fxy.f, self.fxy.x, self.fxy.y, self.depth + ) + } +} + +impl Display for ArchivedBitMapEntry { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{:02}{:02}{:03} | Depth: {}", + self.fxy.f, self.fxy.x, self.fxy.y, self.depth + ) + } +} + +impl TableEntry for BitMapEntry { + fn fxy(&self) -> FXY { + self.fxy + } +} + impl TableEntry for DTableEntry { fn fxy(&self) -> FXY { self.fxy diff --git a/rbufr/Cargo.toml b/rbufr/Cargo.toml index 8804f60..21c005d 100644 --- a/rbufr/Cargo.toml +++ b/rbufr/Cargo.toml @@ -16,3 +16,7 @@ serde = { version = "1.0.228", features = ["derive"] } thiserror = "2.0.17" gentools = { path = "../gen" } anyhow = "1.0.100" + +[features] +default = ["opera"] +opera = ["gentools/opera"] diff --git a/rbufr/src/block.rs b/rbufr/src/block.rs index 16ddbc2..13ded01 100644 --- a/rbufr/src/block.rs +++ b/rbufr/src/block.rs @@ -1,7 +1,11 @@ use genlib::BUFRTableMPH; +#[cfg(feature = "opera")] +use genlib::prelude::BUFRTableBitMap; use genlib::tables::TableTypeTrait; use crate::errors::Result; +#[cfg(feature = "opera")] +use crate::structs::GENCENTER; use crate::structs::data_parser::DataParser; use crate::structs::versions::{BUFRMessage, MessageVersion}; use crate::tables::*; @@ -52,7 +56,25 @@ impl MessageBlock { (None, None) }; - let mut parser = DataParser::new(master_b, master_d, local_b, local_d); + #[cfg(feature = "opera")] + let opera_bitmap_table = self + .load_opera_bitmap_table( + table_info.center_id, + GENCENTER, + table_info.local_table_version, + master_table_version, + ) + .ok(); + + let mut parser = DataParser::new( + self.message.version(), + master_b, + master_d, + local_b, + local_d, + #[cfg(feature = "opera")] + opera_bitmap_table, + ); parser.parse(&self.message)?; @@ -77,6 +99,22 @@ impl MessageBlock { }) .ok_or(crate::errors::Error::TableNotFoundEmpty) } + + #[cfg(feature = "opera")] + fn load_opera_bitmap_table( + &self, + subcenter: u16, + center: u16, + local_version: u8, + master_version: u8, + ) -> Result { + TableLoader.load_table(BitmapTable::new( + center, + subcenter, + local_version, + master_version, + )) + } } pub struct BUFRFile { diff --git a/rbufr/src/opera.rs b/rbufr/src/opera.rs index e6d4480..da8c8b0 100644 --- a/rbufr/src/opera.rs +++ b/rbufr/src/opera.rs @@ -1,3 +1,18 @@ +use crate::structs::data_parser::Value; + /// This Module contains functions specific to handling BUFR Opera files. -pub struct OperaBitmapParser; +pub struct OperaBitmapParser { + values: Vec, + dw: u8, +} + +impl OperaBitmapParser { + pub fn new(dw: u8) -> Self { + OperaBitmapParser { values: vec![], dw } + } + + pub fn values(&mut self) -> &mut Vec { + &mut self.values + } +} diff --git a/rbufr/src/structs/data_parser.rs b/rbufr/src/structs/data_parser.rs index a9de127..6ae4cd0 100644 --- a/rbufr/src/structs/data_parser.rs +++ b/rbufr/src/structs/data_parser.rs @@ -1,14 +1,22 @@ +use std::collections::VecDeque; + use crate::{ errors::{Error, Result}, structs::versions::MessageVersion, }; +#[cfg(feature = "opera")] +use genlib::tables::ArchivedBitMapEntry; use genlib::{ FXY, opera, - prelude::{BUFRTableB, BUFRTableD}, + prelude::{BUFRTableB, BUFRTableBitMap, BUFRTableD}, tables::{ArchivedBTableEntry, ArchivedDTableEntry, BTableEntry}, }; +use serde::de; + +const MISS_VAL: f64 = 99999.999999; pub struct DataParser { + bufr_edition: u8, master_b: BUFRTableB, master_d: BUFRTableD, // local @@ -17,22 +25,28 @@ pub struct DataParser { // Common State common_scale: Option, common_ref_value: Option, - common_data_width: Option, + common_data_width: Option, common_str_width: Option, // Localized State - local_data_width: Option, + local_data_width: Option, // Temporary storage - temp_operator: Option, + temp_operator: Option, + // OPERA Bitmap Table + #[cfg(feature = "opera")] + opera_bitmap_table: Option, } impl DataParser { pub fn new( + edition: u8, master_b: BUFRTableB, master_d: BUFRTableD, local_b: Option, local_d: Option, + #[cfg(feature = "opera")] opera_bitmap_table: Option, ) -> Self { DataParser { + bufr_edition: edition, master_b, master_d, local_b, @@ -43,6 +57,8 @@ impl DataParser { common_str_width: None, local_data_width: None, temp_operator: None, + #[cfg(feature = "opera")] + opera_bitmap_table, } } @@ -64,27 +80,24 @@ impl DataParser { fn parser_inner<'a>( &mut self, values: &mut Vec, - mut descriptors: Vec, - mut data: BitInput<'a>, - ) -> Result<(Vec, BitInput<'a>)> { + mut descriptors: VecDeque, + data: BitInput<'a>, + ) -> Result<(VecDeque, BitInput<'a>)> { if descriptors.is_empty() { return Ok((descriptors, data)); } - let des = descriptors[0]; + let des = descriptors.pop_front().unwrap(); println!("Processing descriptor {:?}", des); match des.f { 0 => { // Element descriptor - parse data if let Some(e) = self.lookup_b_descriptor(des) { - // let (value, remaining) = e.parse(data); let (value, remaining) = self.evalute(data, &e)?; - - println!("Parsed value: {}", value); + println!("Evaluated descriptor {}\nTo value {}", e, value); values.push(value); - data = remaining; - descriptors.remove(0); + return Ok((descriptors, remaining)); } else { return Err(Error::ParseError(format!( "Descriptor {:?} not found in Table B", @@ -94,27 +107,57 @@ impl DataParser { } 1 => { let genlib::FXY { x, y, .. } = des; - descriptors.remove(0); + let (mut descriptors, mut data, x, y) = if y == 0 { + // Delayed repetition: parse the next descriptor to get repeat count + let (descriptors, updated_data) = + self.parser_inner(values, descriptors, data)?; + let count = if let Some(count) = values.pop() { + let count = count.as_f64().ok_or_else(|| { + Error::ParseError("Expected numeric value for repeat count".to_string()) + })?; + count.floor() as usize + } else { + return Err(Error::ParseError(format!( + "Expected UInt value for repeat count" + ))); + }; - for i in 0..y { - let descriptors_clone = descriptors.clone(); - let (cde, cd) = - self.repeat_parser(values, descriptors_clone, data, x as usize)?; + (descriptors, updated_data, x as usize, count) + } else { + (descriptors, data, x as usize, y as usize) + }; - if i == y - 1 { - descriptors = cde; + if x > descriptors.len() { + return Err(Error::ParseError(format!( + "Not enough descriptors to repeat: requested {}, available {}", + x, + descriptors.len() + ))); + } + + let seq = descriptors.split_off(x); + + for _ in 0..y { + let mut descriptors_clone = descriptors.clone(); + while !descriptors_clone.is_empty() { + let (_desc, cd) = self.parser_inner(values, descriptors_clone, data)?; + descriptors_clone = _desc; data = cd; } } + + return Ok((seq, data)); } 2 => { let data = self.deal_with_operator(values, des, data)?; - descriptors.remove(0); - return self.parser_inner(values, descriptors, data); + return Ok((descriptors, data)); } 3 => { + #[cfg(feature = "opera")] + let opera_dw = self.parse_opera_bitmap(des).map(|e| e.depth); + if let Some(seq) = self.lookup_d_descriptor(des) { - let mut fxy_chain: Vec = seq + let mut fxy_chain: VecDeque = seq .fxy_chain .iter() .map(|f| { @@ -123,8 +166,16 @@ impl DataParser { result }) .collect(); - fxy_chain.extend(descriptors[1..].into_iter()); - descriptors = fxy_chain; + + #[cfg(feature = "opera")] + if opera_dw.is_some() { + let (_, data) = + self.parse_opera_array(opera_dw.unwrap(), fxy_chain, data)?; + return Ok((descriptors, data)); + } else { + fxy_chain.extend(descriptors); + return Ok((fxy_chain, data)); + } } else { return Err(Error::ParseError(format!( "Sequence descriptor {:?} not found in Table D", @@ -182,20 +233,6 @@ impl DataParser { .or(self.local_d.as_ref().and_then(|t| t.lookup(fxy))) } - fn repeat_parser<'a>( - &mut self, - values: &mut Vec, - descriptors: Vec, - data: BitInput<'a>, - count: usize, - ) -> Result<(Vec, BitInput<'a>)> { - if count == 0 || descriptors.is_empty() { - return Ok((descriptors, data)); - } - let (desc, data) = self.parser_inner(values, descriptors, data)?; - return self.repeat_parser(values, desc, data, count - 1); - } - fn evalute<'a>( &self, data: BitInput<'a>, @@ -210,22 +247,92 @@ impl DataParser { return Ok((Value::String(s), data)); } _ => { - let datawidth = self - .common_data_width - .unwrap_or(e.bufr_datawidth_bits.to_native()); - - let scale = 10f32.powi(-self.common_scale.unwrap_or(e.bufr_scale.to_native())); - let reference_value = - self.common_ref_value - .unwrap_or(e.bufr_reference_value.to_native()) as f32; - + let datawidth = self.datawidth(e); + let scale = self.scale(e) as f64; + let reference_value = self.reference_value(e) as f64; let (value, data) = data.get_arbitary_bits(datawidth as usize)?; - let result = (value as f32) / scale + reference_value; - return Ok((Value::Float(result), data)); + let mv = (1 << datawidth) - 1; + if value == mv && e.fxy.x != 31 { + return Ok((Value::Missing, data)); + } + let result = ((value as f64) + reference_value) * 10.0f64.powi(-scale as i32); + return Ok((Value::Number(result), data)); } } } + #[inline] + fn no_change(&self, e: &ArchivedBTableEntry) -> bool { + let is_flag = match e.bufr_unit.as_str() { + "flag table" | "flag-table" => true, + _ => false, + }; + + let is_code = match e.bufr_unit.as_str() { + "code table" | "code-table" => true, + _ => false, + }; + + let delay_repeat_count = match (e.fxy.f.to_native(), e.fxy.x.to_native()) { + (0, 31) => true, + _ => false, + }; + + is_flag || is_code || delay_repeat_count + } + + fn datawidth(&self, e: &ArchivedBTableEntry) -> u32 { + let v = if self.no_change(e) { + e.bufr_datawidth_bits.to_native() + } else { + self.common_data_width + .map(|c| { + let (v, _) = e + .bufr_datawidth_bits + .to_native() + .overflowing_add_signed(c - 128); + v + }) + .unwrap_or(e.bufr_datawidth_bits.to_native()) + }; + + if self.temp_operator.is_some() { + e.bufr_datawidth_bits.to_native() + (10 * self.temp_operator.unwrap()) as u32 + } else { + v + } + } + + fn scale(&self, e: &ArchivedBTableEntry) -> i32 { + let v = if self.no_change(e) { + e.bufr_scale.to_native() + } else { + self.common_scale + .map(|c| { + let (v, _) = e.bufr_scale.to_native().overflowing_add(128 - c); + v + }) + .unwrap_or(e.bufr_scale.to_native()) + }; + + if self.temp_operator.is_some() { + e.bufr_scale.to_native() + self.temp_operator.unwrap() + } else { + v + } + } + + fn reference_value(&self, e: &ArchivedBTableEntry) -> i32 { + let v = e.bufr_reference_value.to_native(); + + if self.temp_operator.is_some() { + (e.bufr_reference_value.to_native() as f32 * 10_f32.powi(self.temp_operator.unwrap())) + as i32 + } else { + v + } + } + fn deal_with_operator<'a>( &mut self, values: &mut Vec, @@ -238,7 +345,7 @@ impl DataParser { self.common_data_width = None; } _ => { - self.common_data_width = Some(operator.y as u32); + self.common_data_width = Some(operator.y); } }, 2 => match operator.y { @@ -264,10 +371,10 @@ impl DataParser { 6 => { let localized_width = operator.y; - self.local_data_width = Some(localized_width as u32); + self.local_data_width = Some(localized_width); } 7 => { - self.temp_operator = Some(operator.y as u32); + self.temp_operator = Some(operator.y); } 8 => match operator.y { 0 => { @@ -283,26 +390,75 @@ impl DataParser { Ok(data) } + #[cfg(feature = "opera")] + fn parse_opera_bitmap(&self, des: FXY) -> Option<&ArchivedBitMapEntry> { + self.opera_bitmap_table + .as_ref() + .map(|t| t.lookup(des)) + .flatten() + } + + #[cfg(feature = "opera")] + fn parse_opera_array<'a>( + &mut self, + dw: u8, + mut descs: VecDeque, + mut data: BitInput<'a>, + ) -> Result<(VecDeque, BitInput<'a>)> { + use crate::opera::OperaBitmapParser; + + let mut opera_bitmap = OperaBitmapParser::new(dw); + + while !descs.is_empty() { + let (_descs, _data) = self.parser_inner(opera_bitmap.values(), descs, data)?; + descs = _descs; + data = _data; + } + Ok((descs, data)) + } + // fn seq_parser(descriptors: &[genlib::FXY]) -> Result<()> {} } #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] pub enum Value { - Float(f32), - Double(f64), - Int(i32), - UInt(u32), + Number(f64), + Missing, String(String), } impl std::fmt::Display for Value { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Value::Float(v) => write!(f, "{}", v), - Value::Double(v) => write!(f, "{}", v), - Value::Int(v) => write!(f, "{}", v), - Value::UInt(v) => write!(f, "{}", v), + Value::Number(v) => write!(f, "{}", v), Value::String(v) => write!(f, "{}", v), + Value::Missing => write!(f, "MISSING"), + } + } +} + +impl Value { + pub fn as_f64(&self) -> Option { + match self { + Value::Number(v) => Some(*v), + Value::Missing => Some(MISS_VAL), + Value::String(_) => None, + } + } + + pub fn as_str(&self) -> Option<&str> { + match self { + Value::String(v) => Some(v), + Value::Number(_) => None, + Value::Missing => None, + } + } + + pub fn as_bytes(&self) -> Option> { + match self { + Value::String(_) => None, + Value::Number(n) => Some(n.to_le_bytes().to_vec()), + Value::Missing => None, } } } @@ -335,12 +491,12 @@ impl<'a> BitInput<'a> { Ok((s, remaining_input)) } - pub fn get_arbitary_bits(self, nbits: usize) -> Result<(u32, BitInput<'a>)> { + pub fn get_arbitary_bits(self, nbits: usize) -> Result<(u64, BitInput<'a>)> { if nbits == 0 { return Ok((0, self)); } - let mut value: u32 = 0; + let mut value: u64 = 0; let mut remaining_bits = nbits; let mut bit_offset = self.1; // Current bit position in the first byte (0-7) let mut byte_data = self.0; // Remaining bytes @@ -364,7 +520,7 @@ impl<'a> BitInput<'a> { let extracted_bits = (current_byte >> shift) & mask; // Add to value - value = (value << bits_to_read) | extracted_bits as u32; + value = (value << bits_to_read) | extracted_bits as u64; remaining_bits -= bits_to_read; bit_offset += bits_to_read; diff --git a/rbufr/src/structs/mod.rs b/rbufr/src/structs/mod.rs index 68fa492..d6492d3 100644 --- a/rbufr/src/structs/mod.rs +++ b/rbufr/src/structs/mod.rs @@ -8,6 +8,9 @@ pub mod data_parser; pub(super) mod tools; pub mod versions; +#[cfg(feature = "opera")] +pub(super) const GENCENTER: u16 = 247; + #[inline] pub fn skip(n: usize) -> impl Fn(&[u8]) -> IResult<&[u8], ()> { move |input: &[u8]| { diff --git a/rbufr/src/structs/tools.rs b/rbufr/src/structs/tools.rs index c9536ee..ec94d2a 100644 --- a/rbufr/src/structs/tools.rs +++ b/rbufr/src/structs/tools.rs @@ -1,18 +1,20 @@ -use crate::errors::{Error, Result}; -use crate::structs::bit::{self, BitInput, parse_arbitrary_bits}; -use nom::{IResult, Parser, multi::many1}; +use std::collections::VecDeque; -pub(super) fn parse_descriptors(input: &[u8]) -> Result> { +use crate::errors::{Error, Result}; +use crate::structs::bit::{BitInput, parse_arbitrary_bits}; +use nom::IResult; + +pub(super) fn parse_descriptors(input: &[u8]) -> Result> { parse_descriptors_inner(input) .map(|(_, v)| v) .map_err(|_| Error::ParseError(format!("Can't parse descriptors from section3"))) } -fn parse_descriptors_inner(mut input: &[u8]) -> IResult> { - let mut results = Vec::new(); +fn parse_descriptors_inner(mut input: &[u8]) -> IResult> { + let mut results = VecDeque::new(); while input.len() > 1 { let ((finput, _), fxy) = take_fxy((input, 0))?; - results.push(fxy); + results.push_back(fxy); input = finput; } diff --git a/rbufr/src/structs/versions/mod.rs b/rbufr/src/structs/versions/mod.rs index 5226676..bba1480 100644 --- a/rbufr/src/structs/versions/mod.rs +++ b/rbufr/src/structs/versions/mod.rs @@ -1,5 +1,7 @@ pub mod v2; pub mod v4; +use std::collections::VecDeque; + pub(super) use super::{skip, skip1, skip2}; use crate::errors::{Error, Result}; use genlib::FXY; @@ -95,7 +97,7 @@ macro_rules! message { } } - fn descriptors(&self) -> Result> { + fn descriptors(&self) -> Result> { match self { $( BUFRMessage::$version(msg) => msg.descriptors(), @@ -161,7 +163,7 @@ pub trait MessageVersion: Sized { fn ndescs(&self) -> usize; - fn descriptors(&self) -> Result>; + fn descriptors(&self) -> Result>; fn data_block(&self) -> Result<&[u8]>; } diff --git a/rbufr/src/structs/versions/v2.rs b/rbufr/src/structs/versions/v2.rs index e1c8783..ed8f64b 100644 --- a/rbufr/src/structs/versions/v2.rs +++ b/rbufr/src/structs/versions/v2.rs @@ -1,3 +1,6 @@ +use std::collections::VecDeque; + +use genlib::FXY; use nom::{ IResult, bytes::complete::{tag, take}, @@ -62,7 +65,7 @@ impl MessageVersion for BUFRMessageV2 { self.section3.data.len() / 2 } - fn descriptors(&self) -> Result> { + fn descriptors(&self) -> Result> { parse_descriptors(&self.section3.data) } diff --git a/rbufr/src/structs/versions/v4.rs b/rbufr/src/structs/versions/v4.rs index 497bfbe..3fe66d2 100644 --- a/rbufr/src/structs/versions/v4.rs +++ b/rbufr/src/structs/versions/v4.rs @@ -1,3 +1,5 @@ +use std::collections::VecDeque; + use crate::errors::Result; use crate::structs::{tools::parse_descriptors, versions::MessageVersion}; use nom::{ @@ -64,7 +66,7 @@ impl MessageVersion for BUFRMessageV4 { self.section3.data.len() / 2 } - fn descriptors(&self) -> Result> { + fn descriptors(&self) -> Result> { parse_descriptors(&self.section3.data) } diff --git a/rbufr/src/tables.rs b/rbufr/src/tables.rs index a9e74d6..0f85d39 100644 --- a/rbufr/src/tables.rs +++ b/rbufr/src/tables.rs @@ -23,6 +23,25 @@ pub struct LocalTable { version: u8, } +#[derive(Debug, Clone, Copy)] +pub struct BitmapTable { + center: u16, + subcenter: u16, + local_version: u8, + master_version: u8, +} + +impl BitmapTable { + pub fn new(center: u16, subcenter: u16, local_version: u8, master_version: u8) -> Self { + BitmapTable { + center, + subcenter, + local_version, + master_version, + } + } +} + impl LocalTable { pub fn new(sub_center: Option, version: u8) -> Self { LocalTable { @@ -83,6 +102,22 @@ impl TableTrait for LocalTable { } } +impl TableTrait for BitmapTable { + fn file_path(&self, table_type: TableType) -> PathBuf { + match table_type { + TableType::BitMap => { + let mut base_dir = PathBuf::new(); + base_dir.push("tables/opera"); + let file_name = format!("BUFR_Opera_Bitmap_{}.bufrtbl", self.center); + base_dir.join(file_name) + } + _ => { + unreachable!("Table type not supported for BitmapTable") + } + } + } +} + pub struct TableLoader; impl TableLoader { diff --git a/rbufr/tables/local/BUFR_TableB_10.bufrtbl b/rbufr/tables/local/BUFR_TableB_10.bufrtbl index 9857b05..2b7d4f8 100644 Binary files a/rbufr/tables/local/BUFR_TableB_10.bufrtbl and b/rbufr/tables/local/BUFR_TableB_10.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_11.bufrtbl b/rbufr/tables/local/BUFR_TableB_11.bufrtbl index 22bd4aa..1bdbc1b 100644 Binary files a/rbufr/tables/local/BUFR_TableB_11.bufrtbl and b/rbufr/tables/local/BUFR_TableB_11.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_12.bufrtbl b/rbufr/tables/local/BUFR_TableB_12.bufrtbl index a46a16b..ffbcee3 100644 Binary files a/rbufr/tables/local/BUFR_TableB_12.bufrtbl and b/rbufr/tables/local/BUFR_TableB_12.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_13.bufrtbl b/rbufr/tables/local/BUFR_TableB_13.bufrtbl index c3ffe89..2dce6b3 100644 Binary files a/rbufr/tables/local/BUFR_TableB_13.bufrtbl and b/rbufr/tables/local/BUFR_TableB_13.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_14.bufrtbl b/rbufr/tables/local/BUFR_TableB_14.bufrtbl index 8646cba..0e0c662 100644 Binary files a/rbufr/tables/local/BUFR_TableB_14.bufrtbl and b/rbufr/tables/local/BUFR_TableB_14.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_15.bufrtbl b/rbufr/tables/local/BUFR_TableB_15.bufrtbl index 56cf33f..58751fe 100644 Binary files a/rbufr/tables/local/BUFR_TableB_15.bufrtbl and b/rbufr/tables/local/BUFR_TableB_15.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_16.bufrtbl b/rbufr/tables/local/BUFR_TableB_16.bufrtbl index 25e0318..52d7262 100644 Binary files a/rbufr/tables/local/BUFR_TableB_16.bufrtbl and b/rbufr/tables/local/BUFR_TableB_16.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_18.bufrtbl b/rbufr/tables/local/BUFR_TableB_18.bufrtbl index 811d1af..aaab01a 100644 Binary files a/rbufr/tables/local/BUFR_TableB_18.bufrtbl and b/rbufr/tables/local/BUFR_TableB_18.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_2.bufrtbl b/rbufr/tables/local/BUFR_TableB_2.bufrtbl index a05bf41..c087a37 100644 Binary files a/rbufr/tables/local/BUFR_TableB_2.bufrtbl and b/rbufr/tables/local/BUFR_TableB_2.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_247_7.bufrtbl b/rbufr/tables/local/BUFR_TableB_247_7.bufrtbl index db81fb7..63b359c 100644 Binary files a/rbufr/tables/local/BUFR_TableB_247_7.bufrtbl and b/rbufr/tables/local/BUFR_TableB_247_7.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_247_8.bufrtbl b/rbufr/tables/local/BUFR_TableB_247_8.bufrtbl index 88d0883..15850c7 100644 Binary files a/rbufr/tables/local/BUFR_TableB_247_8.bufrtbl and b/rbufr/tables/local/BUFR_TableB_247_8.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_247_9.bufrtbl b/rbufr/tables/local/BUFR_TableB_247_9.bufrtbl index 6bb2637..37791f8 100644 Binary files a/rbufr/tables/local/BUFR_TableB_247_9.bufrtbl and b/rbufr/tables/local/BUFR_TableB_247_9.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_255_1.bufrtbl b/rbufr/tables/local/BUFR_TableB_255_1.bufrtbl index bfc8842..b4c2ecd 100644 Binary files a/rbufr/tables/local/BUFR_TableB_255_1.bufrtbl and b/rbufr/tables/local/BUFR_TableB_255_1.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_255_5.bufrtbl b/rbufr/tables/local/BUFR_TableB_255_5.bufrtbl index 3fef9e5..438eea2 100644 Binary files a/rbufr/tables/local/BUFR_TableB_255_5.bufrtbl and b/rbufr/tables/local/BUFR_TableB_255_5.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_255_6.bufrtbl b/rbufr/tables/local/BUFR_TableB_255_6.bufrtbl index b6b78a8..add5824 100644 Binary files a/rbufr/tables/local/BUFR_TableB_255_6.bufrtbl and b/rbufr/tables/local/BUFR_TableB_255_6.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_3.bufrtbl b/rbufr/tables/local/BUFR_TableB_3.bufrtbl index 61a86dd..927bb06 100644 Binary files a/rbufr/tables/local/BUFR_TableB_3.bufrtbl and b/rbufr/tables/local/BUFR_TableB_3.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_6.bufrtbl b/rbufr/tables/local/BUFR_TableB_6.bufrtbl index f59a9aa..78b411c 100644 Binary files a/rbufr/tables/local/BUFR_TableB_6.bufrtbl and b/rbufr/tables/local/BUFR_TableB_6.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_65279_4.bufrtbl b/rbufr/tables/local/BUFR_TableB_65279_4.bufrtbl index b6b78a8..add5824 100644 Binary files a/rbufr/tables/local/BUFR_TableB_65279_4.bufrtbl and b/rbufr/tables/local/BUFR_TableB_65279_4.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_65535_1.bufrtbl b/rbufr/tables/local/BUFR_TableB_65535_1.bufrtbl index 1d41f68..d6aecdd 100644 Binary files a/rbufr/tables/local/BUFR_TableB_65535_1.bufrtbl and b/rbufr/tables/local/BUFR_TableB_65535_1.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_65535_12.bufrtbl b/rbufr/tables/local/BUFR_TableB_65535_12.bufrtbl index 2fe6d37..ea3b3e7 100644 Binary files a/rbufr/tables/local/BUFR_TableB_65535_12.bufrtbl and b/rbufr/tables/local/BUFR_TableB_65535_12.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_65535_2.bufrtbl b/rbufr/tables/local/BUFR_TableB_65535_2.bufrtbl index ba7cbbf..4e2dbcf 100644 Binary files a/rbufr/tables/local/BUFR_TableB_65535_2.bufrtbl and b/rbufr/tables/local/BUFR_TableB_65535_2.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_65535_3.bufrtbl b/rbufr/tables/local/BUFR_TableB_65535_3.bufrtbl index 809e09e..a876d4c 100644 Binary files a/rbufr/tables/local/BUFR_TableB_65535_3.bufrtbl and b/rbufr/tables/local/BUFR_TableB_65535_3.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_65535_4.bufrtbl b/rbufr/tables/local/BUFR_TableB_65535_4.bufrtbl index def4085..3318a7e 100644 Binary files a/rbufr/tables/local/BUFR_TableB_65535_4.bufrtbl and b/rbufr/tables/local/BUFR_TableB_65535_4.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_65535_5.bufrtbl b/rbufr/tables/local/BUFR_TableB_65535_5.bufrtbl index 3fef9e5..438eea2 100644 Binary files a/rbufr/tables/local/BUFR_TableB_65535_5.bufrtbl and b/rbufr/tables/local/BUFR_TableB_65535_5.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_65535_6.bufrtbl b/rbufr/tables/local/BUFR_TableB_65535_6.bufrtbl index b6b78a8..add5824 100644 Binary files a/rbufr/tables/local/BUFR_TableB_65535_6.bufrtbl and b/rbufr/tables/local/BUFR_TableB_65535_6.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_65535_7.bufrtbl b/rbufr/tables/local/BUFR_TableB_65535_7.bufrtbl index 214ba2b..eb964a2 100644 Binary files a/rbufr/tables/local/BUFR_TableB_65535_7.bufrtbl and b/rbufr/tables/local/BUFR_TableB_65535_7.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_1.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_1.bufrtbl index 7e5b6c4..d46ee61 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_1.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_1.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_10.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_10.bufrtbl index 9273c38..fe1838b 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_10.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_10.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_11.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_11.bufrtbl index b9183f4..8e91b77 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_11.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_11.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_12.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_12.bufrtbl index cc1fc13..486c3fb 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_12.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_12.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_13.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_13.bufrtbl index 5747816..b0386e7 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_13.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_13.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_14.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_14.bufrtbl index 2e2ae02..80f191e 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_14.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_14.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_15.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_15.bufrtbl index 1efc6fc..095b594 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_15.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_15.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_16.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_16.bufrtbl index 1efc6fc..095b594 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_16.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_16.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_17.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_17.bufrtbl index 1efc6fc..095b594 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_17.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_17.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_18.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_18.bufrtbl index 8131e6c..83d8f30 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_18.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_18.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_19.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_19.bufrtbl index 3b98df6..5a72950 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_19.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_19.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_2.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_2.bufrtbl index cd4e9e5..c33dca7 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_2.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_2.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_20.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_20.bufrtbl index 2038a58..b90921b 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_20.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_20.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_3.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_3.bufrtbl index f60d7a6..528600c 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_3.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_3.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_4.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_4.bufrtbl index be89204..f3ed73c 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_4.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_4.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_5.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_5.bufrtbl index 709c24f..cd1ab59 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_5.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_5.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_6.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_6.bufrtbl index 00a5cff..7e0d463 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_6.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_6.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_7.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_7.bufrtbl index 244dcfc..93740fc 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_7.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_7.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_8.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_8.bufrtbl index 38f67c8..2c7210e 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_8.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_8.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_9.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_9.bufrtbl index f1de391..831f7d6 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_9.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_9.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableB_85_99.bufrtbl b/rbufr/tables/local/BUFR_TableB_85_99.bufrtbl index ee23bb8..2f97ca7 100644 Binary files a/rbufr/tables/local/BUFR_TableB_85_99.bufrtbl and b/rbufr/tables/local/BUFR_TableB_85_99.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_10.bufrtbl b/rbufr/tables/local/BUFR_TableD_10.bufrtbl index 6120792..b15aa74 100644 Binary files a/rbufr/tables/local/BUFR_TableD_10.bufrtbl and b/rbufr/tables/local/BUFR_TableD_10.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_11.bufrtbl b/rbufr/tables/local/BUFR_TableD_11.bufrtbl index d58ec86..8ccb341 100644 Binary files a/rbufr/tables/local/BUFR_TableD_11.bufrtbl and b/rbufr/tables/local/BUFR_TableD_11.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_12.bufrtbl b/rbufr/tables/local/BUFR_TableD_12.bufrtbl index f609747..ec27762 100644 Binary files a/rbufr/tables/local/BUFR_TableD_12.bufrtbl and b/rbufr/tables/local/BUFR_TableD_12.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_13.bufrtbl b/rbufr/tables/local/BUFR_TableD_13.bufrtbl index 16cb706..5fd8f74 100644 Binary files a/rbufr/tables/local/BUFR_TableD_13.bufrtbl and b/rbufr/tables/local/BUFR_TableD_13.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_14.bufrtbl b/rbufr/tables/local/BUFR_TableD_14.bufrtbl index 5b47764..89bff86 100644 Binary files a/rbufr/tables/local/BUFR_TableD_14.bufrtbl and b/rbufr/tables/local/BUFR_TableD_14.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_15.bufrtbl b/rbufr/tables/local/BUFR_TableD_15.bufrtbl index ecc23fd..26a3020 100644 Binary files a/rbufr/tables/local/BUFR_TableD_15.bufrtbl and b/rbufr/tables/local/BUFR_TableD_15.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_16.bufrtbl b/rbufr/tables/local/BUFR_TableD_16.bufrtbl index d9000ff..417c8d0 100644 Binary files a/rbufr/tables/local/BUFR_TableD_16.bufrtbl and b/rbufr/tables/local/BUFR_TableD_16.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_18.bufrtbl b/rbufr/tables/local/BUFR_TableD_18.bufrtbl index 3773a04..ad85f21 100644 Binary files a/rbufr/tables/local/BUFR_TableD_18.bufrtbl and b/rbufr/tables/local/BUFR_TableD_18.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_2.bufrtbl b/rbufr/tables/local/BUFR_TableD_2.bufrtbl index eceeb8c..924efa9 100644 Binary files a/rbufr/tables/local/BUFR_TableD_2.bufrtbl and b/rbufr/tables/local/BUFR_TableD_2.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_247_7.bufrtbl b/rbufr/tables/local/BUFR_TableD_247_7.bufrtbl index 0328cc2..5e1ebab 100644 Binary files a/rbufr/tables/local/BUFR_TableD_247_7.bufrtbl and b/rbufr/tables/local/BUFR_TableD_247_7.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_247_8.bufrtbl b/rbufr/tables/local/BUFR_TableD_247_8.bufrtbl index 0328cc2..5e1ebab 100644 Binary files a/rbufr/tables/local/BUFR_TableD_247_8.bufrtbl and b/rbufr/tables/local/BUFR_TableD_247_8.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_247_9.bufrtbl b/rbufr/tables/local/BUFR_TableD_247_9.bufrtbl index 9240715..f42718f 100644 Binary files a/rbufr/tables/local/BUFR_TableD_247_9.bufrtbl and b/rbufr/tables/local/BUFR_TableD_247_9.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_255_1.bufrtbl b/rbufr/tables/local/BUFR_TableD_255_1.bufrtbl index b7b0192..bc40ca7 100644 Binary files a/rbufr/tables/local/BUFR_TableD_255_1.bufrtbl and b/rbufr/tables/local/BUFR_TableD_255_1.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_255_5.bufrtbl b/rbufr/tables/local/BUFR_TableD_255_5.bufrtbl index 8fff7dd..cabaf39 100644 Binary files a/rbufr/tables/local/BUFR_TableD_255_5.bufrtbl and b/rbufr/tables/local/BUFR_TableD_255_5.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_255_6.bufrtbl b/rbufr/tables/local/BUFR_TableD_255_6.bufrtbl index 1467958..9b94aff 100644 Binary files a/rbufr/tables/local/BUFR_TableD_255_6.bufrtbl and b/rbufr/tables/local/BUFR_TableD_255_6.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_3.bufrtbl b/rbufr/tables/local/BUFR_TableD_3.bufrtbl index 34bd4f6..852a1c0 100644 Binary files a/rbufr/tables/local/BUFR_TableD_3.bufrtbl and b/rbufr/tables/local/BUFR_TableD_3.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_6.bufrtbl b/rbufr/tables/local/BUFR_TableD_6.bufrtbl index cdeab56..1b5944f 100644 Binary files a/rbufr/tables/local/BUFR_TableD_6.bufrtbl and b/rbufr/tables/local/BUFR_TableD_6.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_65279_4.bufrtbl b/rbufr/tables/local/BUFR_TableD_65279_4.bufrtbl index 1467958..9b94aff 100644 Binary files a/rbufr/tables/local/BUFR_TableD_65279_4.bufrtbl and b/rbufr/tables/local/BUFR_TableD_65279_4.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_65535_1.bufrtbl b/rbufr/tables/local/BUFR_TableD_65535_1.bufrtbl index b7b0192..bc40ca7 100644 Binary files a/rbufr/tables/local/BUFR_TableD_65535_1.bufrtbl and b/rbufr/tables/local/BUFR_TableD_65535_1.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_65535_12.bufrtbl b/rbufr/tables/local/BUFR_TableD_65535_12.bufrtbl index 34b1fd6..02d6846 100644 Binary files a/rbufr/tables/local/BUFR_TableD_65535_12.bufrtbl and b/rbufr/tables/local/BUFR_TableD_65535_12.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_65535_2.bufrtbl b/rbufr/tables/local/BUFR_TableD_65535_2.bufrtbl index ff55025..7664549 100644 Binary files a/rbufr/tables/local/BUFR_TableD_65535_2.bufrtbl and b/rbufr/tables/local/BUFR_TableD_65535_2.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_65535_3.bufrtbl b/rbufr/tables/local/BUFR_TableD_65535_3.bufrtbl index 73289f7..d9c8da2 100644 Binary files a/rbufr/tables/local/BUFR_TableD_65535_3.bufrtbl and b/rbufr/tables/local/BUFR_TableD_65535_3.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_65535_4.bufrtbl b/rbufr/tables/local/BUFR_TableD_65535_4.bufrtbl index 691ce61..fdb66e2 100644 Binary files a/rbufr/tables/local/BUFR_TableD_65535_4.bufrtbl and b/rbufr/tables/local/BUFR_TableD_65535_4.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_65535_5.bufrtbl b/rbufr/tables/local/BUFR_TableD_65535_5.bufrtbl index 8fff7dd..cabaf39 100644 Binary files a/rbufr/tables/local/BUFR_TableD_65535_5.bufrtbl and b/rbufr/tables/local/BUFR_TableD_65535_5.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_65535_6.bufrtbl b/rbufr/tables/local/BUFR_TableD_65535_6.bufrtbl index 1467958..9b94aff 100644 Binary files a/rbufr/tables/local/BUFR_TableD_65535_6.bufrtbl and b/rbufr/tables/local/BUFR_TableD_65535_6.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_65535_7.bufrtbl b/rbufr/tables/local/BUFR_TableD_65535_7.bufrtbl index 4f6d596..1d6c3c7 100644 Binary files a/rbufr/tables/local/BUFR_TableD_65535_7.bufrtbl and b/rbufr/tables/local/BUFR_TableD_65535_7.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_1.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_1.bufrtbl index 7a2d941..e7ef62a 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_1.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_1.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_10.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_10.bufrtbl index f0b0adf..71f02fc 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_10.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_10.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_11.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_11.bufrtbl index f5cc6ff..6c6d91b 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_11.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_11.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_12.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_12.bufrtbl index 87469fe..d9dfeac 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_12.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_12.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_13.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_13.bufrtbl index 87469fe..d9dfeac 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_13.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_13.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_14.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_14.bufrtbl index 471e415..d6f0045 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_14.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_14.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_15.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_15.bufrtbl index 471e415..d6f0045 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_15.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_15.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_16.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_16.bufrtbl index 471e415..d6f0045 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_16.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_16.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_17.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_17.bufrtbl index 471e415..d6f0045 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_17.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_17.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_18.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_18.bufrtbl index 471e415..d6f0045 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_18.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_18.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_19.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_19.bufrtbl index 471e415..d6f0045 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_19.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_19.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_2.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_2.bufrtbl index 342097d..e3e0c74 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_2.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_2.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_20.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_20.bufrtbl index 471e415..d6f0045 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_20.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_20.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_3.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_3.bufrtbl index 653173b..ccc2193 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_3.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_3.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_4.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_4.bufrtbl index 653173b..ccc2193 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_4.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_4.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_5.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_5.bufrtbl index cf546fc..4e2c662 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_5.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_5.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_6.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_6.bufrtbl index cf546fc..4e2c662 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_6.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_6.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_7.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_7.bufrtbl index beccc10..e681a36 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_7.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_7.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_8.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_8.bufrtbl index beccc10..e681a36 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_8.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_8.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_9.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_9.bufrtbl index c7e7e3c..ca20fa6 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_9.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_9.bufrtbl differ diff --git a/rbufr/tables/local/BUFR_TableD_85_99.bufrtbl b/rbufr/tables/local/BUFR_TableD_85_99.bufrtbl index f0b0adf..71f02fc 100644 Binary files a/rbufr/tables/local/BUFR_TableD_85_99.bufrtbl and b/rbufr/tables/local/BUFR_TableD_85_99.bufrtbl differ diff --git a/rbufr/tables/master/BUFR_TableB_16.bufrtbl b/rbufr/tables/master/BUFR_TableB_16.bufrtbl index 25e0318..52d7262 100644 Binary files a/rbufr/tables/master/BUFR_TableB_16.bufrtbl and b/rbufr/tables/master/BUFR_TableB_16.bufrtbl differ diff --git a/rbufr/tables/master/BUFR_TableD_16.bufrtbl b/rbufr/tables/master/BUFR_TableD_16.bufrtbl index d9000ff..417c8d0 100644 Binary files a/rbufr/tables/master/BUFR_TableD_16.bufrtbl and b/rbufr/tables/master/BUFR_TableD_16.bufrtbl differ diff --git a/rbufr/tables/opera/BUFR_Opera_Bitmap_247.bufrtbl b/rbufr/tables/opera/BUFR_Opera_Bitmap_247.bufrtbl new file mode 100644 index 0000000..488d945 Binary files /dev/null and b/rbufr/tables/opera/BUFR_Opera_Bitmap_247.bufrtbl differ diff --git a/rbufr/tables/opera/BUFR_Opera_Bitmap_65535.bufrtbl b/rbufr/tables/opera/BUFR_Opera_Bitmap_65535.bufrtbl new file mode 100644 index 0000000..5ad9d3b Binary files /dev/null and b/rbufr/tables/opera/BUFR_Opera_Bitmap_65535.bufrtbl differ