cranpose_foundation/lazy/
prefetch.rs1use std::collections::VecDeque;
7
8#[derive(Clone, Debug)]
10pub struct PrefetchStrategy {
11 pub prefetch_count: usize,
14
15 pub enabled: bool,
17}
18
19impl Default for PrefetchStrategy {
20 fn default() -> Self {
21 Self {
22 prefetch_count: 2,
23 enabled: true,
24 }
25 }
26}
27
28impl PrefetchStrategy {
29 pub fn new(prefetch_count: usize) -> Self {
31 Self {
32 prefetch_count,
33 enabled: true,
34 }
35 }
36
37 pub fn disabled() -> Self {
39 Self {
40 prefetch_count: 0,
41 enabled: false,
42 }
43 }
44}
45
46#[derive(Debug, Default)]
51pub struct PrefetchScheduler {
52 prefetch_queue: VecDeque<usize>,
53}
54
55impl PrefetchScheduler {
56 pub fn new() -> Self {
58 Self::default()
59 }
60
61 pub fn update(
70 &mut self,
71 first_visible_index: usize,
72 last_visible_index: usize,
73 total_items: usize,
74 scroll_direction: f32,
75 strategy: &PrefetchStrategy,
76 ) {
77 if !strategy.enabled {
78 self.prefetch_queue.clear();
79 return;
80 }
81
82 self.prefetch_queue.clear();
83
84 let prefetch_count = strategy.prefetch_count;
85
86 if scroll_direction >= 0.0 {
87 for i in 1..=prefetch_count {
88 let index = last_visible_index.saturating_add(i);
89 if index < total_items {
90 self.prefetch_queue.push_back(index);
91 }
92 }
93 } else {
94 for i in 1..=prefetch_count {
95 if first_visible_index >= i {
96 let index = first_visible_index - i;
97 self.prefetch_queue.push_back(index);
98 }
99 }
100 }
101 }
102
103 pub fn next_prefetch(&mut self) -> Option<usize> {
105 self.prefetch_queue.pop_front()
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn test_prefetch_forward_scroll() {
115 let mut scheduler = PrefetchScheduler::new();
116 let strategy = PrefetchStrategy::new(2);
117
118 scheduler.update(5, 10, 100, 1.0, &strategy);
119
120 assert_eq!(scheduler.next_prefetch(), Some(11));
121 assert_eq!(scheduler.next_prefetch(), Some(12));
122 assert_eq!(scheduler.next_prefetch(), None);
123 }
124
125 #[test]
126 fn test_prefetch_backward_scroll() {
127 let mut scheduler = PrefetchScheduler::new();
128 let strategy = PrefetchStrategy::new(2);
129
130 scheduler.update(5, 10, 100, -1.0, &strategy);
131
132 assert_eq!(scheduler.next_prefetch(), Some(4));
133 assert_eq!(scheduler.next_prefetch(), Some(3));
134 assert_eq!(scheduler.next_prefetch(), None);
135 }
136
137 #[test]
138 fn test_prefetch_at_end() {
139 let mut scheduler = PrefetchScheduler::new();
140 let strategy = PrefetchStrategy::new(2);
141
142 scheduler.update(95, 99, 100, 1.0, &strategy);
143
144 assert_eq!(scheduler.next_prefetch(), None);
145 }
146
147 #[test]
148 fn test_prefetch_disabled() {
149 let mut scheduler = PrefetchScheduler::new();
150 let strategy = PrefetchStrategy::disabled();
151
152 scheduler.update(5, 10, 100, 1.0, &strategy);
153
154 assert_eq!(scheduler.next_prefetch(), None);
155 }
156}