use std::ops::{Deref, DerefMut};
use std::sync::atomic::{AtomicU8, Ordering};
use std::cell::UnsafeCell;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u8)]
pub enum SovereignState {
Domestic = 0,
Exiled = 1,
}
pub struct Sovereign<T> {
inner: UnsafeCell<T>,
state: AtomicU8,
}
impl<T> Sovereign<T> {
pub fn new(value: T) -> Self {
Self {
inner: UnsafeCell::new(value),
state: AtomicU8::new(SovereignState::Domestic as u8),
}
}
pub fn annex(&self) -> Result<(), String> {
let current = self.state.load(Ordering::SeqCst);
if current == SovereignState::Exiled as u8 {
return Err("Resource is already under foreign jurisdiction.".to_string());
}
self.state.store(SovereignState::Exiled as u8, Ordering::SeqCst);
Ok(())
}
fn verify_jurisdiction(&self) {
if self.state.load(Ordering::SeqCst) == SovereignState::Exiled as u8 {
panic!("SOVEREIGNTY VIOLATION: Resource is under foreign jurisdiction.");
}
}
}
impl<T> Deref for Sovereign<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.verify_jurisdiction();
unsafe { &*self.inner.get() }
}
}
impl<T> DerefMut for Sovereign<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.verify_jurisdiction();
unsafe { &mut *self.inner.get() }
}
}
unsafe impl<T: Send> Send for Sovereign<T> {}
unsafe impl<T: Sync> Sync for Sovereign<T> {}
pub trait CheckProtocol {
fn enforce_law(&self);
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LeaseError {
AlreadyLeased,
ForeignJurisdiction,
}
pub struct Lease<T> {
pub holder: u128,
pub duration: std::time::Duration,
_phantom: std::marker::PhantomData<T>,
}
impl<T> Lease<T> {
pub fn new(holder: u128, duration: std::time::Duration) -> Self {
Self {
holder,
duration,
_phantom: std::marker::PhantomData,
}
}
}
pub trait DistributedBorrow<T> {
fn try_hire(&self, candidate_id: u128, term: std::time::Duration) -> Result<Lease<T>, LeaseError>;
}
impl<T> DistributedBorrow<T> for Sovereign<T> {
fn try_hire(&self, candidate_id: u128, term: std::time::Duration) -> Result<Lease<T>, LeaseError> {
let current = self.state.load(Ordering::SeqCst);
if current == SovereignState::Exiled as u8 {
return Err(LeaseError::AlreadyLeased);
}
self.state.store(SovereignState::Exiled as u8, Ordering::SeqCst);
Ok(Lease::new(candidate_id, term))
}
}