use bytemuck::{CheckedBitPattern, NoUninit};
use enumset::EnumSetType;
#[derive(Default, Debug, EnumSetType)]
#[repr(u8)]
pub enum Command2 {
#[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,
}
unsafe impl NoUninit for Command2 {}
unsafe impl CheckedBitPattern for Command2 {
type Bits = u8;
fn is_valid_bit_pattern(bits: &u8) -> bool {
*bits <= Self::RangeEvicted 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..=21 {
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] = 22;
assert!(bytemuck::checked::try_from_bytes::<GenericHeader>(&buf).is_err());
}
}