use arrow_array::UInt32Array;
pub(crate) enum PermutationStorage {
InMemory(UInt32Array),
#[cfg(feature = "mmap")]
Mmap {
map: memmap2::Mmap,
len: usize,
_file: tempfile::NamedTempFile,
},
#[cfg(feature = "persist")]
MmapPersisted {
map: memmap2::Mmap,
len: usize,
path: std::path::PathBuf,
},
}
#[cfg(feature = "persist")]
const PERSIST_HEADER: usize = 16;
impl PermutationStorage {
pub(crate) fn len(&self) -> usize {
match self {
Self::InMemory(arr) => arr.len(),
#[cfg(feature = "mmap")]
Self::Mmap { len, .. } => *len,
#[cfg(feature = "persist")]
Self::MmapPersisted { len, .. } => *len,
}
}
pub(crate) fn read_range(&self, start: usize, end: usize) -> Vec<u32> {
let end = end.min(self.len());
if start >= end {
return Vec::new();
}
match self {
Self::InMemory(arr) => arr.values().as_ref()[start..end].to_vec(),
#[cfg(feature = "mmap")]
Self::Mmap { map, .. } => read_u32s_from_bytes(map, 0, start, end),
#[cfg(feature = "persist")]
Self::MmapPersisted { map, .. } => {
read_u32s_from_bytes(map, PERSIST_HEADER, start, end)
}
}
}
pub(crate) fn into_vec(self) -> Vec<u32> {
match self {
Self::InMemory(arr) => arr.values().to_vec(),
#[cfg(feature = "mmap")]
Self::Mmap { map, len, .. } => read_u32s_from_bytes(&map, 0, 0, len),
#[cfg(feature = "persist")]
Self::MmapPersisted { map, len, .. } => {
read_u32s_from_bytes(&map, PERSIST_HEADER, 0, len)
}
}
}
}
#[cfg(feature = "mmap")]
fn read_u32s_from_bytes(bytes: &[u8], header: usize, start: usize, end: usize) -> Vec<u32> {
let byte_start = header + start * 4;
let byte_end = header + end * 4;
bytes[byte_start..byte_end]
.chunks_exact(4)
.map(|c| u32::from_le_bytes(c.try_into().expect("chunks_exact(4)")))
.collect()
}
impl std::fmt::Debug for PermutationStorage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::InMemory(arr) => write!(f, "InMemory(len={})", arr.len()),
#[cfg(feature = "mmap")]
Self::Mmap { len, .. } => write!(f, "Mmap(len={len})"),
#[cfg(feature = "persist")]
Self::MmapPersisted { len, path, .. } => {
write!(f, "MmapPersisted(len={len}, path={})", path.display())
}
}
}
}