use crate::fs::WriteLifetime;
use alloc::sync::Arc;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct LifetimeGroups(u8);
impl LifetimeGroups {
pub const ONE: Self = Self(1);
pub const MAX: Self = Self(4);
#[must_use]
pub const fn new(count: u8) -> Option<Self> {
if count == 0 || count > Self::MAX.0 {
None
} else {
Some(Self(count))
}
}
#[must_use]
pub const fn get(self) -> u8 {
self.0
}
#[must_use]
pub(crate) fn cap(self, class: u8) -> u8 {
class.min(self.0 - 1)
}
#[must_use]
pub(crate) fn fresh(self) -> u8 {
self.cap(1)
}
#[must_use]
pub(crate) fn relocated(self, source: u8) -> u8 {
self.cap(self.cap(source) + 1)
}
#[must_use]
pub(crate) fn write_lifetime(self, class: u8) -> Option<WriteLifetime> {
if self.0 == 1 {
return None;
}
Some(match self.cap(class) {
0 => WriteLifetime::Short,
1 => WriteLifetime::Medium,
2 => WriteLifetime::Long,
_ => WriteLifetime::Extreme,
})
}
}
impl Default for LifetimeGroups {
fn default() -> Self {
Self::MAX
}
}
#[derive(Copy, Clone)]
pub struct LifetimeClassifier<'a> {
pub(crate) groups: LifetimeGroups,
pub(crate) hint: Option<&'a LifetimeHint>,
}
impl LifetimeClassifier<'_> {
#[must_use]
pub(crate) fn is_grouping(&self) -> bool {
self.groups != LifetimeGroups::ONE
}
#[must_use]
pub(crate) fn class_of(&self, key: &[u8], overwritten: bool) -> u8 {
if !self.is_grouping() {
return 0;
}
match self.hint.and_then(|hint| hint.class_of(key)) {
Some(class) => self.groups.cap(class),
None if overwritten => 0,
None => self.groups.fresh(),
}
}
}
pub type LifetimeHintFn = dyn Fn(&[u8]) -> Option<u8> + Send + Sync;
#[derive(Clone)]
pub struct LifetimeHint(pub(crate) Arc<LifetimeHintFn>);
impl LifetimeHint {
pub fn new(hint: impl Fn(&[u8]) -> Option<u8> + Send + Sync + 'static) -> Self {
Self(Arc::new(hint))
}
pub(crate) fn class_of(&self, key: &[u8]) -> Option<u8> {
(self.0)(key)
}
}
impl core::fmt::Debug for LifetimeHint {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("LifetimeHint")
}
}
impl PartialEq for LifetimeHint {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.0, &other.0)
}
}