use crate::*;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct Paging {
pub sequence: Axis,
pub position: Axis,
pub page_size: usize,
}
impl Paging {
pub(crate) fn of_pool(
sequence: Axis,
position: Axis,
shape: &[usize],
projection: &Projection,
stored_tiles: &[(Axis, usize)],
delivery: Delivery,
) -> Result<Paging, Refusal> {
let unsized_paging = Paging {
sequence,
position,
page_size: 0,
};
let page_size = unsized_paging
.dims(projection)
.map_or(0, |(_, position)| shape[position]);
let paging = Paging {
page_size,
..unsized_paging
};
paging.validate(projection, stored_tiles, delivery)?;
let (sequence, _) = paging.dims(projection)?;
match shape[sequence] {
0 => Err(Refusal::PagingOfAnEmptyPool),
_ => Ok(paging),
}
}
pub(crate) fn dims(&self, projection: &Projection) -> Result<(usize, usize), Refusal> {
let dim = |axis: Axis| {
(0..projection.physical_rank())
.find(|&pa| projection.physical_axis(pa).is_identity(axis))
.ok_or(Refusal::PagingOfAnUnlabelledAxis(axis))
};
let (sequence, position) = (dim(self.sequence)?, dim(self.position)?);
match sequence == position {
true => Err(Refusal::PagingOfOneDim(self.sequence)),
false => Ok((sequence, position)),
}
}
pub(crate) fn validate(
&self,
projection: &Projection,
stored_tiles: &[(Axis, usize)],
delivery: Delivery,
) -> Result<(), Refusal> {
if !projection.is_direct() || projection.is_tiled() || !stored_tiles.is_empty() {
return Err(Refusal::PagingOfAStatedLayout);
}
if !matches!(delivery, Delivery::SyncPerUnit | Delivery::AsyncPerUnit) {
return Err(Refusal::PagingMovedByRuns);
}
let (sequence, _) = self.dims(projection)?;
if sequence == projection.physical_rank() - 1 {
return Err(Refusal::PagesAlongALine(self.sequence));
}
match self.page_size {
0 => Err(Refusal::PagingOfAnEmptyPool),
_ => Ok(()),
}
}
}