Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add serde support #102

Merged
merged 15 commits into from
Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ nom = { version = "7.1.1", default-features = false }
# we include num-traits only when `std` is not enabled
# because of `fract()` and `trunc()` methods
num-traits = { version = "0.2", default-features = false, features = ["libm"]}

cfg-if = "1"
serde = { version = "1.0.163", default-features = false, optional = true }
serde_with = { version = "3.0.0", default-features = false, optional = true }

[dev-dependencies]
approx = "0.5.1"
Expand All @@ -47,6 +48,14 @@ criterion = "0.4"
[features]
default = ["std", "all-sentences"]
std = ["nom/std", "chrono/std", "arrayvec/std"]
Copy link
Member

@elpiel elpiel Jul 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind adding serde?/std and serde_with?/std to the std feature list as well

serde = [
"serde/derive",
"serde_with/macros",
"serde_with/chrono_0_4",
"heapless/serde",
"chrono/serde",
"arrayvec/serde"
]


all-sentences = ["GNSS", "waypoint", "maritime", "water", "vendor-specific", "other"]
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
//!
//! - `default` features - `std`
//! - `std` - enable `std`
//! - `serde` - enable `serde`
//!
//! [`Nmea::parse()`]: Nmea::parse
//! [`Nmea::parse_for_fix()`]: Nmea::parse_for_fix
Expand Down
3 changes: 3 additions & 0 deletions src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use nom::{
};

use cfg_if::cfg_if;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::{sentences::*, Error, SentenceType};

Expand All @@ -35,6 +37,7 @@ pub const SENTENCE_MAX_LEN: usize = 102;
pub const TEXT_PARAMETER_MAX_LEN: usize = 64;

/// A known and parsable Nmea sentence type.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct NmeaSentence<'a> {
pub talker_id: &'a str,
pub message_id: SentenceType,
Expand Down
56 changes: 56 additions & 0 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ use crate::{
Error, ParseResult,
};

#[cfg(feature = "serde")]
use serde::{de::Visitor, ser::SerializeSeq, Deserialize, Serialize};

/// NMEA parser
///
/// This struct parses NMEA sentences, including checksum checks and sentence
Expand All @@ -31,6 +34,7 @@ use crate::{
/// # }

/// ```
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Default)]
pub struct Nmea {
pub fix_time: Option<NaiveTime>,
Expand Down Expand Up @@ -434,6 +438,7 @@ impl fmt::Display for Nmea {
}
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Default)]
struct SatsPack {
/// max number of visible GNSS satellites per hemisphere, assuming global coverage
Expand All @@ -442,10 +447,59 @@ struct SatsPack {
/// BeiDou: 12 + 3 IGSO + 3 GEO
/// Galileo: 12
/// => 58 total Satellites => max 15 rows of data
#[cfg_attr(feature = "serde", serde(with = "serde_deq"))]
data: Deque<Vec<Option<Satellite>, 4>, 15>,
max_len: usize,
}

#[cfg(feature = "serde")]
mod serde_deq {
use super::*;

pub fn serialize<S>(v: &Deque<Vec<Option<Satellite>, 4>, 15>, s: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut seq = s.serialize_seq(Some(15))?;
for e in v.iter() {
seq.serialize_element(e)?;
}
seq.end()
}

struct DequeVisitor;

impl<'de> Visitor<'de> for DequeVisitor {
type Value = Deque<Vec<Option<Satellite>, 4>, 15>;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("deque of vectors containing optional Satellite structs")
}

fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
let mut deq: Deque<Vec<Option<Satellite>, 4>, 15> = Deque::new();

while let Some(v) = seq.next_element()? {
deq.push_back(v)
.map_err(|_| serde::de::Error::invalid_length(deq.capacity() + 1, &self))?;
}

Ok(deq)
}
}

pub fn deserialize<'de, D>(d: D) -> Result<Deque<Vec<Option<Satellite>, 4>, 15>, D::Error>
where
D: serde::Deserializer<'de>,
{
d.deserialize_seq(DequeVisitor)
}
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, PartialEq)]
/// Satellite information
pub struct Satellite {
Expand Down Expand Up @@ -708,6 +762,7 @@ define_sentence_type_enum! {
/// ### Vendor extensions
///
/// - [`SentenceType::RMZ`]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
#[allow(rustdoc::bare_urls)]
Expand Down Expand Up @@ -1191,6 +1246,7 @@ define_sentence_type_enum! {
}
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
pub struct SentenceMask {
mask: u128,
Expand Down
4 changes: 4 additions & 0 deletions src/sentences/aam.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ use nom::{
number::complete::float,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::{parse::NmeaSentence, sentences::utils::array_string, Error, SentenceType};

/// AAM - Waypoint Arrival Alarm
Expand All @@ -30,6 +33,7 @@ use crate::{parse::NmeaSentence, sentences::utils::array_string, Error, Sentence
/// Example: $GPAAM,A,A,0.10,N,WPTNME*43
/// WPTNME is the waypoint name.
/// ```
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq)]
pub struct AamData {
pub arrival_circle_entered: Option<bool>,
Expand Down
4 changes: 4 additions & 0 deletions src/sentences/alm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ use nom::{
IResult,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::{Error, NmeaSentence, SentenceType};

use super::utils::number;
Expand Down Expand Up @@ -44,6 +47,7 @@ use super::utils::number;
/// 16. Checksum
///
/// Fields 5 through 15 are dumped as raw hex.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AlmData {
pub total_number_of_messages: Option<u16>,
Expand Down
4 changes: 4 additions & 0 deletions src/sentences/bod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ use nom::{
sequence::preceded,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

/// BOD - Bearing - Waypoint to Waypoint
///
/// <https://gpsd.gitlab.io/gpsd/NMEA.html#_bod_bearing_waypoint_to_waypoint>
Expand All @@ -18,6 +21,7 @@ use nom::{
/// | | | | | | |
/// $--BOD,x.x,T,x.x,M,c--c,c--c*hh<CR><LF>
/// ```
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct BodData {
pub bearing_true: Option<f32>,
Expand Down
4 changes: 4 additions & 0 deletions src/sentences/bwc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ use nom::{
bytes::complete::is_not, character::complete::char, combinator::opt, number::complete::float,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::{
parse::{NmeaSentence, TEXT_PARAMETER_MAX_LEN},
sentences::utils::{parse_hms, parse_lat_lon},
Expand All @@ -20,6 +23,7 @@ use crate::{
/// | | | | | | | | | | | | | |
/// $--BWC,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x.x,T,x.x,M,x.x,N,c--c,m,*hh<CR><LF>
/// ```
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq)]
pub struct BwcData {
pub fix_time: Option<NaiveTime>,
Expand Down
4 changes: 4 additions & 0 deletions src/sentences/bww.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use nom::{
bytes::complete::is_not, character::complete::char, combinator::opt, number::complete::float,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::{
parse::{NmeaSentence, TEXT_PARAMETER_MAX_LEN},
Error, SentenceType,
Expand All @@ -29,6 +32,7 @@ use super::utils::array_string;
/// 6. FROM Waypoint ID
/// 7. Checksum

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq)]
pub struct BwwData {
pub true_bearing: Option<f32>,
Expand Down
4 changes: 4 additions & 0 deletions src/sentences/dbk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ use nom::{
IResult,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::{parse::NmeaSentence, Error, ParseResult, SentenceType};

/// DBK - Depth Below Keel
Expand All @@ -24,6 +27,7 @@ use crate::{parse::NmeaSentence, Error, ParseResult, SentenceType};
/// 5: Depth, Fathoms
/// 6: F = Fathoms
/// 7: Mandatory NMEA checksum
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq)]
pub struct DbkData {
pub depth_feet: Option<f64>,
Expand Down
5 changes: 5 additions & 0 deletions src/sentences/faa_mode.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use nom::{character::complete::anychar, combinator::opt, IResult};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use super::{nom_parse_failure, FixType};

/// for now let's handle only two GPS and GLONASS
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct FaaModes {
sys_state0: FaaMode,
Expand All @@ -24,6 +28,7 @@ impl From<FaaModes> for FixType {
}
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum FaaMode {
/// A - Autonomous mode
Expand Down
4 changes: 4 additions & 0 deletions src/sentences/fix_type.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

/// Fix type
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum FixType {
Invalid,
Expand Down
4 changes: 4 additions & 0 deletions src/sentences/gbs.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use chrono::NaiveTime;
use nom::{character::complete::char, combinator::opt, number::complete::float, IResult};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::{
parse::NmeaSentence,
sentences::utils::{number, parse_hms, parse_lat_lon},
Expand All @@ -16,6 +19,7 @@ use crate::{
/// | | | | | | | | |
/// $--GBS,hhmmss.ss,x.x,x.x,x.x,x.x,x.x,x.x,x.x*hh<CR><LF>
/// ```
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct GbsData {
pub time: Option<NaiveTime>,
Expand Down
4 changes: 4 additions & 0 deletions src/sentences/gga.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ use nom::{
IResult,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::{
parse::NmeaSentence,
sentences::{
Expand All @@ -26,6 +29,7 @@ use crate::{
/// | | | | | | | | | | | | | | |
/// $--GGA,hhmmss.ss,ddmm.mm,a,ddmm.mm,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh<CR><LF>
/// ```
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq)]
pub struct GgaData {
pub fix_time: Option<NaiveTime>,
Expand Down
5 changes: 5 additions & 0 deletions src/sentences/gll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ use nom::{
IResult,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use super::{faa_mode::parse_faa_mode, nom_parse_failure, FaaMode};
use crate::{
parse::NmeaSentence,
Expand All @@ -28,6 +31,8 @@ use crate::{
/// | | | | | | |
/// $--GLL,ddmm.mm,a,dddmm.mm,a,hhmmss.ss,a,m*hh<CR><LF>
/// ```

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq)]
pub struct GllData {
pub latitude: Option<f64>,
Expand Down
5 changes: 5 additions & 0 deletions src/sentences/gns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ use nom::{
IResult,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use super::{
faa_mode::parse_faa_modes,
utils::{number, parse_hms, parse_lat_lon},
Expand All @@ -24,6 +27,7 @@ use crate::{parse::NmeaSentence, Error, SentenceType};
/// | | | | | | | | | | | | |
/// $--GNS,hhmmss.ss,ddmm.mm,a,dddmm.mm,a,c--c,xx,x.x,x.x,x.x,x.x,x.x*hh
/// ```
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq)]
pub struct GnsData {
pub fix_time: Option<NaiveTime>,
Expand All @@ -37,6 +41,7 @@ pub struct GnsData {
pub nav_status: Option<NavigationStatus>,
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum NavigationStatus {
Safe,
Expand Down
5 changes: 4 additions & 1 deletion src/sentences/gnss_type.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::count_tts;
use core::fmt;

use crate::count_tts;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

macro_rules! define_enum_with_count {
(
Expand All @@ -11,6 +13,7 @@ macro_rules! define_enum_with_count {
),* $(,)* }
) => {
$(#[$outer])*
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(PartialEq, Debug, Hash, Eq, Clone, Copy)]
#[repr(u8)]
pub enum $Name {
Expand Down
Loading