diff --git a/Cargo.lock b/Cargo.lock index 4273b66..783b095 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,7 +97,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "framed" -version = "0.4.1" +version = "0.4.2" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cobs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -115,7 +115,7 @@ dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.0-beta.5 (registry+https://github.com/rust-lang/crates.io-index)", "derive-error 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "framed 0.4.1", + "framed 0.4.2", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -123,7 +123,7 @@ dependencies = [ name = "framed_test_type" version = "0.1.0" dependencies = [ - "framed 0.4.1", + "framed 0.4.2", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/framed/Cargo.toml b/framed/Cargo.toml index 9c92aa4..9a764c8 100644 --- a/framed/Cargo.toml +++ b/framed/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "framed" -version = "0.4.1" +version = "0.4.2" description = "Send and receive data over lossy streams of bytes." authors = ["Alex Helfet "] categories = ["no-std", "embedded", "encoding", "network-programming"] diff --git a/framed/src/bytes.rs b/framed/src/bytes.rs index ac300ce..04b2d86 100644 --- a/framed/src/bytes.rs +++ b/framed/src/bytes.rs @@ -156,27 +156,17 @@ impl Config { } } -const MAX_HEADER_LEN: usize = 0; - -const MAX_FOOTER_LEN: usize = MAX_CHECKSUM_LEN + 1; - -const MAX_FRAMING_LEN: usize = MAX_HEADER_LEN + MAX_FOOTER_LEN; +const MAX_FRAMING_LEN: usize = MAX_CHECKSUM_LEN + 1; impl Codec { fn checksum(&self) -> &Checksum { &self.config.checksum } - fn header_len(&self) -> usize { - 0 - } - - fn footer_len(&self) -> usize { - 1 + self.checksum().len() - } - - fn framing_len(&self) -> usize { - self.header_len() + self.footer_len() + fn min_frame_len(&self) -> usize { + 0 // payload length + + self.checksum().len() + + 1 // sentinel length } /// Encode the supplied payload data as a frame at the beginning of @@ -198,30 +188,25 @@ impl Codec { println!("framed::encode: Payload = {:?}", p); } - let cobs_len = cobs::encode(&p, &mut dest[self.header_len()..]); - let checksum = self.checksum(); - let checksum_value = checksum.calculate(p); - let checksum_len = checksum.len(); + let checksum_type = self.checksum(); + let checksum_value = checksum_type.calculate(p); - { - let mut _header = &mut dest[0..self.header_len()]; + let cobs_len = { + let mut cobs_enc = cobs::CobsEncoder::new(dest); + cobs_enc.push(p) + .map_err(|_| Error::CobsEncodeFailed)?; + if checksum_value.len() > 0 { + cobs_enc.push(&*checksum_value) + .map_err(|_| Error::CobsEncodeFailed)?; + } + let cobs_len = cobs_enc.finalize() + .map_err(|_| Error::CobsEncodeFailed)?; + cobs_len + }; + dest[cobs_len] = FRAME_END_SYMBOL; - #[cfg(feature = "trace")] { - println!("framed::encode: Header = {:?}", _header); - } - } - { - let footer = &mut dest[ - (self.header_len() + cobs_len) - .. - (self.header_len() + cobs_len + self.footer_len())]; - footer[0..checksum_len].copy_from_slice(&*checksum_value); - footer[checksum_len] = FRAME_END_SYMBOL; - #[cfg(feature = "trace")] { - println!("framed::encode: Footer = {:?}", footer); - } - } - let len = self.header_len() + cobs_len + self.footer_len(); + // len is cobs_len + len(FRAME_END_SYMBOL) + let len = cobs_len + 1; #[cfg(feature = "trace")] { println!("framed::encode: Frame = {:?}", &dest[0..len]); } @@ -287,7 +272,7 @@ impl Codec { return Err(Error::EofBeforeFrame); } - if e.len() < self.framing_len() { + if e.len() < self.min_frame_len() { return Err(Error::EofDuringFrame); } @@ -298,47 +283,39 @@ impl Codec { assert!(dest.len() >= max_decoded_len(e.len())); assert_eq!(e[e.len() - 1], FRAME_END_SYMBOL); - let _header = &e[0..self.header_len()]; - let body = &e[self.header_len()..(e.len() - self.footer_len())]; - let footer = &e[(e.len() - self.footer_len())..e.len()]; - - #[cfg(feature = "trace")] { - println!("framed::decode: header = {:?}\n\ - framed::decode: body = {:?}\n\ - framed::decode: footer = {:?}", - _header, body, footer); - } - - let decoded_len = - if body.len() == 0 { + let cobs_payload = &e[0..e.len() - 1]; + let cobs_decoded_len = + if cobs_payload.len() == 0 { 0 } else { - cobs::decode(body, dest) + cobs::decode(cobs_payload, dest) .map_err(|_| Error::CobsDecodeFailed)? }; - - let decoded = &dest[0..decoded_len]; + let cobs_decoded = &dest[0..cobs_decoded_len]; + let payload = &cobs_decoded[0..cobs_decoded_len - self.checksum().len()]; #[cfg(feature = "trace")] { + println!("framed::decode: cobs_decoded = {:?}", + cobs_decoded); println!("framed::decode: payload = {:?}", - decoded); + payload); } let checksum = self.checksum(); - let calc_checksum = checksum.calculate(decoded); - let received_checksum = &footer[0..checksum.len()]; + let calc_checksum = checksum.calculate(payload); + let recv_checksum = &cobs_decoded[payload.len() .. payload.len() + checksum.len()]; #[cfg(feature = "trace")] { - println!("framed::decode: calc checksum = {:?}\n\ - framed::decode: recv checksum = {:?}", - calc_checksum, received_checksum); + println!("framed::decode: calc_checksum = {:?}\n\ + framed::decode: recv_checksum = {:?}", + calc_checksum, recv_checksum); } - if &*calc_checksum != received_checksum { + if &*calc_checksum != recv_checksum { return Err(Error::ChecksumError); } - Ok(decoded_len) + Ok(payload.len()) } /// Decode the supplied encoded frame, returning the payload on the heap. @@ -634,7 +611,7 @@ mod tests { #[cfg(feature = "use_std")] fn decode_to_slice_encoded_too_short() { let mut c = codec(); - let encoded = vec![FRAME_END_SYMBOL; c.framing_len() - 1]; + let encoded = vec![FRAME_END_SYMBOL; c.min_frame_len() - 1]; let mut decoded_buf = []; let res = c.decode_to_slice(&*encoded, &mut decoded_buf); @@ -663,7 +640,7 @@ mod tests { let mut c = codec(); let encoded = c.encode_to_box(&PAYLOAD).unwrap(); let mut encoded = Vec::from(&*encoded); - let checksum_offset = encoded.len() - c.footer_len(); + let checksum_offset = encoded.len() - c.checksum().len() - 1; { let checksum = diff --git a/framed/src/error.rs b/framed/src/error.rs index 059eab9..6de17e4 100644 --- a/framed/src/error.rs +++ b/framed/src/error.rs @@ -19,6 +19,9 @@ pub enum Error { /// COBS decode failed CobsDecodeFailed, + /// COBS encode failed + CobsEncodeFailed, + /// Checksum error: the received frame was corrupted. ChecksumError, diff --git a/framed/src/lib.rs b/framed/src/lib.rs index aa2165a..8c149ef 100644 --- a/framed/src/lib.rs +++ b/framed/src/lib.rs @@ -22,12 +22,12 @@ //! //! Currently the encoding is: //! -//! * Header: -//! * Nothing here yet. -//! * Body: payload [COBS]-encoded to remove bytes equal to zero -//! * Footer: -//! * A variable length checksum, depending on configuration in `framed::bytes::Config`. -//! * A terminating zero byte. +//! * Frame [COBS]-encoded to remove bytes equal to zero +//! * Payload: supplied by user +//! * Footer: +//! * A checksum computed over the payload. The type of checksum depends +//! on the configuration in `framed::bytes::Config`. +//! * A terminating zero byte. //! //! [COBS]: https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing //!