grib/decoder/complex/
diff.rs

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