use std::hash::{Hash, Hasher};
use crate::data::atomic::Word;
pub trait Identifier: Hash {
fn to_usize(&self) -> usize;
}
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Address(u64);
impl Address {
pub const fn new(value: u64) -> Self {
Self(value)
}
pub const fn to_u64(&self) -> u64 { self.0 }
pub const fn from_word(word: Word) -> Self { Self::new(word.to_u64()) }
pub fn from<T: Identifier>(identifier: T) -> Self { Self::new(identifier.to_usize() as u64) }
pub const fn to_word(&self) -> Word { Word::new(self.0) }
pub fn increment(&mut self) {
self.0 += 1;
}
pub fn offset(&self, offset: u64) -> Address { Address(self.0 + offset) }
}
impl Hash for Address {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write(&self.0.to_be_bytes());
}
}
impl Identifier for Address {
fn to_usize(&self) -> usize { self.to_u64() as usize }
}
#[derive(Copy, Clone)]
pub struct Area {
start: Address,
len: usize,
count: usize,
}
impl Area {
pub fn new(start: Address, item_size: usize, item_count: usize) -> Self {
Self { start, len: item_size, count: item_count }
}
pub fn region(start: Address, count: usize) -> Self { Self::new(start, 1, count) }
pub fn from(start: Address, end: Address) -> Self {
if start > end {
panic!("start > end")
}
Self::new(start, 1, end.to_usize() - start.to_usize())
}
pub fn count(&self) -> usize { self.count }
pub fn size(&self) -> usize { self.offset(self.count) }
pub fn is_null(&self) -> bool { self.size() == 0 }
pub fn start(&self) -> Address { self.start }
pub fn end(&self) -> Address { self.start.offset(self.size() as u64) }
pub fn constraint(&self, pointer: Address) -> Address {
match pointer {
Address(addr) if addr < self.start.to_u64() => self.start,
Address(addr) if addr > self.end().to_u64() => self.end(),
address => address
}
}
pub fn offset(&self, index: usize) -> usize { self.len * index }
pub fn next_address(&self, cursor: Address) -> Address {
let cursor = cursor.offset(self.offset(1) as u64);
self.constraint(cursor)
}
}
pub struct Cursor {
pub area: Area,
pub pointer: Address,
}
impl Cursor {
pub fn next(&self) -> Address { self.area.next_address(self.pointer) }
}