use integer_encoding::VarInt;
pub const MAX_ENCODED_SIZE: usize = 10;
pub fn encode_size<'a>(message: &[u8], buf: &'a mut [u8; MAX_ENCODED_SIZE]) -> &'a [u8] {
let varint_size = message.len().encode_var(buf);
&buf[..varint_size]
}
pub fn decode_size(data: &[u8]) -> Option<(usize, usize)> {
usize::decode_var(data)
}
pub struct Decoder {
stored: Vec<u8>,
}
impl Default for Decoder {
fn default() -> Decoder {
Decoder { stored: Vec::new() }
}
}
impl Decoder {
fn try_decode(&mut self, data: &[u8], mut decoded_callback: impl FnMut(&[u8])) {
let mut next_data = data;
loop {
if let Some((expected_size, used_bytes)) = decode_size(&next_data) {
let remaining = &next_data[used_bytes..];
if remaining.len() >= expected_size {
let (decoded, not_decoded) = remaining.split_at(expected_size);
decoded_callback(decoded);
if !not_decoded.is_empty() {
next_data = not_decoded;
continue
}
else {
break
}
}
}
self.stored.extend_from_slice(next_data);
break
}
}
fn store_and_decoded_data<'a>(&mut self, data: &'a [u8]) -> Option<(&[u8], &'a [u8])> {
let ((expected_size, used_bytes), data) = match decode_size(&self.stored) {
Some(size_info) => (size_info, data),
None => {
let max_remaining = (MAX_ENCODED_SIZE - self.stored.len()).min(data.len());
self.stored.extend_from_slice(&data[..max_remaining]);
if let Some(x) = decode_size(&self.stored) {
(x, &data[max_remaining..])
}
else {
return None
}
}
};
let remaining = expected_size - (self.stored.len() - used_bytes);
if data.len() < remaining {
self.stored.extend_from_slice(data);
None
}
else {
let (to_store, remaining) = data.split_at(remaining);
self.stored.extend_from_slice(to_store);
Some((&self.stored[used_bytes..], remaining))
}
}
pub fn decode(&mut self, data: &[u8], mut decoded_callback: impl FnMut(&[u8])) {
if self.stored.is_empty() {
self.try_decode(data, decoded_callback);
}
else {
if let Some((decoded_data, remaining)) = self.store_and_decoded_data(data) {
decoded_callback(decoded_data);
self.stored.clear();
self.try_decode(remaining, decoded_callback);
}
}
}
pub fn stored_size(&self) -> usize {
self.stored.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
const MESSAGE_SIZE: usize = 20;
const ENCODED_MESSAGE_SIZE: usize = 1 + MESSAGE_SIZE;
const MESSAGE: [u8; MESSAGE_SIZE] = [42; MESSAGE_SIZE];
const MESSAGE_A: [u8; MESSAGE_SIZE] = ['A' as u8; MESSAGE_SIZE];
const MESSAGE_B: [u8; MESSAGE_SIZE] = ['B' as u8; MESSAGE_SIZE];
const MESSAGE_C: [u8; MESSAGE_SIZE] = ['C' as u8; MESSAGE_SIZE];
fn encode_message(buffer: &mut Vec<u8>, message: &[u8]) {
let mut buf = [0; MAX_ENCODED_SIZE];
buffer.extend_from_slice(&*encode_size(message, &mut buf));
buffer.extend_from_slice(message);
}
#[test]
fn encode_one_message() {
let mut buffer = Vec::new();
encode_message(&mut buffer, &MESSAGE);
assert_eq!(ENCODED_MESSAGE_SIZE, buffer.len());
let (expected_size, used_bytes) = decode_size(&buffer).unwrap();
assert_eq!(MESSAGE_SIZE, expected_size);
assert_eq!(used_bytes, 1);
assert_eq!(&MESSAGE, &buffer[used_bytes..]);
}
#[test]
fn encode_one_big_message() {
let mut buffer = Vec::new();
encode_message(&mut buffer, &vec![0; 1000]);
assert_eq!(1002, buffer.len());
let (expected_size, used_bytes) = decode_size(&buffer).unwrap();
assert_eq!(1000, expected_size);
assert_eq!(used_bytes, 2);
assert_eq!(&vec![0; 1000], &buffer[used_bytes..]);
}
#[test]
fn decode_one_message() {
let mut buffer = Vec::new();
encode_message(&mut buffer, &MESSAGE);
let mut decoder = Decoder::default();
let mut times_called = 0;
decoder.decode(&buffer, |decoded| {
times_called += 1;
assert_eq!(MESSAGE, decoded);
});
assert_eq!(1, times_called);
assert_eq!(0, decoder.stored.len());
}
#[test]
fn decode_message_no_size() {
let mut buffer = Vec::new();
encode_message(&mut buffer, &[]);
let mut decoder = Decoder::default();
let mut times_called = 0;
decoder.decode(&buffer, |_decoded| {
times_called += 1;
});
assert_eq!(1, times_called);
assert_eq!(0, decoder.stored.len());
}
#[test]
fn decode_message_one_byte() {
let mut buffer = Vec::new();
encode_message(&mut buffer, &[0xFF]);
let mut decoder = Decoder::default();
let mut times_called = 0;
decoder.decode(&buffer, |decoded| {
times_called += 1;
assert_eq!([0xFF], decoded);
});
assert_eq!(1, times_called);
assert_eq!(0, decoder.stored.len());
}
#[test]
fn decode_multiple_messages_exact() {
let mut buffer = Vec::new();
let messages = [&MESSAGE_A, &MESSAGE_B, &MESSAGE_C];
encode_message(&mut buffer, messages[0]);
encode_message(&mut buffer, messages[1]);
encode_message(&mut buffer, messages[2]);
let mut decoder = Decoder::default();
let mut times_called = 0;
decoder.decode(&buffer, |decoded| {
assert_eq!(messages[times_called], decoded);
times_called += 1;
});
assert_eq!(3, times_called);
assert_eq!(0, decoder.stored.len());
}
#[test]
fn decode_one_message_in_two_parts() {
let mut buffer = Vec::new();
encode_message(&mut buffer, &MESSAGE);
const SPLIT: usize = ENCODED_MESSAGE_SIZE / 2;
let (first, second) = buffer.split_at(SPLIT);
let mut decoder = Decoder::default();
let mut times_called = 0;
decoder.decode(&first, |_decoded| {
times_called += 1;
});
assert_eq!(0, times_called);
assert_eq!(SPLIT, decoder.stored.len());
decoder.decode(&second, |decoded| {
times_called += 1;
assert_eq!(MESSAGE, decoded);
});
assert_eq!(1, times_called);
assert_eq!(0, decoder.stored.len());
}
#[test]
fn decode_two_messages_in_two_parts() {
let mut buffer = Vec::new();
encode_message(&mut buffer, &MESSAGE);
encode_message(&mut buffer, &MESSAGE);
const SPLIT: usize = ENCODED_MESSAGE_SIZE * 2 / 3;
let (first, second) = buffer.split_at(SPLIT);
let mut decoder = Decoder::default();
let mut times_called = 0;
decoder.decode(&first, |_decoded| {
times_called += 1;
});
assert_eq!(0, times_called);
assert_eq!(SPLIT, decoder.stored.len());
decoder.decode(&second, |decoded| {
times_called += 1;
assert_eq!(MESSAGE, decoded);
});
assert_eq!(2, times_called);
assert_eq!(0, decoder.stored.len());
}
#[test]
fn decode_byte_per_byte() {
let mut buffer = Vec::new();
encode_message(&mut buffer, &MESSAGE);
let mut decoder = Decoder::default();
let mut times_called = 0;
for i in 0..buffer.len() {
decoder.decode(&buffer[i..i + 1], |decoded| {
assert_eq!(buffer.len() - 1, i);
times_called += 1;
assert_eq!(MESSAGE, decoded);
});
if i < buffer.len() - 1 {
assert_eq!(i + 1, decoder.stored.len());
}
}
assert_eq!(0, decoder.stored.len());
assert_eq!(1, times_called);
}
#[test]
fn decode_message_after_non_enough_padding() {
let msg = [0; 1000];
let mut buffer = Vec::new();
encode_message(&mut buffer, &msg);
let (start_1b, remaining) = buffer.split_at(2);
let mut decoder = Decoder::default();
let mut times_called = 0;
decoder.decode(&start_1b, |_decoded| {
times_called += 1;
});
assert_eq!(0, times_called);
assert_eq!(2, decoder.stored.len());
decoder.decode(&remaining, |decoded| {
times_called += 1;
assert_eq!(msg, decoded);
});
assert_eq!(1, times_called);
assert_eq!(0, decoder.stored.len());
}
#[test]
fn decode_message_var_size_in_two_data() {
let msg = [0; 1000];
let mut buffer = Vec::new();
encode_message(&mut buffer, &msg);
let (start_1b, remaining) = buffer.split_at(1);
let mut decoder = Decoder::default();
let mut times_called = 0;
decoder.decode(&start_1b, |_decoded| {
times_called += 1;
});
assert_eq!(0, times_called);
assert_eq!(1, decoder.stored.len());
let (next_1b, remaining) = remaining.split_at(1);
let mut times_called = 0;
decoder.decode(&next_1b, |_decoded| {
times_called += 1;
});
assert_eq!(0, times_called);
assert_eq!(2, decoder.stored.len());
decoder.decode(&remaining, |decoded| {
times_called += 1;
assert_eq!(msg, decoded);
});
assert_eq!(1, times_called);
assert_eq!(0, decoder.stored.len());
}
}