use o3::depot::map::{compact, compact::Access as _};
use crate::payload::compress::dynamic::hash;
pub(super) mod raw;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Error(compact::Error);
pub(super) struct Search<Q: compact::raw::Query>(Q);
impl<Q: compact::raw::Query> Search<Q> {
pub(super) const fn new(owner: Q) -> Self {
Self(owner)
}
pub(super) fn find<I: Copy>(
self,
hash: u64,
mut accept: impl FnMut(Q::Item) -> Option<(usize, I)>,
) -> Option<I> {
let mut best: Option<(usize, I)> = None;
self.0.scan(hash, |item| {
if let Some(found) = accept(item)
&& best.is_none_or(|current| found.0 < current.0)
{
best = Some(found);
}
});
best.map(|found| found.1)
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub(in crate::payload::compress::dynamic) enum Key {
Name,
Exact,
}
impl Key {
pub(in crate::payload::compress::dynamic) const fn staged<const N: usize>() -> Self {
if N == 0 { Self::Name } else { Self::Exact }
}
pub(in crate::payload::compress::dynamic) fn of(self, digest: hash::Digest) -> u64 {
match self {
Self::Name => digest.name(),
Self::Exact => digest.exact(),
}
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct State {
planes: compact::Planes<2>,
}
impl State {
pub(super) fn new(entries: usize, start: usize) -> Result<(Self, usize), Error> {
let (planes, end) = compact::Planes::try_new([entries; 2], start).map_err(Error)?;
Ok((Self { planes }, end))
}
pub(super) const fn layout(self, key: Key) -> compact::Layout {
match key {
Key::Name => self.planes.layout::<0>(),
Key::Exact => self.planes.layout::<1>(),
}
}
pub(super) fn byte(self, offset: usize) -> u8 {
self.planes.byte(offset)
}
}