Skip to content

Commit

Permalink
BINEX: little endian streams (#279)
Browse files Browse the repository at this point in the history
* Fix:

  * encoding_size would not work on large message: fixed
  * decode MID for 0x5 (now available) and others that we do not support yet

* Test & verify little endian streams
* update readme
* Unlock md5 checksum calculation
* BINEX: run clippy

---------

Signed-off-by: Guillaume W. Bres <[email protected]>
  • Loading branch information
gwbres authored Nov 8, 2024
1 parent 36fbfe7 commit 4df1574
Show file tree
Hide file tree
Showing 21 changed files with 525 additions and 542 deletions.
8 changes: 8 additions & 0 deletions binex/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ or undisclosed elements. (private prototypes)

* or use Message::decode to work on your own buffer directly.

Current limitations
===================

+ Big endian streams are fully validated & tested
+ Little endian streams are tested & verified but we don't have a dataset to confirm yet
+ Enhanced CRC (robust messaging) is not supported yet
+ MD5 checksum (very lengthy message prototypes) is implemented but not verified yet

Message Decoding
================

Expand Down
8 changes: 4 additions & 4 deletions binex/src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl<'a, R: Read> Decoder<'a, R> {
/// // and user should react accordingly,
/// break;
/// },
/// Error::ReversedStream | Error::LittleEndianStream => {
/// Error::ReversedStream => {
/// // this library is currently limited:
/// // - reversed streams are not supported yet
/// // - little endian streams are not supported yet
Expand Down Expand Up @@ -138,7 +138,7 @@ impl<'a, R: Read> Decoder<'a, R> {
/// // and user should react accordingly,
/// break;
/// },
/// Error::ReversedStream | Error::LittleEndianStream => {
/// Error::ReversedStream => {
/// // this library is currently limited:
/// // - reversed streams are not supported yet
/// // - little endian streams are not supported yet
Expand Down Expand Up @@ -198,7 +198,7 @@ impl<'a, R: Read> Iterator for Decoder<'a, R> {
// we can safely discard everything
self.wr_ptr = 0;
self.rd_ptr = 0;
if self.eos == true {
if self.eos {
// consumed everything and EOS has been reached
return None;
}
Expand All @@ -211,7 +211,7 @@ impl<'a, R: Read> Iterator for Decoder<'a, R> {
self.wr_ptr = 0;
}

if self.eos == true {
if self.eos {
// consumed everything and EOS has been reached
return None;
}
Expand Down
4 changes: 1 addition & 3 deletions binex/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub mod prelude {
message::{
EphemerisFrame, GALEphemeris, GLOEphemeris, GPSEphemeris, GPSRaw, Message, Meta,
MonumentGeoMetadata, MonumentGeoRecord, PositionEcef3d, PositionGeo3d, Record,
SBASEphemeris, Solutions, TemporalSolution, Velocity3d, VelocityNED3d,
SBASEphemeris, Solutions, SolutionsFrame, TemporalSolution, Velocity3d, VelocityNED3d,
},
stream::{ClosedSourceElement, Provider, StreamElement},
ClosedSourceMeta, Error,
Expand Down Expand Up @@ -58,8 +58,6 @@ pub enum Error {
// InvalidStartofStream,
/// Library limitation: reversed streams are not supported
ReversedStream,
/// Library limitation: little endian streams are not verified yet
LittleEndianStream,
/// Library limitation: enhanced CRC is not supported yet
EnhancedCrc,
/// Found an unsupported timescale that we cannot interprate.
Expand Down
36 changes: 25 additions & 11 deletions binex/src/message/checksum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,21 +84,19 @@ impl Checksum {
if enhanced {
if mlen < 128 {
Self::XOR16
} else if mlen < 1048575 {
} else if mlen < 1048576 {
Self::XOR32
} else {
Self::MD5
}
} else if mlen < 128 {
Self::XOR8
} else if mlen < 4096 {
Self::XOR16
} else if mlen < 1048576 {
Self::XOR32
} else {
if mlen < 128 {
Self::XOR8
} else if mlen < 4096 {
Self::XOR16
} else if mlen < 1048575 {
Self::XOR32
} else {
Self::MD5
}
Self::MD5
}
}
/// Length we need to decode/encode this type of Checksum
Expand Down Expand Up @@ -129,8 +127,18 @@ impl Checksum {
u32::from_le_bytes([slice[0], slice[1], slice[2], slice[3]])
};
val_u32 as u128
} else if big_endian {
u128::from_be_bytes([
slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14],
slice[15],
])
} else {
unimplemented!("md5");
u128::from_le_bytes([
slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14],
slice[15],
])
}
}
/// Calculates expected Checksum for this msg
Expand Down Expand Up @@ -273,4 +281,10 @@ mod test {

assert_eq!(Checksum::XOR16.calc(&buf, buf.len()), 0x5376);
}
#[test]
fn test_md5() {
let ck = Checksum::MD5;
let bytes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
let _ = ck.calc(&bytes, bytes.len());
}
}
76 changes: 35 additions & 41 deletions binex/src/message/meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,27 +40,21 @@ impl Meta {
} else {
Self::REV_SYNC_BE_STANDARD_CRC
}
} else if self.enhanced_crc {
Self::REV_SYNC_LE_ENHANCED_CRC
} else {
if self.enhanced_crc {
Self::REV_SYNC_LE_ENHANCED_CRC
} else {
Self::REV_SYNC_LE_STANDARD_CRC
}
Self::REV_SYNC_LE_STANDARD_CRC
}
} else {
if self.big_endian {
if self.enhanced_crc {
Self::FWD_SYNC_BE_ENHANCED_CRC
} else {
Self::FWD_SYNC_BE_STANDARD_CRC
}
} else if self.big_endian {
if self.enhanced_crc {
Self::FWD_SYNC_BE_ENHANCED_CRC
} else {
if self.enhanced_crc {
Self::FWD_SYNC_LE_ENHANCED_CRC
} else {
Self::FWD_SYNC_LE_STANDARD_CRC
}
Self::FWD_SYNC_BE_STANDARD_CRC
}
} else if self.enhanced_crc {
Self::FWD_SYNC_LE_ENHANCED_CRC
} else {
Self::FWD_SYNC_LE_STANDARD_CRC
}
}
/// Locate SYNC byte in provided buffer
Expand Down Expand Up @@ -192,65 +186,65 @@ mod test {
// FWD +LE +STANDARD
let (meta, size) = meta.expect("did not detect sync byte");
assert_eq!(size, 1);
assert_eq!(meta.reversed, false);
assert_eq!(meta.big_endian, false);
assert_eq!(meta.enhanced_crc, false);
assert!(!meta.reversed);
assert!(!meta.big_endian);
assert!(!meta.enhanced_crc);
},
0xe2 => {
// FWD +BE +STANDARD
let (meta, size) = meta.expect("did not detect sync byte");
assert_eq!(size, 1);
assert_eq!(meta.reversed, false);
assert_eq!(meta.big_endian, true);
assert_eq!(meta.enhanced_crc, false);
assert!(!meta.reversed);
assert!(meta.big_endian);
assert!(!meta.enhanced_crc);
},
0xc8 => {
// FWD +LE +ENHANCED
let (meta, size) = meta.expect("did not detect sync byte");
assert_eq!(size, 1);
assert_eq!(meta.reversed, false);
assert_eq!(meta.big_endian, false);
assert_eq!(meta.enhanced_crc, true);
assert!(!meta.reversed);
assert!(!meta.big_endian);
assert!(meta.enhanced_crc);
},
0xe8 => {
// FWD +BE +ENHANCED
let (meta, size) = meta.expect("did not detect sync byte");
assert_eq!(size, 1);
assert_eq!(meta.reversed, false);
assert_eq!(meta.big_endian, true);
assert_eq!(meta.enhanced_crc, true);
assert!(!meta.reversed);
assert!(meta.big_endian);
assert!(meta.enhanced_crc);
},
0xd2 => {
// REV +LE +STANDARD
let (meta, size) = meta.expect("did not detect sync byte");
assert_eq!(size, 1);
assert_eq!(meta.reversed, true);
assert_eq!(meta.big_endian, false);
assert_eq!(meta.enhanced_crc, false);
assert!(meta.reversed);
assert!(!meta.big_endian);
assert!(!meta.enhanced_crc);
},
0xf2 => {
// REV +BE + STANDARD
let (meta, size) = meta.expect("did not detect sync byte");
assert_eq!(size, 1);
assert_eq!(meta.reversed, true);
assert_eq!(meta.big_endian, true);
assert_eq!(meta.enhanced_crc, false);
assert!(meta.reversed);
assert!(meta.big_endian);
assert!(!meta.enhanced_crc);
},
0xd8 => {
// REV +LE +ENHANCED
let (meta, size) = meta.expect("did not detect sync byte");
assert_eq!(size, 1);
assert_eq!(meta.reversed, true);
assert_eq!(meta.big_endian, false);
assert_eq!(meta.enhanced_crc, true);
assert!(meta.reversed);
assert!(!meta.big_endian);
assert!(meta.enhanced_crc);
},
0xf8 => {
// REV +BE +ENHANCED
let (meta, size) = meta.expect("did not detect sync byte");
assert_eq!(size, 1);
assert_eq!(meta.reversed, true);
assert_eq!(meta.big_endian, true);
assert_eq!(meta.enhanced_crc, true);
assert!(meta.reversed);
assert!(meta.big_endian);
assert!(meta.enhanced_crc);
},
_ => {
assert!(meta.is_none(), "found invalid sync byte for 0x{:01x}", val8);
Expand Down
40 changes: 20 additions & 20 deletions binex/src/message/mid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ pub enum MessageID {
SiteMonumentMarker = 0,
/// Decode Ephemeris frame
Ephemeris = 1,
/// Observation time tag and receiver info
ObservationTimeTagRxInfo = 2,
/// Observation, time tag and receiver info
Observation = 2,
/// Local Meteorological and Geophysical information
Meteo = 3,
/// Receiver info: BINEX specific
ReceiverInfo = 4,
/// Processed Solutions like PVT
ProcessedSolutions = 5,
// Receiver info prototyping: BINEX specific
ReceiverInfoPrototyping = 125,
/// Meteo prototyping: BINEX specific
MeteoPrototyping = 126,
/// Observation time tag prototyping: BINEX specific
ObservationTimeTagRxPrototyping = 127,
// Receiver info prototype: BINEX specific
ReceiverInfoPrototype = 125,
/// Meteo prototype: BINEX specific
MeteoPrototype = 126,
/// Observation, time tag and receiver info prototype
ObservationPrototype = 127,
// Unknown / unsupported message
#[default]
Unknown = 0xffffffff,
Expand All @@ -33,13 +33,13 @@ impl From<u32> for MessageID {
match val {
0 => Self::SiteMonumentMarker,
1 => Self::Ephemeris,
2 => Self::ObservationTimeTagRxInfo,
2 => Self::Observation,
3 => Self::Meteo,
4 => Self::ReceiverInfo,
5 => Self::ProcessedSolutions,
125 => Self::ReceiverInfoPrototyping,
126 => Self::MeteoPrototyping,
127 => Self::ObservationTimeTagRxPrototyping,
125 => Self::ReceiverInfoPrototype,
126 => Self::MeteoPrototype,
127 => Self::ObservationPrototype,
_ => Self::Unknown,
}
}
Expand All @@ -50,14 +50,14 @@ impl From<MessageID> for u32 {
match val {
MessageID::SiteMonumentMarker => 0,
MessageID::Ephemeris => 1,
// MessageID::ObservationTimeTagRxInfo => 0x02,
// MessageID::Meteo => 0x03,
// MessageID::ReceiverInfo => 0x04,
// MessageID::ProcessedSolutions => 0x05,
// MessageID::ReceiverInfoPrototyping => 0x7d,
// MessageID::MeteoPrototyping => 0x7e,
// MessageID::ObservationTimeTagRxPrototyping => 0x7f,
_ => 0xffffffff,
MessageID::Observation => 2,
MessageID::Meteo => 3,
MessageID::ReceiverInfo => 4,
MessageID::ProcessedSolutions => 5,
MessageID::ReceiverInfoPrototype => 125,
MessageID::MeteoPrototype => 126,
MessageID::ObservationPrototype => 127,
_ => 0xff,
}
}
}
21 changes: 8 additions & 13 deletions binex/src/message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ pub use record::{
};

pub use meta::Meta;
pub use time::TimeResolution;

pub(crate) use mid::MessageID;

Expand Down Expand Up @@ -46,14 +45,15 @@ impl Message {
let mut total = 1; // SYNC

let mid = self.record.to_message_id() as u32;
total += Self::bnxi_encoding_size(mid);
let mid_1_4 = Self::bnxi_encoding_size(mid);
total += mid_1_4;

let mlen = self.record.encoding_size();
total += Self::bnxi_encoding_size(mlen as u32);
let mlen_1_4 = Self::bnxi_encoding_size(mlen as u32);
total += mlen_1_4;
total += mlen;

total += self.record.encoding_size();

let ck = Checksum::from_len(mlen, self.meta.enhanced_crc);
let ck = Checksum::from_len(mlen_1_4 + mlen + mid_1_4, self.meta.enhanced_crc);
total += ck.len();

total
Expand Down Expand Up @@ -82,7 +82,6 @@ impl Message {
/////////////////////////////////////
// TODO: current library limitations
/////////////////////////////////////

if reversed {
// Reversed streams: not understood
return Err(Error::ReversedStream);
Expand All @@ -91,10 +90,6 @@ impl Message {
// Enhanced CRC scheme not implemented
return Err(Error::EnhancedCrc);
}
if !big_endian {
// Little endianess not tested
return Err(Error::LittleEndianStream);
}

// make sure we can parse up to 4 byte MID
if buf_len - sync_off < 4 {
Expand Down Expand Up @@ -131,15 +126,15 @@ impl Message {
// 4. parse RECORD
let record = match mid {
MessageID::SiteMonumentMarker => {
let rec = MonumentGeoRecord::decode(mlen as usize, big_endian, &buf[ptr..])?;
let rec = MonumentGeoRecord::decode(mlen, big_endian, &buf[ptr..])?;
Record::new_monument_geo(rec)
},
MessageID::Ephemeris => {
let fr = EphemerisFrame::decode(big_endian, &buf[ptr..])?;
Record::new_ephemeris_frame(fr)
},
MessageID::ProcessedSolutions => {
let solutions = Solutions::decode(mlen as usize, big_endian, &buf[ptr..])?;
let solutions = Solutions::decode(mlen, big_endian, &buf[ptr..])?;
Record::new_solutions(solutions)
},
MessageID::Unknown => {
Expand Down
Loading

0 comments on commit 4df1574

Please sign in to comment.