1use std::vec::IntoIter;
2
3use crate::{
4 TryFromSlice as _,
5 context::{SectionBody, SubMessage},
6 decoder::{
7 bitmap::{BitmapDecodeIterator, dummy_bitmap_for_nonnullable_data},
8 complex::ComplexPackingDecoded,
9 simple::SimplePackingDecoder,
10 stream::NBitwiseIterator,
11 },
12 def::grib2::{DataRepresentationTemplate, Section5},
13 error::*,
14 reader::Grib2Read,
15};
16
17pub struct Grib2SubmessageDecoder {
87 num_points_total: usize,
88 sect5_param: Section5,
89 sect6_bytes: Vec<u8>,
90 sect7_bytes: Vec<u8>,
91}
92
93impl Grib2SubmessageDecoder {
94 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 mut pos = 0;
105 let sect5_param = Section5::try_from_slice(§5_bytes, &mut pos)
106 .map_err(|e| GribError::DecodeError(DecodeError::from(e)))?;
107 let sect6_bytes = match sect6_bytes[5] {
108 0x00 => sect6_bytes,
109 0xff => {
110 let mut sect6_bytes = sect6_bytes;
111 sect6_bytes.append(&mut dummy_bitmap_for_nonnullable_data(num_points_total));
112 sect6_bytes
113 }
114 n => {
115 return Err(GribError::DecodeError(DecodeError::NotSupported(
116 "GRIB2 code table 6.0 (bit map indicator)",
117 n.into(),
118 )));
119 }
120 };
121
122 Ok(Self {
123 num_points_total,
124 sect5_param,
125 sect6_bytes,
126 sect7_bytes,
127 })
128 }
129
130 pub fn from<R: Grib2Read>(submessage: SubMessage<R>) -> Result<Self, GribError> {
132 let mut reader = submessage.9;
133 let sect5 = submessage.5.body;
134 let sect6 = submessage.6.body;
135 let sect7 = submessage.7.body;
136 let sect3_body = match submessage.3.body.body.as_ref() {
137 Some(SectionBody::Section3(b3)) => b3,
138 _ => return Err(GribError::InternalDataError),
139 };
140 let sect3_num_points = sect3_body.num_points() as usize;
141
142 Self::new(
143 sect3_num_points,
144 reader.read_sect_as_slice(sect5)?,
145 reader.read_sect_as_slice(sect6)?,
146 reader.read_sect_as_slice(sect7)?,
147 )
148 }
149
150 pub fn dispatch(
152 &self,
153 ) -> Result<Grib2DecodedValues<'_, impl Iterator<Item = f32> + '_>, GribError> {
154 let decoder = match &self.sect5_param.payload.template {
155 DataRepresentationTemplate::_5_0(template) => {
156 Grib2ValueIterator::SigSTNS(simple::Simple(self, template).iter()?)
157 }
158 DataRepresentationTemplate::_5_2(template) => {
159 Grib2ValueIterator::SigSC(complex::Complex(self, template).iter()?)
160 }
161 DataRepresentationTemplate::_5_3(template) => {
162 Grib2ValueIterator::SigSSCI(complex::ComplexSpatial(self, template).iter()?)
163 }
164 #[cfg(any(
165 feature = "jpeg2000-unpack-with-openjpeg",
166 feature = "jpeg2000-unpack-with-hayro"
167 ))]
168 DataRepresentationTemplate::_5_40(template) => {
169 Grib2ValueIterator::SigSIm(jpeg2000::Jpeg2000(self, template).iter()?)
170 }
171 #[cfg(feature = "png-unpack-with-png-crate")]
172 DataRepresentationTemplate::_5_41(template) => {
173 Grib2ValueIterator::SigSNV(png::Png(self, template).iter()?)
174 }
175 #[cfg(any(
176 feature = "ccsds-unpack-with-libaec",
177 feature = "ccsds-unpack-with-rust-aec"
178 ))]
179 DataRepresentationTemplate::_5_42(template) => {
180 Grib2ValueIterator::SigSNV(ccsds::Ccsds(self, template).iter()?)
181 }
182 DataRepresentationTemplate::_5_200(template) => {
183 Grib2ValueIterator::SigI(run_length::RunLength(self, template).iter()?)
184 }
185 #[allow(unreachable_patterns)]
186 _ => {
187 return Err(GribError::DecodeError(DecodeError::NotSupported(
188 "GRIB2 code table 5.0 (data representation template number)",
189 self.sect5_param.payload.template_num,
190 )));
191 }
192 };
193
194 let bitmap_slice = &self.sect6_bytes[6..];
195 bitmap::check_consistency(
196 self.num_points_total,
197 self.num_encoded_points(),
198 bitmap_slice,
199 )?;
200 let decoder =
201 BitmapDecodeIterator::new(bitmap_slice.iter(), decoder, self.num_points_total);
202 Ok(Grib2DecodedValues(decoder))
203 }
204
205 pub(crate) fn num_encoded_points(&self) -> usize {
206 self.sect5_param.payload.num_encoded_points as usize
207 }
208
209 pub(crate) fn sect7_payload(&self) -> &[u8] {
210 &self.sect7_bytes[5..]
211 }
212
213 pub fn section5(&self) -> &Section5 {
254 &self.sect5_param
255 }
256}
257
258pub(crate) fn orig_field_type_is_supported(orig_field_type: u8) -> Result<(), DecodeError> {
259 if orig_field_type != 0 {
260 return Err(DecodeError::NotSupported(
261 "GRIB2 code table 5.1 (type of original field values)",
262 orig_field_type.into(),
263 ));
264 }
265 Ok(())
266}
267
268pub struct Grib2DecodedValues<'b, I>(BitmapDecodeIterator<std::slice::Iter<'b, u8>, I>);
269
270impl<I> Iterator for Grib2DecodedValues<'_, I>
271where
272 I: Iterator<Item = f32>,
273{
274 type Item = f32;
275
276 fn next(&mut self) -> Option<Self::Item> {
277 let Self(inner) = self;
278 inner.next()
279 }
280
281 fn size_hint(&self) -> (usize, Option<usize>) {
282 let Self(inner) = self;
283 inner.size_hint()
284 }
285}
286
287enum Grib2ValueIterator<'d> {
288 SigSTNS(SimplePackingDecoder<std::iter::Take<NBitwiseIterator<&'d [u8]>>>),
289 SigSC(SimplePackingDecoder<ComplexPackingDecoded<'d>>),
290 SigSSCI(
291 SimplePackingDecoder<
292 complex::SpatialDifferencingDecodeIterator<ComplexPackingDecoded<'d>, IntoIter<i32>>,
293 >,
294 ),
295 #[allow(dead_code)]
296 SigSI(SimplePackingDecoder<IntoIter<i32>>),
297 #[cfg(any(
298 feature = "jpeg2000-unpack-with-openjpeg",
299 feature = "jpeg2000-unpack-with-hayro"
300 ))]
301 SigSIm(SimplePackingDecoder<self::jpeg2000::ImageIntoIter>),
302 #[allow(dead_code)]
303 SigSNV(SimplePackingDecoder<NBitwiseIterator<Vec<u8>>>),
304 SigI(IntoIter<f32>),
305}
306
307impl<'d> Iterator for Grib2ValueIterator<'d> {
308 type Item = f32;
309
310 fn next(&mut self) -> Option<Self::Item> {
311 match self {
312 Self::SigSTNS(inner) => inner.next(),
313 Self::SigSC(inner) => inner.next(),
314 Self::SigSSCI(inner) => inner.next(),
315 Self::SigSI(inner) => inner.next(),
316 #[cfg(any(
317 feature = "jpeg2000-unpack-with-openjpeg",
318 feature = "jpeg2000-unpack-with-hayro"
319 ))]
320 Self::SigSIm(inner) => inner.next(),
321 Self::SigSNV(inner) => inner.next(),
322 Self::SigI(inner) => inner.next(),
323 }
324 }
325
326 fn size_hint(&self) -> (usize, Option<usize>) {
327 match self {
328 Self::SigSTNS(inner) => inner.size_hint(),
329 Self::SigSC(inner) => inner.size_hint(),
330 Self::SigSSCI(inner) => inner.size_hint(),
331 Self::SigSI(inner) => inner.size_hint(),
332 #[cfg(any(
333 feature = "jpeg2000-unpack-with-openjpeg",
334 feature = "jpeg2000-unpack-with-hayro"
335 ))]
336 Self::SigSIm(inner) => inner.size_hint(),
337 Self::SigSNV(inner) => inner.size_hint(),
338 Self::SigI(inner) => inner.size_hint(),
339 }
340 }
341}
342
343#[derive(Debug, Clone, PartialEq, Eq, Hash)]
344#[non_exhaustive]
345pub enum DecodeError {
346 NotSupported(&'static str, u16),
347 LengthMismatch,
348 UnclassifiedError(String),
349}
350
351impl From<String> for DecodeError {
352 fn from(value: String) -> Self {
353 Self::UnclassifiedError(value)
354 }
355}
356
357impl From<&str> for DecodeError {
358 fn from(value: &str) -> Self {
359 Self::UnclassifiedError(value.to_owned())
360 }
361}
362
363pub(crate) trait Grib2GpvUnpack {
364 type Iter<'a>: Iterator<Item = f32>
365 where
366 Self: 'a;
367
368 fn iter<'a>(&'a self) -> Result<Self::Iter<'a>, DecodeError>;
369}
370
371mod bitmap;
372#[cfg(any(
373 feature = "ccsds-unpack-with-libaec",
374 feature = "ccsds-unpack-with-rust-aec"
375))]
376mod ccsds;
377mod complex;
378mod helpers;
379#[cfg(any(
380 feature = "jpeg2000-unpack-with-openjpeg",
381 feature = "jpeg2000-unpack-with-hayro"
382))]
383mod jpeg2000;
384#[cfg(feature = "png-unpack-with-png-crate")]
385mod png;
386mod run_length;
387mod simple;
388mod stream;
389#[cfg(test)]
390mod tests;