From 3a68b28d1c280d994fd29c114c8ebdf4964fc797 Mon Sep 17 00:00:00 2001 From: gwbres Date: Sat, 2 Nov 2024 23:15:48 +0100 Subject: [PATCH] BINEX: fix CRC16 calculations (#276) * CRC verification * Fix CRC16 calc * Update docs * ClosedSourceMeta: - the decoding process will need it --------- Signed-off-by: Guillaume W. Bres --- binex/Cargo.toml | 2 +- binex/README.md | 66 +++++++- binex/src/decoder.rs | 23 +++ binex/src/lib.rs | 20 ++- binex/src/message/checksum.rs | 132 +++++++++++++--- binex/src/message/mod.rs | 129 ++++++++++------ binex/src/message/record/ephemeris/mod.rs | 24 +-- binex/src/message/record/monument/frame.rs | 51 ++++++ binex/src/message/record/monument/mod.rs | 101 ++++++------ binex/src/stream.rs | 171 +++++++++++++++++---- binex/tests/decoder.rs | 4 +- binex/tests/message.rs | 20 ++- binex/tools/crc16.py | 2 +- binex/tools/crc32.py | 2 +- 14 files changed, 564 insertions(+), 183 deletions(-) create mode 100644 binex/src/message/record/monument/frame.rs diff --git a/binex/Cargo.toml b/binex/Cargo.toml index f58dfcb4a..fd3e6e0ce 100644 --- a/binex/Cargo.toml +++ b/binex/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "binex" -version = "0.2.0" +version = "0.3.0" license = "MIT OR Apache-2.0" authors = ["Guillaume W. Bres "] description = "BINEX Binary RINEX encoder and decoder" diff --git a/binex/README.md b/binex/README.md index c1eb88432..bb6cbd624 100644 --- a/binex/README.md +++ b/binex/README.md @@ -1,9 +1,7 @@ # BINEX [![Rust](https://github.com/georust/rinex/actions/workflows/rust.yml/badge.svg)](https://github.com/georust/rinex/actions/workflows/rust.yml) -[![Rust](https://github.com/georust/rinex/actions/workflows/daily.yml/badge.svg)](https://github.com/georust/rinex/actions/workflows/daily.yml) -[![crates.io](https://img.shields.io/crates/v/binex.svg)](https://crates.io/crates/binex) -[![crates.io](https://docs.rs/binex/badge.svg)](https://docs.rs/binex/badge.svg) +[![Rust](https://github.com/georust/rinex/actions/workflows/daily.yml/badge.svg)](https://github.com/georust/rinex/actions/workflows/daily.yml) [![crates.io](https://img.shields.io/crates/v/binex.svg)](https://crates.io/crates/binex) [![crates.io](https://docs.rs/binex/badge.svg)](https://docs.rs/binex/badge.svg) BINEX is a simple library to decode and encode BINEX messages. BINEX stands for BINary EXchange and is the "real time" stream oriented @@ -16,14 +14,70 @@ hardware orientated (at the GNSS receiver firmware level). This library allows easy message encoding and decoding, and aims at providing seamless convertion from RINEX back and forth. -## Message Decoding +You have two scenarios to approach a BINEX stream: -Use the BINEX `Decoder` to decode messages from a `Readable` interface: +* use our Decoder object, which works on I/O interface directly +and can represent a stream of continuous of either Messages (open source) +or undisclosed elements. (private prototypes) + +* or use Message::decode to work on your own buffer directly. + +Message Decoding +================ + +Use the BINEX `Decoder` to decode a `Readable` interface streaming +BINEX messages. Decoder exposes both open source Messages that +were fully interprated and closed source Messages (undisclosed prototypes) +that it cannot interprate: ```rust +use std::fs::File; +use binex::prelude::{Decoder, StreamElement, Provider, Error}; + +let fd = File::open("../test_resources/BIN/mfle20190130.bnx") + .unwrap(); + +let mut decoder = Decoder::new(fd); + +loop { + match decoder.next() { + Some(Ok(StreamElement::OpenSource(msg))) => { + // fully interprated element + }, + Some(Ok(StreamElement::ClosedSource(element))) => { + // verify this is your organization + if element.meta.provider == Provider::JPL { + // grab fields that you probably need to decode + let mid = element.meta.mid; + let mlen = element.meta.mlen; + let big_endian = element.meta.big_endian; + let is_reversed = element.meta.reversed; + let enhanced_crc = element.meta.enhanced_crc; + + // now, proceed to interpretation of this element, + // using undisclosed method + element.interprate(&|data| { + match mid { + _ => {}, + } + }); + } + }, + Some(Err(e)) => { + // it is possible that some frames may not + // be supported yet. + // Any I/O error should not happen. + }, + None => { + // end of stream + break; + }, + } +} ``` -## Message forging +Message Forging +=============== The BINEX library allows easy message forging. Each message can be easily encoded and then streamed into a `Writable` interface: diff --git a/binex/src/decoder.rs b/binex/src/decoder.rs index 1845cd3af..0e994293e 100644 --- a/binex/src/decoder.rs +++ b/binex/src/decoder.rs @@ -236,6 +236,29 @@ impl<'a, R: Read> Iterator for Decoder<'a, R> { return Some(Err(Error::IncompleteMessage(mlen))); } }, + Error::ClosedSourceMessage(meta) => { + // determine whether + // - this element is self sustained (ie., fully described by this meta) + // - the followup of previous elements + // - or the last element of a serie + if self.rd_ptr + meta.mlen < 4096 { + // content is fully wrapped in buffer: expose as is + // self.past_element = Some(ClosedSourceElement { + // provider: meta.provider, + // size: meta.mlen, + // total: meta.mlen, + // raw: self.buf[self.rd_ptr..self.rd_ptr +meta.mlen], + // }); + } else { + // content is not fully wrapped up here; + // initiate or continue a serie of undisclosed element + } + return Some(Err(Error::IncompleteMessage(meta.mlen))); + }, + Error::UnknownMessage => { + // panic!("unknown message\nrd_ptr={}\nbuf={:?}", self.rd_ptr, &self.buf[self.rd_ptr-1..self.rd_ptr+4]); + self.rd_ptr += 1; + }, _ => { // bad content that does not look like valid BINEX. // This is very inefficient. If returned error would increment diff --git a/binex/src/lib.rs b/binex/src/lib.rs index 5acb99a52..2df4a82ec 100644 --- a/binex/src/lib.rs +++ b/binex/src/lib.rs @@ -19,7 +19,7 @@ pub mod prelude { MonumentGeoMetadata, MonumentGeoRecord, Record, SBASEphemeris, TimeResolution, }, stream::{ClosedSourceElement, Provider, StreamElement}, - Error, + ClosedSourceMeta, Error, }; // re-export pub use hifitime::Epoch; @@ -32,12 +32,18 @@ use crate::stream::Provider; pub struct ClosedSourceMeta { // decoded MID (as is) pub mid: u32, - // decoded MLEN (as is) - pub mlen: u32, - // payload offset in buffer - pub offset: usize, - // [Provider] of this message. Only this organization may continue the decoding process. + /// decoded MLEN (as is) + pub mlen: usize, + /// Whether this item is reversed or not + pub reversed: bool, + /// Whether this item uses enhanced CRC or not + pub enhanced_crc: bool, + /// Whether this is big endian encoded or not + pub big_endian: bool, + /// [Provider] of this message. Only this organization may continue the decoding process. pub provider: Provider, + // payload offset in buffer + offset: usize, } #[derive(Debug)] @@ -67,7 +73,7 @@ pub enum Error { CorrupctBadCRC, /// Incomplete message: need more data to complete IncompleteMessage(usize), - /// Library limitation: not all open source [Message]s supported yet + /// Library limitation: not all open source Messages supported yet NonSupportedMesssage(usize), /// Library limtation: should never happen, because this library /// will be designed to parse all open source [Message]s. diff --git a/binex/src/message/checksum.rs b/binex/src/message/checksum.rs index 79eabef66..c5906f74e 100644 --- a/binex/src/message/checksum.rs +++ b/binex/src/message/checksum.rs @@ -112,17 +112,17 @@ impl Checksum { } /// Helper to decode checksum value as unsigned 128, /// which covers all scenarios - pub fn decode(&self, slice: &[u8], len: usize, big_endian: bool) -> u128 { - if len == 1 { + pub fn decode(&self, slice: &[u8], ck_len: usize, big_endian: bool) -> u128 { + if ck_len == 1 { slice[0] as u128 - } else if len == 2 { + } else if ck_len == 2 { let val_u16 = if big_endian { u16::from_be_bytes([slice[0], slice[1]]) } else { u16::from_le_bytes([slice[0], slice[1]]) }; val_u16 as u128 - } else if len == 4 { + } else if ck_len == 4 { let val_u32 = if big_endian { u32::from_be_bytes([slice[0], slice[1], slice[2], slice[3]]) } else { @@ -134,12 +134,12 @@ impl Checksum { } } /// Calculates expected Checksum for this msg - pub fn calc(&self, bytes: &[u8], mlen: usize) -> u128 { + pub fn calc(&self, bytes: &[u8], size: usize) -> u128 { match self { - Self::XOR8 => Self::xor8_calc(bytes, mlen), - Self::XOR16 => Self::xor16_calc(bytes), - Self::XOR32 => Self::xor32_calc(bytes), - Self::MD5 => Self::md5_calc(bytes), + Self::XOR8 => Self::xor8_calc(bytes, size), + Self::XOR16 => Self::xor16_calc(bytes, size), + Self::XOR32 => Self::xor32_calc(bytes, size), + Self::MD5 => Self::md5_calc(bytes, size), } } /// Calculates expected Checksum using XOR8 algorithm @@ -151,29 +151,29 @@ impl Checksum { xor as u128 } /// Calculates expected Checksum using XOR16 algorithm - fn xor16_calc(bytes: &[u8]) -> u128 { - let mut crc = 0xffff_u16; - for byte in bytes.iter() { - let tmp = (*byte as u16) ^ crc; - crc >>= 8; - crc ^= CRC16_TABLE[(tmp as usize) % 256]; + fn xor16_calc(bytes: &[u8], size: usize) -> u128 { + let mut crc = 0_u16; + for i in 0..size { + let index = (((crc >> 8) ^ bytes[i] as u16) & 0xff) as usize; + crc = (crc << 8) ^ CRC16_TABLE[index]; + crc &= 0xffff; } crc as u128 } /// Calculates expected Checksum using XO32 algorithm - fn xor32_calc(bytes: &[u8]) -> u128 { - let mut crc = 0xffffffff_u32; - for byte in bytes.iter() { - let tmp = (*byte as u32) ^ crc; - crc >>= 8; - crc ^= CRC32_TABLE[(tmp as usize) % 256]; + fn xor32_calc(bytes: &[u8], size: usize) -> u128 { + let mut crc = 0_u32; + for i in 0..size { + let index = (((crc >> 24) ^ bytes[i] as u32) & 0xff) as usize; + crc = (crc << 8) ^ CRC32_TABLE[index]; + crc &= 0xffffffff; } crc as u128 } /// Calculates expected Checksum using MD5 algorithm - fn md5_calc(bytes: &[u8]) -> u128 { + fn md5_calc(bytes: &[u8], size: usize) -> u128 { let mut hasher = Md5::new(); - hasher.update(bytes); + hasher.update(&bytes[..size]); let md5 = hasher.finalize(); u128::from_le_bytes(md5.into()) } @@ -186,5 +186,91 @@ mod test { fn test_xor8() { let buf = [0, 1, 2, 3, 4]; assert_eq!(Checksum::XOR8.calc(&buf, 5), 4); + + let buf = [ + 0x00, 0x1f, 0x01, 0x39, 0x87, 0x20, 0x00, 0x00, 0x00, 0x17, 0x42, 0x49, 0x4e, 0x45, + 0x58, 0x20, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x65, 0x64, 0x21, + ]; + assert_eq!(Checksum::XOR8.calc(&buf, buf.len()), 0x84); + } + + #[test] + fn test_xor16() { + // e2, 01 81 + let buf = [ + 0x01, 0x81, 0x00, 0x01, 0x1d, 0x07, 0xf6, 0x00, 0x03, 0xd8, 0x72, 0x00, 0x03, 0xf4, + 0x80, 0x31, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xac, + 0xdc, 0x00, 0x00, 0xb8, 0x38, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0xd5, 0x5c, + 0x00, 0xbf, 0xf8, 0x96, 0x4c, 0x65, 0x6e, 0xda, 0x41, 0x3f, 0x6d, 0x97, 0xd5, 0xd0, + 0x00, 0x00, 0x00, 0x40, 0xb4, 0x21, 0xa2, 0x39, 0x40, 0x00, 0x00, 0x32, 0x20, 0x00, + 0x00, 0x43, 0x44, 0xf8, 0x00, 0xb3, 0x18, 0x00, 0x00, 0x42, 0x78, 0x60, 0x00, 0x36, + 0x49, 0xa0, 0x00, 0x37, 0x16, 0x60, 0x00, 0x40, 0x02, 0xa8, 0x2c, 0x0b, 0x2a, 0x18, + 0x0c, 0xc0, 0x08, 0x23, 0xb8, 0x97, 0xbd, 0xf9, 0x99, 0x3f, 0xee, 0x23, 0x55, 0xce, + 0x2e, 0x11, 0x70, 0xb1, 0x31, 0xa4, 0x00, 0xad, 0xac, 0x00, 0x00, 0x41, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x04, + ]; + + assert_eq!(Checksum::XOR16.calc(&buf, buf.len()), 0x7d49); + + let buf = [ + 0x01, 0x81, 0x00, 0x01, 0x07, 0x07, 0xf6, 0x00, 0x03, 0xd8, 0x72, 0x00, 0x03, 0xf4, + 0x80, 0x31, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0xab, + 0xc0, 0x00, 0x00, 0xb9, 0x09, 0x3b, 0x60, 0x00, 0x00, 0x00, 0x1d, 0x30, 0xc3, 0x30, + 0x00, 0x3f, 0xf9, 0xa2, 0xc9, 0x26, 0x53, 0xc2, 0x7b, 0x3f, 0x71, 0x2c, 0xe0, 0xd8, + 0x00, 0x00, 0x00, 0x40, 0xb4, 0x21, 0xb0, 0xf1, 0x60, 0x00, 0x00, 0x33, 0xa0, 0x00, + 0x00, 0x43, 0x98, 0x64, 0x00, 0xb2, 0x60, 0x00, 0x00, 0xc2, 0x2f, 0xa0, 0x00, 0xb6, + 0x0c, 0xe0, 0x00, 0x36, 0x83, 0xc0, 0x00, 0xbf, 0xfe, 0xa8, 0x9a, 0xfb, 0x49, 0x69, + 0xb2, 0xbf, 0xd7, 0x73, 0x3f, 0x12, 0x4a, 0xa8, 0x69, 0x3f, 0xef, 0x09, 0xab, 0xae, + 0x21, 0x65, 0xd4, 0xb1, 0x33, 0xe8, 0x00, 0xae, 0xa1, 0xc0, 0x00, 0x41, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x04, + ]; + + assert_eq!(Checksum::XOR16.calc(&buf, buf.len()), 0x6c23); + + let buf = [ + 0x01, 0x81, 0x00, 0x01, 0x06, 0x07, 0xf6, 0x00, 0x03, 0xd8, 0x72, 0x00, 0x03, 0xf4, + 0x80, 0xb2, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0xac, + 0xfc, 0x00, 0x00, 0x38, 0x31, 0xab, 0x80, 0x00, 0x00, 0x00, 0x53, 0x30, 0xc5, 0x24, + 0x00, 0xbf, 0xf8, 0xbb, 0x57, 0x3d, 0x09, 0x5f, 0x9d, 0x3f, 0x88, 0xee, 0x38, 0x68, + 0x00, 0x00, 0x00, 0x40, 0xb4, 0x21, 0x9d, 0xac, 0xc0, 0x00, 0x00, 0x34, 0x5a, 0x00, + 0x00, 0x43, 0x48, 0x50, 0x00, 0xb3, 0xe4, 0x00, 0x00, 0x42, 0x67, 0x40, 0x00, 0x36, + 0x42, 0x80, 0x00, 0x37, 0x16, 0xe8, 0x00, 0x40, 0x02, 0x6a, 0xdc, 0xf8, 0x6b, 0x10, + 0x56, 0xc0, 0x03, 0xd3, 0x59, 0xfa, 0x22, 0x6d, 0x54, 0x3f, 0xee, 0x99, 0xf5, 0x34, + 0x32, 0xf3, 0xdd, 0xb1, 0x2b, 0xf6, 0x00, 0xac, 0xe8, 0x00, 0x00, 0x41, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x04, + ]; + + assert_eq!(Checksum::XOR16.calc(&buf, buf.len()), 0x1919); + + let buf = [ + 0x01, 0x81, 0x00, 0x01, 0x11, 0x07, 0xf6, 0x00, 0x03, 0xe5, 0x74, 0x00, 0x03, 0xf4, + 0x80, 0xb1, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x2c, + 0x84, 0x00, 0x00, 0x37, 0xae, 0x23, 0x00, 0x00, 0x00, 0x00, 0x68, 0x30, 0xc9, 0xa4, + 0x00, 0xbf, 0xf2, 0x1b, 0xb8, 0xd2, 0xf3, 0x07, 0xe2, 0x3f, 0x8e, 0xbe, 0xca, 0x08, + 0x00, 0x00, 0x00, 0x40, 0xb4, 0x21, 0xbe, 0x8a, 0x80, 0x00, 0x00, 0xb3, 0xc0, 0x00, + 0x00, 0x43, 0x53, 0x30, 0x00, 0x34, 0xb4, 0x00, 0x00, 0xc2, 0x64, 0xa0, 0x00, 0xb6, + 0x3f, 0xa0, 0x00, 0x37, 0x0e, 0xf8, 0x00, 0xbf, 0xec, 0xde, 0x8f, 0x8b, 0x25, 0x86, + 0x86, 0x3f, 0xf5, 0xf8, 0xf4, 0xf0, 0x6d, 0x38, 0x8e, 0x3f, 0xee, 0x7c, 0xb1, 0xdf, + 0xad, 0x10, 0xdf, 0xb1, 0x34, 0x46, 0x00, 0xaa, 0x80, 0x00, 0x00, 0x41, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x04, + ]; + + assert_eq!(Checksum::XOR16.calc(&buf, buf.len()), 0x72d8); + + let buf = [ + 0x01, 0x81, 0x00, 0x01, 0x00, 0x07, 0xf6, 0x00, 0x03, 0xf2, 0x6a, 0x00, 0x03, 0xf4, + 0x80, 0x31, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0xac, + 0xec, 0x00, 0x00, 0xb9, 0x21, 0x70, 0x60, 0x00, 0x00, 0x00, 0x5b, 0x30, 0xb1, 0xd4, + 0x00, 0xbf, 0xed, 0x6f, 0x04, 0x75, 0x35, 0xbf, 0x7c, 0x3f, 0x81, 0x09, 0xb5, 0x7c, + 0x00, 0x00, 0x00, 0x40, 0xb4, 0x21, 0xa9, 0xec, 0xa0, 0x00, 0x00, 0x34, 0x3c, 0x00, + 0x00, 0x43, 0x55, 0xd8, 0x00, 0x33, 0xec, 0x00, 0x00, 0xc2, 0x6f, 0xc0, 0x00, 0xb6, + 0x55, 0x80, 0x00, 0x37, 0x16, 0x80, 0x00, 0xbf, 0xeb, 0x2f, 0xea, 0x1a, 0x2d, 0x94, + 0x4f, 0x3f, 0xe5, 0xf2, 0x7f, 0x44, 0xff, 0xc4, 0xc1, 0x3f, 0xef, 0x2d, 0x2d, 0x85, + 0x03, 0xc4, 0xfb, 0xb1, 0x2c, 0x40, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x41, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x04, + ]; + + assert_eq!(Checksum::XOR16.calc(&buf, buf.len()), 0x5376); } } diff --git a/binex/src/message/mod.rs b/binex/src/message/mod.rs index 2913bdd2c..e633892ec 100644 --- a/binex/src/message/mod.rs +++ b/binex/src/message/mod.rs @@ -84,35 +84,34 @@ impl Message { let mut reversed = false; let mut enhanced_crc = false; let time_res = TimeResolution::QuarterSecond; - let mut closed_provider = Option::::None; // 1. locate SYNC byte - if let Some(offset) = Self::locate(Constants::FWDSYNC_BE_STANDARD_CRC, buf) { + if let Some(offset) = Self::find(Constants::FWDSYNC_BE_STANDARD_CRC, buf) { big_endian = true; sync_off = offset; - } else if let Some(offset) = Self::locate(Constants::FWDSYNC_LE_STANDARD_CRC, buf) { + } else if let Some(offset) = Self::find(Constants::FWDSYNC_LE_STANDARD_CRC, buf) { sync_off = offset; big_endian = false; - } else if let Some(offset) = Self::locate(Constants::FWDSYNC_BE_ENHANCED_CRC, buf) { + } else if let Some(offset) = Self::find(Constants::FWDSYNC_BE_ENHANCED_CRC, buf) { big_endian = true; enhanced_crc = true; sync_off = offset; - } else if let Some(offset) = Self::locate(Constants::FWDSYNC_LE_ENHANCED_CRC, buf) { + } else if let Some(offset) = Self::find(Constants::FWDSYNC_LE_ENHANCED_CRC, buf) { enhanced_crc = true; sync_off = offset; - } else if let Some(offset) = Self::locate(Constants::REVSYNC_LE_STANDARD_CRC, buf) { + } else if let Some(offset) = Self::find(Constants::REVSYNC_LE_STANDARD_CRC, buf) { reversed = true; sync_off = offset; - } else if let Some(offset) = Self::locate(Constants::REVSYNC_BE_STANDARD_CRC, buf) { + } else if let Some(offset) = Self::find(Constants::REVSYNC_BE_STANDARD_CRC, buf) { reversed = true; big_endian = true; sync_off = offset; - } else if let Some(offset) = Self::locate(Constants::REVSYNC_BE_ENHANCED_CRC, buf) { + } else if let Some(offset) = Self::find(Constants::REVSYNC_BE_ENHANCED_CRC, buf) { reversed = true; big_endian = true; enhanced_crc = true; sync_off = offset; - } else if let Some(offset) = Self::locate(Constants::REVSYNC_LE_ENHANCED_CRC, buf) { + } else if let Some(offset) = Self::find(Constants::REVSYNC_LE_ENHANCED_CRC, buf) { reversed = true; enhanced_crc = true; sync_off = offset; @@ -143,9 +142,14 @@ impl Message { let mut ptr = sync_off + 1; // 2. parse MID - let (bnxi, size) = Self::decode_bnxi(&buf[ptr..], big_endian); + let (bnxi, mid_1_4) = Self::decode_bnxi(&buf[ptr..], big_endian); let mid = MessageID::from(bnxi); - ptr += size; + + if mid == MessageID::Unknown { + return Err(Error::UnknownMessage); + } + + ptr += mid_1_4; // make sure we can parse up to 4 byte MLEN if buf_len - ptr < 4 { @@ -153,15 +157,16 @@ impl Message { } // 3. parse MLEN - let (mlen, size) = Self::decode_bnxi(&buf[ptr..], big_endian); + let (mlen, mlen_1_4) = Self::decode_bnxi(&buf[ptr..], big_endian); let mlen = mlen as usize; - // println!("mlen={}", mlen); + //println!("mid={:?}/mlen={}/ptr={}", mid, mlen, ptr); - if buf_len - ptr < mlen { + if ptr + mlen > buf_len { // buffer does not contain complete message! return Err(Error::IncompleteMessage(mlen)); } - ptr += size; + + ptr += mlen_1_4; // 4. parse RECORD let record = match mid { @@ -174,17 +179,20 @@ impl Message { let fr = EphemerisFrame::decode(big_endian, &buf[ptr..])?; Record::new_ephemeris_frame(fr) }, - id => { - // verify this is not a closed source message + _ => { + // check whether this message is undisclosed or not if let Some(provider) = Provider::match_any(mid.into()) { return Err(Error::ClosedSourceMessage(ClosedSourceMeta { - mid: mid.into(), - mlen: mlen as u32, - offset: ptr, + mlen, provider, + offset: ptr, + big_endian, + reversed, + enhanced_crc, + mid: mid.into(), })); } else { - println!("found unsupported msg id={:?}", id); + // println!("found unsupported msg id={:?}", id); return Err(Error::NonSupportedMesssage(mlen)); } }, @@ -202,20 +210,20 @@ impl Message { let ck = checksum.decode(&buf[ptr + mlen..], ck_len, big_endian); // verify - let expected = checksum.calc(&buf[sync_off + 1..], mlen + 2); + let expected = checksum.calc(&buf[sync_off + 1..], mlen + mid_1_4 + mlen_1_4); - // if expected != ck { - // Err(Error::BadCRC) - // } else { - Ok(Self { - mid, - record, - reversed, - time_res, - big_endian, - enhanced_crc, - }) - // } + if expected != ck { + Err(Error::CorrupctBadCRC) + } else { + Ok(Self { + mid, + record, + reversed, + time_res, + big_endian, + enhanced_crc, + }) + } } /// [Message] encoding attempt into buffer. @@ -233,11 +241,13 @@ impl Message { // Encode MID let mid = self.record.to_message_id() as u32; - ptr += Self::encode_bnxi(mid, self.big_endian, &mut buf[ptr..])?; + let mid_1_4 = Self::encode_bnxi(mid, self.big_endian, &mut buf[ptr..])?; + ptr += mid_1_4; // Encode MLEN let mlen = self.record.encoding_size(); - ptr += Self::encode_bnxi(mlen as u32, self.big_endian, &mut buf[ptr..])?; + let mlen_1_4 = Self::encode_bnxi(mlen as u32, self.big_endian, &mut buf[ptr..])?; + ptr += mlen_1_4; // Encode message match &self.record { @@ -252,14 +262,39 @@ impl Message { // encode CRC let ck = Checksum::from_len(mlen, self.enhanced_crc); let ck_len = ck.len(); - let crc_u128 = ck.calc(&buf[1..], mlen + 2); - let crc_bytes = crc_u128.to_le_bytes(); + let crc_u128 = ck.calc(&buf[1..], mlen + mid_1_4 + mlen_1_4); - // if ck_len == 1 { - // buf[ptr] = crc_u128 as u8; - // } else { - // buf[ptr..ptr + ck_len].copy_from_slice(&crc_bytes[..ck_len]); - // } + if ck_len == 1 { + buf[ptr] = crc_u128 as u8; + } else if ck_len == 2 { + let crc_bytes = if self.big_endian { + (crc_u128 as u16).to_be_bytes() + } else { + (crc_u128 as u16).to_le_bytes() + }; + + for i in 0..ck_len { + buf[ptr + i] = crc_bytes[i]; + } + } else if ck_len == 4 { + let crc_bytes = if self.big_endian { + (crc_u128 as u32).to_be_bytes() + } else { + (crc_u128 as u32).to_le_bytes() + }; + for i in 0..ck_len { + buf[ptr + i] = crc_bytes[i]; + } + } else { + let crc_bytes = if self.big_endian { + crc_u128.to_be_bytes() + } else { + crc_u128.to_le_bytes() + }; + for i in 0..ck_len { + buf[ptr + i] = crc_bytes[i]; + } + } Ok(ptr + ck_len) } @@ -298,7 +333,7 @@ impl Message { } /// Tries to locate desired byte within buffer - fn locate(to_find: u8, buf: &[u8]) -> Option { + fn find(to_find: u8, buf: &[u8]) -> Option { buf.iter().position(|b| *b == to_find) } @@ -685,7 +720,7 @@ mod test { let mut encoded = [0; 256]; msg.encode(&mut encoded).unwrap(); - assert_eq!(encoded[17], 0); + assert_eq!(encoded[17], 3); // parse back let parsed = Message::decode(&encoded).unwrap(); @@ -733,7 +768,7 @@ mod test { let gps_eph_len = gps_eph.encoding_size(); let record = Record::new_ephemeris_frame(gps_eph); - assert_eq!(gps_eph_len, 128); + assert_eq!(gps_eph_len, 129); let msg = Message::new( big_endian, @@ -764,7 +799,7 @@ mod test { let eph_len = eph.encoding_size(); let record = Record::new_ephemeris_frame(eph); - assert_eq!(eph_len, 128); + assert_eq!(eph_len, 129); let msg = Message::new( big_endian, diff --git a/binex/src/message/record/ephemeris/mod.rs b/binex/src/message/record/ephemeris/mod.rs index 5c7bc34d3..8ce8d94f2 100644 --- a/binex/src/message/record/ephemeris/mod.rs +++ b/binex/src/message/record/ephemeris/mod.rs @@ -37,13 +37,17 @@ impl EphemerisFrame { /// Returns total length (bytewise) required to fully encode [Self]. /// Use this to fulfill [Self::encode] requirements. pub fn encoding_size(&self) -> usize { - match self { + let fid_1_4 = Message::bnxi_encoding_size(self.to_field_id() as u32); + + let size = match self { Self::GPSRaw(_) => GPSRaw::encoding_size(), Self::GPS(_) => GPSEphemeris::encoding_size(), Self::GLO(_) => GLOEphemeris::encoding_size(), Self::SBAS(_) => SBASEphemeris::encoding_size(), Self::GAL(_) => GALEphemeris::encoding_size(), - } + }; + + size + fid_1_4 } /// Returns expected [FieldID] for [Self] @@ -104,13 +108,15 @@ impl EphemerisFrame { let fid = self.to_field_id() as u32; let offset = Message::encode_bnxi(fid, big_endian, buf)?; - match self { - Self::GPSRaw(r) => r.encode(big_endian, &mut buf[offset..]), - Self::GPS(r) => r.encode(big_endian, &mut buf[offset..]), - Self::GLO(r) => r.encode(big_endian, &mut buf[offset..]), - Self::GAL(r) => r.encode(big_endian, &mut buf[offset..]), - Self::SBAS(r) => r.encode(big_endian, &mut buf[offset..]), - } + let size = match self { + Self::GPSRaw(r) => r.encode(big_endian, &mut buf[offset..])?, + Self::GPS(r) => r.encode(big_endian, &mut buf[offset..])?, + Self::GLO(r) => r.encode(big_endian, &mut buf[offset..])?, + Self::GAL(r) => r.encode(big_endian, &mut buf[offset..])?, + Self::SBAS(r) => r.encode(big_endian, &mut buf[offset..])?, + }; + + Ok(size + offset) } /// Creates new [GPSRaw] frame diff --git a/binex/src/message/record/monument/frame.rs b/binex/src/message/record/monument/frame.rs new file mode 100644 index 000000000..a2171a872 --- /dev/null +++ b/binex/src/message/record/monument/frame.rs @@ -0,0 +1,51 @@ +//! Monument Geodetic marker specific frames + +use crate::{ + message::{record::monument::FieldID, Message}, + Error, +}; + +// use log::error; + +#[cfg(test)] +mod test { + use super::*; + #[test] + fn geo_comments() { + let frame = MonumentGeoFrame::Comment("Hello".to_string()); + assert_eq!(frame.encoding_size(), 5 + 2); + + let big_endian = true; + let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let size = frame.encode(big_endian, &mut buf).unwrap(); + + assert_eq!(size, frame.encoding_size()); + assert_eq!( + buf, + [0, 5, 'H' as u8, 'e' as u8, 'l' as u8, 'l' as u8, 'o' as u8, 0, 0, 0, 0, 0, 0] + ); + + let decoded = MonumentGeoFrame::decode(big_endian, &buf).unwrap(); + + assert_eq!(decoded, frame); + } + #[test] + fn geo_climatic() { + let frame = MonumentGeoFrame::Climatic("ABC".to_string()); + assert_eq!(frame.encoding_size(), 3 + 2); + + let big_endian = true; + let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let size = frame.encode(big_endian, &mut buf).unwrap(); + + assert_eq!(size, frame.encoding_size()); + assert_eq!( + buf, + [14, 3, 'A' as u8, 'B' as u8, 'C' as u8, 0, 0, 0, 0, 0, 0] + ); + + let decoded = MonumentGeoFrame::decode(big_endian, &buf).unwrap(); + + assert_eq!(decoded, frame); + } +} diff --git a/binex/src/message/record/monument/mod.rs b/binex/src/message/record/monument/mod.rs index a228547c8..09550e1f0 100644 --- a/binex/src/message/record/monument/mod.rs +++ b/binex/src/message/record/monument/mod.rs @@ -24,10 +24,10 @@ pub use src::MonumentGeoMetadata; /// [GeoStringFrame] helps us encode / decode /// readable [MonumentGeoRecord] entries, which makes /// the vast majority of supported frames -struct GeoStringFrame { +pub struct GeoStringFrame { /// [FieldID] frame identifier - pub fid: FieldID, - /// readable string + pub(crate) fid: FieldID, + /// Readable string pub string: String, } @@ -38,13 +38,6 @@ impl GeoStringFrame { string: s.to_string(), } } - pub fn encoding_size(&self) -> usize { - let mut size = 2; // FID + FID_1_4 (will never exceed 1) - let s_len = self.string.len(); - size += Message::bnxi_encoding_size(s_len as u32); - size += s_len; - size - } } #[derive(Debug, Clone, Default, PartialEq)] @@ -56,7 +49,7 @@ pub struct MonumentGeoRecord { /// Readable comments (if any), repeat as needed. pub comments: Vec, /// Readable frames that we expose with high level methods - frames: Vec, + pub frames: Vec, } impl MonumentGeoRecord { @@ -90,8 +83,8 @@ impl MonumentGeoRecord { /// ); /// /// // customize as you need - /// let record = record. - /// with_comment("you can add") + /// let record = record + /// .with_comment("you can add") /// .with_comment("as many as you need") /// .with_extra_info("Experiment or setup context") /// .with_geophysical_info("Eurasian plate") @@ -276,7 +269,19 @@ impl MonumentGeoRecord { // bad ID: debug trace ? }, _ => { - ret.frames.push(GeoStringFrame::new(fid, s)); + // reflect uniqueness of this information + // if stream badly encodes many of these, we only lacth the latest one + if let Some(fr) = ret + .frames + .iter_mut() + .filter(|fr| fr.fid == fid) + .reduce(|k, _| k) + { + fr.string = s.to_string(); // overwrite with latest + } else { + // store new readable element + ret.frames.push(GeoStringFrame::new(fid, s)); + } }, } } @@ -383,97 +388,103 @@ impl MonumentGeoRecord { s } + // reflect uniqueness of this information + // if stream badly encodes many of these, we only lacth the latest one + fn push_or_update(&mut self, fid: FieldID, value: &str) { + if let Some(fr) = self + .frames + .iter_mut() + .filter(|fr| fr.fid == fid) + .reduce(|k, _| k) + { + fr.string = value.to_string(); // overwrite / update + } else { + // store new readable element + self.frames.push(GeoStringFrame::new(fid, value)); + } + } + /// Define receiver model. pub fn with_receiver_model(&self, model: &str) -> Self { let mut s = self.clone(); - s.frames - .push(GeoStringFrame::new(FieldID::ReceiverType, model)); + s.push_or_update(FieldID::ReceiverType, model); s } + /// Define receiver serial number (if known). pub fn with_receiver_serial_number(&self, sn: &str) -> Self { let mut s = self.clone(); - s.frames - .push(GeoStringFrame::new(FieldID::ReceiverNumber, sn)); + s.push_or_update(FieldID::ReceiverNumber, sn); s } + /// Define receiver firmware version (if known). pub fn with_receiver_firm_version(&self, version: &str) -> Self { let mut s = self.clone(); - s.frames.push(GeoStringFrame::new( - FieldID::ReceiverFirmwareVersion, - version, - )); + s.push_or_update(FieldID::ReceiverFirmwareVersion, version); s } /// Define name of observer pub fn with_observer(&self, observer: &str) -> Self { let mut s = self.clone(); - s.frames - .push(GeoStringFrame::new(FieldID::ObserverName, observer)); + s.push_or_update(FieldID::ObserverName, observer); s } /// Define observer's contact (email address) pub fn with_observer_contact(&self, contact: &str) -> Self { let mut s = self.clone(); - s.frames - .push(GeoStringFrame::new(FieldID::ObserverContact, contact)); + s.push_or_update(FieldID::ObserverContact, contact); s } + /// Define Geodetic marker name pub fn with_geodetic_marker_name(&self, name: &str) -> Self { let mut s = self.clone(); - s.frames - .push(GeoStringFrame::new(FieldID::MarkerName, name)); + s.push_or_update(FieldID::MarkerName, name); s } /// Define Geodetic marker number (DOMES) pub fn with_geodetic_marker_number(&self, domes: &str) -> Self { let mut s = self.clone(); - s.frames - .push(GeoStringFrame::new(FieldID::MarkerNumber, domes)); + s.push_or_update(FieldID::MarkerNumber, domes); s } /// Define Locatio of this geodetic site pub fn with_site_location(&self, location: &str) -> Self { let mut s = self.clone(); - s.frames - .push(GeoStringFrame::new(FieldID::SiteLocation, location)); + s.push_or_update(FieldID::SiteLocation, location); s } /// Define Agency (Organization) pub fn with_agency(&self, agency: &str) -> Self { let mut s = self.clone(); - s.frames - .push(GeoStringFrame::new(FieldID::AgencyName, agency)); + s.push_or_update(FieldID::AgencyName, agency); s } /// Define Antenna model (if known) pub fn with_antenna_model(&self, model: &str) -> Self { let mut s = self.clone(); - s.frames - .push(GeoStringFrame::new(FieldID::AntennaType, model)); + s.push_or_update(FieldID::AntennaType, model); s } /// Define Antenna serial number (if known) pub fn with_antenna_serial_number(&self, sn: &str) -> Self { let mut s = self.clone(); - s.frames - .push(GeoStringFrame::new(FieldID::AntennaNumber, sn)); + s.push_or_update(FieldID::AntennaNumber, sn); s } /// Define name of Geodetic site pub fn with_site_name(&self, name: &str) -> Self { let mut s = self.clone(); - s.frames.push(GeoStringFrame::new(FieldID::SiteName, name)); + s.push_or_update(FieldID::SiteName, name); s } @@ -482,8 +493,7 @@ impl MonumentGeoRecord { /// otherwise, the message will not respect the standard definitions. pub fn with_geophysical_info(&self, info: &str) -> Self { let mut s = self.clone(); - s.frames - .push(GeoStringFrame::new(FieldID::Geophysical, info)); + s.push_or_update(FieldID::Geophysical, info); s } @@ -492,7 +502,7 @@ impl MonumentGeoRecord { /// the message will not respect the standard definitions. pub fn with_climatic_info(&self, info: &str) -> Self { let mut s = self.clone(); - s.frames.push(GeoStringFrame::new(FieldID::Climatic, info)); + s.push_or_update(FieldID::Climatic, info); s } @@ -501,15 +511,14 @@ impl MonumentGeoRecord { /// the message will not respect the standard definitions. pub fn with_user_id(&self, userid: &str) -> Self { let mut s = self.clone(); - s.frames.push(GeoStringFrame::new(FieldID::UserID, userid)); + s.push_or_update(FieldID::UserID, userid); s } /// Provide the name of this Geodetic project (if any). pub fn with_project_name(&self, name: &str) -> Self { let mut s = self.clone(); - s.frames - .push(GeoStringFrame::new(FieldID::ProjectName, name)); + s.push_or_update(FieldID::ProjectName, name); s } @@ -517,7 +526,7 @@ impl MonumentGeoRecord { /// or experiment) pub fn with_extra_info(&self, extra: &str) -> Self { let mut s = self.clone(); - s.frames.push(GeoStringFrame::new(FieldID::Extra, extra)); + s.push_or_update(FieldID::Extra, extra); s } } diff --git a/binex/src/stream.rs b/binex/src/stream.rs index ba5db854d..19eb26b0f 100644 --- a/binex/src/stream.rs +++ b/binex/src/stream.rs @@ -1,5 +1,5 @@ //! BINEX Stream representation -use crate::prelude::Message; +use crate::prelude::{ClosedSourceMeta, Message}; /// [Message] [Provider] #[derive(Debug, Copy, Clone, PartialEq)] @@ -12,7 +12,7 @@ pub enum Provider { ColoradoUnivBoulder, /// NRCan for internal needs or prototyping. NRCan, - /// UCAR COSMIC [https://www.cosmic.ucar.edu] + /// UCAR COSMIC UCAR, /// GPS Solutions Inc. GPSSolutions, @@ -49,24 +49,18 @@ impl Provider { /// Closed source frame that we can encode but not interprate. /// This particular [StreamElement] can be either a part of a continuous serie or self sustainable. pub struct ClosedSourceElement<'a> { - /// Provider of this frame. - /// Only this organization may have capabilities to interprate this frame. - pub provider: Provider, - /// Size of this element. Use this to determine the packet index - /// in a continuous stream of undisclosed [StreamElement]s. + /// [ClosedSourceMeta] + pub meta: ClosedSourceMeta, + /// Size of this [StreamElement]: this is not + /// the size of the complete message, in case this is part + /// of a serie of [StreamElement]s. pub size: usize, - /// Total size of this undisclosed message. Use this to determine the packet index - /// in a continuous stream of undisclosed [StreamElement]s. - pub total: usize, - /// Raw data content that we can encode, decode but not interprate. - raw: &'a [u8], + /// Raw data starting at first byte of undisclosed payload. + pub raw: &'a [u8], } impl<'a> ClosedSourceElement<'a> { /// Interprate this [ClosedSourceElement] using custom undisclosed method. - /// ``` - /// - /// ``` pub fn interprate(&self, f: &dyn Fn(&[u8])) { f(&self.raw[..self.size]) } @@ -104,13 +98,32 @@ impl<'a> StreamElement<'a> { /// - provider: specific [Provider] /// - raw: content we can encode, decode but not interprate /// - size: size of this [StreamElement] - /// - total: total size of the [StreamElement] serie - pub fn new_prototype(provider: Provider, raw: &'a [u8], size: usize, total: usize) -> Self { + /// - mlen: total message lenth + /// - reversed: whether this uses the reversed stream algorithm or not + /// - enhanced_crc: whether this uses the enhanced CRC or not + /// - big_endian: whether we'll use "big" endianess when encoding, or not. + pub fn new_prototype( + provider: Provider, + mid: u32, + raw: &'a [u8], + size: usize, + mlen: usize, + reversed: bool, + enhanced_crc: bool, + big_endian: bool, + ) -> Self { Self::ClosedSource(ClosedSourceElement { raw, - total, size, - provider, + meta: ClosedSourceMeta { + mid, + mlen, + reversed, + enhanced_crc, + big_endian, + provider, + offset: 0, + }, }) } @@ -120,8 +133,28 @@ impl<'a> StreamElement<'a> { /// - raw: content we can encode, decode but not interprate /// - size: size of the provided buffer (bytewise) /// - total: total size of the closed source Message (bytewise) - pub fn jpl_prototype(raw: &'a [u8], size: usize, total: usize) -> Self { - Self::new_prototype(Provider::JPL, raw, size, total) + /// - reversed: whether this uses the reversed stream algorithm or not + /// - enhanced_crc: whether this uses the enhanced CRC or not + /// - big_endian: whether we'll use "big" endianess when encoding, or not. + pub fn jpl_prototype( + raw: &'a [u8], + mid: u32, + size: usize, + total: usize, + reversed: bool, + enhanced_crc: bool, + big_endian: bool, + ) -> Self { + Self::new_prototype( + Provider::JPL, + mid, + raw, + size, + total, + reversed, + enhanced_crc, + big_endian, + ) } /// Add one closed source [StreamElement]s provided by desired [Provider::JPL]. @@ -130,8 +163,28 @@ impl<'a> StreamElement<'a> { /// - raw: content we can encode, decode but not interprate /// - size: size of the provided buffer (bytewise) /// - total: total size of the closed source Message (bytewise) - pub fn igs_prototype(raw: &'a [u8], size: usize, total: usize) -> Self { - Self::new_prototype(Provider::IGS, raw, size, total) + /// - reversed: whether this uses the reversed stream algorithm or not + /// - enhanced_crc: whether this uses the enhanced CRC or not + /// - big_endian: whether we'll use "big" endianess when encoding, or not. + pub fn igs_prototype( + raw: &'a [u8], + mid: u32, + size: usize, + total: usize, + reversed: bool, + enhanced_crc: bool, + big_endian: bool, + ) -> Self { + Self::new_prototype( + Provider::IGS, + mid, + raw, + size, + total, + reversed, + enhanced_crc, + big_endian, + ) } /// Add one closed source [StreamElement]s provided by desired [Provider::ColoradoUnivBoulder]. @@ -140,8 +193,28 @@ impl<'a> StreamElement<'a> { /// - raw: content we can encode, decode but not interprate /// - size: size of the provided buffer (bytewise) /// - total: total size of the closed source Message (bytewise) - pub fn cuboulder_prototype(raw: &'a [u8], size: usize, total: usize) -> Self { - Self::new_prototype(Provider::ColoradoUnivBoulder, raw, size, total) + /// - reversed: whether this uses the reversed stream algorithm or not + /// - enhanced_crc: whether this uses the enhanced CRC or not + /// - big_endian: whether we'll use "big" endianess when encoding, or not. + pub fn cuboulder_prototype( + raw: &'a [u8], + mid: u32, + size: usize, + total: usize, + reversed: bool, + enhanced_crc: bool, + big_endian: bool, + ) -> Self { + Self::new_prototype( + Provider::ColoradoUnivBoulder, + mid, + raw, + size, + total, + reversed, + enhanced_crc, + big_endian, + ) } /// Add one closed source [StreamElement]s provided by desired [Provider::NRCan]. @@ -150,8 +223,28 @@ impl<'a> StreamElement<'a> { /// - raw: content we can encode, decode but not interprate /// - size: size of the provided buffer (bytewise) /// - total: total size of the closed source Message (bytewise) - pub fn nrcan_prototype(raw: &'a [u8], size: usize, total: usize) -> Self { - Self::new_prototype(Provider::NRCan, raw, size, total) + /// - reversed: whether this uses the reversed stream algorithm or not + /// - enhanced_crc: whether this uses the enhanced CRC or not + /// - big_endian: whether we'll use "big" endianess when encoding, or not. + pub fn nrcan_prototype( + raw: &'a [u8], + mid: u32, + size: usize, + total: usize, + reversed: bool, + enhanced_crc: bool, + big_endian: bool, + ) -> Self { + Self::new_prototype( + Provider::NRCan, + mid, + raw, + size, + total, + reversed, + enhanced_crc, + big_endian, + ) } /// Add one closed source [StreamElement]s provided by desired [Provider::UCAR]. @@ -160,7 +253,27 @@ impl<'a> StreamElement<'a> { /// - raw: content we can encode, decode but not interprate /// - size: size of the provided buffer (bytewise) /// - total: total size of the closed source Message (bytewise) - pub fn ucar_prototype(raw: &'a [u8], size: usize, total: usize) -> Self { - Self::new_prototype(Provider::UCAR, raw, size, total) + /// - reversed: whether this uses the reversed stream algorithm or not + /// - enhanced_crc: whether this uses the enhanced CRC or not + /// - big_endian: whether we'll use "big" endianess when encoding, or not. + pub fn ucar_prototype( + raw: &'a [u8], + mid: u32, + size: usize, + total: usize, + reversed: bool, + enhanced_crc: bool, + big_endian: bool, + ) -> Self { + Self::new_prototype( + Provider::UCAR, + mid, + raw, + size, + total, + reversed, + enhanced_crc, + big_endian, + ) } } diff --git a/binex/tests/decoder.rs b/binex/tests/decoder.rs index b1786d622..70bb652bc 100644 --- a/binex/tests/decoder.rs +++ b/binex/tests/decoder.rs @@ -14,7 +14,7 @@ fn mfle20190130() { found += 1; println!("parsed: {:?}", msg); }, - Some(Ok(StreamElement::ClosedSource(element))) => {}, + Some(Ok(StreamElement::ClosedSource(_))) => {}, Some(Err(e)) => match e { Error::IoError => panic!("i/o error"), e => { @@ -44,7 +44,7 @@ fn gziped_files() { found += 1; println!("parsed: {:?}", msg); }, - Some(Ok(StreamElement::ClosedSource(element))) => {}, + Some(Ok(StreamElement::ClosedSource(_))) => {}, Some(Err(e)) => match e { Error::IoError => panic!("i/o error"), e => { diff --git a/binex/tests/message.rs b/binex/tests/message.rs index 37df33a00..920c30f6a 100644 --- a/binex/tests/message.rs +++ b/binex/tests/message.rs @@ -1,6 +1,5 @@ use binex::prelude::{ - EphemerisFrame, Epoch, GPSEphemeris, GPSRaw, Message, MonumentGeoMetadata, MonumentGeoRecord, - Record, TimeResolution, + EphemerisFrame, Epoch, GPSEphemeris, GPSRaw, Message, MonumentGeoRecord, Record, TimeResolution, }; #[test] @@ -60,7 +59,7 @@ fn test_crc16_geo() { } #[test] -fn test_crc8_eph() { +fn test_crc8_gps() { let msg = Message::new( true, TimeResolution::QuarterSecond, @@ -74,15 +73,14 @@ fn test_crc8_eph() { assert_eq!(buf[0], 226); // SYNC assert_eq!(buf[1], 1); // MID - assert_eq!(buf[2], 78); // RLEN - // assert_eq!(buf[3 + 78], 79); // CRC TODO + assert_eq!(buf[2], 79); // RLEN let parsed = Message::decode(&buf).unwrap(); assert_eq!(msg, parsed); } #[test] -fn test_crc16_eph() { +fn test_crc16_gps() { let msg = Message::new( true, TimeResolution::QuarterSecond, @@ -91,12 +89,12 @@ fn test_crc16_eph() { Record::new_ephemeris_frame(EphemerisFrame::new_gps(GPSEphemeris::default())), ); - let mut buf = [0; 128]; - assert!(msg.encode(&mut buf).is_err()); + let mut encoded = [0; 128]; + assert!(msg.encode(&mut encoded).is_err()); - let mut buf = [0; 256]; - msg.encode(&mut buf).unwrap(); + let mut encoded = [0; 256]; + msg.encode(&mut encoded).unwrap(); - let parsed = Message::decode(&buf).unwrap(); + let parsed = Message::decode(&encoded).unwrap(); assert_eq!(msg, parsed); } diff --git a/binex/tools/crc16.py b/binex/tools/crc16.py index 43fa011f5..65be05d92 100755 --- a/binex/tools/crc16.py +++ b/binex/tools/crc16.py @@ -13,7 +13,7 @@ def generate_crc16_look_up_table(): crc &= 0xffff fd.write("0x{:04X}, ".format(crc)) - if (i+1) % 4 == 0 : + if (i+1) % 8 == 0 : fd.write("\n") if __name__ == "__main__": diff --git a/binex/tools/crc32.py b/binex/tools/crc32.py index daf32ba46..e72cf8a20 100755 --- a/binex/tools/crc32.py +++ b/binex/tools/crc32.py @@ -10,8 +10,8 @@ def generate_crc32_look_up_table(): crc = (crc << 1) ^ polynomial else: crc = crc << 1 - crc &= 0xffffffff + fd.write("0x{:04X}, ".format(crc)) if (i+1) % 8 == 0 : fd.write("\n")