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}