use std::collections::VecDeque;
#[derive(Clone, Debug)]
pub struct PrefetchStrategy {
pub prefetch_count: usize,
pub enabled: bool,
}
impl Default for PrefetchStrategy {
fn default() -> Self {
Self {
prefetch_count: 2,
enabled: true,
}
}
}
impl PrefetchStrategy {
pub fn new(prefetch_count: usize) -> Self {
Self {
prefetch_count,
enabled: true,
}
}
pub fn disabled() -> Self {
Self {
prefetch_count: 0,
enabled: false,
}
}
}
#[derive(Debug, Default)]
pub struct PrefetchScheduler {
prefetch_queue: VecDeque<usize>,
}
impl PrefetchScheduler {
pub fn new() -> Self {
Self::default()
}
pub fn update(
&mut self,
first_visible_index: usize,
last_visible_index: usize,
total_items: usize,
scroll_direction: f32,
strategy: &PrefetchStrategy,
) {
if !strategy.enabled {
self.prefetch_queue.clear();
return;
}
self.prefetch_queue.clear();
let prefetch_count = strategy.prefetch_count;
if scroll_direction >= 0.0 {
for i in 1..=prefetch_count {
let index = last_visible_index.saturating_add(i);
if index < total_items {
self.prefetch_queue.push_back(index);
}
}
} else {
for i in 1..=prefetch_count {
if first_visible_index >= i {
let index = first_visible_index - i;
self.prefetch_queue.push_back(index);
}
}
}
}
pub fn next_prefetch(&mut self) -> Option<usize> {
self.prefetch_queue.pop_front()
}
pub fn pending_prefetches(&self) -> &VecDeque<usize> {
&self.prefetch_queue
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_prefetch_forward_scroll() {
let mut scheduler = PrefetchScheduler::new();
let strategy = PrefetchStrategy::new(2);
scheduler.update(5, 10, 100, 1.0, &strategy);
assert_eq!(scheduler.next_prefetch(), Some(11));
assert_eq!(scheduler.next_prefetch(), Some(12));
assert_eq!(scheduler.next_prefetch(), None);
}
#[test]
fn test_prefetch_backward_scroll() {
let mut scheduler = PrefetchScheduler::new();
let strategy = PrefetchStrategy::new(2);
scheduler.update(5, 10, 100, -1.0, &strategy);
assert_eq!(scheduler.next_prefetch(), Some(4));
assert_eq!(scheduler.next_prefetch(), Some(3));
assert_eq!(scheduler.next_prefetch(), None);
}
#[test]
fn test_prefetch_at_end() {
let mut scheduler = PrefetchScheduler::new();
let strategy = PrefetchStrategy::new(2);
scheduler.update(95, 99, 100, 1.0, &strategy);
assert_eq!(scheduler.next_prefetch(), None);
}
#[test]
fn test_prefetch_disabled() {
let mut scheduler = PrefetchScheduler::new();
let strategy = PrefetchStrategy::disabled();
scheduler.update(5, 10, 100, 1.0, &strategy);
assert_eq!(scheduler.next_prefetch(), None);
}
}