nexrad_data/volume/
file.rs

1use crate::result::Result;
2use crate::volume::{split_compressed_records, Header, Record};
3use std::fmt::Debug;
4
5/// A NEXRAD Archive II volume data file.
6#[derive(Clone, PartialEq, Eq, Hash)]
7pub struct File(Vec<u8>);
8
9impl File {
10    /// Creates a new Archive II volume file with the provided data.
11    pub fn new(data: Vec<u8>) -> Self {
12        Self(data)
13    }
14
15    /// The file's encoded and compressed data.
16    pub fn data(&self) -> &Vec<u8> {
17        &self.0
18    }
19
20    /// The file's decoded Archive II volume header.
21    #[cfg(all(feature = "serde", feature = "bincode"))]
22    pub fn header(&self) -> Result<Header> {
23        Header::deserialize(&mut self.0.as_slice())
24    }
25
26    /// The file's LDM records.
27    pub fn records(&self) -> Vec<Record> {
28        split_compressed_records(&self.0[size_of::<Header>()..])
29    }
30
31    /// Decodes this volume file into a common model scan containing sweeps and radials with moment
32    /// data.
33    #[cfg(all(feature = "nexrad-model", feature = "decode"))]
34    pub fn scan(&self) -> Result<nexrad_model::data::Scan> {
35        use crate::result::Error;
36        use nexrad_decode::messages::MessageContents;
37        use nexrad_model::data::{Scan, Sweep};
38
39        let mut coverage_pattern_number = None;
40        let mut radials = Vec::new();
41        for mut record in self.records() {
42            if record.compressed() {
43                record = record.decompress()?;
44            }
45
46            let messages = record.messages()?;
47            for message in messages {
48                let contents = message.into_contents();
49                if let MessageContents::DigitalRadarData(radar_data_message) = contents {
50                    if coverage_pattern_number.is_none() {
51                        if let Some(volume_block) = &radar_data_message.volume_data_block {
52                            coverage_pattern_number =
53                                Some(volume_block.volume_coverage_pattern_number);
54                        }
55                    }
56
57                    radials.push(radar_data_message.into_radial()?);
58                }
59            }
60        }
61
62        Ok(Scan::new(
63            coverage_pattern_number.ok_or(Error::MissingCoveragePattern)?,
64            Sweep::from_radials(radials),
65        ))
66    }
67}
68
69impl Debug for File {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        let mut debug = f.debug_struct("File");
72        debug.field("data.len()", &self.data().len());
73
74        #[cfg(all(feature = "serde", feature = "bincode"))]
75        debug.field("header", &self.header());
76
77        #[cfg(all(feature = "nexrad-model", feature = "decode"))]
78        debug.field("records.len()", &self.records().len());
79
80        debug.finish()
81    }
82}