rtcm_rs/
message_frame.rs

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