# nmeasis
nmeasis is safe, zero-copy, `no_std` compatible NMEA0183 protocol parser written in Rust meant for use in embedded and constrainted contexts. It also comes with a C FFI, allowing you to integrate with projects in other languages.
## Features
- Written entirely in `#![deny(unsafe_code)]` `no_std` Rust.
- Fully complete C FFI, allowing for use in C (with a provided example).
- No memory allocations at all.
- `NmeaNumber` perserves the precision of provided, eliding floating point error.
- Access to raw sentence fields alongside parsed fields.
- Parser is fuzzed on input, hardening against runtime panics.
## Example
### Rust
```rust
use nmeasis::parser::NmeaParser;
fn main() {
let mut parser = NmeaParser::<256>::default();
let input = b"$GPGGA,092750.000,5321.6802,N,00630.3372,W,1,8,1.03,61.7,M,55.2,M,,*76\r\n";
let buf = parser.buffer();
let n = input.len().min(buf.len());
buf[..n].copy_from_slice(&input[..n]);
parser.commit(n, |result| match result {
Ok(sentence) => println!("{sentence:?}"),
Err(e) => eprintln!("error: {e}"),
});
}
```
### C
```c
#include <stdio.h>
#include <stdlib.h>
#include "nmeasis.h"
static void on_sentence(const Sentence *sentence, void *userdata) {
(void)userdata;
if (nmea_sentence_message_kind(sentence) != MESSAGE_TYPE_GGA) return;
const Gga *gga = nmea_sentence_gga(sentence);
if (!gga || !nmea_gga_has_fix(gga)) return;
NmeaCoordinates coords;
NmeaNumber altitude;
if (!nmea_gga_coordinates(gga, &coords)) return;
if (!nmea_gga_altitude(gga, &altitude)) return;
printf("lat=%.6f lon=%.6f alt=%.1fm\n",
coords.latitude.degrees + nmea_number_to_f64(coords.latitude.minutes) / 60.0,
coords.longitude.degrees + nmea_number_to_f64(coords.longitude.minutes) / 60.0,
nmea_number_to_f64(altitude));
}
int main(void) {
CNmeaParser *parser = malloc(nmea_parser_size());
nmea_parser_init(parser);
const char *input = "$GPGGA,092750.000,5321.6802,N,00630.3372,W,1,8,1.03,61.7,M,55.2,M,,*76\r\n";
uint8_t *buf;
size_t len;
nmea_parser_buffer(parser, &buf, &len);
size_t n = strlen(input) < len ? strlen(input) : len;
memcpy(buf, input, n);
nmea_parser_commit(parser, n, on_sentence, NULL);
free(parser);
return 0;
}
```
## Sentences
- `AAM` - Waypoint Arrival Alarm
- `GGA` - Global Positioning System Fix Data
- `GLL` - Geographic Position (Latitude/Longitude)
- `GNS` - GNSS Fix Data
- `GSA` - GPS Dilution of Precision and Active Satellites
- `GST` - GPS Pseudorange Noise Statistics
- `GSV` - Satellites in View
- `RMC` - Recommended Minimum Navigation Information
- `TXT` - Text Transmission
- `VTG` - Track made good and Ground Speed
- `ZDA` - Time & Date
## `NmeaTime`/`NmeaDate`/`NmeaDateTime`/`NmeaDateTimeOffset`
All of these are our internal representations of dates and times that were parsed from the protocol. They are provided as is but can be converted to friendlier formats if you are using the library from Rust.
All of these have a `TryFrom` implementation to their analog from the [time](https://docs.rs/time/latest/time/) if you enable the `time` feature.
All of these have a `TryFrom` implementation to their analog from the [chrono](https://docs.rs/chrono/latest/chrono/) if you enable the `chrono` feature.
## `NmeaNumber`
This is our internal representation of floating point number that was parsed. This preserves all of the precision and is provided as is.
This has `From` implementations to `f32` and `f64` if you enable the `float` feature. This is also provided in the C FFI under `nmea_number_to_f32` and `nmea_number_to_f64`.
## `NmeaCoordinates`
This is our internal representation of the coordinates provided by the protocol. This mostly just wraps the `NmeaNumber` with some convenience for parsing.
This has a `From` implementation for a variety of types from the [geo_types](https://docs.rs/geo-types/latest/geo_types/) crate if you enable the `geo` feature.
## Contributing
Contributions are welcome. Feel free to add any of the missing NMEA sentences.
## License
Licensed under either of
* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
additional terms or conditions.