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::{create_bitmap_for_nonnullable_data, BitmapDecodeIterator},
12 complex::ComplexPackingDecodeError,
13 png::PngDecodeError,
14 run_length::RunLengthEncodingDecodeError,
15 simple::{SimplePackingDecodeError, SimplePackingDecodeIteratorWrapper},
16 },
17 error::*,
18 reader::Grib2Read,
19};
20
21pub struct Grib2SubmessageDecoder {
50 num_points_total: usize,
51 pub(crate) num_points_encoded: usize,
52 template_num: u16,
53 pub(crate) sect5_payload: Box<[u8]>,
54 bitmap: Vec<u8>,
55 pub(crate) sect7_payload: Box<[u8]>,
56}
57
58impl Grib2SubmessageDecoder {
59 fn new(
60 num_points_total: usize,
61 num_points_encoded: usize,
62 template_num: u16,
63 sect5_payload: Box<[u8]>,
64 bitmap: Vec<u8>,
65 sect7_payload: Box<[u8]>,
66 ) -> Self {
67 Self {
68 num_points_total,
69 num_points_encoded,
70 template_num,
71 sect5_payload,
72 bitmap,
73 sect7_payload,
74 }
75 }
76
77 pub fn from<R: Grib2Read>(submessage: SubMessage<R>) -> Result<Self, GribError> {
79 let mut reader = submessage.9;
80 let sect5 = submessage.5.body;
81 let sect6 = submessage.6.body;
82 let sect7 = submessage.7.body;
83 let (sect3_body, sect5_body, sect6_body) = match (
84 submessage.3.body.body.as_ref(),
85 sect5.body.as_ref(),
86 sect6.body.as_ref(),
87 ) {
88 (
89 Some(SectionBody::Section3(b3)),
90 Some(SectionBody::Section5(b5)),
91 Some(SectionBody::Section6(b6)),
92 ) => (b3, b5, b6),
93 _ => return Err(GribError::InternalDataError),
94 };
95 let sect3_num_points = sect3_body.num_points() as usize;
96
97 let bitmap = match sect6_body.bitmap_indicator {
98 0x00 => {
99 let sect6_data = reader.read_sect_payload_as_slice(sect6)?;
100 sect6_data[1..].into()
101 }
102 0xff => {
103 let num_points = sect3_num_points;
104 create_bitmap_for_nonnullable_data(num_points)
105 }
106 _ => {
107 return Err(GribError::DecodeError(
108 DecodeError::BitMapIndicatorUnsupported,
109 ));
110 }
111 };
112
113 Ok(Self::new(
114 sect3_num_points,
115 sect5_body.num_points() as usize,
116 sect5_body.repr_tmpl_num(),
117 reader.read_sect_payload_as_slice(sect5)?,
118 bitmap,
119 reader.read_sect_payload_as_slice(sect7)?,
120 ))
121 }
122
123 pub fn dispatch(
125 &self,
126 ) -> Result<Grib2DecodedValues<'_, impl Iterator<Item = f32> + '_>, GribError> {
127 let decoder = match self.template_num {
128 0 => Grib2ValueIterator::Template0(simple::decode(self)?),
129 2 => Grib2ValueIterator::Template2(complex::decode_7_2(self)?),
130 3 => Grib2ValueIterator::Template3(complex::decode_7_3(self)?),
131 #[cfg(not(target_arch = "wasm32"))]
132 40 => Grib2ValueIterator::Template40(jpeg2000::decode(self)?),
133 41 => Grib2ValueIterator::Template41(png::decode(self)?),
134 200 => Grib2ValueIterator::Template200(run_length::decode(self)?),
135 _ => {
136 return Err(GribError::DecodeError(
137 DecodeError::TemplateNumberUnsupported,
138 ))
139 }
140 };
141 let decoder =
142 BitmapDecodeIterator::new(self.bitmap.iter(), decoder, self.num_points_total)?;
143 Ok(Grib2DecodedValues(decoder))
144 }
145}
146
147pub struct Grib2DecodedValues<'b, I>(BitmapDecodeIterator<std::slice::Iter<'b, u8>, I>);
148
149impl<I> Iterator for Grib2DecodedValues<'_, I>
150where
151 I: Iterator<Item = f32>,
152{
153 type Item = f32;
154
155 fn next(&mut self) -> Option<Self::Item> {
156 let Self(inner) = self;
157 inner.next()
158 }
159
160 fn size_hint(&self) -> (usize, Option<usize>) {
161 let Self(inner) = self;
162 inner.size_hint()
163 }
164}
165
166#[cfg(target_arch = "wasm32")]
171type Grib2ValueIterator<T0, T2, T3, T41> =
172 Grib2SubmessageDecoderIteratorWrapper<T0, T2, T3, std::vec::IntoIter<f32>, T41>;
173#[cfg(not(target_arch = "wasm32"))]
174type Grib2ValueIterator<T0, T2, T3, T40, T41> =
175 Grib2SubmessageDecoderIteratorWrapper<T0, T2, T3, T40, T41>;
176
177enum Grib2SubmessageDecoderIteratorWrapper<T0, T2, T3, T40, T41> {
178 Template0(SimplePackingDecodeIteratorWrapper<T0>),
179 Template2(SimplePackingDecodeIteratorWrapper<T2>),
180 Template3(SimplePackingDecodeIteratorWrapper<T3>),
181 #[allow(dead_code)]
182 #[cfg(target_arch = "wasm32")]
183 Template40(PhantomData<T40>),
184 #[cfg(not(target_arch = "wasm32"))]
185 Template40(SimplePackingDecodeIteratorWrapper<T40>),
186 Template41(SimplePackingDecodeIteratorWrapper<T41>),
187 Template200(std::vec::IntoIter<f32>),
188}
189
190impl<T0, T2, T3, T40, T41> Iterator for Grib2SubmessageDecoderIteratorWrapper<T0, T2, T3, T40, T41>
191where
192 T0: Iterator,
193 <T0 as Iterator>::Item: ToPrimitive,
194 T2: Iterator,
195 <T2 as Iterator>::Item: ToPrimitive,
196 T3: Iterator,
197 <T3 as Iterator>::Item: ToPrimitive,
198 T40: Iterator,
199 <T40 as Iterator>::Item: ToPrimitive,
200 T41: Iterator,
201 <T41 as Iterator>::Item: ToPrimitive,
202{
203 type Item = f32;
204
205 fn next(&mut self) -> Option<Self::Item> {
206 match self {
207 Self::Template0(inner) => inner.next(),
208 Self::Template2(inner) => inner.next(),
209 Self::Template3(inner) => inner.next(),
210 #[cfg(not(target_arch = "wasm32"))]
211 Self::Template40(inner) => inner.next(),
212 #[cfg(target_arch = "wasm32")]
213 Self::Template40(_) => unreachable!(),
214 Self::Template41(inner) => inner.next(),
215 Self::Template200(inner) => inner.next(),
216 }
217 }
218
219 fn size_hint(&self) -> (usize, Option<usize>) {
220 match self {
221 Self::Template0(inner) => inner.size_hint(),
222 Self::Template2(inner) => inner.size_hint(),
223 Self::Template3(inner) => inner.size_hint(),
224 #[cfg(not(target_arch = "wasm32"))]
225 Self::Template40(inner) => inner.size_hint(),
226 #[cfg(target_arch = "wasm32")]
227 Self::Template40(_) => unreachable!(),
228 Self::Template41(inner) => inner.size_hint(),
229 Self::Template200(inner) => inner.size_hint(),
230 }
231 }
232}
233
234#[derive(Debug, Clone, PartialEq, Eq, Hash)]
235pub enum DecodeError {
236 TemplateNumberUnsupported,
237 BitMapIndicatorUnsupported,
238 SimplePackingDecodeError(SimplePackingDecodeError),
239 ComplexPackingDecodeError(ComplexPackingDecodeError),
240 #[cfg(not(target_arch = "wasm32"))]
241 Jpeg2000CodeStreamDecodeError(Jpeg2000CodeStreamDecodeError),
242 PngDecodeError(PngDecodeError),
243 RunLengthEncodingDecodeError(RunLengthEncodingDecodeError),
244 LengthMismatch,
245}
246
247impl From<SimplePackingDecodeError> for DecodeError {
248 fn from(e: SimplePackingDecodeError) -> Self {
249 Self::SimplePackingDecodeError(e)
250 }
251}
252
253impl From<ComplexPackingDecodeError> for DecodeError {
254 fn from(e: ComplexPackingDecodeError) -> Self {
255 Self::ComplexPackingDecodeError(e)
256 }
257}
258
259#[cfg(not(target_arch = "wasm32"))]
260impl From<Jpeg2000CodeStreamDecodeError> for DecodeError {
261 fn from(e: Jpeg2000CodeStreamDecodeError) -> Self {
262 Self::Jpeg2000CodeStreamDecodeError(e)
263 }
264}
265
266impl From<RunLengthEncodingDecodeError> for DecodeError {
267 fn from(e: RunLengthEncodingDecodeError) -> Self {
268 Self::RunLengthEncodingDecodeError(e)
269 }
270}
271
272mod bitmap;
273mod complex;
274#[cfg(not(target_arch = "wasm32"))]
275mod jpeg2000;
276mod param;
277mod png;
278mod run_length;
279mod simple;
280mod stream;