pipeline_script/lexer/
position.rs

1use std::ops::{Add, AddAssign};
2use std::string::ToString;
3
4#[derive(Debug, Clone)]
5pub struct Position {
6    pub(crate) pos: usize,
7    pub(crate) span: usize,
8    pub module_name: String,
9}
10
11impl Add for Position {
12    type Output = Position;
13
14    fn add(self, rhs: Self) -> Self::Output {
15        let mut pos = self.clone();
16        pos.span = rhs.pos.abs_diff(self.pos) + rhs.span;
17        pos
18    }
19}
20impl AddAssign for Position {
21    fn add_assign(&mut self, rhs: Self) {
22        self.span = rhs.pos.abs_diff(self.pos) + rhs.span;
23    }
24}
25impl Position {
26    pub fn none() -> Self {
27        Self {
28            pos: 0,
29            span: 0,
30            module_name: "None".to_string(),
31        }
32    }
33    pub fn new(module_name: String, pos: usize, end_pos: usize) -> Self {
34        Self {
35            pos,
36            span: end_pos.saturating_sub(pos),
37            module_name,
38        }
39    }
40
41    /// 兼容旧版本的构造函数
42    pub fn new_legacy(pos: usize, span: usize, module_name: &str) -> Self {
43        Self {
44            pos,
45            span,
46            module_name: module_name.into(),
47        }
48    }
49    #[allow(unused)]
50    pub fn set_span(&mut self, span: usize) {
51        self.span = span;
52    }
53    #[allow(unused)]
54    pub fn set_pos(&mut self, pos: usize) {
55        self.pos = pos;
56    }
57    #[allow(unused)]
58    pub fn add_span(&mut self, add: usize) {
59        self.span += add
60    }
61    #[allow(unused)]
62    pub fn is_none(&self) -> bool {
63        if self.pos == 0 && self.span == 0 {
64            return true;
65        }
66        false
67    }
68    #[allow(unused)]
69    pub fn get_raw_string(&self, source: &[char]) -> String {
70        let utf8_bytes = source[self.pos..self.pos + self.span]
71            .iter()
72            .flat_map(|&c| c.encode_utf8(&mut [0; 4]).bytes().collect::<Vec<_>>())
73            .collect::<Vec<_>>();
74        String::from_utf8(utf8_bytes).unwrap()
75    }
76    #[allow(unused)]
77    pub fn get_row_col(&self, source: &[char]) -> (usize, usize) {
78        let mut row = 0;
79        let mut col = 0;
80        for (i, &ch) in source.iter().enumerate() {
81            // 如果已经到达或超过pos指定的位置,则退出循环
82            if i >= self.pos {
83                break;
84            }
85            // 如果遇到换行符,则行数增加,列数重置(除非换行符是最后一个字符)
86            if ch == '\n' {
87                row += 1;
88                col = 0;
89            } else {
90                col += 1;
91            }
92        }
93        // 由于循环在到达pos时退出,我们需要检查最后一个字符是否是换行符
94        // 如果是,则实际的列数应该是换行符之前的列数
95        if let Some(&last_char) = source.get(self.pos - 1) {
96            if last_char == '\n' {
97                col = 0;
98            }
99        }
100        // 返回计算出的行和列
101        (row, col)
102    }
103}