1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct ZoomRange {
16 pub from_index: usize,
17 pub to_index: usize,
18}
19
20impl ZoomRange {
21 #[must_use]
23 pub const fn len(self) -> usize {
24 self.to_index - self.from_index + 1
27 }
28
29 #[must_use]
30 pub const fn is_empty(self) -> bool {
31 self.from_index > self.to_index
32 }
33
34 #[must_use]
37 pub const fn offset_to_original(self, display_index: usize) -> usize {
38 self.from_index + display_index
39 }
40}
41
42pub const MIN_ZOOM_SPAN: usize = 2;
47
48#[must_use]
53pub fn commit_drag(a: usize, b: usize, n_points: usize) -> Option<ZoomRange> {
54 if n_points == 0 {
55 return None;
56 }
57 let last = n_points - 1;
58 let lo = a.min(b).min(last);
59 let hi = a.max(b).min(last);
60 if hi - lo + 1 < MIN_ZOOM_SPAN {
61 return None;
62 }
63 Some(ZoomRange {
64 from_index: lo,
65 to_index: hi,
66 })
67}
68
69#[cfg(test)]
70mod tests {
71 #![allow(
72 clippy::expect_used,
73 reason = "panicking helpers are fine in unit tests; failure is what we want"
74 )]
75 use super::*;
76
77 #[test]
78 fn commit_drag_oriented_lr() {
79 let z = commit_drag(2, 5, 10).expect("ok");
80 assert_eq!(z.from_index, 2);
81 assert_eq!(z.to_index, 5);
82 assert_eq!(z.len(), 4);
83 }
84
85 #[test]
86 fn commit_drag_oriented_rl_normalizes() {
87 let z = commit_drag(5, 2, 10).expect("ok");
88 assert_eq!(z.from_index, 2);
89 assert_eq!(z.to_index, 5);
90 }
91
92 #[test]
93 fn commit_drag_clamps_to_last_index() {
94 let z = commit_drag(0, 999, 10).expect("ok");
95 assert_eq!(z.from_index, 0);
96 assert_eq!(z.to_index, 9);
97 }
98
99 #[test]
100 fn commit_drag_rejects_tiny_spans() {
101 assert!(commit_drag(4, 4, 10).is_none());
103 }
104
105 #[test]
106 fn commit_drag_accepts_min_span() {
107 let z = commit_drag(3, 4, 10).expect("min span ok");
109 assert_eq!(z.len(), 2);
110 }
111
112 #[test]
113 fn commit_drag_handles_empty_input() {
114 assert!(commit_drag(0, 0, 0).is_none());
115 }
116
117 #[test]
118 fn offset_to_original_shifts_by_from_index() {
119 let z = ZoomRange {
120 from_index: 7,
121 to_index: 12,
122 };
123 assert_eq!(z.offset_to_original(0), 7);
124 assert_eq!(z.offset_to_original(5), 12);
125 }
126}