pub const KNOWN_DELETED_BIT: u8 = 0x01;
pub const DIRTY_BIT: u8 = 0x02;
pub const MIGRATE_BIT: u8 = 0x04;
pub const PENDING_DELETED_BIT: u8 = 0x08;
pub const EMBEDDED_LN_BIT: u8 = 0x10;
pub const NO_DATA_LN_BIT: u8 = 0x20;
pub const UPDATE_KEY_WHEN_LOGGED: u8 = 0x40;
pub const TOMBSTONE_BIT: u8 = 0x80;
pub const TRANSIENT_BITS: u8 = MIGRATE_BIT | UPDATE_KEY_WHEN_LOGGED;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct SlotState(u8);
impl SlotState {
#[inline]
pub fn new() -> Self {
SlotState(0)
}
#[inline]
pub fn from_byte(byte: u8) -> Self {
SlotState(byte)
}
#[inline]
pub fn as_byte(self) -> u8 {
self.0
}
#[inline]
pub fn is_known_deleted(self) -> bool {
(self.0 & KNOWN_DELETED_BIT) != 0
}
#[inline]
pub fn set_known_deleted(&mut self) {
self.0 |= KNOWN_DELETED_BIT;
}
#[inline]
pub fn clear_known_deleted(&mut self) {
self.0 &= !KNOWN_DELETED_BIT;
}
#[inline]
pub fn is_dirty(self) -> bool {
(self.0 & DIRTY_BIT) != 0
}
#[inline]
pub fn set_dirty(&mut self) {
self.0 |= DIRTY_BIT;
}
#[inline]
pub fn clear_dirty(&mut self) {
self.0 &= !DIRTY_BIT;
}
#[inline]
pub fn is_migrate(self) -> bool {
(self.0 & MIGRATE_BIT) != 0
}
#[inline]
pub fn set_migrate(&mut self) {
self.0 |= MIGRATE_BIT;
}
#[inline]
pub fn clear_migrate(&mut self) {
self.0 &= !MIGRATE_BIT;
}
#[inline]
pub fn is_pending_deleted(self) -> bool {
(self.0 & PENDING_DELETED_BIT) != 0
}
#[inline]
pub fn set_pending_deleted(&mut self) {
self.0 |= PENDING_DELETED_BIT;
}
#[inline]
pub fn clear_pending_deleted(&mut self) {
self.0 &= !PENDING_DELETED_BIT;
}
#[inline]
pub fn is_embedded_ln(self) -> bool {
(self.0 & EMBEDDED_LN_BIT) != 0
}
#[inline]
pub fn set_embedded_ln(&mut self) {
self.0 |= EMBEDDED_LN_BIT;
}
#[inline]
pub fn clear_embedded_ln(&mut self) {
self.0 &= !EMBEDDED_LN_BIT;
}
#[inline]
pub fn is_no_data_ln(self) -> bool {
(self.0 & NO_DATA_LN_BIT) != 0
}
#[inline]
pub fn set_no_data_ln(&mut self) {
self.0 |= NO_DATA_LN_BIT;
}
#[inline]
pub fn clear_no_data_ln(&mut self) {
self.0 &= !NO_DATA_LN_BIT;
}
#[inline]
pub fn is_update_key_when_logged(self) -> bool {
(self.0 & UPDATE_KEY_WHEN_LOGGED) != 0
}
#[inline]
pub fn set_update_key_when_logged(&mut self) {
self.0 |= UPDATE_KEY_WHEN_LOGGED;
}
#[inline]
pub fn clear_update_key_when_logged(&mut self) {
self.0 &= !UPDATE_KEY_WHEN_LOGGED;
}
#[inline]
pub fn is_tombstone(self) -> bool {
(self.0 & TOMBSTONE_BIT) != 0
}
#[inline]
pub fn set_tombstone(&mut self) {
self.0 |= TOMBSTONE_BIT;
}
#[inline]
pub fn clear_tombstone(&mut self) {
self.0 &= !TOMBSTONE_BIT;
}
#[inline]
pub fn clear_transient_bits(&mut self) {
self.0 &= !TRANSIENT_BITS;
}
#[inline]
pub fn with_transient_bits_cleared(self) -> Self {
SlotState(self.0 & !TRANSIENT_BITS)
}
}
impl From<u8> for SlotState {
fn from(byte: u8) -> Self {
SlotState(byte)
}
}
impl From<SlotState> for u8 {
fn from(state: SlotState) -> Self {
state.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_state_is_clear() {
let state = SlotState::new();
assert_eq!(state.as_byte(), 0);
assert!(!state.is_known_deleted());
assert!(!state.is_dirty());
assert!(!state.is_embedded_ln());
}
#[test]
fn test_known_deleted() {
let mut state = SlotState::new();
assert!(!state.is_known_deleted());
state.set_known_deleted();
assert!(state.is_known_deleted());
assert_eq!(state.as_byte(), KNOWN_DELETED_BIT);
state.clear_known_deleted();
assert!(!state.is_known_deleted());
assert_eq!(state.as_byte(), 0);
}
#[test]
fn test_dirty() {
let mut state = SlotState::new();
assert!(!state.is_dirty());
state.set_dirty();
assert!(state.is_dirty());
assert_eq!(state.as_byte(), DIRTY_BIT);
state.clear_dirty();
assert!(!state.is_dirty());
}
#[test]
fn test_multiple_flags() {
let mut state = SlotState::new();
state.set_dirty();
state.set_embedded_ln();
assert!(state.is_dirty());
assert!(state.is_embedded_ln());
assert!(!state.is_known_deleted());
assert_eq!(state.as_byte(), DIRTY_BIT | EMBEDDED_LN_BIT);
state.clear_dirty();
assert!(!state.is_dirty());
assert!(state.is_embedded_ln());
}
#[test]
fn test_transient_bits() {
let mut state = SlotState::new();
state.set_migrate();
state.set_update_key_when_logged();
state.set_dirty();
assert!(state.is_migrate());
assert!(state.is_update_key_when_logged());
assert!(state.is_dirty());
state.clear_transient_bits();
assert!(!state.is_migrate());
assert!(!state.is_update_key_when_logged());
assert!(state.is_dirty()); }
#[test]
fn test_with_transient_bits_cleared() {
let mut state = SlotState::new();
state.set_migrate();
state.set_dirty();
state.set_embedded_ln();
let cleared = state.with_transient_bits_cleared();
assert!(!cleared.is_migrate());
assert!(cleared.is_dirty());
assert!(cleared.is_embedded_ln());
assert!(state.is_migrate());
}
#[test]
fn test_tombstone() {
let mut state = SlotState::new();
assert!(!state.is_tombstone());
state.set_tombstone();
assert!(state.is_tombstone());
assert_eq!(state.as_byte(), TOMBSTONE_BIT);
state.clear_tombstone();
assert!(!state.is_tombstone());
}
#[test]
fn test_update_key_when_logged() {
let mut state = SlotState::new();
assert!(!state.is_update_key_when_logged());
state.set_update_key_when_logged();
assert!(state.is_update_key_when_logged());
state.clear_transient_bits();
assert!(!state.is_update_key_when_logged());
}
#[test]
fn test_from_byte() {
let state = SlotState::from_byte(DIRTY_BIT | EMBEDDED_LN_BIT);
assert!(state.is_dirty());
assert!(state.is_embedded_ln());
assert!(!state.is_known_deleted());
}
#[test]
fn test_conversions() {
let byte: u8 = DIRTY_BIT | PENDING_DELETED_BIT;
let state = SlotState::from(byte);
assert!(state.is_dirty());
assert!(state.is_pending_deleted());
let back: u8 = state.into();
assert_eq!(back, byte);
}
#[test]
fn test_all_flags() {
let mut state = SlotState::new();
state.set_known_deleted();
state.set_dirty();
state.set_migrate();
state.set_pending_deleted();
state.set_embedded_ln();
state.set_no_data_ln();
state.set_update_key_when_logged();
state.set_tombstone();
assert!(state.is_known_deleted());
assert!(state.is_dirty());
assert!(state.is_migrate());
assert!(state.is_pending_deleted());
assert!(state.is_embedded_ln());
assert!(state.is_no_data_ln());
assert!(state.is_update_key_when_logged());
assert!(state.is_tombstone());
}
}