#[derive(Debug, Default)]
pub(crate) struct DictAttach<T> {
table: Option<T>,
region_len: usize,
primed: bool,
}
impl<T: Clone> Clone for DictAttach<T> {
fn clone(&self) -> Self {
Self {
table: self.table.clone(),
region_len: self.region_len,
primed: self.primed,
}
}
fn clone_from(&mut self, source: &Self) {
self.table.clone_from(&source.table);
self.region_len = source.region_len;
self.primed = source.primed;
}
}
impl<T> DictAttach<T> {
pub(crate) const fn new() -> Self {
Self {
table: None,
region_len: 0,
primed: false,
}
}
#[inline]
pub(crate) fn is_attached(&self) -> bool {
self.table.is_some()
}
#[inline]
pub(crate) fn table(&self) -> Option<&T> {
self.table.as_ref()
}
#[inline]
pub(crate) fn region_len(&self) -> usize {
self.region_len
}
#[inline]
pub(crate) fn set_region_len(&mut self, region_len: usize) {
self.region_len = region_len;
}
#[inline]
pub(crate) fn is_primed(&self) -> bool {
self.primed
}
#[inline]
pub(crate) fn mark_primed(&mut self) {
if self.table.is_some() {
self.primed = true;
}
}
#[inline]
pub(crate) fn table_mut_or_init(&mut self, init: impl FnOnce() -> T) -> &mut T {
self.table.get_or_insert_with(init)
}
#[inline]
pub(crate) fn table_mut(&mut self) -> Option<&mut T> {
self.table.as_mut()
}
#[inline]
pub(crate) fn invalidate(&mut self) {
self.table = None;
self.region_len = 0;
self.primed = false;
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::{vec, vec::Vec};
#[test]
fn lifecycle_attach_prime_invalidate() {
let mut da: DictAttach<Vec<u32>> = DictAttach::new();
assert!(!da.is_attached());
assert!(!da.is_primed());
assert_eq!(da.region_len(), 0);
da.set_region_len(128);
da.mark_primed();
assert!(!da.is_primed());
da.table_mut_or_init(|| vec![0u32; 16]).fill(7);
assert!(da.is_attached());
assert_eq!(da.table().unwrap()[0], 7);
da.mark_primed();
assert!(da.is_primed());
assert_eq!(da.region_len(), 128);
da.invalidate();
assert!(!da.is_attached());
assert!(!da.is_primed());
assert_eq!(da.region_len(), 0);
}
}