1pub fn abs_of(seq: u64, len: usize, idx: usize) -> u64 {
10 seq - len as u64 + idx as u64
11}
12
13pub fn index_of(seq: u64, len: usize, abs: u64) -> Option<usize> {
16 if len == 0 {
17 return None;
18 }
19 let first = seq - len as u64;
20 Some(abs.saturating_sub(first).min(len as u64 - 1) as usize)
21}
22
23pub fn step(seq: u64, len: usize, abs: u64, delta: i64) -> u64 {
25 let Some(i) = index_of(seq, len, abs) else {
26 return abs;
27 };
28 let to = (i as i64).saturating_add(delta).clamp(0, len as i64 - 1);
29 abs_of(seq, len, to as usize)
30}
31
32pub fn newer(seq: u64, len: usize, abs: u64) -> u64 {
34 match index_of(seq, len, abs) {
35 Some(i) => (len - 1 - i) as u64,
36 None => 0,
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 #[test]
45 fn absolute_numbers_survive_eviction_growth_and_backfill() {
46 assert_eq!(abs_of(105, 5, 0), 100);
48 assert_eq!(abs_of(105, 5, 4), 104);
49 let cursor = abs_of(105, 5, 3); assert_eq!(index_of(106, 5, cursor), Some(2));
52 assert_eq!(index_of(105, 9, cursor), Some(7));
54 assert_eq!(abs_of(105, 9, 7), cursor);
55 }
56
57 #[test]
58 fn index_clamps_to_what_is_held() {
59 assert_eq!(index_of(105, 5, 10), Some(0), "evicted → oldest");
60 assert_eq!(index_of(105, 5, 999), Some(4), "future → newest");
61 assert_eq!(index_of(0, 0, 0), None);
62 }
63
64 #[test]
65 fn step_moves_and_stops_at_both_ends() {
66 let (seq, len) = (105, 5);
67 let mid = abs_of(seq, len, 2);
68 assert_eq!(step(seq, len, mid, -1), 101);
69 assert_eq!(step(seq, len, mid, 1), 103);
70 assert_eq!(step(seq, len, mid, -50), 100, "top");
71 assert_eq!(step(seq, len, mid, 50), 104, "bottom");
72 assert_eq!(
73 step(seq, len, 3, 1),
74 101,
75 "an evicted cursor snaps in first"
76 );
77 assert_eq!(step(0, 0, 7, 3), 7, "empty buffer: unchanged");
78 assert_eq!(step(seq, len, mid, i64::MIN), 100);
79 assert_eq!(step(seq, len, mid, i64::MAX), 104);
80 }
81
82 #[test]
83 fn newer_counts_lines_below_the_cursor() {
84 assert_eq!(newer(105, 5, 104), 0);
85 assert_eq!(newer(105, 5, 100), 4);
86 assert_eq!(newer(108, 5, 102), 4);
89 assert_eq!(newer(108, 5, 105), 2);
90 assert_eq!(newer(0, 0, 0), 0);
91 }
92}