use bytemuck::{CheckedBitPattern, NoUninit};
use enumset::EnumSetType;
#[derive(Default, Debug, EnumSetType)]
#[repr(u8)]
pub enum Command {
#[default]
Reserved = 0,
Ping = 1,
Pong = 2,
PingClient = 3,
PongClient = 4,
Request = 5,
Prepare = 6,
PrepareOk = 7,
Reply = 8,
Commit = 9,
StartViewChange = 10,
DoViewChange = 11,
StartView = 12,
Eviction = 13,
ReplicaHello = 14,
ReplicaChallenge = 15,
ReplicaFinish = 16,
RequestStartView = 17,
RequestPrepares = 18,
RepairPrepare = 19,
RepairDone = 20,
RangeEvicted = 21,
RequestStateTransfer = 22,
StateTransferTarget = 23,
RequestStateChunk = 24,
StateChunk = 25,
ForwardRegister = 26,
ForwardRegisterResult = 27,
ForwardLogout = 28,
ForwardLogoutResult = 29,
ConsumerSessionHeartbeat = 30,
SessionRetirementProgress = 31,
ForwardCompletion = 32,
PrimaryRebalance = 33,
SegmentDelete = 34,
}
unsafe impl NoUninit for Command {}
unsafe impl CheckedBitPattern for Command {
type Bits = u8;
fn is_valid_bit_pattern(bits: &u8) -> bool {
*bits <= Self::SegmentDelete as u8
}
}
#[cfg(test)]
mod tests {
use crate::consensus::GenericHeader;
use aligned_vec::{AVec, ConstAlign};
#[test]
fn invalid_bit_pattern_rejected() {
let mut buf: AVec<u8, ConstAlign<16>> = AVec::new(16);
buf.resize(256, 0);
buf[60] = 99;
let result = bytemuck::checked::try_from_bytes::<GenericHeader>(&buf);
assert!(result.is_err());
}
#[test]
fn replica_auth_commands_are_valid_bit_patterns() {
for command in 14u8..=34 {
let mut buf: AVec<u8, ConstAlign<16>> = AVec::new(16);
buf.resize(256, 0);
buf[60] = command;
assert!(bytemuck::checked::try_from_bytes::<GenericHeader>(&buf).is_ok());
}
let mut buf: AVec<u8, ConstAlign<16>> = AVec::new(16);
buf.resize(256, 0);
buf[60] = 35;
assert!(bytemuck::checked::try_from_bytes::<GenericHeader>(&buf).is_err());
}
}