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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//! RTCM 3 differential-GNSS stream decoding and encoding.
//!
//! RTCM 10403.x ("RTCM Standard for Differential GNSS Services, Version 3") is
//! the dominant wire format for real-time GNSS correction and observation
//! streams: base-station observations, reference coordinates, antenna metadata,
//! and broadcast ephemerides flow from a caster to a rover as a sequence of
//! framed binary messages. This module is a sans-I/O codec for that stream,
//! built to the same shape as the crate's RINEX / SP3 / IONEX parsers:
//!
//! 1. a forgiving byte-level frame layer ([`framing`]) that syncs on the `0xD3`
//! preamble, reads the 10-bit length, and verifies the 24-bit CRC-24Q;
//! 2. a format-agnostic canonical IR ([`Message`] and its typed variants) that
//! stores each field as its raw transmitted integer; and
//! 3. an encoder that turns the IR back into bytes, so a decode followed by an
//! encode round-trips byte-for-byte.
//!
//! ## Message coverage
//!
//! Decoded and encoded:
//!
//! | Message | Numbers | IR type |
//! |--------------------|------------------------------------------|---------|
//! | MSM4 observations | 1074 / 1084 / 1094 / 1104 / 1114 / 1124 / 1134 | [`MsmMessage`] |
//! | MSM7 observations | 1077 / 1087 / 1097 / 1107 / 1117 / 1127 / 1137 | [`MsmMessage`] |
//! | Station coordinates| 1005 / 1006 | [`StationCoordinates`] |
//! | Antenna / receiver | 1007 / 1008 / 1033 | [`AntennaDescriptor`] |
//! | GPS ephemeris | 1019 | [`GpsEphemeris`] |
//! | GLONASS ephemeris | 1020 | [`GlonassEphemeris`] |
//!
//! Any other message number is preserved losslessly as [`Message::Unsupported`]
//! (its raw body is kept so the frame still round-trips). Deferred message types
//! include the other MSM variants (MSM1/2/3/5/6), the legacy L1/L1-L2
//! observation messages (1001-1004, 1009-1012), the network-RTK and SSR
//! correction families, and the Galileo / BeiDou / QZSS ephemerides
//! (1042-1046). They decode as `Unsupported` rather than erroring.
//!
//! ## Quick start
//!
//! ```
//! use sidereon_core::rtcm::{self, Message, StationCoordinates};
//!
//! // Build a 1006 reference-coordinate message and frame it.
//! let station = StationCoordinates {
//! message_number: 1006,
//! reference_station_id: 2003,
//! itrf_realization_year: 0,
//! gps_indicator: true,
//! glonass_indicator: true,
//! galileo_indicator: false,
//! reference_station_indicator: false,
//! ecef_x: 11_446_021_400,
//! single_receiver_oscillator: false,
//! reserved: false,
//! ecef_y: -7_415_136_500,
//! quarter_cycle_indicator: 0,
//! ecef_z: 12_602_528_900,
//! antenna_height: Some(15_000),
//! };
//! // A constructed message encodes either directly on the typed value or
//! // through the [`Message`] wrapper; both produce the same body bytes.
//! let body = station.encode();
//! assert_eq!(body, Message::StationCoordinates(station).encode());
//! let frame = rtcm::encode_frame(&body).unwrap();
//!
//! // Decode it back out of the framed stream.
//! let decoded = rtcm::decode_messages(&frame);
//! assert_eq!(decoded.len(), 1);
//! match &decoded[0] {
//! Message::StationCoordinates(s) => assert_eq!(s.reference_station_id, 2003),
//! _ => panic!("expected station coordinates"),
//! }
//! ```
use crateResult;
use BitReader;
pub use AntennaDescriptor;
pub use ;
pub use ;
pub use ;
pub use StationCoordinates;
/// A message whose number is recognized but whose body this codec does not
/// decode. The raw body is preserved so the frame still round-trips.
/// The canonical, format-agnostic RTCM 3 message IR.
///
/// Each variant stores raw transmitted field integers (see the per-type docs),
/// and [`Message::encode`] is the exact inverse of [`Message::decode`].
///
/// The variant set is the codec's full supported coverage; any other message
/// number decodes to [`Message::Unsupported`], so the enum is exhaustive and a
/// caller can both build any variant from scratch and match every case.
/// Read the 12-bit RTCM message number from the start of a message body.
///
/// Returns [`Error::Parse`] if the body is shorter than 12 bits.
/// Decode every CRC-valid frame in a byte buffer into the message IR.
///
/// Frames whose CRC fails, or whose body cannot be decoded, are skipped; the
/// scan resynchronizes on the next preamble. This is the forgiving stream entry
/// point for a noisy serial feed.