1use crate::error::{Error, Result};
4use crate::util::grib_i16;
5
6#[derive(Debug, Clone, PartialEq)]
8pub enum DataRepresentation {
9 SimplePacking(SimplePackingParams),
11 ComplexPacking(ComplexPackingParams),
13 Unsupported(u16),
15}
16
17#[derive(Debug, Clone, PartialEq)]
19pub struct SimplePackingParams {
20 pub encoded_values: usize,
21 pub reference_value: f32,
22 pub binary_scale: i16,
23 pub decimal_scale: i16,
24 pub bits_per_value: u8,
25 pub original_field_type: u8,
26}
27
28#[derive(Debug, Clone, PartialEq)]
30pub struct ComplexPackingParams {
31 pub encoded_values: usize,
32 pub reference_value: f32,
33 pub binary_scale: i16,
34 pub decimal_scale: i16,
35 pub group_reference_bits: u8,
36 pub original_field_type: u8,
37 pub group_splitting_method: u8,
38 pub missing_value_management: u8,
39 pub primary_missing_substitute: u32,
40 pub secondary_missing_substitute: u32,
41 pub num_groups: usize,
42 pub group_width_reference: u8,
43 pub group_width_bits: u8,
44 pub group_length_reference: u32,
45 pub group_length_increment: u8,
46 pub true_length_last_group: u32,
47 pub scaled_group_length_bits: u8,
48 pub spatial_differencing: Option<SpatialDifferencingParams>,
49}
50
51#[derive(Debug, Clone, Copy, PartialEq, Eq)]
53pub struct SpatialDifferencingParams {
54 pub order: u8,
55 pub descriptor_octets: u8,
56}
57
58pub trait DecodeSample: Copy + Sized {
60 fn from_f64(value: f64) -> Self;
61 fn nan() -> Self;
62}
63
64impl DecodeSample for f32 {
65 fn from_f64(value: f64) -> Self {
66 value as f32
67 }
68
69 fn nan() -> Self {
70 f32::NAN
71 }
72}
73
74impl DecodeSample for f64 {
75 fn from_f64(value: f64) -> Self {
76 value
77 }
78
79 fn nan() -> Self {
80 f64::NAN
81 }
82}
83
84impl DataRepresentation {
85 pub fn parse(section_bytes: &[u8]) -> Result<Self> {
86 if section_bytes.len() < 11 {
87 return Err(Error::InvalidSection {
88 section: 5,
89 reason: format!("expected at least 11 bytes, got {}", section_bytes.len()),
90 });
91 }
92 if section_bytes[4] != 5 {
93 return Err(Error::InvalidSection {
94 section: section_bytes[4],
95 reason: "not a data representation section".into(),
96 });
97 }
98
99 let template = u16::from_be_bytes(section_bytes[9..11].try_into().unwrap());
100 match template {
101 0 => parse_simple_packing(section_bytes),
102 2 => parse_complex_packing(section_bytes, false),
103 3 => parse_complex_packing(section_bytes, true),
104 _ => Ok(Self::Unsupported(template)),
105 }
106 }
107
108 pub fn encoded_values(&self) -> Option<usize> {
109 match self {
110 Self::SimplePacking(params) => Some(params.encoded_values),
111 Self::ComplexPacking(params) => Some(params.encoded_values),
112 Self::Unsupported(_) => None,
113 }
114 }
115}
116
117pub fn decode_field(
119 data_section: &[u8],
120 representation: &DataRepresentation,
121 bitmap_section: Option<&[u8]>,
122 num_grid_points: usize,
123) -> Result<Vec<f64>> {
124 if data_section.len() < 5 || data_section[4] != 7 {
125 return Err(Error::InvalidSection {
126 section: data_section.get(4).copied().unwrap_or(7),
127 reason: "not a data section".into(),
128 });
129 }
130
131 decode_payload(
132 &data_section[5..],
133 representation,
134 bitmap_section,
135 num_grid_points,
136 )
137}
138
139pub fn decode_field_into<T: DecodeSample>(
142 data_section: &[u8],
143 representation: &DataRepresentation,
144 bitmap_section: Option<&[u8]>,
145 num_grid_points: usize,
146 out: &mut [T],
147) -> Result<()> {
148 if data_section.len() < 5 || data_section[4] != 7 {
149 return Err(Error::InvalidSection {
150 section: data_section.get(4).copied().unwrap_or(7),
151 reason: "not a data section".into(),
152 });
153 }
154
155 decode_payload_into(
156 &data_section[5..],
157 representation,
158 bitmap_section,
159 num_grid_points,
160 out,
161 )
162}
163
164pub(crate) fn decode_payload(
165 payload: &[u8],
166 representation: &DataRepresentation,
167 bitmap_section: Option<&[u8]>,
168 num_grid_points: usize,
169) -> Result<Vec<f64>> {
170 let mut values = vec![0.0; num_grid_points];
171 decode_payload_into(
172 payload,
173 representation,
174 bitmap_section,
175 num_grid_points,
176 &mut values,
177 )?;
178 Ok(values)
179}
180
181pub(crate) fn decode_payload_into<T: DecodeSample>(
182 payload: &[u8],
183 representation: &DataRepresentation,
184 bitmap_section: Option<&[u8]>,
185 num_grid_points: usize,
186 out: &mut [T],
187) -> Result<()> {
188 if out.len() != num_grid_points {
189 return Err(Error::DataLengthMismatch {
190 expected: num_grid_points,
191 actual: out.len(),
192 });
193 }
194
195 let expected_values = match representation {
196 DataRepresentation::SimplePacking(params) => params.encoded_values,
197 DataRepresentation::ComplexPacking(params) => params.encoded_values,
198 DataRepresentation::Unsupported(template) => {
199 return Err(Error::UnsupportedDataTemplate(*template));
200 }
201 };
202 match bitmap_section {
203 Some(bitmap_payload) => {
204 let present_values = count_bitmap_present_points(bitmap_payload, num_grid_points)?;
205 if expected_values != present_values {
206 return Err(Error::DataLengthMismatch {
207 expected: present_values,
208 actual: expected_values,
209 });
210 }
211 }
212 None if expected_values != num_grid_points => {
213 return Err(Error::DataLengthMismatch {
214 expected: num_grid_points,
215 actual: expected_values,
216 });
217 }
218 None => {}
219 }
220
221 let mut output = OutputCursor::new(out, bitmap_section);
222 match representation {
223 DataRepresentation::SimplePacking(params) => {
224 unpack_simple_into(payload, params, expected_values, &mut output)?
225 }
226 DataRepresentation::ComplexPacking(params) => {
227 unpack_complex_into(payload, params, &mut output)?
228 }
229 DataRepresentation::Unsupported(_) => unreachable!(),
230 }
231 output.finish()
232}
233
234pub fn bitmap_payload(section_bytes: &[u8]) -> Result<Option<&[u8]>> {
236 if section_bytes.len() < 6 {
237 return Err(Error::InvalidSection {
238 section: 6,
239 reason: format!("expected at least 6 bytes, got {}", section_bytes.len()),
240 });
241 }
242 if section_bytes[4] != 6 {
243 return Err(Error::InvalidSection {
244 section: section_bytes[4],
245 reason: "not a bitmap section".into(),
246 });
247 }
248
249 match section_bytes[5] {
250 255 => Ok(None),
251 0 => Ok(Some(§ion_bytes[6..])),
252 indicator => Err(Error::UnsupportedBitmapIndicator(indicator)),
253 }
254}
255
256pub(crate) fn count_bitmap_present_points(
257 bitmap_payload: &[u8],
258 num_grid_points: usize,
259) -> Result<usize> {
260 let full_bytes = num_grid_points / 8;
261 let remaining_bits = num_grid_points % 8;
262 let required_bytes = full_bytes + usize::from(remaining_bits > 0);
263 if bitmap_payload.len() < required_bytes {
264 return Err(Error::DataLengthMismatch {
265 expected: required_bytes,
266 actual: bitmap_payload.len(),
267 });
268 }
269
270 let mut present = bitmap_payload[..full_bytes]
271 .iter()
272 .map(|byte| byte.count_ones() as usize)
273 .sum();
274 if remaining_bits > 0 {
275 let mask = u8::MAX << (8 - remaining_bits);
276 present += (bitmap_payload[full_bytes] & mask).count_ones() as usize;
277 }
278
279 Ok(present)
280}
281
282fn parse_simple_packing(data: &[u8]) -> Result<DataRepresentation> {
283 if data.len() < 21 {
284 return Err(Error::InvalidSection {
285 section: 5,
286 reason: format!("template 5.0 requires 21 bytes, got {}", data.len()),
287 });
288 }
289
290 let encoded_values = u32::from_be_bytes(data[5..9].try_into().unwrap()) as usize;
291 let reference_value = f32::from_be_bytes(data[11..15].try_into().unwrap());
292 let binary_scale = grib_i16(&data[15..17]).unwrap();
293 let decimal_scale = grib_i16(&data[17..19]).unwrap();
294 let bits_per_value = data[19];
295 let original_field_type = data[20];
296
297 Ok(DataRepresentation::SimplePacking(SimplePackingParams {
298 encoded_values,
299 reference_value,
300 binary_scale,
301 decimal_scale,
302 bits_per_value,
303 original_field_type,
304 }))
305}
306
307fn parse_complex_packing(
308 data: &[u8],
309 with_spatial_differencing: bool,
310) -> Result<DataRepresentation> {
311 let required = if with_spatial_differencing { 49 } else { 47 };
312 if data.len() < required {
313 return Err(Error::InvalidSection {
314 section: 5,
315 reason: format!(
316 "template 5.{} requires {required} bytes, got {}",
317 if with_spatial_differencing { 3 } else { 2 },
318 data.len()
319 ),
320 });
321 }
322
323 let group_splitting_method = data[21];
324 if group_splitting_method != 1 {
325 return Err(Error::UnsupportedGroupSplittingMethod(
326 group_splitting_method,
327 ));
328 }
329
330 let missing_value_management = data[22];
331 if missing_value_management > 2 {
332 return Err(Error::UnsupportedMissingValueManagement(
333 missing_value_management,
334 ));
335 }
336
337 let spatial_differencing = if with_spatial_differencing {
338 let order = data[47];
339 if !matches!(order, 1 | 2) {
340 return Err(Error::UnsupportedSpatialDifferencingOrder(order));
341 }
342 Some(SpatialDifferencingParams {
343 order,
344 descriptor_octets: data[48],
345 })
346 } else {
347 None
348 };
349
350 Ok(DataRepresentation::ComplexPacking(ComplexPackingParams {
351 encoded_values: u32::from_be_bytes(data[5..9].try_into().unwrap()) as usize,
352 reference_value: f32::from_be_bytes(data[11..15].try_into().unwrap()),
353 binary_scale: grib_i16(&data[15..17]).unwrap(),
354 decimal_scale: grib_i16(&data[17..19]).unwrap(),
355 group_reference_bits: data[19],
356 original_field_type: data[20],
357 group_splitting_method,
358 missing_value_management,
359 primary_missing_substitute: u32::from_be_bytes(data[23..27].try_into().unwrap()),
360 secondary_missing_substitute: u32::from_be_bytes(data[27..31].try_into().unwrap()),
361 num_groups: u32::from_be_bytes(data[31..35].try_into().unwrap()) as usize,
362 group_width_reference: data[35],
363 group_width_bits: data[36],
364 group_length_reference: u32::from_be_bytes(data[37..41].try_into().unwrap()),
365 group_length_increment: data[41],
366 true_length_last_group: u32::from_be_bytes(data[42..46].try_into().unwrap()),
367 scaled_group_length_bits: data[46],
368 spatial_differencing,
369 }))
370}
371
372pub fn unpack_simple(
374 data_bytes: &[u8],
375 params: &SimplePackingParams,
376 num_values: usize,
377) -> Result<Vec<f64>> {
378 let mut values = vec![0.0; num_values];
379 let mut output = OutputCursor::new(&mut values, None);
380 unpack_simple_into(data_bytes, params, num_values, &mut output)?;
381 output.finish()?;
382 Ok(values)
383}
384
385fn unpack_simple_into<T: DecodeSample>(
386 data_bytes: &[u8],
387 params: &SimplePackingParams,
388 num_values: usize,
389 output: &mut OutputCursor<'_, T>,
390) -> Result<()> {
391 let bits = params.bits_per_value as usize;
392 let binary_factor = 2.0_f64.powi(params.binary_scale as i32);
393 let decimal_factor = 10.0_f64.powi(-(params.decimal_scale as i32));
394 let reference = params.reference_value as f64;
395 if bits == 0 {
396 let constant = T::from_f64(scale_decoded_value(
397 reference,
398 0.0,
399 binary_factor,
400 decimal_factor,
401 ));
402 for _ in 0..num_values {
403 output.push_present(constant)?;
404 }
405 return Ok(());
406 }
407 if bits > u64::BITS as usize {
408 return Err(Error::UnsupportedPackingWidth(params.bits_per_value));
409 }
410
411 let required_bits = bits
412 .checked_mul(num_values)
413 .ok_or_else(|| Error::Other("bit count overflow during unpacking".into()))?;
414 let required_bytes = required_bits.div_ceil(8);
415 if data_bytes.len() < required_bytes {
416 return Err(Error::Truncated {
417 offset: data_bytes.len() as u64,
418 });
419 }
420
421 let mut reader = BitReader::new(data_bytes);
422
423 for _ in 0..num_values {
424 let packed = reader.read(bits)?;
425 output.push_present(T::from_f64(scale_decoded_value(
426 reference,
427 packed as f64,
428 binary_factor,
429 decimal_factor,
430 )))?;
431 }
432
433 Ok(())
434}
435
436#[cfg(test)]
437fn unpack_complex(data_bytes: &[u8], params: &ComplexPackingParams) -> Result<Vec<f64>> {
438 let mut values = vec![0.0; params.encoded_values];
439 let mut output = OutputCursor::new(&mut values, None);
440 unpack_complex_into(data_bytes, params, &mut output)?;
441 output.finish()?;
442 Ok(values)
443}
444
445fn unpack_complex_into<T: DecodeSample>(
446 data_bytes: &[u8],
447 params: &ComplexPackingParams,
448 output: &mut OutputCursor<'_, T>,
449) -> Result<()> {
450 if params.num_groups == 0 {
451 return Err(Error::InvalidSection {
452 section: 5,
453 reason: "complex packing requires at least one group".into(),
454 });
455 }
456
457 let mut reader = BitReader::new(data_bytes);
458 let mut spatial = params
459 .spatial_differencing
460 .map(|spatial| read_spatial_descriptors(&mut reader, spatial))
461 .transpose()?
462 .map(SpatialRestoreState::new);
463
464 let layout = GroupReaderLayout::new(reader.bit_offset, params)?;
465 let mut reference_reader = BitReader::with_offset(data_bytes, layout.reference_offset);
466 let mut width_reader = BitReader::with_offset(data_bytes, layout.width_offset);
467 let mut length_reader = BitReader::with_offset(data_bytes, layout.length_offset);
468 let mut value_reader = BitReader::with_offset(data_bytes, layout.value_offset);
469 let binary_factor = 2.0_f64.powi(params.binary_scale as i32);
470 let decimal_factor = 10.0_f64.powi(-(params.decimal_scale as i32));
471 let reference = params.reference_value as f64;
472 let mut actual_total = 0usize;
473
474 for group_index in 0..params.num_groups {
475 let group_reference = reference_reader.read(params.group_reference_bits as usize)?;
476 let width_delta = width_reader.read(params.group_width_bits as usize)?;
477 let group_width = usize::from(params.group_width_reference)
478 .checked_add(width_delta as usize)
479 .ok_or_else(|| Error::Other("group width overflow".into()))?;
480 let group_length = read_group_length(&mut length_reader, params, group_index)?;
481
482 actual_total = actual_total
483 .checked_add(group_length)
484 .ok_or_else(|| Error::Other("group length overflow".into()))?;
485
486 if group_width == 0 {
487 let raw_value = decode_constant_group_value(
488 group_reference,
489 params.group_reference_bits as usize,
490 params.missing_value_management,
491 )?;
492 for _ in 0..group_length {
493 let value = spatial
494 .as_mut()
495 .map_or(Ok(raw_value), |state| state.restore(raw_value))?;
496 output.push_present(scale_complex_value(
497 reference,
498 binary_factor,
499 decimal_factor,
500 value,
501 ))?;
502 }
503 continue;
504 }
505
506 if group_width > u64::BITS as usize {
507 return Err(Error::UnsupportedPackingWidth(group_width as u8));
508 }
509
510 let group_reference = i64::try_from(group_reference)
511 .map_err(|_| Error::Other("group reference exceeds i64 range".into()))?;
512 for _ in 0..group_length {
513 let packed = value_reader.read(group_width)?;
514 let value = decode_group_value(
515 group_reference,
516 packed,
517 group_width,
518 params.missing_value_management,
519 )?;
520 let value = spatial
521 .as_mut()
522 .map_or(Ok(value), |state| state.restore(value))?;
523 output.push_present(scale_complex_value(
524 reference,
525 binary_factor,
526 decimal_factor,
527 value,
528 ))?;
529 }
530 }
531
532 if actual_total != params.encoded_values {
533 return Err(Error::DataLengthMismatch {
534 expected: params.encoded_values,
535 actual: actual_total,
536 });
537 }
538
539 if output.values_written() != params.encoded_values {
540 return Err(Error::DataLengthMismatch {
541 expected: params.encoded_values,
542 actual: output.values_written(),
543 });
544 }
545
546 if let Some(spatial) = spatial {
547 spatial.finish()?;
548 }
549
550 Ok(())
551}
552
553fn read_group_length(
554 reader: &mut BitReader<'_>,
555 params: &ComplexPackingParams,
556 group_index: usize,
557) -> Result<usize> {
558 if params.scaled_group_length_bits as usize > u64::BITS as usize {
559 return Err(Error::UnsupportedPackingWidth(
560 params.scaled_group_length_bits,
561 ));
562 }
563
564 if group_index + 1 == params.num_groups {
565 return Ok(params.true_length_last_group as usize);
566 }
567
568 let scaled = reader
569 .read(params.scaled_group_length_bits as usize)?
570 .checked_mul(u64::from(params.group_length_increment))
571 .ok_or_else(|| Error::Other("group length overflow".into()))?;
572 let length = u64::from(params.group_length_reference)
573 .checked_add(scaled)
574 .ok_or_else(|| Error::Other("group length overflow".into()))?;
575 usize::try_from(length).map_err(|_| Error::Other("group length overflow".into()))
576}
577
578fn read_spatial_descriptors(
579 reader: &mut BitReader<'_>,
580 params: SpatialDifferencingParams,
581) -> Result<SpatialDescriptors> {
582 if params.descriptor_octets == 0 {
583 return Err(Error::InvalidSection {
584 section: 5,
585 reason: "spatial differencing requires at least one descriptor octet".into(),
586 });
587 }
588
589 let bit_count = usize::from(params.descriptor_octets) * 8;
590 if bit_count > u64::BITS as usize {
591 return Err(Error::Other(
592 "spatial differencing descriptors wider than 8 octets are not supported".into(),
593 ));
594 }
595
596 let first_value = reader.read_signed(bit_count)?;
597 let second_value = if params.order == 2 {
598 Some(reader.read_signed(bit_count)?)
599 } else {
600 None
601 };
602 for _ in usize::from(params.order.min(2))..params.order as usize {
603 let _ = reader.read_signed(bit_count)?;
604 }
605 let overall_minimum = reader.read_signed(bit_count)?;
606
607 Ok(SpatialDescriptors {
608 order: params.order,
609 first_value,
610 second_value,
611 overall_minimum,
612 })
613}
614
615fn decode_constant_group_value(
616 group_reference: u64,
617 group_reference_bits: usize,
618 missing_value_management: u8,
619) -> Result<Option<i64>> {
620 if is_missing_code(
621 group_reference,
622 group_reference_bits,
623 missing_value_management,
624 MissingKind::Primary,
625 )? || is_missing_code(
626 group_reference,
627 group_reference_bits,
628 missing_value_management,
629 MissingKind::Secondary,
630 )? {
631 return Ok(None);
632 }
633
634 let value = i64::try_from(group_reference)
635 .map_err(|_| Error::Other("group reference exceeds i64 range".into()))?;
636 Ok(Some(value))
637}
638
639fn decode_group_value(
640 group_reference: i64,
641 packed: u64,
642 group_width: usize,
643 missing_value_management: u8,
644) -> Result<Option<i64>> {
645 if is_missing_code(
646 packed,
647 group_width,
648 missing_value_management,
649 MissingKind::Primary,
650 )? || is_missing_code(
651 packed,
652 group_width,
653 missing_value_management,
654 MissingKind::Secondary,
655 )? {
656 return Ok(None);
657 }
658
659 let packed =
660 i64::try_from(packed).map_err(|_| Error::Other("packed value exceeds i64 range".into()))?;
661 let value = group_reference
662 .checked_add(packed)
663 .ok_or_else(|| Error::Other("decoded complex packing value overflow".into()))?;
664 Ok(Some(value))
665}
666
667fn is_missing_code(
668 value: u64,
669 bit_width: usize,
670 missing_value_management: u8,
671 kind: MissingKind,
672) -> Result<bool> {
673 let required_mode = match kind {
674 MissingKind::Primary => 1,
675 MissingKind::Secondary => 2,
676 };
677 if missing_value_management < required_mode {
678 return Ok(false);
679 }
680
681 let Some(code) = missing_code(bit_width, kind)? else {
682 return Ok(false);
683 };
684 Ok(value == code)
685}
686
687fn missing_code(bit_width: usize, kind: MissingKind) -> Result<Option<u64>> {
688 if bit_width == 0 {
689 return Ok(None);
690 }
691 if bit_width > u64::BITS as usize {
692 return Err(Error::UnsupportedPackingWidth(bit_width as u8));
693 }
694
695 let max_value = if bit_width == u64::BITS as usize {
696 u64::MAX
697 } else {
698 (1u64 << bit_width) - 1
699 };
700
701 let code = match kind {
702 MissingKind::Primary => max_value,
703 MissingKind::Secondary => max_value.saturating_sub(1),
704 };
705 Ok(Some(code))
706}
707
708fn scale_complex_value<T: DecodeSample>(
709 reference: f64,
710 binary_factor: f64,
711 decimal_factor: f64,
712 value: Option<i64>,
713) -> T {
714 match value {
715 Some(value) => T::from_f64(scale_decoded_value(
716 reference,
717 value as f64,
718 binary_factor,
719 decimal_factor,
720 )),
721 None => T::nan(),
722 }
723}
724
725fn scale_decoded_value(
726 reference: f64,
727 packed_delta: f64,
728 binary_factor: f64,
729 decimal_factor: f64,
730) -> f64 {
731 (reference + packed_delta * binary_factor) * decimal_factor
732}
733
734fn bitmap_bit(bitmap_payload: &[u8], index: usize) -> Result<bool> {
735 let byte_index = index / 8;
736 let bit_index = index % 8;
737 let byte = bitmap_payload
738 .get(byte_index)
739 .copied()
740 .ok_or(Error::DataLengthMismatch {
741 expected: byte_index + 1,
742 actual: bitmap_payload.len(),
743 })?;
744 Ok(((byte >> (7 - bit_index)) & 1) != 0)
745}
746
747struct GroupReaderLayout {
748 reference_offset: usize,
749 width_offset: usize,
750 length_offset: usize,
751 value_offset: usize,
752}
753
754impl GroupReaderLayout {
755 fn new(start_bit_offset: usize, params: &ComplexPackingParams) -> Result<Self> {
756 if params.group_reference_bits as usize > u64::BITS as usize {
757 return Err(Error::UnsupportedPackingWidth(params.group_reference_bits));
758 }
759 if params.group_width_bits as usize > u64::BITS as usize {
760 return Err(Error::UnsupportedPackingWidth(params.group_width_bits));
761 }
762 if params.scaled_group_length_bits as usize > u64::BITS as usize {
763 return Err(Error::UnsupportedPackingWidth(
764 params.scaled_group_length_bits,
765 ));
766 }
767
768 let reference_offset = start_bit_offset;
769 let width_offset = align_bit_offset(add_group_bits(
770 reference_offset,
771 params.num_groups,
772 params.group_reference_bits as usize,
773 )?)?;
774 let length_offset = align_bit_offset(add_group_bits(
775 width_offset,
776 params.num_groups,
777 params.group_width_bits as usize,
778 )?)?;
779 let value_offset = align_bit_offset(add_group_bits(
780 length_offset,
781 params.num_groups,
782 params.scaled_group_length_bits as usize,
783 )?)?;
784
785 Ok(Self {
786 reference_offset,
787 width_offset,
788 length_offset,
789 value_offset,
790 })
791 }
792}
793
794fn add_group_bits(start_bit_offset: usize, count: usize, bits_per_group: usize) -> Result<usize> {
795 count
796 .checked_mul(bits_per_group)
797 .and_then(|total_bits| start_bit_offset.checked_add(total_bits))
798 .ok_or_else(|| Error::Other("bit offset overflow".into()))
799}
800
801fn align_bit_offset(bit_offset: usize) -> Result<usize> {
802 let remainder = bit_offset % 8;
803 if remainder == 0 {
804 Ok(bit_offset)
805 } else {
806 bit_offset
807 .checked_add(8 - remainder)
808 .ok_or_else(|| Error::Other("bit offset overflow".into()))
809 }
810}
811
812struct OutputCursor<'a, T> {
813 output: &'a mut [T],
814 bitmap: Option<&'a [u8]>,
815 next_index: usize,
816 values_written: usize,
817}
818
819impl<'a, T: DecodeSample> OutputCursor<'a, T> {
820 fn new(output: &'a mut [T], bitmap: Option<&'a [u8]>) -> Self {
821 Self {
822 output,
823 bitmap,
824 next_index: 0,
825 values_written: 0,
826 }
827 }
828
829 fn push_present(&mut self, value: T) -> Result<()> {
830 match self.bitmap {
831 Some(bitmap) => {
832 while self.next_index < self.output.len() {
833 if bitmap_bit(bitmap, self.next_index)? {
834 self.output[self.next_index] = value;
835 self.next_index += 1;
836 self.values_written += 1;
837 return Ok(());
838 }
839
840 self.output[self.next_index] = T::nan();
841 self.next_index += 1;
842 }
843
844 let expected = count_bitmap_present_points(bitmap, self.output.len())?;
845 Err(Error::DataLengthMismatch {
846 expected,
847 actual: self.values_written + 1,
848 })
849 }
850 None => {
851 if self.next_index >= self.output.len() {
852 return Err(Error::DataLengthMismatch {
853 expected: self.output.len(),
854 actual: self.next_index + 1,
855 });
856 }
857
858 self.output[self.next_index] = value;
859 self.next_index += 1;
860 self.values_written += 1;
861 Ok(())
862 }
863 }
864 }
865
866 fn finish(mut self) -> Result<()> {
867 if let Some(bitmap) = self.bitmap {
868 while self.next_index < self.output.len() {
869 if bitmap_bit(bitmap, self.next_index)? {
870 return Err(Error::DataLengthMismatch {
871 expected: count_bitmap_present_points(bitmap, self.output.len())?,
872 actual: self.values_written,
873 });
874 }
875 self.output[self.next_index] = T::nan();
876 self.next_index += 1;
877 }
878 }
879
880 if self.next_index != self.output.len() {
881 return Err(Error::DataLengthMismatch {
882 expected: self.output.len(),
883 actual: self.next_index,
884 });
885 }
886
887 Ok(())
888 }
889 fn values_written(&self) -> usize {
890 self.values_written
891 }
892}
893
894struct BitReader<'a> {
895 data: &'a [u8],
896 bit_offset: usize,
897}
898
899impl<'a> BitReader<'a> {
900 fn new(data: &'a [u8]) -> Self {
901 Self {
902 data,
903 bit_offset: 0,
904 }
905 }
906
907 fn with_offset(data: &'a [u8], bit_offset: usize) -> Self {
908 Self { data, bit_offset }
909 }
910
911 fn read(&mut self, bit_count: usize) -> Result<u64> {
912 if bit_count == 0 {
913 return Ok(0);
914 }
915
916 let mut remaining = bit_count;
917 let mut value = 0u64;
918
919 while remaining > 0 {
920 let byte_index = self.bit_offset / 8;
921 let bit_index = self.bit_offset % 8;
922 let byte = *self.data.get(byte_index).ok_or(Error::Truncated {
923 offset: byte_index as u64,
924 })?;
925 let available = 8 - bit_index;
926 let take = remaining.min(available);
927 let mask = ((1u16 << take) - 1) as u8;
928 let shift = available - take;
929 let bits = (byte >> shift) & mask;
930
931 value = (value << take) | bits as u64;
932 self.bit_offset += take;
933 remaining -= take;
934 }
935
936 Ok(value)
937 }
938
939 fn read_signed(&mut self, bit_count: usize) -> Result<i64> {
940 let value = self.read(bit_count)?;
941 if bit_count == 0 {
942 return Ok(0);
943 }
944
945 let sign_mask = 1u64 << (bit_count - 1);
946 if value & sign_mask == 0 {
947 return i64::try_from(value)
948 .map_err(|_| Error::Other("signed value exceeds i64 range".into()));
949 }
950
951 let magnitude_mask = sign_mask - 1;
952 let magnitude = value & magnitude_mask;
953 let magnitude = i64::try_from(magnitude)
954 .map_err(|_| Error::Other("signed value exceeds i64 range".into()))?;
955 Ok(-magnitude)
956 }
957}
958
959#[derive(Debug, Clone)]
960struct SpatialDescriptors {
961 order: u8,
962 first_value: i64,
963 second_value: Option<i64>,
964 overall_minimum: i64,
965}
966
967#[derive(Debug, Clone)]
968struct SpatialRestoreState {
969 descriptors: SpatialDescriptors,
970 previous: Option<i64>,
971 previous_difference: Option<i64>,
972 non_missing_seen: usize,
973}
974
975impl SpatialRestoreState {
976 fn new(descriptors: SpatialDescriptors) -> Self {
977 Self {
978 descriptors,
979 previous: None,
980 previous_difference: None,
981 non_missing_seen: 0,
982 }
983 }
984
985 fn restore(&mut self, value: Option<i64>) -> Result<Option<i64>> {
986 let Some(value) = value else {
987 return Ok(None);
988 };
989
990 let restored = match self.descriptors.order {
991 1 => self.restore_first_order(value)?,
992 2 => self.restore_second_order(value)?,
993 other => return Err(Error::UnsupportedSpatialDifferencingOrder(other)),
994 };
995
996 self.previous = Some(restored);
997 self.non_missing_seen += 1;
998 Ok(Some(restored))
999 }
1000
1001 fn finish(self) -> Result<()> {
1002 let expected = match self.descriptors.order {
1003 1 => 1,
1004 2 => 2,
1005 other => return Err(Error::UnsupportedSpatialDifferencingOrder(other)),
1006 };
1007 if self.non_missing_seen < expected {
1008 return Err(Error::DataLengthMismatch {
1009 expected,
1010 actual: self.non_missing_seen,
1011 });
1012 }
1013 Ok(())
1014 }
1015
1016 fn restore_first_order(&mut self, value: i64) -> Result<i64> {
1017 if self.non_missing_seen == 0 {
1018 return Ok(self.descriptors.first_value);
1019 }
1020
1021 let delta = value
1022 .checked_add(self.descriptors.overall_minimum)
1023 .ok_or_else(|| Error::Other("spatial differencing overflow".into()))?;
1024 self.previous
1025 .and_then(|previous| previous.checked_add(delta))
1026 .ok_or_else(|| Error::Other("spatial differencing overflow".into()))
1027 }
1028
1029 fn restore_second_order(&mut self, value: i64) -> Result<i64> {
1030 match self.non_missing_seen {
1031 0 => Ok(self.descriptors.first_value),
1032 1 => {
1033 let second_value = self.descriptors.second_value.ok_or(Error::InvalidSection {
1034 section: 5,
1035 reason: "missing second-order spatial differencing descriptors".into(),
1036 })?;
1037 self.previous_difference = second_value.checked_sub(self.descriptors.first_value);
1038 self.previous_difference
1039 .ok_or_else(|| Error::Other("spatial differencing overflow".into()))?;
1040 Ok(second_value)
1041 }
1042 _ => {
1043 let second_difference = value
1044 .checked_add(self.descriptors.overall_minimum)
1045 .ok_or_else(|| Error::Other("spatial differencing overflow".into()))?;
1046 let difference = self
1047 .previous_difference
1048 .and_then(|previous_difference| {
1049 previous_difference.checked_add(second_difference)
1050 })
1051 .ok_or_else(|| Error::Other("spatial differencing overflow".into()))?;
1052 let next = self
1053 .previous
1054 .and_then(|previous| previous.checked_add(difference))
1055 .ok_or_else(|| Error::Other("spatial differencing overflow".into()))?;
1056 self.previous_difference = Some(difference);
1057 Ok(next)
1058 }
1059 }
1060 }
1061}
1062
1063#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1064enum MissingKind {
1065 Primary,
1066 Secondary,
1067}
1068
1069#[cfg(test)]
1070mod tests {
1071 use super::{
1072 bitmap_payload, count_bitmap_present_points, decode_field, unpack_complex, unpack_simple,
1073 ComplexPackingParams, DataRepresentation, SimplePackingParams, SpatialDifferencingParams,
1074 };
1075 use crate::error::Error;
1076
1077 #[test]
1078 fn unpack_simple_constant() {
1079 let params = SimplePackingParams {
1080 encoded_values: 5,
1081 reference_value: 42.0,
1082 binary_scale: 0,
1083 decimal_scale: 0,
1084 bits_per_value: 0,
1085 original_field_type: 0,
1086 };
1087 let values = unpack_simple(&[], ¶ms, 5).unwrap();
1088 assert_eq!(values, vec![42.0; 5]);
1089 }
1090
1091 #[test]
1092 fn unpack_simple_basic() {
1093 let params = SimplePackingParams {
1094 encoded_values: 5,
1095 reference_value: 0.0,
1096 binary_scale: 0,
1097 decimal_scale: 0,
1098 bits_per_value: 8,
1099 original_field_type: 0,
1100 };
1101 let values = unpack_simple(&[0, 1, 2, 3, 4], ¶ms, 5).unwrap();
1102 assert_eq!(values, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
1103 }
1104
1105 #[test]
1106 fn unpack_simple_applies_decimal_scale_to_reference_and_values() {
1107 let params = SimplePackingParams {
1108 encoded_values: 2,
1109 reference_value: 10.0,
1110 binary_scale: 0,
1111 decimal_scale: 1,
1112 bits_per_value: 8,
1113 original_field_type: 0,
1114 };
1115
1116 let values = unpack_simple(&[0, 20], ¶ms, 2).unwrap();
1117 assert!((values[0] - 1.0).abs() < 1e-12);
1118 assert!((values[1] - 3.0).abs() < 1e-12);
1119 }
1120
1121 #[test]
1122 fn decodes_bitmap_masked_field() {
1123 let data_section = [0, 0, 0, 8, 7, 10, 20, 30];
1124 let bitmap_section = [0, 0, 0, 7, 6, 0, 0b1011_0000];
1125 let representation = DataRepresentation::SimplePacking(SimplePackingParams {
1126 encoded_values: 3,
1127 reference_value: 0.0,
1128 binary_scale: 0,
1129 decimal_scale: 0,
1130 bits_per_value: 8,
1131 original_field_type: 0,
1132 });
1133
1134 let bitmap = bitmap_payload(&bitmap_section).unwrap();
1135 let decoded = decode_field(&data_section, &representation, bitmap, 4).unwrap();
1136 assert_eq!(decoded[0], 10.0);
1137 assert!(decoded[1].is_nan());
1138 assert_eq!(decoded[2], 20.0);
1139 assert_eq!(decoded[3], 30.0);
1140 }
1141
1142 #[test]
1143 fn rejects_simple_packing_wider_than_u64() {
1144 let params = SimplePackingParams {
1145 encoded_values: 1,
1146 reference_value: 0.0,
1147 binary_scale: 0,
1148 decimal_scale: 0,
1149 bits_per_value: 65,
1150 original_field_type: 0,
1151 };
1152 let err = unpack_simple(&[0; 9], ¶ms, 1).unwrap_err();
1153 assert!(matches!(err, Error::UnsupportedPackingWidth(65)));
1154 }
1155
1156 #[test]
1157 fn rejects_encoded_value_count_mismatch_without_bitmap() {
1158 let data_section = [0, 0, 0, 8, 7, 10, 20, 30];
1159 let representation = DataRepresentation::SimplePacking(SimplePackingParams {
1160 encoded_values: 3,
1161 reference_value: 0.0,
1162 binary_scale: 0,
1163 decimal_scale: 0,
1164 bits_per_value: 8,
1165 original_field_type: 0,
1166 });
1167
1168 let err = decode_field(&data_section, &representation, None, 4).unwrap_err();
1169 assert!(matches!(
1170 err,
1171 Error::DataLengthMismatch {
1172 expected: 4,
1173 actual: 3,
1174 }
1175 ));
1176 }
1177
1178 #[test]
1179 fn rejects_bitmap_present_count_mismatch() {
1180 let data_section = [0, 0, 0, 7, 7, 10, 20];
1181 let bitmap_section = [0, 0, 0, 7, 6, 0, 0b1011_0000];
1182 let representation = DataRepresentation::SimplePacking(SimplePackingParams {
1183 encoded_values: 2,
1184 reference_value: 0.0,
1185 binary_scale: 0,
1186 decimal_scale: 0,
1187 bits_per_value: 8,
1188 original_field_type: 0,
1189 });
1190
1191 let bitmap = bitmap_payload(&bitmap_section).unwrap();
1192 let err = decode_field(&data_section, &representation, bitmap, 4).unwrap_err();
1193 assert!(matches!(
1194 err,
1195 Error::DataLengthMismatch {
1196 expected: 3,
1197 actual: 2,
1198 }
1199 ));
1200 }
1201
1202 #[test]
1203 fn counts_bitmap_present_points_with_partial_bytes() {
1204 let present = count_bitmap_present_points(&[0b1011_1111], 3).unwrap();
1205 assert_eq!(present, 2);
1206 }
1207
1208 #[test]
1209 fn unpacks_complex_packing_with_explicit_missing() {
1210 let params = ComplexPackingParams {
1211 encoded_values: 4,
1212 reference_value: 0.0,
1213 binary_scale: 0,
1214 decimal_scale: 0,
1215 group_reference_bits: 4,
1216 original_field_type: 0,
1217 group_splitting_method: 1,
1218 missing_value_management: 1,
1219 primary_missing_substitute: u32::MAX,
1220 secondary_missing_substitute: u32::MAX,
1221 num_groups: 2,
1222 group_width_reference: 0,
1223 group_width_bits: 2,
1224 group_length_reference: 2,
1225 group_length_increment: 1,
1226 true_length_last_group: 2,
1227 scaled_group_length_bits: 0,
1228 spatial_differencing: None,
1229 };
1230
1231 let values = unpack_complex(&[0x79, 0x90, 0x34], ¶ms).unwrap();
1232 assert_eq!(values[0], 7.0);
1233 assert!(values[1].is_nan());
1234 assert_eq!(values[2], 9.0);
1235 assert!(values[3].is_nan());
1236 }
1237
1238 #[test]
1239 fn unpacks_complex_packing_applies_decimal_scale_to_reference_and_values() {
1240 let params = ComplexPackingParams {
1241 encoded_values: 2,
1242 reference_value: 10.0,
1243 binary_scale: 0,
1244 decimal_scale: 1,
1245 group_reference_bits: 4,
1246 original_field_type: 0,
1247 group_splitting_method: 1,
1248 missing_value_management: 0,
1249 primary_missing_substitute: u32::MAX,
1250 secondary_missing_substitute: u32::MAX,
1251 num_groups: 1,
1252 group_width_reference: 4,
1253 group_width_bits: 0,
1254 group_length_reference: 2,
1255 group_length_increment: 1,
1256 true_length_last_group: 2,
1257 scaled_group_length_bits: 0,
1258 spatial_differencing: None,
1259 };
1260
1261 let values = unpack_complex(&[0x10, 0x02], ¶ms).unwrap();
1262 assert!((values[0] - 1.1).abs() < 1e-12);
1263 assert!((values[1] - 1.3).abs() < 1e-12);
1264 }
1265
1266 #[test]
1267 fn unpacks_complex_packing_with_second_order_spatial_differencing() {
1268 let params = ComplexPackingParams {
1269 encoded_values: 4,
1270 reference_value: 0.0,
1271 binary_scale: 0,
1272 decimal_scale: 0,
1273 group_reference_bits: 1,
1274 original_field_type: 0,
1275 group_splitting_method: 1,
1276 missing_value_management: 0,
1277 primary_missing_substitute: u32::MAX,
1278 secondary_missing_substitute: u32::MAX,
1279 num_groups: 1,
1280 group_width_reference: 1,
1281 group_width_bits: 0,
1282 group_length_reference: 4,
1283 group_length_increment: 1,
1284 true_length_last_group: 4,
1285 scaled_group_length_bits: 0,
1286 spatial_differencing: Some(SpatialDifferencingParams {
1287 order: 2,
1288 descriptor_octets: 2,
1289 }),
1290 };
1291
1292 let values =
1293 unpack_complex(&[0x00, 0x0A, 0x00, 0x0D, 0x00, 0x03, 0x00, 0x10], ¶ms).unwrap();
1294 assert_eq!(values, vec![10.0, 13.0, 19.0, 29.0]);
1295 }
1296
1297 #[test]
1298 fn unpacks_complex_packing_with_spatial_differencing_and_missing_values() {
1299 let params = ComplexPackingParams {
1300 encoded_values: 4,
1301 reference_value: 0.0,
1302 binary_scale: 0,
1303 decimal_scale: 0,
1304 group_reference_bits: 1,
1305 original_field_type: 0,
1306 group_splitting_method: 1,
1307 missing_value_management: 1,
1308 primary_missing_substitute: u32::MAX,
1309 secondary_missing_substitute: u32::MAX,
1310 num_groups: 1,
1311 group_width_reference: 2,
1312 group_width_bits: 0,
1313 group_length_reference: 4,
1314 group_length_increment: 1,
1315 true_length_last_group: 4,
1316 scaled_group_length_bits: 0,
1317 spatial_differencing: Some(SpatialDifferencingParams {
1318 order: 1,
1319 descriptor_octets: 2,
1320 }),
1321 };
1322
1323 let values = unpack_complex(&[0x00, 0x0A, 0x00, 0x03, 0x00, 0x32], ¶ms).unwrap();
1324 assert_eq!(values[0], 10.0);
1325 assert!(values[1].is_nan());
1326 assert_eq!(values[2], 13.0);
1327 assert_eq!(values[3], 18.0);
1328 }
1329}