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>,
54}
55
56impl PrefetchScheduler {
57 pub fn new() -> Self {
59 Self::default()
60 }
61
62 pub fn update(
71 &mut self,
72 first_visible_index: usize,
73 last_visible_index: usize,
74 total_items: usize,
75 scroll_direction: f32,
76 strategy: &PrefetchStrategy,
77 ) {
78 if !strategy.enabled {
79 self.prefetch_queue.clear();
80 return;
81 }
82
83 self.prefetch_queue.clear();
84
85 let prefetch_count = strategy.prefetch_count;
86
87 if scroll_direction >= 0.0 {
88 for i in 1..=prefetch_count {
90 let index = last_visible_index.saturating_add(i);
91 if index < total_items {
92 self.prefetch_queue.push_back(index);
93 }
94 }
95 } else {
96 for i in 1..=prefetch_count {
98 if first_visible_index >= i {
99 let index = first_visible_index - i;
100 self.prefetch_queue.push_back(index);
101 }
102 }
103 }
104 }
105
106 pub fn next_prefetch(&mut self) -> Option<usize> {
108 self.prefetch_queue.pop_front()
109 }
110
111 pub fn pending_prefetches(&self) -> &VecDeque<usize> {
113 &self.prefetch_queue
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn test_prefetch_forward_scroll() {
123 let mut scheduler = PrefetchScheduler::new();
124 let strategy = PrefetchStrategy::new(2);
125
126 scheduler.update(5, 10, 100, 1.0, &strategy);
127
128 assert_eq!(scheduler.next_prefetch(), Some(11));
129 assert_eq!(scheduler.next_prefetch(), Some(12));
130 assert_eq!(scheduler.next_prefetch(), None);
131 }
132
133 #[test]
134 fn test_prefetch_backward_scroll() {
135 let mut scheduler = PrefetchScheduler::new();
136 let strategy = PrefetchStrategy::new(2);
137
138 scheduler.update(5, 10, 100, -1.0, &strategy);
139
140 assert_eq!(scheduler.next_prefetch(), Some(4));
141 assert_eq!(scheduler.next_prefetch(), Some(3));
142 assert_eq!(scheduler.next_prefetch(), None);
143 }
144
145 #[test]
146 fn test_prefetch_at_end() {
147 let mut scheduler = PrefetchScheduler::new();
148 let strategy = PrefetchStrategy::new(2);
149
150 scheduler.update(95, 99, 100, 1.0, &strategy);
152
153 assert_eq!(scheduler.next_prefetch(), None);
155 }
156
157 #[test]
158 fn test_prefetch_disabled() {
159 let mut scheduler = PrefetchScheduler::new();
160 let strategy = PrefetchStrategy::disabled();
161
162 scheduler.update(5, 10, 100, 1.0, &strategy);
163
164 assert_eq!(scheduler.next_prefetch(), None);
165 }
166}