use bytes::{BufMut, Bytes, BytesMut};
use super::DeserializeError;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SeqBlock {
pub base_sequence: u64,
pub block_size: u64,
}
impl SeqBlock {
pub fn new(base_sequence: u64, block_size: u64) -> Self {
Self {
base_sequence,
block_size,
}
}
pub fn serialize(&self) -> Bytes {
let mut buf = BytesMut::with_capacity(16);
buf.put_u64(self.base_sequence);
buf.put_u64(self.block_size);
buf.freeze()
}
pub fn deserialize(data: &[u8]) -> Result<Self, DeserializeError> {
if data.len() < 16 {
return Err(DeserializeError {
message: format!(
"buffer too short for SeqBlock value: need 16 bytes, got {}",
data.len()
),
});
}
let base_sequence = u64::from_be_bytes([
data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
]);
let block_size = u64::from_be_bytes([
data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15],
]);
Ok(SeqBlock {
base_sequence,
block_size,
})
}
pub fn next_base(&self) -> u64 {
self.base_sequence + self.block_size
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn should_serialize_and_deserialize_seq_block() {
let value = SeqBlock::new(1000, 100);
let serialized = value.serialize();
let deserialized = SeqBlock::deserialize(&serialized).unwrap();
assert_eq!(deserialized, value);
assert_eq!(serialized.len(), 16);
}
#[test]
fn should_calculate_next_base() {
let value = SeqBlock::new(1000, 100);
let next = value.next_base();
assert_eq!(next, 1100);
}
#[test]
fn should_fail_deserialize_when_buffer_too_short() {
let data = vec![0u8; 15];
let result = SeqBlock::deserialize(&data);
assert!(result.is_err());
assert!(
result
.unwrap_err()
.message
.contains("buffer too short for SeqBlock value")
);
}
#[test]
fn should_serialize_in_big_endian() {
let value = SeqBlock::new(0x0102030405060708, 0x1112131415161718);
let serialized = value.serialize();
assert_eq!(
serialized.as_ref(),
&[
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, ]
);
}
#[test]
fn should_handle_zero_values() {
let value = SeqBlock::new(0, 0);
let serialized = value.serialize();
let deserialized = SeqBlock::deserialize(&serialized).unwrap();
assert_eq!(deserialized.base_sequence, 0);
assert_eq!(deserialized.block_size, 0);
assert_eq!(deserialized.next_base(), 0);
}
#[test]
fn should_handle_max_values() {
let value = SeqBlock::new(u64::MAX, u64::MAX);
let serialized = value.serialize();
let deserialized = SeqBlock::deserialize(&serialized).unwrap();
assert_eq!(deserialized.base_sequence, u64::MAX);
assert_eq!(deserialized.block_size, u64::MAX);
}
}