Skip to content

Commit

Permalink
Merge pull request #102 from grupacosmo/serde_support
Browse files Browse the repository at this point in the history
Add serde support
  • Loading branch information
elpiel authored Jul 20, 2023
2 parents 6f9d9cf + e5f9bc9 commit c7ba32e
Show file tree
Hide file tree
Showing 32 changed files with 210 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:

matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
rust: ["1.60", stable, beta]
rust: ["1.61", stable, beta]
env:
RUSTUP_MAX_RETRIES: 10
CARGO_NET_RETRY: 10
Expand Down
23 changes: 16 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ repository = "https://github.com/AeroRust/nmea"
readme = "README.md"

edition = "2021"
rust-version = "1.60"
rust-version = "1.61"

[package.metadata.docs.rs]
all-features = true
Expand All @@ -29,25 +29,34 @@ rustdoc-args = ["--cfg", "docsrs"]
arrayvec = { version = "0.7.2", default-features = false }
chrono = { version = "0.4.19", default-features = false }
heapless = "0.7.15"
nom = { version = "7.1.1", default-features = false }
nom = { version = "7.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", default-features = false, optional = true }
serde_with = { version = "3.0", default-features = false, optional = true }

[dev-dependencies]
approx = "0.5.1"
approx = "0.5"
doc-comment = "0.3"
pretty_assertions = "1"
quickcheck = { version = "1.0.3", default-features = false }
quickcheck = { version = "1", default-features = false }
# criterion 0.5 has clap_builder version which requires at least Rust 1.64
criterion = "0.4"

[features]
default = ["std", "all-sentences"]
std = ["nom/std", "chrono/std", "arrayvec/std"]

std = ["nom/std", "chrono/std", "arrayvec/std", "serde?/std", "serde_with?/std"]
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"]
# GNSS specific sentences related to the possition or speed relative to the ground
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
Loading

0 comments on commit c7ba32e

Please sign in to comment.