1#[cfg(target_arch = "wasm32")]
2use std::marker::PhantomData;
3
4use num::ToPrimitive;
5
6#[cfg(not(target_arch = "wasm32"))]
7use crate::decoder::jpeg2000::Jpeg2000CodeStreamDecodeError;
8use crate::{
9 context::{SectionBody, SubMessage},
10 decoder::{
11 bitmap::{dummy_bitmap_for_nonnullable_data, BitmapDecodeIterator},
12 complex::ComplexPackingDecodeError,
13 param::Section5Param,
14 png::PngDecodeError,
15 run_length::RunLengthEncodingDecodeError,
16 simple::{SimplePackingDecodeError, SimplePackingDecodeIteratorWrapper},
17 },
18 error::*,
19 reader::Grib2Read,
20};
21
22pub struct Grib2SubmessageDecoder {
90 num_points_total: usize,
91 sect5_param: Section5Param,
92 pub(crate) sect5_bytes: Vec<u8>,
93 sect6_bytes: Vec<u8>,
94 sect7_bytes: Vec<u8>,
95}
96
97impl Grib2SubmessageDecoder {
98 pub fn new(
103 num_points_total: usize,
104 sect5_bytes: Vec<u8>,
105 sect6_bytes: Vec<u8>,
106 sect7_bytes: Vec<u8>,
107 ) -> Result<Self, GribError> {
108 let sect5_param = Section5Param::from_buf(§5_bytes[5..11]);
109 let sect6_bytes = match sect6_bytes[5] {
110 0x00 => sect6_bytes,
111 0xff => {
112 let mut sect6_bytes = sect6_bytes;
113 sect6_bytes.append(&mut dummy_bitmap_for_nonnullable_data(num_points_total));
114 sect6_bytes
115 }
116 _ => {
117 return Err(GribError::DecodeError(
118 DecodeError::BitMapIndicatorUnsupported,
119 ))
120 }
121 };
122
123 Ok(Self {
124 num_points_total,
125 sect5_param,
126 sect5_bytes,
127 sect6_bytes,
128 sect7_bytes,
129 })
130 }
131
132 pub fn from<R: Grib2Read>(submessage: SubMessage<R>) -> Result<Self, GribError> {
134 let mut reader = submessage.9;
135 let sect5 = submessage.5.body;
136 let sect6 = submessage.6.body;
137 let sect7 = submessage.7.body;
138 let sect3_body = match submessage.3.body.body.as_ref() {
139 Some(SectionBody::Section3(b3)) => b3,
140 _ => return Err(GribError::InternalDataError),
141 };
142 let sect3_num_points = sect3_body.num_points() as usize;
143
144 Self::new(
145 sect3_num_points,
146 reader.read_sect_as_slice(sect5)?,
147 reader.read_sect_as_slice(sect6)?,
148 reader.read_sect_as_slice(sect7)?,
149 )
150 }
151
152 pub fn dispatch(
154 &self,
155 ) -> Result<Grib2DecodedValues<'_, impl Iterator<Item = f32> + '_>, GribError> {
156 let decoder = match self.sect5_param.template_num {
157 0 => Grib2ValueIterator::Template0(simple::decode(self)?),
158 2 => Grib2ValueIterator::Template2(complex::decode_7_2(self)?),
159 3 => Grib2ValueIterator::Template3(complex::decode_7_3(self)?),
160 #[cfg(not(target_arch = "wasm32"))]
161 40 => Grib2ValueIterator::Template40(jpeg2000::decode(self)?),
162 41 => Grib2ValueIterator::Template41(png::decode(self)?),
163 #[cfg(not(target_arch = "wasm32"))]
164 42 => Grib2ValueIterator::Template42(ccsds::decode(self)?),
165 200 => Grib2ValueIterator::Template200(run_length::decode(self)?),
166 _ => {
167 return Err(GribError::DecodeError(
168 DecodeError::TemplateNumberUnsupported,
169 ))
170 }
171 };
172 let decoder = BitmapDecodeIterator::new(
173 self.sect6_bytes[6..].iter(),
174 decoder,
175 self.num_points_total,
176 )?;
177 Ok(Grib2DecodedValues(decoder))
178 }
179
180 pub(crate) fn num_points_encoded(&self) -> usize {
181 self.sect5_param.num_points_encoded as usize
182 }
183
184 pub(crate) fn sect7_payload(&self) -> &[u8] {
185 &self.sect7_bytes[5..]
186 }
187}
188
189pub struct Grib2DecodedValues<'b, I>(BitmapDecodeIterator<std::slice::Iter<'b, u8>, I>);
190
191impl<I> Iterator for Grib2DecodedValues<'_, I>
192where
193 I: Iterator<Item = f32>,
194{
195 type Item = f32;
196
197 fn next(&mut self) -> Option<Self::Item> {
198 let Self(inner) = self;
199 inner.next()
200 }
201
202 fn size_hint(&self) -> (usize, Option<usize>) {
203 let Self(inner) = self;
204 inner.size_hint()
205 }
206}
207
208#[cfg(target_arch = "wasm32")]
213type Grib2ValueIterator<T0, T2, T3, T41> = Grib2SubmessageDecoderIteratorWrapper<
214 T0,
215 T2,
216 T3,
217 std::vec::IntoIter<f32>,
218 T41,
219 std::vec::IntoIter<f32>,
220>;
221#[cfg(not(target_arch = "wasm32"))]
222type Grib2ValueIterator<T0, T2, T3, T40, T41, T42> =
223 Grib2SubmessageDecoderIteratorWrapper<T0, T2, T3, T40, T41, T42>;
224
225enum Grib2SubmessageDecoderIteratorWrapper<T0, T2, T3, T40, T41, T42> {
226 Template0(SimplePackingDecodeIteratorWrapper<T0>),
227 Template2(SimplePackingDecodeIteratorWrapper<T2>),
228 Template3(SimplePackingDecodeIteratorWrapper<T3>),
229 #[allow(dead_code)]
230 #[cfg(target_arch = "wasm32")]
231 Template40(PhantomData<T40>),
232 #[cfg(not(target_arch = "wasm32"))]
233 Template40(SimplePackingDecodeIteratorWrapper<T40>),
234 Template41(SimplePackingDecodeIteratorWrapper<T41>),
235 #[allow(dead_code)]
236 #[cfg(target_arch = "wasm32")]
237 Template42(PhantomData<T42>),
238 #[cfg(not(target_arch = "wasm32"))]
239 Template42(SimplePackingDecodeIteratorWrapper<T42>),
240 Template200(std::vec::IntoIter<f32>),
241}
242
243impl<T0, T2, T3, T40, T41, T42> Iterator
244 for Grib2SubmessageDecoderIteratorWrapper<T0, T2, T3, T40, T41, T42>
245where
246 T0: Iterator,
247 <T0 as Iterator>::Item: ToPrimitive,
248 T2: Iterator,
249 <T2 as Iterator>::Item: ToPrimitive,
250 T3: Iterator,
251 <T3 as Iterator>::Item: ToPrimitive,
252 T40: Iterator,
253 <T40 as Iterator>::Item: ToPrimitive,
254 T41: Iterator,
255 <T41 as Iterator>::Item: ToPrimitive,
256 T42: Iterator,
257 <T42 as Iterator>::Item: ToPrimitive,
258{
259 type Item = f32;
260
261 fn next(&mut self) -> Option<Self::Item> {
262 match self {
263 Self::Template0(inner) => inner.next(),
264 Self::Template2(inner) => inner.next(),
265 Self::Template3(inner) => inner.next(),
266 #[cfg(not(target_arch = "wasm32"))]
267 Self::Template40(inner) => inner.next(),
268 #[cfg(target_arch = "wasm32")]
269 Self::Template40(_) => unreachable!(),
270 Self::Template41(inner) => inner.next(),
271 #[cfg(not(target_arch = "wasm32"))]
272 Self::Template42(inner) => inner.next(),
273 #[cfg(target_arch = "wasm32")]
274 Self::Template42(_) => unreachable!(),
275 Self::Template200(inner) => inner.next(),
276 }
277 }
278
279 fn size_hint(&self) -> (usize, Option<usize>) {
280 match self {
281 Self::Template0(inner) => inner.size_hint(),
282 Self::Template2(inner) => inner.size_hint(),
283 Self::Template3(inner) => inner.size_hint(),
284 #[cfg(not(target_arch = "wasm32"))]
285 Self::Template40(inner) => inner.size_hint(),
286 #[cfg(target_arch = "wasm32")]
287 Self::Template40(_) => unreachable!(),
288 Self::Template41(inner) => inner.size_hint(),
289 #[cfg(not(target_arch = "wasm32"))]
290 Self::Template42(inner) => inner.size_hint(),
291 #[cfg(target_arch = "wasm32")]
292 Self::Template42(_) => unreachable!(),
293 Self::Template200(inner) => inner.size_hint(),
294 }
295 }
296}
297
298#[derive(Debug, Clone, PartialEq, Eq, Hash)]
299pub enum DecodeError {
300 TemplateNumberUnsupported,
301 BitMapIndicatorUnsupported,
302 SimplePackingDecodeError(SimplePackingDecodeError),
303 ComplexPackingDecodeError(ComplexPackingDecodeError),
304 #[cfg(not(target_arch = "wasm32"))]
305 Jpeg2000CodeStreamDecodeError(Jpeg2000CodeStreamDecodeError),
306 PngDecodeError(PngDecodeError),
307 RunLengthEncodingDecodeError(RunLengthEncodingDecodeError),
308 LengthMismatch,
309 Unknown(String),
310}
311
312impl From<SimplePackingDecodeError> for DecodeError {
313 fn from(e: SimplePackingDecodeError) -> Self {
314 Self::SimplePackingDecodeError(e)
315 }
316}
317
318impl From<ComplexPackingDecodeError> for DecodeError {
319 fn from(e: ComplexPackingDecodeError) -> Self {
320 Self::ComplexPackingDecodeError(e)
321 }
322}
323
324#[cfg(not(target_arch = "wasm32"))]
325impl From<Jpeg2000CodeStreamDecodeError> for DecodeError {
326 fn from(e: Jpeg2000CodeStreamDecodeError) -> Self {
327 Self::Jpeg2000CodeStreamDecodeError(e)
328 }
329}
330
331impl From<RunLengthEncodingDecodeError> for DecodeError {
332 fn from(e: RunLengthEncodingDecodeError) -> Self {
333 Self::RunLengthEncodingDecodeError(e)
334 }
335}
336
337mod bitmap;
338#[cfg(not(target_arch = "wasm32"))]
339mod ccsds;
340mod complex;
341#[cfg(not(target_arch = "wasm32"))]
342mod jpeg2000;
343mod param;
344mod png;
345mod run_length;
346mod simple;
347mod stream;