nexrad_data/volume/
record.rs1use std::fmt::Debug;
2
3#[derive(Clone, PartialEq, Eq, Hash)]
4enum RecordData<'a> {
5 Borrowed(&'a [u8]),
6 Owned(Vec<u8>),
7}
8
9impl Debug for RecordData<'_> {
10 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11 match self {
12 RecordData::Borrowed(data) => write!(f, "RecordData::Borrowed({} bytes)", data.len()),
13 RecordData::Owned(data) => write!(f, "RecordData::Owned({} bytes)", data.len()),
14 }
15 }
16}
17
18#[derive(Clone, PartialEq, Eq, Hash)]
25pub struct Record<'a>(RecordData<'a>);
26
27impl<'a> Record<'a> {
28 pub fn new(data: Vec<u8>) -> Self {
30 Record(RecordData::Owned(data))
31 }
32
33 pub fn from_slice(data: &'a [u8]) -> Self {
35 Record(RecordData::Borrowed(data))
36 }
37
38 pub fn data(&self) -> &[u8] {
40 match &self.0 {
41 RecordData::Borrowed(data) => data,
42 RecordData::Owned(data) => data,
43 }
44 }
45
46 pub fn compressed(&self) -> bool {
48 self.data().len() >= 6 && self.data()[4..6].as_ref() == b"BZ"
49 }
50
51 #[cfg(feature = "bzip2")]
53 pub fn decompress<'b>(&self) -> crate::result::Result<Record<'b>> {
54 use crate::result::Error;
55 use bzip2::read::BzDecoder;
56 use std::io::Read;
57
58 if !self.compressed() {
59 return Err(Error::UncompressedDataError);
60 }
61
62 let data = self.data().split_at(4).1;
64
65 let mut decompressed_data = Vec::new();
66 BzDecoder::new(data).read_to_end(&mut decompressed_data)?;
67
68 Ok(Record::new(decompressed_data))
69 }
70
71 #[cfg(feature = "decode")]
73 pub fn messages(&self) -> crate::result::Result<Vec<nexrad_decode::messages::Message>> {
74 use crate::result::Error;
75 use nexrad_decode::messages::decode_messages;
76 use std::io::Cursor;
77
78 if self.compressed() {
79 return Err(Error::CompressedDataError);
80 }
81
82 let mut reader = Cursor::new(self.data());
83 Ok(decode_messages(&mut reader)?)
84 }
85}
86
87impl Debug for Record<'_> {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 let mut debug = f.debug_struct("Record");
90 debug.field("data.len()", &self.data().len());
91 debug.field(
92 "borrowed",
93 match &self.0 {
94 RecordData::Borrowed(_) => &true,
95 RecordData::Owned(_) => &false,
96 },
97 );
98 debug.field("compressed", &self.compressed());
99
100 #[cfg(feature = "decode")]
101 debug.field(
102 "messages.len()",
103 &self.messages().map(|messages| messages.len()),
104 );
105
106 debug.finish()
107 }
108}
109
110pub fn split_compressed_records(data: &[u8]) -> Vec<Record> {
113 let mut records = Vec::new();
114
115 let mut position = 0;
116 loop {
117 if position >= data.len() {
118 break;
119 }
120
121 let mut record_size = [0; 4];
122 record_size.copy_from_slice(&data[position..position + 4]);
123 let record_size = i32::from_be_bytes(record_size).unsigned_abs() as usize;
124
125 records.push(Record::from_slice(
126 &data[position..position + record_size + 4],
127 ));
128 position += record_size + 4;
129 }
130
131 records
132}