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