yanp/
parse.rs

1use crate::errors::NmeaSentenceError;
2use crate::parsers;
3use crate::sentences::{GeneralSentence, SentenceType};
4
5macro_rules! status {
6    ($($name:ident, $type:ty : [$($input:tt => $status:ident),+ error: $error:ident]),+) => {
7        #[derive(Debug, Clone, Copy, PartialEq)]
8        pub enum StatusParsingError {
9            $(
10                $error,
11            )+
12        }
13        $(
14            #[derive(Debug, Clone, Copy, PartialEq)]
15            pub enum $name {
16                $(
17                    $status,
18                )+
19            }
20
21            impl $name {
22                #[allow(unused)]
23                pub (crate) fn try_from<'a>(num: $type) -> Result<Self, NmeaSentenceError<'a>> {
24                    match num {
25                        $(
26                            $input => Ok($name::$status),
27                        )+
28                        _ => Err(NmeaSentenceError::StatusParsingError(StatusParsingError::$error)),
29                    }
30                }
31            }
32        )+
33    }
34}
35
36status! {
37    RmStatus, char: [
38        'A' => Active,
39        'V' => Warning,
40        'P' => Precise
41        error: RmStatusError
42    ],
43    LatitudeDirection, char: [
44        'N' => North,
45        'S' => South
46        error: LatitudeDirectionError
47    ],
48    LongitudeDirection, char: [
49        'E' => East,
50        'W' => West
51        error: LongitudeDirectionError
52    ],
53    GpsQuality, u8: [
54        0 => FixNotAvailable,
55        1 => Fix,
56        2 => DifferentialFix
57        error: GpsQualityError
58    ],
59    GllStatus, char: [
60        'A' => DataValid,
61        'V' => DataInvalid,
62        'P' => Precise
63        error: GllStatusError
64    ],
65    GsaMode, u8: [
66        1 => FixNotAvailable,
67        2 => Fix2D,
68        3 => Fix3D
69        error: GsaModeError
70    ],
71    GsaSelectionMode, char: [
72        'M' => Manual,
73        'A' => Automatic
74        error: GsaSelectionModeError
75    ],
76    SteerDirection, char: [
77        'L' => Left,
78        'R' => Right
79        error: SteerDirectionError
80    ],
81    ArrivalStatus, char: [
82        'A' => Arrived,
83        'V' => NotArrived
84        error: ArrivalStatusError
85    ],
86    RteMode, char: [
87        'c' => CompleteRoute,
88        'w' => WorkingRoute
89        error: RteModeError
90    ],
91    DataValidity, char: [
92        'A' => DataValid
93        error: DataValidityError
94    ],
95    GnsMode, char: [
96        'N' => NoFix,
97        'A' => AutonomousFix,
98        'D' => DifferentialFix,
99        'P' => Precise,
100        'R' => RealTime,
101        'F' => FloatRTK,
102        'E' => Estimated,
103        'M' => Manual,
104        'S' => Simulator
105        error: GnsModeError
106    ]
107}
108
109/// An enum storing consisting of all NMEA sentence types
110/// together with their corresponding data structs
111#[derive(Debug, Clone, PartialEq)]
112pub enum SentenceData<'a> {
113    AAM(AamData),
114    ABK(AbkData),
115    ACK(AckData),
116    ALM(AlmData),
117    APA(ApaData),
118    APB(ApbData),
119    BEC(BecData),
120    BOD(BodData<'a>),
121    BWC(BwcData<'a>),
122    BWR(BwrData),
123    BWW(BwwData),
124    DBK(DbkData),
125    DBS(DbsData),
126    DBT(DbtData),
127    DCN(DcnData),
128    DPT(DptData),
129    DTM(DtmData),
130    FSI(FsiData),
131    GBS(GbsData),
132    GGA(GgaData),
133    GLC(GlcData),
134    GLL(GllData),
135    GNS(GnsData),
136    GRS(GrsData),
137    GST(GstData),
138    GSA(GsaData),
139    GSV(GsvData),
140    GTD(GtdData),
141    GXA(GxaData),
142    HDG(HdgData),
143    HDM(HdmData),
144    HDT(HdtData),
145    HSC(HscData),
146    LCD(LcdData),
147    MSK(MskData),
148    MTW(MtwData),
149    MWV(MwvData),
150    OLN(OlnData),
151    OSD(OsdData),
152    ROO(RooData),
153    RMA(RmaData),
154    RMB(RmbData<'a>),
155    RMC(RmcData),
156    ROT(RotData),
157    RPM(RpmData),
158    RSA(RsaData),
159    RSD(RsdData),
160    RTE(RteData),
161    SFI(SfiData),
162    STN(StnData),
163    TLL(TllData),
164    TTM(TtmData),
165    VBW(VbwData),
166    VDR(VdrData),
167    VHW(VhwData),
168    VLW(VlwData),
169    VPW(VpwData),
170    VTG(VtgData),
171    VWR(VwrData),
172    WCV(WcvData),
173    WNC(WncData),
174    WPL(WplData<'a>),
175    XDR(XdrData),
176    XTE(XteData),
177    XTR(XtrData),
178    ZDA(ZdaData),
179    ZFO(ZfoData),
180    ZTG(ZtgData),
181}
182
183#[derive(Debug, Clone, Copy, PartialEq)]
184/// Represents a UTC timestamp
185pub struct GpsTime {
186    pub hour: u8,
187    pub minute: u8,
188    pub second: f32,
189}
190
191#[derive(Debug, Clone, Copy, PartialEq)]
192/// Represents a geographical position
193pub struct GpsPosition {
194    pub lat: f32,
195    pub lat_dir: LatitudeDirection,
196    pub lon: f32,
197    pub lon_dir: LongitudeDirection,
198}
199
200#[derive(Debug, Clone, Copy, PartialEq)]
201/// Represents the current date
202pub struct GpsDate {
203    pub day: u8,
204    pub month: u8,
205    pub year: u64,
206}
207
208#[derive(Debug, Clone, Copy, PartialEq)]
209/// Represents a GSV satellite
210pub struct GsvSatellite {
211    pub sat_id: Option<u8>,
212    pub elevation: Option<f32>,
213    pub true_azimuth: Option<f32>,
214    pub snr: Option<u8>,
215}
216
217#[derive(Debug, Clone, Copy, PartialEq)]
218pub struct AamData {}
219#[derive(Debug, Clone, Copy, PartialEq)]
220pub struct AbkData {}
221#[derive(Debug, Clone, Copy, PartialEq)]
222pub struct AckData {}
223#[derive(Debug, Clone, Copy, PartialEq)]
224pub struct AlmData {}
225#[derive(Debug, Clone, Copy, PartialEq)]
226pub struct ApaData {}
227#[derive(Debug, Clone, Copy, PartialEq)]
228pub struct ApbData {}
229#[derive(Debug, Clone, Copy, PartialEq)]
230pub struct BecData {}
231#[derive(Debug, Clone, Copy, PartialEq)]
232pub struct BodData<'a> {
233    pub bearing_true: Option<f32>,
234    pub bearing_magnetic: Option<f32>,
235    pub to_waypoint: Option<&'a [u8]>,
236    pub from_waypoint: Option<&'a [u8]>,
237}
238#[derive(Debug, Clone, Copy, PartialEq)]
239pub struct BwcData<'a> {
240    pub time: Option<GpsTime>,
241    pub waypoint_position: GpsPosition,
242    pub bearing_true: Option<f32>,
243    pub bearing_magnetic: Option<f32>,
244    pub nautical_miles: Option<f32>,
245    pub waypoint: Option<&'a [u8]>,
246}
247#[derive(Debug, Clone, Copy, PartialEq)]
248pub struct BwrData {}
249#[derive(Debug, Clone, Copy, PartialEq)]
250pub struct BwwData {}
251#[derive(Debug, Clone, Copy, PartialEq)]
252pub struct DbkData {}
253#[derive(Debug, Clone, Copy, PartialEq)]
254pub struct DbsData {}
255#[derive(Debug, Clone, Copy, PartialEq)]
256pub struct DbtData {}
257#[derive(Debug, Clone, Copy, PartialEq)]
258pub struct DcnData {}
259#[derive(Debug, Clone, Copy, PartialEq)]
260pub struct DptData {}
261#[derive(Debug, Clone, Copy, PartialEq)]
262pub struct DtmData {}
263#[derive(Debug, Clone, Copy, PartialEq)]
264pub struct FsiData {}
265#[derive(Debug, Clone, Copy, PartialEq)]
266pub struct GbsData {
267    pub time: Option<GpsTime>,
268    pub lat_error: Option<f32>,
269    pub lon_error: Option<f32>,
270    pub alt_error: Option<f32>,
271    pub most_likely_failed_sat: Option<u8>,
272    pub missed_probability: Option<f32>,
273    pub bias_estimate: Option<f32>,
274    pub bias_standard_deviation: Option<f32>,
275}
276#[derive(Debug, Clone, Copy, PartialEq)]
277pub struct GgaData {
278    pub time: Option<GpsTime>,
279    pub position: GpsPosition,
280    pub quality: Option<GpsQuality>,
281    pub sats_in_view: Option<u8>,
282    pub hdop: Option<f32>,
283    pub altitude: Option<f32>,
284    pub geoid_altitude: Option<f32>,
285    pub age_of_differential: Option<f32>,
286    pub differential_station_id: Option<u16>,
287}
288#[derive(Debug, Clone, Copy, PartialEq)]
289pub struct GlcData {}
290#[derive(Debug, Clone, Copy, PartialEq)]
291pub struct GllData {
292    pub position: GpsPosition,
293    pub time: Option<GpsTime>,
294    pub status: Option<GllStatus>,
295}
296#[cfg(feature = "alloc")]
297#[derive(Debug, Clone, PartialEq)]
298pub struct GnsData {
299    pub time: Option<GpsTime>,
300    pub position: GpsPosition,
301    pub mode: Option<alloc::vec::Vec<GnsMode>>,
302    pub sats_in_use: Option<u8>,
303    pub hdop: Option<f32>,
304    pub orthometric_height: Option<f32>,
305    pub geoid_seperation: Option<f32>,
306    pub age_of_differential: Option<f32>,
307    pub differential_station_id: Option<u16>,
308}
309
310#[cfg(not(feature = "alloc"))]
311#[derive(Debug, Clone, Copy, PartialEq)]
312pub struct GnsData {}
313
314#[derive(Debug, Clone, Copy, PartialEq)]
315pub struct GrsData {}
316#[derive(Debug, Clone, Copy, PartialEq)]
317pub struct GstData {}
318#[derive(Debug, Clone, Copy, PartialEq)]
319pub struct GsaData {
320    pub selection_mode: Option<GsaSelectionMode>,
321    pub mode: Option<GsaMode>,
322    pub satellites: [Option<u8>; 12],
323    pub pdob: Option<f32>,
324    pub hdop: Option<f32>,
325    pub vdop: Option<f32>,
326}
327#[derive(Debug, Clone, Copy, PartialEq)]
328pub struct GtdData {}
329#[derive(Debug, Clone, Copy, PartialEq)]
330pub struct GsvData {
331    pub number_of_sentences: Option<u16>,
332    pub sentence_num: Option<u16>,
333    pub sats_in_view: Option<u8>,
334    pub sats_info: [Option<GsvSatellite>; 4],
335}
336#[derive(Debug, Clone, Copy, PartialEq)]
337pub struct GxaData {}
338#[derive(Debug, Clone, Copy, PartialEq)]
339pub struct HdgData {}
340#[derive(Debug, Clone, Copy, PartialEq)]
341pub struct HdmData {}
342#[derive(Debug, Clone, Copy, PartialEq)]
343pub struct HdtData {
344    pub heading_true: Option<f32>,
345}
346#[derive(Debug, Clone, Copy, PartialEq)]
347pub struct HscData {}
348#[derive(Debug, Clone, Copy, PartialEq)]
349pub struct LcdData {}
350#[derive(Debug, Clone, Copy, PartialEq)]
351pub struct MskData {}
352#[derive(Debug, Clone, Copy, PartialEq)]
353pub struct MtwData {}
354#[derive(Debug, Clone, Copy, PartialEq)]
355pub struct MwvData {}
356#[derive(Debug, Clone, Copy, PartialEq)]
357pub struct OlnData {}
358#[derive(Debug, Clone, Copy, PartialEq)]
359pub struct OsdData {}
360#[derive(Debug, Clone, Copy, PartialEq)]
361pub struct RooData {}
362#[derive(Debug, Clone, Copy, PartialEq)]
363pub struct RmaData {
364    pub status: Option<RmStatus>,
365    pub position: GpsPosition,
366    pub time_diff_a: Option<f32>,
367    pub time_diff_b: Option<f32>,
368    pub speed: Option<f32>,
369    pub heading: Option<f32>,
370    pub magnetic_variation: Option<f32>,
371    pub magnetic_direction: Option<LongitudeDirection>,
372}
373#[derive(Debug, Clone, Copy, PartialEq)]
374pub struct RmbData<'a> {
375    pub status: Option<RmStatus>,
376    pub cross_error: Option<f32>,
377    pub steer_direction: Option<SteerDirection>,
378    pub to_waypoint: Option<&'a [u8]>,
379    pub from_waypoint: Option<&'a [u8]>,
380    pub dest_position: GpsPosition,
381    pub range_to_dest: Option<f32>,
382    pub bearing: Option<f32>,
383    pub closing_velocity: Option<f32>,
384    pub arrival_status: Option<ArrivalStatus>,
385}
386#[derive(Debug, Clone, Copy, PartialEq)]
387pub struct RmcData {
388    pub time: Option<GpsTime>,
389    pub status: Option<RmStatus>,
390    pub position: GpsPosition,
391    pub speed: Option<f32>,
392    pub heading: Option<f32>,
393    pub date: Option<GpsDate>,
394    pub magnetic_variation: Option<f32>,
395    pub magnetic_direction: Option<LongitudeDirection>,
396}
397
398#[derive(Debug, Clone, Copy, PartialEq)]
399pub struct RotData {}
400#[derive(Debug, Clone, Copy, PartialEq)]
401pub struct RpmData {}
402#[derive(Debug, Clone, Copy, PartialEq)]
403pub struct RsaData {}
404#[derive(Debug, Clone, Copy, PartialEq)]
405pub struct RsdData {}
406#[derive(Debug, Clone, Copy, PartialEq)]
407pub struct RteData {}
408#[derive(Debug, Clone, Copy, PartialEq)]
409pub struct SfiData {}
410#[derive(Debug, Clone, Copy, PartialEq)]
411pub struct StnData {
412    pub talker_id: u8,
413}
414#[derive(Debug, Clone, Copy, PartialEq)]
415pub struct TllData {}
416#[derive(Debug, Clone, Copy, PartialEq)]
417pub struct TtmData {}
418#[derive(Debug, Clone, Copy, PartialEq)]
419pub struct VbwData {
420    pub lon_water_speed: Option<f32>,
421    pub transverse_water_speed: Option<f32>,
422    pub water_validity: Option<DataValidity>,
423    pub lon_ground_speed: Option<f32>,
424    pub transverse_ground_speed: Option<f32>,
425    pub ground_validity: Option<DataValidity>,
426}
427#[derive(Debug, Clone, Copy, PartialEq)]
428pub struct VdrData {}
429#[derive(Debug, Clone, Copy, PartialEq)]
430pub struct VhwData {}
431#[derive(Debug, Clone, Copy, PartialEq)]
432pub struct VlwData {}
433#[derive(Debug, Clone, Copy, PartialEq)]
434pub struct VpwData {}
435#[derive(Debug, Clone, Copy, PartialEq)]
436pub struct VtgData {
437    pub bearing_true: Option<f32>,
438    pub bearing_magnetic: Option<f32>,
439    pub speed_knots: Option<f32>,
440    pub speed_kmh: Option<f32>,
441}
442#[derive(Debug, Clone, Copy, PartialEq)]
443pub struct VwrData {}
444#[derive(Debug, Clone, Copy, PartialEq)]
445pub struct WcvData {}
446#[derive(Debug, Clone, Copy, PartialEq)]
447pub struct WncData {}
448#[derive(Debug, Clone, Copy, PartialEq)]
449pub struct WplData<'a> {
450    pub position: Option<GpsPosition>,
451    pub waypoint_name: Option<&'a [u8]>,
452}
453#[derive(Debug, Clone, Copy, PartialEq)]
454pub struct XdrData {}
455#[derive(Debug, Clone, Copy, PartialEq)]
456pub struct XteData {}
457#[derive(Debug, Clone, Copy, PartialEq)]
458pub struct XtrData {}
459#[derive(Debug, Clone, Copy, PartialEq)]
460pub struct ZdaData {}
461#[derive(Debug, Clone, Copy, PartialEq)]
462pub struct ZfoData {}
463#[derive(Debug, Clone, Copy, PartialEq)]
464pub struct ZtgData {}
465
466macro_rules! sentence_parse_generator {
467    ($sentence:ident : [$($TYPE:ident => $function:path,)+]) => {
468        match $sentence.sentence_type {
469            $(
470                SentenceType::$TYPE => Ok(SentenceData::$TYPE(parse_result_to_data($function($sentence.data))?)),
471            )+
472            _ => Err(NmeaSentenceError::TypeNotImplementedError($sentence.sentence_type)),
473        }
474    }
475}
476
477fn parse_result_to_data<'a, Data>(
478    parse_result: Result<(&'a [u8], Data), nom::Err<(&'a [u8], nom::error::ErrorKind)>>,
479) -> Result<Data, NmeaSentenceError<'a>> {
480    match parse_result {
481        Ok(value) => Ok(value.1),
482        Err(val) => Err(NmeaSentenceError::DataParsingError(val)),
483    }
484}
485
486pub(crate) fn parse_sentence_data<'a>(
487    general_sentence: GeneralSentence<'a>,
488) -> Result<SentenceData, NmeaSentenceError<'a>> {
489    sentence_parse_generator!(
490        general_sentence: [
491            //AAM => parse_aam,
492            //ABK => parse_abk,
493            //ACK => parse_ack,
494            //ALM => parse_alm,
495            //APA => parse_apa,
496            //APB => parse_apb,
497            //BEC => parse_bec,
498            BOD => parsers::bod::parse_bod,
499            BWC => parsers::bwc::parse_bwc,
500            //BWR => parse_bwr,
501            //BWW => parse_bww,
502            //DBK => parse_dbk,
503            //DBS => parse_dbs,
504            //DBT => parse_dbt,
505            //DCN => parse_dcn,
506            //DPT => parse_dpt,
507            //DTM => parse_dtm,
508            //FSI => parse_fsi,
509            GBS => parsers::gbs::parse_gbs,
510            GGA => parsers::gga::parse_gga,
511            //GLC => parse_glc,
512            GLL => parsers::gll::parse_gll,
513            GNS => parsers::gns::parse_gns,
514            //GRS => parse_grs,
515            //GST => parse_gst,
516            GSA => parsers::gsa::parse_gsa,
517            GSV => parsers::gsv::parse_gsv,
518            //GTD => parse_gtd,
519            //GXA => parse_gxa,
520            //HDG => parse_hdg,
521            //HDM => parse_hdm,
522            HDT => parsers::hdt::parse_hdt,
523            //HSC => parse_hsc,
524            //LCD => parse_lcd,
525            //MSK => parse_msk,
526            //MTW => parse_mtw,
527            //MWV => parse_mwv,
528            //OLN => parse_oln,
529            //OSD => parse_osd,
530            //ROO => parse_roo,
531            RMA => parsers::rma::parse_rma,
532            RMB => parsers::rmb::parse_rmb,
533            RMC => parsers::rmc::parse_rmc,
534            //ROT => parse_rot,
535            //RPM => parse_rpm,
536            //RSA => parse_rsa,
537            //RSD => parse_rsd,
538            //RTE => parse_rte,
539            //SFI => parse_sfi,
540            STN => parsers::stn::parse_stn,
541            //TLL => parse_tll,
542            //TTM => parse_ttm,
543            VBW => parsers::vbw::parse_vbw,
544            //VDR => parse_vdr,
545            //VHW => parse_vhw,
546            //VLW => parse_vlw,
547            //VPW => parse_vpw,
548            VTG => parsers::vtg::parse_vtg,
549            //VWR => parse_vwr,
550            //WCV => parse_wcv,
551            //WNC => parse_wnc,
552            WPL => parsers::wpl::parse_wpl,
553            //XDR => parse_xdr,
554            //XTE => parse_xte,
555            //XTR => parse_xtr,
556            //ZDA => parse_zda,
557            //ZFO => parse_zfo,
558            //ZTG => parse_ztg,
559        ]
560    )
561}