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
16pub 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 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(§5_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 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 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;