onion_vm/utils/
mod.rs

1use crate::types::object::OnionObject;
2pub mod fastmap;
3
4const MAX_DEBUG_LEN: usize = 120; // 定义一个合理的单行最大长度
5
6/// 一个辅助函数,用于格式化 OnionObject,如果太长则截断。
7pub fn format_object_summary(obj: &OnionObject) -> String {
8    // 使用非 pretty 的 debug 格式化,这样可以得到一个单行的表示
9    let debug_str = obj.repr(&vec![]).unwrap_or("<unknown>".to_string());
10
11    if debug_str.len() > MAX_DEBUG_LEN {
12        // 如果字符串太长,截断并加上 "..."
13        // 我们需要小心处理多字节字符,所以使用 chars()
14        let mut truncated: String = debug_str.chars().take(MAX_DEBUG_LEN).collect();
15        truncated.push_str("...");
16        truncated
17    } else {
18        // 如果长度合适,直接返回
19        debug_str
20    }
21}
22
23
24/// 从原始源码字符串中根据字符索引查找行号和列号
25/// 这是更准确的版本,直接使用原始源码而不是重构的文本
26pub fn find_line_and_col_from_source(char_pos: usize, source: &str) -> (usize, usize) {
27    let chars: Vec<char> = source.chars().collect();
28
29    // 如果位置超出范围,返回最后位置
30    if char_pos >= chars.len() {
31        let line_count = source.lines().count();
32        return (line_count.saturating_sub(1), 0);
33    }
34
35    // 逐字符遍历,正确处理换行符
36    let mut current_line = 0;
37    let mut current_col = 0;
38
39    for (i, &ch) in chars.iter().enumerate() {
40        if i == char_pos {
41            return (current_line, current_col);
42        }
43
44        if ch == '\n' {
45            current_line += 1;
46            current_col = 0;
47        } else if ch == '\r' {
48            // 检查是否是 \r\n (Windows)
49            if i + 1 < chars.len() && chars[i + 1] == '\n' {
50                // 这是 \r\n,跳过 \r,让 \n 处理换行
51                continue;
52            } else {
53                // 这是单独的 \r (旧Mac风格)
54                current_line += 1;
55                current_col = 0;
56            }
57        } else {
58            current_col += 1;
59        }
60    }
61
62    // 如果到达这里,说明 char_pos 就是最后一个字符
63    (current_line, current_col)
64}