1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#![forbid(unsafe_code)]
use anyhow::Result;
use bytecode_source_map::source_map::SourceMap;
use crate::{
bytecode_viewer::{BytecodeInfo, BytecodeViewer},
interfaces::{RightScreen, SourceContext},
};
use move_binary_format::file_format::CompiledModule;
use std::{cmp, fs, path::Path};
const CONTEXT_SIZE: usize = 1000;
#[derive(Debug, Clone)]
pub struct ModuleViewer {
file_index: usize,
source_code: Vec<String>,
source_map: SourceMap,
module: CompiledModule,
}
impl ModuleViewer {
pub fn new(module: CompiledModule, source_map: SourceMap, source_location: &Path) -> Self {
let mut source_code = vec![];
let file_contents = fs::read_to_string(source_location).unwrap();
let file_index = source_code.len() - 1;
source_code.push(file_contents);
Self {
file_index,
source_code,
source_map,
module,
}
}
}
impl<'a> RightScreen<BytecodeViewer<'a>> for ModuleViewer {
fn source_for_code_location(&self, bytecode_info: &BytecodeInfo) -> Result<SourceContext> {
let loc = self
.source_map
.get_code_location(bytecode_info.function_index, bytecode_info.code_offset)?;
let loc_start = loc.start() as usize;
let loc_end = loc.end() as usize;
let source = &self.source_code[self.file_index];
let source_span_end = source.len();
let context_start = loc_start.saturating_sub(CONTEXT_SIZE);
let context_end = cmp::min(loc_end.checked_add(CONTEXT_SIZE).unwrap(), source_span_end);
let left = &source[context_start..loc_start];
let highlight = source[loc_start..loc_end].to_owned();
let remainder = &source[loc_end..context_end];
Ok(SourceContext {
left: left.to_string(),
highlight,
remainder: remainder.to_string(),
})
}
fn backing_string(&self) -> String {
self.source_code[self.file_index].clone()
}
}