paged 0.1.1

Read and create read-only paged database files
Documentation
use std::{cmp::Ordering, marker::PhantomData};

use super::cache::{Binder, UnboundRef, UnboundSliceIter};

pub struct Page<T> {
	entries: Vec<T>,
}

impl<T> Default for Page<T> {
	fn default() -> Self {
		Self {
			entries: Vec::new(),
		}
	}
}

impl<T> Page<T> {
	pub fn get(&self, i: u32) -> Option<&T> {
		self.entries.get(i as usize)
	}

	pub fn iter(&self) -> Iter<T> {
		self.entries.iter()
	}

	pub fn binary_search_by_key<C>(
		&self,
		context: &C,
		f: impl Fn(&T, &C) -> Ordering,
	) -> Result<u32, Ordering> {
		if self.entries.is_empty() {
			Err(Ordering::Equal)
		} else if f(self.entries.first().unwrap(), context).is_gt() {
			Err(Ordering::Greater)
		} else if f(self.entries.last().unwrap(), context).is_lt() {
			Err(Ordering::Less)
		} else {
			match self.entries.binary_search_by(|t| f(t, context)) {
				Ok(i) => Ok(i as u32),
				Err(_) => Err(Ordering::Equal),
			}
		}
	}

	pub fn push(&mut self, entry: T) {
		self.entries.push(entry)
	}
}

impl<T> sharded_slab::Clear for Page<T> {
	fn clear(&mut self) {
		self.entries.clear()
	}
}

pub type Iter<'a, T> = std::slice::Iter<'a, T>;

pub type UnboundIter<T> = UnboundSliceIter<T>;

pub struct GetEntryBinder<T> {
	index: u32,
	t: PhantomData<T>,
}

impl<T> GetEntryBinder<T> {
	pub fn new(index: u32) -> Self {
		Self {
			index,
			t: PhantomData,
		}
	}
}

impl<'a, T> Binder<'a, UnboundRef<Page<T>>, UnboundRef<T>> for GetEntryBinder<T> {
	fn bind<'t>(self, page: &'t Page<T>) -> &'t T
	where
		'a: 't,
	{
		page.get(self.index).unwrap()
	}
}

pub struct IterBinder<T>(PhantomData<T>);

impl<T> Default for IterBinder<T> {
	fn default() -> Self {
		Self::new()
	}
}

impl<T> IterBinder<T> {
	pub fn new() -> Self {
		Self(PhantomData)
	}
}

impl<'a, T> Binder<'a, UnboundRef<Page<T>>, UnboundIter<T>> for IterBinder<T> {
	fn bind<'t>(self, page: &'t Page<T>) -> Iter<'t, T>
	where
		'a: 't,
	{
		page.iter()
	}
}