lib_ruby_parser_ast/
loc.rs1use std::convert::TryInto;
2
3#[repr(C)]
5#[derive(Clone, PartialEq, Eq, Copy, Default)]
6pub struct Loc {
7 pub begin: usize,
9
10 pub end: usize,
12}
13
14impl Loc {
15 pub fn to_range(&self) -> std::ops::Range<usize> {
17 self.begin..self.end
18 }
19
20 pub fn size(&self) -> usize {
22 self.end - self.begin
23 }
24
25 pub fn with_begin(&self, begin: usize) -> Loc {
27 Self {
28 begin,
29 end: self.end,
30 }
31 }
32
33 pub fn with_end(&self, end: usize) -> Loc {
35 Self {
36 begin: self.begin,
37 end,
38 }
39 }
40
41 pub fn adjust_begin(&self, delta: i32) -> Loc {
43 let begin: i32 = self
44 .begin
45 .try_into()
46 .expect("failed to convert location to i32 (is it too big?)");
47 let begin: usize = (begin + delta)
48 .try_into()
49 .expect("failed to convert location to usize (is it negative?)");
50 Self {
51 begin,
52 end: self.end,
53 }
54 }
55
56 pub fn adjust_end(&self, d: i32) -> Loc {
58 let end: i32 = self
59 .end
60 .try_into()
61 .expect("failed to convert location to i32 (is it too big?)");
62 let end: usize = (end + d)
63 .try_into()
64 .expect("failed to convert location to usize (is it negative?)");
65 Self {
66 begin: self.begin,
67 end,
68 }
69 }
70
71 pub fn resize(&self, new_size: usize) -> Loc {
74 self.with_end(self.begin + new_size)
75 }
76
77 pub fn join(&self, other: &Self) -> Loc {
79 Self {
80 begin: std::cmp::min(self.begin, other.begin),
81 end: std::cmp::max(self.end, other.end),
82 }
83 }
84
85 pub fn maybe_join(&self, other: &Option<Loc>) -> Loc {
86 match other.as_ref() {
87 Some(other) => self.join(other),
88 None => *self,
89 }
90 }
91
92 pub fn is_empty(&self) -> bool {
94 self.begin == self.end
95 }
96
97 pub fn print(&self, name: &str) {
98 println!(
99 "{}{} {}",
100 " ".repeat(self.begin),
101 "~".repeat(self.size()),
102 name
103 )
104 }
105}
106
107impl std::fmt::Debug for Loc {
108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 f.write_str(&format!("{}...{}", self.begin, self.end))
110 }
111}
112
113#[test]
114fn test_to_range() {
115 assert_eq!(Loc { begin: 10, end: 20 }.to_range(), 10..20)
116}
117
118#[test]
119fn test_fmt() {
120 assert_eq!(format!("{:?}", Loc { begin: 10, end: 20 }), "10...20")
121}
122
123#[test]
124fn test_is_empty() {
125 assert!(Loc { begin: 1, end: 1 }.is_empty());
126 assert!(!Loc { begin: 1, end: 2 }.is_empty());
127}