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 pub(crate) fn len(&self) -> usize {
31 self.slice.len()
32 }
33
34 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}