grib/decoder/complex/
diff.rs

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