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::SigSNS(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(all(
166 feature = "jpeg2000-unpack-with-openjpeg",
167 feature = "jpeg2000-unpack-with-openjpeg-experimental"
168 ))]
169 DataRepresentationTemplate::_5_40(template) => {
170 Grib2ValueIterator::SigSIm(jpeg2000::Jpeg2000(self, template).iter()?)
171 }
172 #[cfg(all(
173 feature = "jpeg2000-unpack-with-openjpeg",
174 not(feature = "jpeg2000-unpack-with-openjpeg-experimental")
175 ))]
176 DataRepresentationTemplate::_5_40(template) => {
177 Grib2ValueIterator::SigSI(jpeg2000::Jpeg2000(self, template).iter()?)
178 }
179 #[cfg(feature = "png-unpack-with-png-crate")]
180 DataRepresentationTemplate::_5_41(template) => {
181 Grib2ValueIterator::SigSNV(png::Png(self, template).iter()?)
182 }
183 #[cfg(feature = "ccsds-unpack-with-libaec")]
184 DataRepresentationTemplate::_5_42(template) => {
185 Grib2ValueIterator::SigSNV(ccsds::Ccsds(self, template).iter()?)
186 }
187 DataRepresentationTemplate::_5_200(template) => {
188 Grib2ValueIterator::SigI(run_length::RunLength(self, template).iter()?)
189 }
190 #[allow(unreachable_patterns)]
191 _ => {
192 return Err(GribError::DecodeError(DecodeError::NotSupported(
193 "GRIB2 code table 5.0 (data representation template number)",
194 self.sect5_param.payload.template_num,
195 )));
196 }
197 };
198 let decoder = BitmapDecodeIterator::new(
199 self.sect6_bytes[6..].iter(),
200 decoder,
201 self.num_points_total,
202 )?;
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 SigSNS(SimplePackingDecoder<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(feature = "jpeg2000-unpack-with-openjpeg-experimental")]
299 SigSIm(SimplePackingDecoder<self::jpeg2000::ImageIntoIter>),
300 #[allow(dead_code)]
301 SigSNV(SimplePackingDecoder<NBitwiseIterator<Vec<u8>>>),
302 SigI(IntoIter<f32>),
303}
304
305impl<'d> Iterator for Grib2ValueIterator<'d> {
306 type Item = f32;
307
308 fn next(&mut self) -> Option<Self::Item> {
309 match self {
310 Self::SigSNS(inner) => inner.next(),
311 Self::SigSC(inner) => inner.next(),
312 Self::SigSSCI(inner) => inner.next(),
313 Self::SigSI(inner) => inner.next(),
314 #[cfg(feature = "jpeg2000-unpack-with-openjpeg-experimental")]
315 Self::SigSIm(inner) => inner.next(),
316 Self::SigSNV(inner) => inner.next(),
317 Self::SigI(inner) => inner.next(),
318 }
319 }
320
321 fn size_hint(&self) -> (usize, Option<usize>) {
322 match self {
323 Self::SigSNS(inner) => inner.size_hint(),
324 Self::SigSC(inner) => inner.size_hint(),
325 Self::SigSSCI(inner) => inner.size_hint(),
326 Self::SigSI(inner) => inner.size_hint(),
327 #[cfg(feature = "jpeg2000-unpack-with-openjpeg-experimental")]
328 Self::SigSIm(inner) => inner.size_hint(),
329 Self::SigSNV(inner) => inner.size_hint(),
330 Self::SigI(inner) => inner.size_hint(),
331 }
332 }
333}
334
335#[derive(Debug, Clone, PartialEq, Eq, Hash)]
336pub enum DecodeError {
337 NotSupported(&'static str, u16),
338 LengthMismatch,
339 UnclassifiedError(String),
340}
341
342impl From<String> for DecodeError {
343 fn from(value: String) -> Self {
344 Self::UnclassifiedError(value)
345 }
346}
347
348impl From<&str> for DecodeError {
349 fn from(value: &str) -> Self {
350 Self::UnclassifiedError(value.to_owned())
351 }
352}
353
354pub(crate) trait Grib2GpvUnpack {
355 type Iter<'a>: Iterator<Item = f32>
356 where
357 Self: 'a;
358
359 fn iter<'a>(&'a self) -> Result<Self::Iter<'a>, DecodeError>;
360}
361
362mod bitmap;
363#[cfg(feature = "ccsds-unpack-with-libaec")]
364mod ccsds;
365mod complex;
366#[cfg(feature = "jpeg2000-unpack-with-openjpeg")]
367mod jpeg2000;
368#[cfg(feature = "png-unpack-with-png-crate")]
369mod png;
370mod run_length;
371mod simple;
372mod stream;