use std::marker::PhantomData;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct FrameCheckpoint {
head: usize,
frame_id: u64,
}
impl FrameCheckpoint {
pub(crate) fn new(head: usize, frame_id: u64) -> Self {
Self { head, frame_id }
}
pub fn head(&self) -> usize {
self.head
}
pub fn frame_id(&self) -> u64 {
self.frame_id
}
}
pub struct CheckpointGuard<'a> {
checkpoint: FrameCheckpoint,
committed: bool,
_marker: PhantomData<&'a ()>,
}
impl<'a> CheckpointGuard<'a> {
pub(crate) fn new(checkpoint: FrameCheckpoint) -> Self {
Self {
checkpoint,
committed: false,
_marker: PhantomData,
}
}
pub fn commit(mut self) {
self.committed = true;
}
pub fn checkpoint(&self) -> FrameCheckpoint {
self.checkpoint
}
pub fn is_committed(&self) -> bool {
self.committed
}
}
impl<'a> Drop for CheckpointGuard<'a> {
fn drop(&mut self) {
if !self.committed {
}
}
}
#[derive(Debug)]
pub enum SpeculativeResult<T, E> {
Success(T),
RolledBack(E),
}
impl<T, E> SpeculativeResult<T, E> {
pub fn is_success(&self) -> bool {
matches!(self, Self::Success(_))
}
pub fn is_rolled_back(&self) -> bool {
matches!(self, Self::RolledBack(_))
}
pub fn into_result(self) -> Result<T, E> {
match self {
Self::Success(t) => Ok(t),
Self::RolledBack(e) => Err(e),
}
}
pub fn unwrap(self) -> T
where
E: std::fmt::Debug,
{
match self {
Self::Success(t) => t,
Self::RolledBack(e) => panic!("called unwrap on RolledBack: {:?}", e),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_checkpoint_creation() {
let cp = FrameCheckpoint::new(1024, 42);
assert_eq!(cp.head(), 1024);
assert_eq!(cp.frame_id(), 42);
}
#[test]
fn test_speculative_result() {
let success: SpeculativeResult<i32, &str> = SpeculativeResult::Success(42);
assert!(success.is_success());
assert_eq!(success.unwrap(), 42);
let rolled_back: SpeculativeResult<i32, &str> = SpeculativeResult::RolledBack("failed");
assert!(rolled_back.is_rolled_back());
assert!(rolled_back.into_result().is_err());
}
}