use std::sync::Arc;
use std::time::Instant;
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct PageId {
pub file_id: Arc<str>,
pub page_index: u64,
}
impl PageId {
pub fn new(file_id: impl Into<Arc<str>>, page_index: u64) -> Self {
Self {
file_id: file_id.into(),
page_index,
}
}
pub fn from_file_offset(file_id: impl Into<Arc<str>>, offset: u64, page_size: u64) -> Self {
assert!(page_size > 0, "page_size must be > 0");
Self {
file_id: file_id.into(),
page_index: offset / page_size,
}
}
pub fn page_start(&self, page_size: u64) -> u64 {
self.page_index * page_size
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub enum CacheScope {
#[default]
Global,
Named(Arc<str>),
}
#[derive(Clone, Debug)]
pub struct PageInfo {
pub page_id: PageId,
pub page_size: u64,
pub dir_index: usize,
pub created_at: Instant,
pub scope: CacheScope,
}
impl PageInfo {
pub fn new(page_id: PageId, page_size: u64, dir_index: usize, scope: CacheScope) -> Self {
Self {
page_id,
page_size,
dir_index,
created_at: Instant::now(),
scope,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn page_index_from_offset() {
let ps = 1024;
assert_eq!(PageId::from_file_offset("f", 0, ps).page_index, 0);
assert_eq!(PageId::from_file_offset("f", 1023, ps).page_index, 0);
assert_eq!(PageId::from_file_offset("f", 1024, ps).page_index, 1);
assert_eq!(PageId::from_file_offset("f", 2049, ps).page_index, 2);
}
#[test]
fn page_start_offset() {
let ps = 1024;
let id = PageId::new("f", 3);
assert_eq!(id.page_start(ps), 3072);
}
#[test]
fn page_id_equality_and_clone_is_cheap() {
let a = PageId::new("file-42", 7);
let b = a.clone();
assert_eq!(a, b);
assert_eq!(a.file_id.as_ref(), "file-42");
}
#[test]
fn default_scope_is_global() {
assert_eq!(CacheScope::default(), CacheScope::Global);
}
}