nexrad_data/volume/
header.rs

1use crate::result::Result;
2use crate::volume::util::get_datetime;
3use chrono::{DateTime, Duration, Utc};
4use std::fmt;
5use std::fmt::{Debug, Formatter};
6use std::io::Read;
7
8/// Header for an Archive II volume file containing metadata about the radar data. This header is
9/// located at the beginning of the file.
10#[repr(C)]
11#[derive(Clone, PartialEq, Eq, Hash)]
12#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
13pub struct Header {
14    /// The tape's filename which indicates the version of the data. Name is in the format
15    /// `AR2V0 0xx.` where `xx` indicates the version of the data.
16    ///
17    /// Versions:
18    ///   02 = Super Resolution disabled at the RDA (pre RDA Build 12.0)
19    ///   03 = Super Resolution (pre RDA Build 12.0)
20    ///   04 = Recombined Super Resolution
21    ///   05 = Super Resolution disabled at the RDA (RDA Build 12.0 and later)
22    ///   06 = Super Resolution (RDA Build 12.0 and later)
23    ///   07 = Recombined Super Resolution (RDA Build 12.0 and later)
24    /// NOTE: Dual-pol data introduced in RDA Build 12.0
25    tape_filename: [u8; 9],
26
27    /// Sequential number assigned to each volume of radar data in the queue, rolling over to 001
28    /// after 999.
29    extension_number: [u8; 3],
30
31    /// This volume's date represented as a count of days since 1 January 1970 00:00 GMT. It is
32    /// also referred-to as a "modified Julian date" where it is the Julian date - 2440586.5.
33    date: u32,
34
35    /// Milliseconds past midnight, GMT.
36    time: u32,
37
38    /// The ICAO identifier of the radar site.
39    icao_of_radar: [u8; 4],
40}
41
42impl Header {
43    /// Deserializes an Archive II header from the provided reader.
44    #[cfg(all(feature = "serde", feature = "bincode"))]
45    pub fn deserialize<R: Read>(reader: &mut R) -> Result<Self> {
46        use bincode::{DefaultOptions, Options};
47        Ok(DefaultOptions::new()
48            .with_fixint_encoding()
49            .with_big_endian()
50            .deserialize_from(reader.by_ref())?)
51    }
52
53    /// The tape's filename which indicates the version of the data. Name is in the format
54    /// `AR2V0 0xx.` where `xx` indicates the version of the data.
55    ///
56    /// Versions:
57    ///   02 = Super Resolution disabled at the RDA (pre RDA Build 12.0)
58    ///   03 = Super Resolution (pre RDA Build 12.0)
59    ///   04 = Recombined Super Resolution
60    ///   05 = Super Resolution disabled at the RDA (RDA Build 12.0 and later)
61    ///   06 = Super Resolution (RDA Build 12.0 and later)
62    ///   07 = Recombined Super Resolution (RDA Build 12.0 and later)
63    /// NOTE: Dual-pol data introduced in RDA Build 12.0
64    pub fn tape_filename(&self) -> Option<String> {
65        String::from_utf8(self.tape_filename.to_vec()).ok()
66    }
67
68    /// Sequential number assigned to each volume of radar data in the queue, rolling over to 001
69    /// after 999.
70    pub fn extension_number(&self) -> Option<String> {
71        String::from_utf8(self.extension_number.to_vec()).ok()
72    }
73
74    /// Returns the date and time of the volume.
75    pub fn date_time(&self) -> Option<DateTime<Utc>> {
76        get_datetime(self.date as u16, Duration::milliseconds(self.time as i64))
77    }
78
79    /// The ICAO identifier of the radar site.
80    pub fn icao_of_radar(&self) -> Option<String> {
81        String::from_utf8(self.icao_of_radar.to_vec()).ok()
82    }
83}
84
85impl Debug for Header {
86    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
87        f.debug_struct("Header")
88            .field("tape_filename", &self.tape_filename())
89            .field("extension_number", &self.extension_number())
90            .field("date_time", &self.date_time())
91            .field("icao_of_radar", &self.icao_of_radar())
92            .finish()
93    }
94}