use super::{
AppendKey, Authority, CodecError, Cursor, ENVELOPE_BYTES, Envelope, Opcode, Packet,
PartitionIncarnation, Policy, capacity, command, decode_common, encode_common, identities,
};
use crate::EnvelopeLimits;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Confirmed {
pub authority: Authority,
pub partition: PartitionIncarnation,
pub owner_epoch: u64,
pub key: AppendKey,
pub end_sequence: u64,
pub first_offset: u64,
pub policy: Policy,
}
pub fn encode_confirmed(
envelope: Envelope,
confirmed: Confirmed,
metadata: &mut Vec<u8>,
limits: EnvelopeLimits,
) -> Result<[u8; ENVELOPE_BYTES], CodecError> {
command(envelope, Opcode::Appended, true)?;
identities(
confirmed.authority,
confirmed.partition,
confirmed.owner_epoch,
confirmed.key,
)?;
range(confirmed)?;
let header = envelope.encode_header(106, 0, limits)?;
capacity(metadata, 106)?;
metadata.clear();
encode_common(
metadata,
confirmed.authority,
confirmed.partition,
confirmed.owner_epoch,
confirmed.key,
);
metadata.extend_from_slice(&confirmed.end_sequence.to_be_bytes());
metadata.extend_from_slice(&confirmed.first_offset.to_be_bytes());
metadata.push(confirmed.policy as u8);
Ok(header)
}
pub fn decode_confirmed(
packet: Packet<'_>,
limits: EnvelopeLimits,
) -> Result<Confirmed, CodecError> {
command(packet.envelope, Opcode::Appended, true)?;
packet
.envelope
.validate_frames(packet.metadata.len(), packet.payload.len(), limits)?;
if !packet.payload.is_empty() || packet.metadata.len() != 106 {
return Err(CodecError::Length);
}
let mut cursor = Cursor(packet.metadata);
let (authority, partition, owner_epoch, key) = decode_common(&mut cursor)?;
let confirmed = Confirmed {
authority,
partition,
owner_epoch,
key,
end_sequence: cursor.u64()?,
first_offset: cursor.u64()?,
policy: Policy::try_from(cursor.byte()?)?,
};
range(confirmed)?;
Ok(confirmed)
}
fn range(confirmed: Confirmed) -> Result<(), CodecError> {
let count = confirmed
.end_sequence
.checked_sub(confirmed.key.first_sequence)
.filter(|&count| count != 0)
.ok_or(CodecError::Length)?;
confirmed
.first_offset
.checked_add(count)
.ok_or(CodecError::Length)?;
Ok(())
}