gistools/readers/grib2/sections/
mod.rs

1/// Import section 0
2pub mod _0;
3/// Import section 1
4pub mod _1;
5/// Import section 2
6pub mod _2;
7/// Import section 3
8pub mod _3;
9/// Import section 4
10pub mod _4;
11/// Import section 5
12pub mod _5;
13/// Import section 6
14pub mod _6;
15/// Import section 7
16pub mod _7;
17/// Import section 8
18pub mod _8;
19/// Import other
20pub mod other;
21
22use crate::parsers::{BufferReader, Reader};
23pub use _0::*;
24pub use _1::*;
25pub use _2::*;
26pub use _3::*;
27pub use _4::*;
28pub use _5::*;
29pub use _6::*;
30pub use _7::*;
31pub use _8::*;
32pub use other::*;
33
34/// A parsed GRIB file and it's sections
35#[derive(Debug, Default, Clone, PartialEq)]
36pub struct Grib2Sections {
37    /// The Indicator Section
38    pub indicator: Option<Grib2IndicatorSection>,
39    /// The Identification Section
40    pub identification: Option<Grib2IdentificationSection>,
41    /// The Local Use Section
42    pub local: Option<Grib2LocalUseSection>,
43    /// The Grid Definition Section
44    pub grid_definition: Option<GridDefinitionSection>,
45    /// The Product Definition Section
46    pub product_definition: Option<Grib2ProductDefinitionSection>,
47    /// The Data Representation Section
48    pub data_representation: Option<Grib2DataRepresentationSection>,
49    /// The Bit Map Section
50    pub bit_map: Option<Grib2BitMapSection>,
51    /// The Data Section
52    pub data: Option<Grib2DataSection>,
53    /// The End Section
54    pub end: Option<Grib2EndSection>,
55}
56
57/// Split the bytes of the GRIB file into individual GRIB chunks that represent sections
58///
59/// ## Parameters
60/// - `grib_chunk`: Buffer containing individual GRIB definition
61///
62/// ## Returns
63/// Array of Section Buffers where the index of the item corresponds to the section number. If a section is missing, it will be represented as null
64pub fn split_section_chunks(grib_chunk: BufferReader) -> Grib2Sections {
65    let mut sections = Grib2Sections::default();
66
67    let mut current_section = grib_chunk;
68    // Split sections in file
69    while current_section.len() != 0 {
70        let section_number = get_section_number(&current_section);
71
72        // First section length is always 16 bytes long and is identified by the first 4 bytes being 'GRIB'
73        let mut length =
74            if section_number == 0 { 16 } else { current_section.uint32_be(Some(0)) } as u64;
75        length = length.min(current_section.len());
76        let section = BufferReader::new(current_section.slice(Some(0), Some(length)));
77        current_section = BufferReader::new(current_section.slice(Some(length), None));
78
79        parse_grib2_section(&section, &mut sections);
80    }
81
82    sections
83}
84
85/// Parse the given section
86///
87/// ## Parameters
88/// - `reader`: The section to parse
89/// - `sections`: The result to write to
90fn parse_grib2_section(reader: &BufferReader, sections: &mut Grib2Sections) {
91    let section_number = get_section_number(reader);
92
93    match section_number {
94        0 => sections.indicator = Some(Grib2IndicatorSection::new(reader)),
95        1 => sections.identification = Some(Grib2IdentificationSection::new(reader)),
96        2 => sections.local = Some(Grib2LocalUseSection::new(reader)),
97        3 => sections.grid_definition = Some(GridDefinitionSection::new(reader)),
98        4 => {
99            sections.product_definition = Some(Grib2ProductDefinitionSection::new(reader, sections))
100        }
101        5 => sections.data_representation = Some(Grib2DataRepresentationSection::new(reader)),
102        6 => sections.bit_map = Some(Grib2BitMapSection::new(reader)),
103        7 => sections.data = Some(Grib2DataSection::new(reader)),
104        8 => sections.end = Some(Grib2EndSection::new(reader)),
105        _ => panic!("Unknown section number: {section_number}"),
106    }
107}
108
109/// Get the section number
110///
111/// ## Parameters
112/// - `section`: Buffer containing GRIB Section data
113///
114/// ## Returns
115/// Section number of the input GRIB Section data
116pub fn get_section_number(section: &BufferReader) -> u8 {
117    let first4_byte_string = section.parse_string(Some(0), Some(4));
118
119    match first4_byte_string.as_ref() {
120        "GRIB" => 0,
121        "7777" => 8,
122        _ => section.uint8(Some(4)),
123    }
124}