use std::sync::atomic::Ordering;
use crate::handlers::*;
use crate::matrix::core::*;
pub struct Looper<'a> {
handler_ref: &'a MatrixHandler,
current_offset: u32,
end_offset: u32,
}
pub struct LoopWindow<'a> {
rel_ptr: RelativePtr<u8>,
handler: &'a MatrixHandler,
}
impl<'a> Iterator for Looper<'a> {
type Item = LoopWindow<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.current_offset >= self.end_offset {
return None;
}
let rel_ptr = self.handler_ref.matrix().query(self.current_offset);
let header = unsafe { rel_ptr.resolve_header(self.handler_ref.base_ptr()) };
let size = header.size.load(Ordering::Acquire);
if size == 0 {
return None;
}
self.current_offset = self
.current_offset
.checked_add(size)
.expect("offset overflow");
Some(LoopWindow::new(rel_ptr, self.handler_ref))
}
}
impl<'a> Looper<'a> {
pub fn new(handler_ref: &'a MatrixHandler) -> Self {
let len = (16 + (std::mem::size_of::<AtomicMatrix>() as u32) + 15) & !15;
let end = handler_ref.matrix().sector_boundaries[0].load(Ordering::Acquire);
Self {
handler_ref,
current_offset: len,
end_offset: end,
}
}
}
unsafe impl<'a> Send for LoopWindow<'a> {}
unsafe impl<'a> Sync for LoopWindow<'a> {}
impl<'a> LoopWindow<'a> {
pub fn new(rel_ptr: RelativePtr<u8>, handler: &'a MatrixHandler) -> Self {
Self { rel_ptr, handler }
}
pub fn view_data_as<T>(&self) -> &'a T {
let block = Block::<T>::from_offset(self.rel_ptr.offset());
let res = unsafe { self.handler.read(&block) };
res
}
pub fn view_data_raw(&self) -> &'a [u8] {
unsafe {
let data_ptr = self.rel_ptr.resolve(self.handler.base_ptr());
let header = self.view_header();
let size = header.size.load(Ordering::Acquire) - 32 - 16;
std::slice::from_raw_parts(data_ptr, size as usize)
}
}
pub fn view_header(&self) -> &'a BlockHeader {
unsafe { self.rel_ptr.resolve_header(self.handler.base_ptr()) }
}
pub fn view_offset(&self) -> u32 {
self.rel_ptr.offset()
}
}
pub mod macros {}