miden_debug_types/
selection.rs1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3
4use super::{ColumnIndex, LineIndex};
5
6#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
10#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
11pub struct Selection {
12 pub start: Position,
13 pub end: Position,
14}
15
16impl Selection {
17 #[inline]
18 pub fn new(start: Position, end: Position) -> Self {
19 if start <= end {
20 Self { start, end }
21 } else {
22 Self { start: end, end: start }
23 }
24 }
25
26 pub fn canonicalize(&mut self) {
27 if self.start > self.end {
28 core::mem::swap(&mut self.start, &mut self.end);
29 }
30 }
31}
32
33impl From<core::ops::Range<Position>> for Selection {
34 #[inline]
35 fn from(value: core::ops::Range<Position>) -> Self {
36 Self::new(value.start, value.end)
37 }
38}
39
40impl From<core::ops::Range<LineIndex>> for Selection {
41 #[inline]
42 fn from(value: core::ops::Range<LineIndex>) -> Self {
43 Self::new(value.start.into(), value.end.into())
44 }
45}
46
47#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
51#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
52pub struct Position {
53 pub line: LineIndex,
54 pub character: ColumnIndex,
55}
56
57impl Position {
58 pub const fn new(line: u32, character: u32) -> Self {
59 Self {
60 line: LineIndex(line),
61 character: ColumnIndex(character),
62 }
63 }
64}
65
66impl From<LineIndex> for Position {
67 #[inline]
68 fn from(line: LineIndex) -> Self {
69 Self { line, character: ColumnIndex(0) }
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn selection_new_orders_bounds_when_reversed() {
79 let a = Position::new(10, 5);
80 let b = Position::new(2, 3);
81 let sel = Selection::new(a, b);
82 assert!(sel.start <= sel.end);
83 assert_eq!(sel.start, b);
84 assert_eq!(sel.end, a);
85 }
86
87 #[test]
88 fn selection_new_keeps_order_when_already_ordered() {
89 let a = Position::new(2, 3);
90 let b = Position::new(10, 5);
91 let sel = Selection::new(a, b);
92 assert_eq!(sel.start, a);
93 assert_eq!(sel.end, b);
94 }
95
96 #[test]
97 fn canonicalize_swaps_only_when_start_greater_than_end() {
98 let a = Position::new(10, 5);
99 let b = Position::new(2, 3);
100 let mut sel = Selection { start: a, end: b };
101 sel.canonicalize();
102 assert!(sel.start <= sel.end);
103 assert_eq!(sel.start, b);
104 assert_eq!(sel.end, a);
105
106 let mut sel2 = Selection { start: b, end: a };
107 sel2.canonicalize();
108 assert_eq!(sel2.start, b);
109 assert_eq!(sel2.end, a);
110 }
111}