COBS encode checksum.
https://github.com/fluffysquirrels/framed-rs/issues/30
This commit is contained in:
parent
8e9fe0e182
commit
18c295391a
5 changed files with 54 additions and 74 deletions
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -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)",
|
||||
]
|
||||
|
|
|
@ -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 <alex.helfet@gmail.com>"]
|
||||
categories = ["no-std", "embedded", "encoding", "network-programming"]
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -19,6 +19,9 @@ pub enum Error {
|
|||
/// COBS decode failed
|
||||
CobsDecodeFailed,
|
||||
|
||||
/// COBS encode failed
|
||||
CobsEncodeFailed,
|
||||
|
||||
/// Checksum error: the received frame was corrupted.
|
||||
ChecksumError,
|
||||
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
//!
|
||||
//! Currently the encoding is:
|
||||
//!
|
||||
//! * Header:
|
||||
//! * Nothing here yet.
|
||||
//! * Body: payload [COBS]-encoded to remove bytes equal to zero
|
||||
//! * Frame [COBS]-encoded to remove bytes equal to zero
|
||||
//! * Payload: supplied by user
|
||||
//! * Footer:
|
||||
//! * A variable length checksum, depending on configuration in `framed::bytes::Config`.
|
||||
//! * 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
|
||||
|
|
Loading…
Reference in a new issue