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)
    }
}