grib/
decoder.rs

1use std::vec::IntoIter;
2
3use crate::{
4    context::{SectionBody, SubMessage},
5    decoder::{
6        bitmap::{dummy_bitmap_for_nonnullable_data, BitmapDecodeIterator},
7        complex::ComplexPackingDecoded,
8        param::Section5Param,
9        simple::SimplePackingDecoder,
10        stream::NBitwiseIterator,
11    },
12    error::*,
13    reader::Grib2Read,
14};
15
16/// Decoder for grid point values of GRIB2 submessages.
17///
18/// # Examples
19/// ```
20/// use grib::Grib2SubmessageDecoder;
21///
22/// fn main() -> Result<(), Box<dyn std::error::Error>> {
23///     let f = std::fs::File::open(
24///         "testdata/Z__C_RJTD_20160822020000_NOWC_GPV_Ggis10km_Pphw10_FH0000-0100_grib2.bin",
25///     )?;
26///     let f = std::io::BufReader::new(f);
27///     let grib2 = grib::from_reader(f)?;
28///     let (_index, first_submessage) = grib2.iter().next().unwrap();
29///
30///     let decoder = Grib2SubmessageDecoder::from(first_submessage)?;
31///     let mut decoded = decoder.dispatch()?;
32///     assert_eq!(decoded.size_hint(), (86016, Some(86016)));
33///
34///     let first_value = decoded.next();
35///     assert_eq!(first_value.map(|f| f.is_nan()), Some(true));
36///
37///     let non_nan_value = decoded.find(|f| !f.is_nan());
38///     assert_eq!(non_nan_value.map(|f| f.round()), Some(1.0_f32));
39///
40///     let last_value = decoded.last();
41///     assert_eq!(last_value.map(|f| f.is_nan()), Some(true));
42///     Ok(())
43/// }
44/// ```
45///
46/// If the byte sequences for Sections 5, 6, and 7 of the GRIB2 data are known,
47/// and the number of grid points (described in Section 3) is also known, it is
48/// also possible to create a decoder instance by passing them to
49/// [`Grib2SubmessageDecoder::new`]. The example above is equivalent to the
50/// following:
51///
52/// ```
53/// use std::io::Read;
54///
55/// use grib::Grib2SubmessageDecoder;
56///
57/// fn main() -> Result<(), Box<dyn std::error::Error>> {
58///     let f = std::fs::File::open(
59///         "testdata/Z__C_RJTD_20160822020000_NOWC_GPV_Ggis10km_Pphw10_FH0000-0100_grib2.bin",
60///     )?;
61///     let mut f = std::io::BufReader::new(f);
62///     let mut buf = Vec::new();
63///     f.read_to_end(&mut buf)?;
64///
65///     let decoder = Grib2SubmessageDecoder::new(
66///         86016,
67///         buf[0x0000008f..0x000000a6].to_vec(),
68///         buf[0x000000a6..0x000000ac].to_vec(),
69///         buf[0x000000ac..0x0000061b].to_vec(),
70///     )?;
71///     let mut decoded = decoder.dispatch()?;
72///     assert_eq!(decoded.size_hint(), (86016, Some(86016)));
73///
74///     let first_value = decoded.next();
75///     assert_eq!(first_value.map(|f| f.is_nan()), Some(true));
76///
77///     let non_nan_value = decoded.find(|f| !f.is_nan());
78///     assert_eq!(non_nan_value.map(|f| f.round()), Some(1.0_f32));
79///
80///     let last_value = decoded.last();
81///     assert_eq!(last_value.map(|f| f.is_nan()), Some(true));
82///     Ok(())
83/// }
84/// ```
85pub struct Grib2SubmessageDecoder {
86    num_points_total: usize,
87    sect5_param: Section5Param,
88    pub(crate) sect5_bytes: Vec<u8>,
89    sect6_bytes: Vec<u8>,
90    sect7_bytes: Vec<u8>,
91}
92
93impl Grib2SubmessageDecoder {
94    /// Creates an instance from the number of grid points (described in Section
95    /// 3) and byte sequences for Sections 5, 6, and 7 of the GRIB2 data.
96    ///
97    /// For code examples, refer to the description of this `struct`.
98    pub fn new(
99        num_points_total: usize,
100        sect5_bytes: Vec<u8>,
101        sect6_bytes: Vec<u8>,
102        sect7_bytes: Vec<u8>,
103    ) -> Result<Self, GribError> {
104        let sect5_param = Section5Param::from_buf(&sect5_bytes[5..11]);
105        let sect6_bytes = match sect6_bytes[5] {
106            0x00 => sect6_bytes,
107            0xff => {
108                let mut sect6_bytes = sect6_bytes;
109                sect6_bytes.append(&mut dummy_bitmap_for_nonnullable_data(num_points_total));
110                sect6_bytes
111            }
112            n => {
113                return Err(GribError::DecodeError(DecodeError::NotSupported(
114                    "GRIB2 code table 6.0 (bit map indicator)",
115                    n.into(),
116                )))
117            }
118        };
119
120        Ok(Self {
121            num_points_total,
122            sect5_param,
123            sect5_bytes,
124            sect6_bytes,
125            sect7_bytes,
126        })
127    }
128
129    /// Sets up a decoder for grid point values of `submessage`.
130    pub fn from<R: Grib2Read>(submessage: SubMessage<R>) -> Result<Self, GribError> {
131        let mut reader = submessage.9;
132        let sect5 = submessage.5.body;
133        let sect6 = submessage.6.body;
134        let sect7 = submessage.7.body;
135        let sect3_body = match submessage.3.body.body.as_ref() {
136            Some(SectionBody::Section3(b3)) => b3,
137            _ => return Err(GribError::InternalDataError),
138        };
139        let sect3_num_points = sect3_body.num_points() as usize;
140
141        Self::new(
142            sect3_num_points,
143            reader.read_sect_as_slice(sect5)?,
144            reader.read_sect_as_slice(sect6)?,
145            reader.read_sect_as_slice(sect7)?,
146        )
147    }
148
149    /// Dispatches a decoding process and gets an iterator of decoded values.
150    pub fn dispatch(
151        &self,
152    ) -> Result<Grib2DecodedValues<'_, impl Iterator<Item = f32> + '_>, GribError> {
153        let decoder = match self.sect5_param.template_num {
154            0 => Grib2ValueIterator::SigSNS(simple::Simple(self).iter()?),
155            2 => Grib2ValueIterator::SigSC(complex::Complex(self).iter()?),
156            3 => Grib2ValueIterator::SigSSCI(complex::ComplexSpatial(self).iter()?),
157            #[cfg(all(
158                feature = "jpeg2000-unpack-with-openjpeg",
159                feature = "jpeg2000-unpack-with-openjpeg-experimental"
160            ))]
161            40 => Grib2ValueIterator::SigSIm(jpeg2000::Jpeg2000(self).iter()?),
162            #[cfg(all(
163                feature = "jpeg2000-unpack-with-openjpeg",
164                not(feature = "jpeg2000-unpack-with-openjpeg-experimental")
165            ))]
166            40 => Grib2ValueIterator::SigSI(jpeg2000::Jpeg2000(self).iter()?),
167            #[cfg(feature = "png-unpack-with-png-crate")]
168            41 => Grib2ValueIterator::SigSNV(png::Png(self).iter()?),
169            #[cfg(feature = "ccsds-unpack-with-libaec")]
170            42 => Grib2ValueIterator::SigSNV(ccsds::Ccsds(self).iter()?),
171            200 => Grib2ValueIterator::SigI(run_length::RunLength(self).iter()?),
172            n => {
173                return Err(GribError::DecodeError(DecodeError::NotSupported(
174                    "GRIB2 code table 5.0 (data representation template number)",
175                    n,
176                )))
177            }
178        };
179        let decoder = BitmapDecodeIterator::new(
180            self.sect6_bytes[6..].iter(),
181            decoder,
182            self.num_points_total,
183        )?;
184        Ok(Grib2DecodedValues(decoder))
185    }
186
187    pub(crate) fn num_points_encoded(&self) -> usize {
188        self.sect5_param.num_points_encoded as usize
189    }
190
191    pub(crate) fn sect7_payload(&self) -> &[u8] {
192        &self.sect7_bytes[5..]
193    }
194}
195
196pub struct Grib2DecodedValues<'b, I>(BitmapDecodeIterator<std::slice::Iter<'b, u8>, I>);
197
198impl<I> Iterator for Grib2DecodedValues<'_, I>
199where
200    I: Iterator<Item = f32>,
201{
202    type Item = f32;
203
204    fn next(&mut self) -> Option<Self::Item> {
205        let Self(inner) = self;
206        inner.next()
207    }
208
209    fn size_hint(&self) -> (usize, Option<usize>) {
210        let Self(inner) = self;
211        inner.size_hint()
212    }
213}
214
215enum Grib2ValueIterator<'d> {
216    SigSNS(SimplePackingDecoder<NBitwiseIterator<&'d [u8]>>),
217    SigSC(SimplePackingDecoder<ComplexPackingDecoded<'d>>),
218    SigSSCI(
219        SimplePackingDecoder<
220            complex::SpatialDifferencingDecodeIterator<ComplexPackingDecoded<'d>, IntoIter<i32>>,
221        >,
222    ),
223    #[allow(dead_code)]
224    SigSI(SimplePackingDecoder<IntoIter<i32>>),
225    #[cfg(feature = "jpeg2000-unpack-with-openjpeg-experimental")]
226    SigSIm(SimplePackingDecoder<self::jpeg2000::ImageIntoIter>),
227    #[allow(dead_code)]
228    SigSNV(SimplePackingDecoder<NBitwiseIterator<Vec<u8>>>),
229    SigI(IntoIter<f32>),
230}
231
232impl<'d> Iterator for Grib2ValueIterator<'d> {
233    type Item = f32;
234
235    fn next(&mut self) -> Option<Self::Item> {
236        match self {
237            Self::SigSNS(inner) => inner.next(),
238            Self::SigSC(inner) => inner.next(),
239            Self::SigSSCI(inner) => inner.next(),
240            Self::SigSI(inner) => inner.next(),
241            #[cfg(feature = "jpeg2000-unpack-with-openjpeg-experimental")]
242            Self::SigSIm(inner) => inner.next(),
243            Self::SigSNV(inner) => inner.next(),
244            Self::SigI(inner) => inner.next(),
245        }
246    }
247
248    fn size_hint(&self) -> (usize, Option<usize>) {
249        match self {
250            Self::SigSNS(inner) => inner.size_hint(),
251            Self::SigSC(inner) => inner.size_hint(),
252            Self::SigSSCI(inner) => inner.size_hint(),
253            Self::SigSI(inner) => inner.size_hint(),
254            #[cfg(feature = "jpeg2000-unpack-with-openjpeg-experimental")]
255            Self::SigSIm(inner) => inner.size_hint(),
256            Self::SigSNV(inner) => inner.size_hint(),
257            Self::SigI(inner) => inner.size_hint(),
258        }
259    }
260}
261
262#[derive(Debug, Clone, PartialEq, Eq, Hash)]
263pub enum DecodeError {
264    NotSupported(&'static str, u16),
265    LengthMismatch,
266    UnclassifiedError(String),
267}
268
269impl From<String> for DecodeError {
270    fn from(value: String) -> Self {
271        Self::UnclassifiedError(value)
272    }
273}
274
275impl From<&str> for DecodeError {
276    fn from(value: &str) -> Self {
277        Self::UnclassifiedError(value.to_owned())
278    }
279}
280
281pub(crate) trait Grib2GpvUnpack {
282    type Iter<'a>: Iterator<Item = f32>
283    where
284        Self: 'a;
285
286    fn iter<'a>(&'a self) -> Result<Self::Iter<'a>, DecodeError>;
287}
288
289mod bitmap;
290#[cfg(feature = "ccsds-unpack-with-libaec")]
291mod ccsds;
292mod complex;
293#[cfg(feature = "jpeg2000-unpack-with-openjpeg")]
294mod jpeg2000;
295mod param;
296#[cfg(feature = "png-unpack-with-png-crate")]
297mod png;
298mod run_length;
299mod simple;
300mod stream;