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

BINEX: little endian streams #279

Merged
merged 11 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
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
Loading