1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
use crate::crc_any::CRC;
use crate::msg::message::Message;
use crate::rtcm_error::RtcmError;
/// Represents the message frame of a RTCM 3.x message.
///
/// Holds a reference to the frame data as a slice for valid RTCM message frames,
/// and provides various methods for access to data segment, message number, and CRC24
pub struct MessageFrame<'a> {
frame_data: &'a [u8],
data: &'a [u8],
crc: u32,
message_number: Option<u16>,
}
impl<'a> MessageFrame<'a> {
/// Creates a new `MessageFrame` from the given frame data.
///
/// Parameters:
/// - `frame_data` - A slice of bytes representing the frame data.
///
/// Errors:
/// - `RtcmError::Incomplete` - The given frame data is incomplete.
/// - `RtcmError::NotValid` - The given frame data is not valid.
///
/// Returns:
/// A `MessageFrame` if the given data represents a valid RTCM message frame.
pub fn new(frame_data: &'a [u8]) -> Result<Self, RtcmError> {
if frame_data.len() < 6 {
return Err(RtcmError::Incomplete);
}
if frame_data[0] != 0xd3 {
return Err(RtcmError::NotValid);
}
let length: usize = ((frame_data[1] as usize & 0b11) << 8) | (frame_data[2] as usize);
if frame_data.len() < length + 6 {
return Err(RtcmError::Incomplete);
}
let mut crc24 = CRC::crc24lte_a();
crc24.digest(&frame_data[0..length + 3]);
let msg_crc = ((frame_data[length + 3] as u32) << 16)
| ((frame_data[length + 4] as u32) << 8)
| (frame_data[length + 5] as u32);
if msg_crc != crc24.get_crc() as u32 {
return Err(RtcmError::NotValid);
}
let message_number: Option<u16> = if frame_data.len() >= 8 {
Some(((frame_data[3] as u16) << 4) | ((frame_data[4] as u16) >> 4))
} else {
None
};
Ok(MessageFrame {
frame_data: &frame_data[..length + 6],
data: &frame_data[3..length + 3],
crc: msg_crc,
message_number,
})
}
/// Returns the data segment bytes of the RTCM frame as a slice
pub fn data(&'a self) -> &'a [u8] {
&*self.data
}
/// Returns the bytes of the whole RTCM frame as a slice
pub fn frame_data(&'a self) -> &'a [u8] {
&*self.frame_data
}
/// Returns the data segment byte length
pub fn data_len(&self) -> usize {
self.data.len()
}
/// Returns the RTCM message frame byte length
pub fn frame_len(&self) -> usize {
self.frame_data.len()
}
/// Returns the RTCM message frame CRC24 checksum
pub fn crc(&self) -> u32 {
self.crc
}
/// Returns the RTCM message number if the frame contains data. Otherwise returns None.
pub fn message_number(&self) -> Option<u16> {
self.message_number
}
/// Decodes the content of the RTCM message frame and returns the result as a `Message` enum.
pub fn get_message(&self) -> Message {
Message::from_message_frame(self)
}
}