diff options
Diffstat (limited to 'src/binary')
-rw-r--r-- | src/binary/mod.rs | 2 | ||||
-rw-r--r-- | src/binary/reverse_appendix.rs | 35 |
2 files changed, 37 insertions, 0 deletions
diff --git a/src/binary/mod.rs b/src/binary/mod.rs new file mode 100644 index 0000000..66f6c30 --- /dev/null +++ b/src/binary/mod.rs @@ -0,0 +1,2 @@ +mod reverse_appendix; +pub use reverse_appendix::*; diff --git a/src/binary/reverse_appendix.rs b/src/binary/reverse_appendix.rs new file mode 100644 index 0000000..d131526 --- /dev/null +++ b/src/binary/reverse_appendix.rs @@ -0,0 +1,35 @@ +use crate::{Codec, Error}; + +/// Reverses payload binary data and writes it ass-first past the end of the original data. A +/// length marker is also prepended to the payload *before reversing* so the decoder knows how long +/// the payload is. +pub struct BinaryReverseAppendixCodec; + +impl Codec for BinaryReverseAppendixCodec { + fn encode(&self, carrier: &[u8], payload: &[u8]) -> Result<Vec<u8>, crate::Error> { + let mut encoded = Vec::<u8>::new(); + encoded.extend(carrier.iter()); + let payload_len = (payload.len() as u64 + 8).to_le_bytes(); + encoded.extend(payload_len.iter().chain(payload.iter()).rev()); + Ok(encoded) + } + + fn decode(&self, encoded: &[u8]) -> Result<(Vec<u8>, Vec<u8>), crate::Error> { + if encoded.len() < 8 { + return Err(Error::DataNotEncoded); + } + + let encoded_len = encoded.len(); + let payload_len = u64::from_le_bytes(encoded.iter().rev().take(8).cloned().collect::<Vec<_>>().try_into().unwrap()) as usize; + if encoded_len < payload_len + 8 || payload_len < 8 { + return Err(Error::DataNotEncoded); + } + + let carrier_len = encoded_len - payload_len; + + let carrier = encoded[..carrier_len].to_vec(); + let payload = encoded.iter().rev().skip(8).take(payload_len - 8).cloned().collect::<Vec<_>>(); + + Ok((carrier, payload)) + } +} |