use crate::archetype::chunk_idx;
#[derive(Clone, Copy)]
pub struct VerifyFetch {
dangling: bool,
visit_chunk: Option<(u32, bool)>,
touch_chunk: Option<u32>,
visit_item: Option<(u32, bool)>,
}
impl VerifyFetch {
#[inline(always)]
pub fn dangling() -> Self {
VerifyFetch {
dangling: true,
visit_chunk: None,
touch_chunk: None,
visit_item: None,
}
}
#[inline(always)]
pub fn new() -> Self {
VerifyFetch {
dangling: false,
visit_chunk: None,
touch_chunk: None,
visit_item: None,
}
}
#[inline(always)]
pub fn visit_chunk(&mut self, chunk_idx: u32, visiting: bool) {
if self.dangling {
panic!("FetchVerify: skip_chunk called for dangling fetch");
}
self.visit_item = None;
self.touch_chunk = None;
self.visit_chunk = Some((chunk_idx, visiting));
}
#[inline(always)]
pub fn touch_chunk(&mut self, chunk_idx: u32) {
if self.dangling {
panic!("FetchVerify: visit_chunk called for dangling fetch");
}
match self.visit_chunk {
None => {
panic!("FetchVerify: visit_chunk called without visit_chunk");
}
Some((visit_chunk_idx, visiting)) => {
if chunk_idx != visit_chunk_idx {
panic!("FetchVerify: visit_chunk called with chunk_idx {}, but last call to `visit_chunk` was with chunk_idx {}", chunk_idx, visit_chunk_idx);
}
if !visiting {
panic!("FetchVerify: visit_chunk called with chunk_idx {}, but `visit_chunk` returned true for this chunk index", chunk_idx);
}
self.touch_chunk = Some(visit_chunk_idx);
}
}
}
#[inline(always)]
pub fn visit_item(&mut self, idx: u32, visiting: bool) {
if self.dangling {
panic!("FetchVerify: visit_item called for dangling fetch");
}
match self.visit_chunk {
None => {
panic!("FetchVerify: visit_item called without visit_chunk");
}
Some((visit_chunk_idx, visiting_chunk)) => {
if chunk_idx(idx) != visit_chunk_idx {
panic!("FetchVerify: visit_item called with idx {} that correspond to chunk {}, but last call to `touch_chunk` was with chunk_idx {}", idx, chunk_idx(idx), visit_chunk_idx);
}
if !visiting_chunk {
panic!("FetchVerify: visit_item called with idx {}, but `visit_chunk` returned false for this idx", idx);
}
self.visit_item = Some((idx, visiting));
}
}
}
#[inline(always)]
pub fn get_item(&mut self, idx: u32) {
if self.dangling {
panic!("FetchVerify: get_item called for dangling fetch");
}
match self.visit_item {
None => {
panic!("FetchVerify: get_item called without visit_item");
}
Some((valid_idx, visiting)) => {
if idx != valid_idx {
panic!("FetchVerify: get_item called with idx {}, but last call to `visit_item` was with idx {}", idx, valid_idx);
}
if !visiting {
panic!("FetchVerify: get_item called with idx {}, but `visit_item` returned true for this idx", idx);
}
self.visit_item = None;
}
}
}
}
pub unsafe trait Fetch<'a> {
type Item: 'a;
#[must_use]
fn dangling() -> Self;
#[inline(always)]
#[must_use]
unsafe fn visit_chunk(&mut self, chunk_idx: u32) -> bool {
let _ = chunk_idx;
true
}
#[inline(always)]
#[must_use]
unsafe fn visit_item(&mut self, idx: u32) -> bool {
let _ = idx;
true
}
#[inline(always)]
unsafe fn touch_chunk(&mut self, chunk_idx: u32) {
let _ = chunk_idx;
}
#[must_use]
unsafe fn get_item(&mut self, idx: u32) -> Self::Item;
}
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct UnitFetch {
#[cfg(debug_assertions)]
verify: VerifyFetch,
}
impl UnitFetch {
pub fn new() -> Self {
UnitFetch {
#[cfg(debug_assertions)]
verify: VerifyFetch::new(),
}
}
}
unsafe impl<'a> Fetch<'a> for UnitFetch {
type Item = ();
#[inline(always)]
fn dangling() -> Self {
UnitFetch {
#[cfg(debug_assertions)]
verify: VerifyFetch::dangling(),
}
}
#[inline(always)]
unsafe fn visit_chunk(&mut self, chunk_idx: u32) -> bool {
let _ = chunk_idx;
#[cfg(debug_assertions)]
self.verify.visit_chunk(chunk_idx, true);
true
}
#[inline(always)]
unsafe fn touch_chunk(&mut self, chunk_idx: u32) {
let _ = chunk_idx;
#[cfg(debug_assertions)]
self.verify.touch_chunk(chunk_idx)
}
#[inline(always)]
unsafe fn visit_item(&mut self, idx: u32) -> bool {
let _ = idx;
#[cfg(debug_assertions)]
self.verify.visit_item(idx, true);
true
}
#[inline(always)]
unsafe fn get_item(&mut self, idx: u32) -> () {
let _ = idx;
#[cfg(debug_assertions)]
self.verify.get_item(idx)
}
}