use crate::handle::{HandleId, LockId};
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum Message {
Start,
Dirty,
Resolved,
Data(HandleId),
Invalidate,
Pause(LockId),
Resume(LockId),
Complete,
Error(HandleId),
Teardown,
}
impl Message {
#[must_use]
pub const fn tier(self) -> u8 {
match self {
Self::Start => 0,
Self::Dirty => 1,
Self::Pause(_) | Self::Resume(_) => 2,
Self::Data(_) | Self::Resolved => 3,
Self::Invalidate => 4,
Self::Complete | Self::Error(_) => 5,
Self::Teardown => 6,
}
}
#[must_use]
pub const fn payload_handle(self) -> Option<HandleId> {
match self {
Self::Data(h) | Self::Error(h) => Some(h),
_ => None,
}
}
#[must_use]
pub const fn is_terminal(self) -> bool {
matches!(self, Self::Complete | Self::Error(_))
}
}
pub type Messages<'a> = &'a [Message];
#[cfg(test)]
mod tests {
use super::*;
use crate::handle::{HandleId, LockId};
const HANDLE_42: HandleId = HandleId::new(42);
const LOCK_7: LockId = LockId::new(7);
#[test]
fn tier_table_matches_canonical_spec_r1_3_7b() {
assert_eq!(Message::Start.tier(), 0);
assert_eq!(Message::Dirty.tier(), 1);
assert_eq!(Message::Pause(LOCK_7).tier(), 2);
assert_eq!(Message::Resume(LOCK_7).tier(), 2);
assert_eq!(Message::Data(HANDLE_42).tier(), 3);
assert_eq!(Message::Resolved.tier(), 3);
assert_eq!(Message::Invalidate.tier(), 4);
assert_eq!(Message::Complete.tier(), 5);
assert_eq!(Message::Error(HANDLE_42).tier(), 5);
assert_eq!(Message::Teardown.tier(), 6);
}
#[test]
fn payload_handle_only_for_data_and_error() {
assert_eq!(Message::Data(HANDLE_42).payload_handle(), Some(HANDLE_42));
assert_eq!(Message::Error(HANDLE_42).payload_handle(), Some(HANDLE_42));
assert_eq!(Message::Start.payload_handle(), None);
assert_eq!(Message::Dirty.payload_handle(), None);
assert_eq!(Message::Resolved.payload_handle(), None);
assert_eq!(Message::Invalidate.payload_handle(), None);
assert_eq!(Message::Pause(LOCK_7).payload_handle(), None);
assert_eq!(Message::Resume(LOCK_7).payload_handle(), None);
assert_eq!(Message::Complete.payload_handle(), None);
assert_eq!(Message::Teardown.payload_handle(), None);
}
#[test]
fn is_terminal_only_complete_and_error() {
assert!(Message::Complete.is_terminal());
assert!(Message::Error(HANDLE_42).is_terminal());
assert!(!Message::Teardown.is_terminal());
assert!(!Message::Start.is_terminal());
assert!(!Message::Data(HANDLE_42).is_terminal());
assert!(!Message::Invalidate.is_terminal());
}
#[test]
fn copy_and_eq_round_trip() {
let m = Message::Data(HANDLE_42);
let copy = m;
assert_eq!(m, copy);
assert_eq!(Message::Resolved, Message::Resolved);
}
}