1use super::{
2 missing::DecodedValue::{self, Normal},
3 ComplexPackingDecodeError,
4};
5use crate::{decoder::DecodeError, error::GribError, helpers::grib_int_from_bytes};
6
7pub(crate) struct SpatialDifferencingExtraDescriptors<'a> {
8 slice: &'a [u8],
9 num_octets: usize,
10}
11
12impl<'a> SpatialDifferencingExtraDescriptors<'a> {
13 pub(crate) fn new(
14 parent_slice: &'a [u8],
15 spdiff_order: u8,
16 num_octets: u8,
17 ) -> Result<Self, GribError> {
18 if num_octets == 0 || num_octets > 4 {
19 return Err(GribError::DecodeError(
20 DecodeError::ComplexPackingDecodeError(ComplexPackingDecodeError::NotSupported),
21 ));
22 }
23 let num_octets = usize::from(num_octets);
24 let byte_length = usize::from(spdiff_order + 1) * num_octets;
25
26 Ok(Self {
27 slice: &parent_slice[..byte_length],
28 num_octets,
29 })
30 }
31
32 pub(crate) fn len(&self) -> usize {
34 self.slice.len()
35 }
36
37 pub(crate) fn minimum(&self) -> i32 {
39 let slice = &self.slice[self.first_value_end_pos()..];
40 grib_int_from_bytes(slice)
41 }
42
43 pub(crate) fn first_values(&self) -> FirstValues<'_, 'a> {
44 FirstValues::new(self)
45 }
46
47 fn first_value_end_pos(&self) -> usize {
48 self.len() - self.num_octets
49 }
50}
51
52pub(crate) struct FirstValues<'s, 'a> {
53 spdiff_info: &'s SpatialDifferencingExtraDescriptors<'a>,
54 pos: usize,
55}
56
57impl<'s, 'a> FirstValues<'s, 'a> {
58 pub(crate) fn new(spdiff_info: &'s SpatialDifferencingExtraDescriptors<'a>) -> Self {
59 Self {
60 spdiff_info,
61 pos: 0,
62 }
63 }
64}
65
66impl Iterator for FirstValues<'_, '_> {
67 type Item = i32;
68
69 fn next(&mut self) -> Option<Self::Item> {
70 if self.pos >= self.spdiff_info.first_value_end_pos() {
71 return None;
72 }
73
74 let num_octets = self.spdiff_info.num_octets;
75 let slice = &self.spdiff_info.slice[self.pos..self.pos + num_octets];
76 let val = grib_int_from_bytes(slice);
77 self.pos += num_octets;
78 Some(val)
79 }
80}
81
82pub(crate) enum SpatialDifferencingDecodeIterator<I, J> {
83 FirstOrder(FirstOrderSpatialDifferencingDecodeIterator<I, J>),
84 SecondOrder(SecondOrderSpatialDifferencingDecodeIterator<I, J>),
85}
86
87impl<I, J> Iterator for SpatialDifferencingDecodeIterator<I, J>
88where
89 I: Iterator<Item = DecodedValue<i32>>,
90 J: Iterator<Item = i32>,
91{
92 type Item = DecodedValue<i32>;
93
94 fn next(&mut self) -> Option<Self::Item> {
95 match self {
96 SpatialDifferencingDecodeIterator::FirstOrder(iter) => iter.next(),
97 SpatialDifferencingDecodeIterator::SecondOrder(iter) => iter.next(),
98 }
99 }
100}
101
102pub(crate) struct FirstOrderSpatialDifferencingDecodeIterator<I, J> {
103 iter: I,
104 first_values: J,
105 count: u32,
106 prev: i32,
107}
108
109impl<I, J> FirstOrderSpatialDifferencingDecodeIterator<I, J> {
110 pub(crate) fn new(iter: I, first_values: J) -> Self {
111 Self {
112 iter,
113 first_values,
114 count: 0,
115 prev: 0,
116 }
117 }
118}
119
120impl<I, J> Iterator for FirstOrderSpatialDifferencingDecodeIterator<I, J>
121where
122 I: Iterator<Item = DecodedValue<i32>>,
123 J: Iterator<Item = i32>,
124{
125 type Item = DecodedValue<i32>;
126
127 fn next(&mut self) -> Option<Self::Item> {
128 match self.iter.next() {
129 None => None,
130 Some(Normal(v)) => match self.count {
131 0 => {
132 self.prev = self.first_values.next().unwrap();
133 self.count += 1;
134 Some(Normal(self.prev))
135 }
136 _ => {
137 let v = v + self.prev;
138 self.prev = v;
139 Some(Normal(v))
140 }
141 },
142 Some(missing) => Some(missing),
143 }
144 }
145}
146
147pub(crate) struct SecondOrderSpatialDifferencingDecodeIterator<I, J> {
148 iter: I,
149 first_values: J,
150 count: u32,
151 prev1: i32,
152 prev2: i32,
153}
154
155impl<I, J> SecondOrderSpatialDifferencingDecodeIterator<I, J> {
156 pub(crate) fn new(iter: I, first_values: J) -> Self {
157 Self {
158 iter,
159 first_values,
160 count: 0,
161 prev1: 0,
162 prev2: 0,
163 }
164 }
165}
166
167impl<I, J> Iterator for SecondOrderSpatialDifferencingDecodeIterator<I, J>
168where
169 I: Iterator<Item = DecodedValue<i32>>,
170 J: Iterator<Item = i32>,
171{
172 type Item = DecodedValue<i32>;
173
174 fn next(&mut self) -> Option<Self::Item> {
175 match self.iter.next() {
176 None => None,
177 Some(Normal(v)) => match self.count {
178 0 => {
179 self.prev2 = self.first_values.next().unwrap();
180 self.count += 1;
181 Some(Normal(self.prev2))
182 }
183 1 => {
184 self.prev1 = self.first_values.next().unwrap();
185 self.count += 1;
186 Some(Normal(self.prev1))
187 }
188 _ => {
189 let v = v + 2 * self.prev1 - self.prev2;
190 self.prev2 = self.prev1;
191 self.prev1 = v;
192 Some(Normal(v))
193 }
194 },
195 Some(missing) => Some(missing),
196 }
197 }
198}
199
200#[cfg(test)]
201mod tests {
202 use super::{
203 super::missing::DecodedValue::{Missing1, Missing2},
204 *,
205 };
206
207 macro_rules! test_spdiff_minimum_value {
208 ($(($name:ident, $num_octets:expr, $expected:expr),)*) => ($(
209 #[test]
210 fn $name() {
211 let octets = (0x00..0x10).collect::<Vec<_>>();
212 let spdiff_params =
213 SpatialDifferencingExtraDescriptors::new(&octets, 2, $num_octets).unwrap();
214 let actual = spdiff_params.minimum();
215 assert_eq!(actual, $expected);
216 }
217 )*);
218 }
219
220 test_spdiff_minimum_value! {
221 (spdiff_minimum_value_when_num_octets_is_1, 1, 0x02),
222 (spdiff_minimum_value_when_num_octets_is_2, 2, 0x04_05),
223 (spdiff_minimum_value_when_num_octets_is_3, 3, 0x06_07_08),
224 (spdiff_minimum_value_when_num_octets_is_4, 4, 0x08_09_0a_0b),
225 }
226
227 macro_rules! test_spdiff_first_values {
228 ($(($name:ident, $num_octets:expr, $expected:expr),)*) => ($(
229 #[test]
230 fn $name() {
231 let octets = (0x00..0x10).collect::<Vec<_>>();
232 let spdiff_params =
233 SpatialDifferencingExtraDescriptors::new(&octets, 2, $num_octets).unwrap();
234 let actual = spdiff_params.first_values().collect::<Vec<_>>();
235 assert_eq!(actual, $expected);
236 }
237 )*);
238 }
239
240 test_spdiff_first_values! {
241 (spdiff_first_values_when_num_octets_is_1, 1, vec![0x00, 0x01]),
242 (spdiff_first_values_when_num_octets_is_2, 2, vec![0x00_01, 0x02_03]),
243 (spdiff_first_values_when_num_octets_is_3, 3, vec![0x00_01_02, 0x03_04_05]),
244 (spdiff_first_values_when_num_octets_is_4, 4, vec![0x00_01_02_03, 0x04_05_06_07]),
245 }
246
247 macro_rules! test_first_order_spatial_differencing_decoding {
248 ($(($name:ident, $input:expr, $expected:expr),)*) => ($(
249 #[test]
250 fn $name() {
251 let input = $input
252 .into_iter();
253 let first_values = vec![100].into_iter();
254 let iter = FirstOrderSpatialDifferencingDecodeIterator::new(input, first_values);
255 assert_eq!(
256 iter.collect::<Vec<_>>(),
257 $expected
258 );
259 }
260 )*);
261 }
262
263 test_first_order_spatial_differencing_decoding! {
264 (
265 first_order_spatial_differencing_decoding_consisting_of_normal_values,
266 (0_u32..10).map(|n| Normal(n as i32 * (-1_i32).pow(n))),
267 vec![
268 Normal(100),
269 Normal(99),
270 Normal(101),
271 Normal(98),
272 Normal(102),
273 Normal(97),
274 Normal(103),
275 Normal(96),
276 Normal(104),
277 Normal(95),
278 ]
279 ),
280 (
281 first_order_spatial_differencing_decoding_with_missing_values_in_first_values,
282 vec![
283 Missing1,
284 Normal(0),
285 Normal(-1),
286 Normal(2),
287 Normal(-3),
288 Normal(4),
289 Normal(-5),
290 Normal(6),
291 Normal(-7),
292 Normal(8),
293 ],
294 vec![
295 Missing1,
296 Normal(100),
297 Normal(99),
298 Normal(101),
299 Normal(98),
300 Normal(102),
301 Normal(97),
302 Normal(103),
303 Normal(96),
304 Normal(104),
305 ]
306 ),
307 (
308 first_order_spatial_differencing_decoding_with_missing_values_in_non_first_values,
309 vec![
310 Normal(0),
311 Normal(-1),
312 Missing1,
313 Normal(2),
314 Normal(-3),
315 Normal(4),
316 Missing2,
317 Normal(-5),
318 Normal(6),
319 Normal(-7),
320 ],
321 vec![
322 Normal(100),
323 Normal(99),
324 Missing1,
325 Normal(101),
326 Normal(98),
327 Normal(102),
328 Missing2,
329 Normal(97),
330 Normal(103),
331 Normal(96),
332 ]
333 ),
334 }
335
336 macro_rules! test_second_order_spatial_differencing_decoding {
337 ($(($name:ident, $input:expr, $expected:expr),)*) => ($(
338 #[test]
339 fn $name() {
340 let input = $input
341 .into_iter();
342 let first_values = vec![100, 99].into_iter();
343 let iter = SecondOrderSpatialDifferencingDecodeIterator::new(input, first_values);
344 assert_eq!(
345 iter.collect::<Vec<_>>(),
346 $expected
347 );
348 }
349 )*);
350 }
351
352 test_second_order_spatial_differencing_decoding! {
353 (
354 second_order_spatial_differencing_decoding_consisting_of_normal_values,
355 (0_u32..10).map(|n| Normal(n as i32 * (-1_i32).pow(n))),
356 vec![
357 Normal(100),
358 Normal(99),
359 Normal(100),
360 Normal(98),
361 Normal(100),
362 Normal(97),
363 Normal(100),
364 Normal(96),
365 Normal(100),
366 Normal(95),
367 ]
368 ),
369 (
370 second_order_spatial_differencing_decoding_with_missing_values_in_first_values,
371 vec![
372 Missing1,
373 Missing2,
374 Normal(0),
375 Normal(-1),
376 Normal(2),
377 Normal(-3),
378 Normal(4),
379 Normal(-5),
380 Normal(6),
381 Normal(-7),
382 ],
383 vec![
384 Missing1,
385 Missing2,
386 Normal(100),
387 Normal(99),
388 Normal(100),
389 Normal(98),
390 Normal(100),
391 Normal(97),
392 Normal(100),
393 Normal(96),
394 ]
395 ),
396 (
397 second_order_spatial_differencing_decoding_with_missing_values_in_non_first_values,
398 vec![
399 Normal(0),
400 Normal(-1),
401 Missing1,
402 Normal(2),
403 Normal(-3),
404 Normal(4),
405 Missing2,
406 Normal(-5),
407 Normal(6),
408 Normal(-7),
409 ],
410 vec![
411 Normal(100),
412 Normal(99),
413 Missing1,
414 Normal(100),
415 Normal(98),
416 Normal(100),
417 Missing2,
418 Normal(97),
419 Normal(100),
420 Normal(96),
421 ]
422 ),
423 }
424}