grib/decoder/complex/
diff.rs

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    // total number of octets for descriptors
33    pub(crate) fn len(&self) -> usize {
34        self.slice.len()
35    }
36
37    // overall minimum of the differences
38    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}