enum RecordData<'a> {
Borrowed(&'a [u8]),
Owned(Vec<u8>),
}
pub struct Record<'a>(RecordData<'a>);
impl<'a> Record<'a> {
pub fn new(data: Vec<u8>) -> Self {
Record(RecordData::Owned(data))
}
pub fn from_slice(data: &'a [u8]) -> Self {
Record(RecordData::Borrowed(data))
}
pub fn data(&self) -> &[u8] {
match &self.0 {
RecordData::Borrowed(data) => data,
RecordData::Owned(data) => data,
}
}
pub fn compressed(&self) -> bool {
self.data().len() >= 6 && self.data()[4..6].as_ref() == b"BZ"
}
#[cfg(feature = "bzip2")]
pub fn decompress<'b>(&self) -> crate::result::Result<Record<'b>> {
use crate::result::Error;
use bzip2::read::BzDecoder;
use std::io::Read;
if !self.compressed() {
return Err(Error::UncompressedDataError);
}
let data = self.data().split_at(4).1;
let mut decompressed_data = Vec::new();
BzDecoder::new(data).read_to_end(&mut decompressed_data)?;
Ok(Record::new(decompressed_data))
}
#[cfg(feature = "decode")]
pub fn messages(
&self,
) -> crate::result::Result<Vec<nexrad_decode::messages::MessageWithHeader>> {
use crate::result::Error;
use nexrad_decode::messages::decode_messages;
use std::io::Cursor;
if self.compressed() {
return Err(Error::CompressedDataError);
}
let mut reader = Cursor::new(self.data());
Ok(decode_messages(&mut reader)?)
}
}
pub fn split_compressed_records(data: &[u8]) -> Vec<Record> {
let mut records = Vec::new();
let mut position = 0;
loop {
if position >= data.len() {
break;
}
let mut record_size = [0; 4];
record_size.copy_from_slice(&data[position..position + 4]);
let record_size = i32::from_be_bytes(record_size).unsigned_abs() as usize;
records.push(Record::from_slice(
&data[position..position + record_size + 4],
));
position += record_size + 4;
}
records
}