impl AgentContextIndex {
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn get_calls(&self, func_idx: usize) -> Vec<&str> {
if let Some(indices) = self.calls.get(&func_idx) {
return indices
.iter()
.map(|&i| self.functions[i].function_name.as_str())
.collect();
}
if let Some(ref db_path) = self.db_path {
if let Ok(conn) = super::sqlite_backend::open_db(db_path) {
if let Ok(indices) = super::sqlite_backend::query_callees(&conn, func_idx) {
return indices
.iter()
.filter(|&&i| i < self.functions.len())
.map(|&i| self.functions[i].function_name.as_str())
.collect();
}
}
}
Vec::new()
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn get_called_by(&self, func_idx: usize) -> Vec<&str> {
if let Some(indices) = self.called_by.get(&func_idx) {
return indices
.iter()
.map(|&i| self.functions[i].function_name.as_str())
.collect();
}
if let Some(ref db_path) = self.db_path {
if let Ok(conn) = super::sqlite_backend::open_db(db_path) {
if let Ok(indices) = super::sqlite_backend::query_callers(&conn, func_idx) {
return indices
.iter()
.filter(|&&i| i < self.functions.len())
.map(|&i| self.functions[i].function_name.as_str())
.collect();
}
}
}
Vec::new()
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn called_by_indices(&self, func_idx: usize) -> Option<&[usize]> {
self.called_by.get(&func_idx).map(|v| v.as_slice())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn calls_indices(&self, func_idx: usize) -> Option<&[usize]> {
self.calls.get(&func_idx).map(|v| v.as_slice())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "non_empty_index")]
pub fn find_function_index(&self, file_path: &str, function_name: &str) -> Option<usize> {
self.functions
.iter()
.position(|f| f.file_path == file_path && f.function_name == function_name)
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn count_cross_project_callers(&self, func_idx: usize) -> u32 {
if func_idx >= self.functions.len() {
return 0;
}
let callee_project = project_prefix(&self.functions[func_idx].file_path);
if let Some(caller_indices) = self.called_by.get(&func_idx) {
return caller_indices
.iter()
.filter(|&&i| {
i < self.functions.len()
&& project_prefix(&self.functions[i].file_path) != callee_project
})
.count() as u32;
}
if let Some(ref db_path) = self.db_path {
if let Ok(conn) = super::sqlite_backend::open_db(db_path) {
if let Ok(indices) = super::sqlite_backend::query_callers(&conn, func_idx) {
return indices
.iter()
.filter(|&&i| {
i < self.functions.len()
&& project_prefix(&self.functions[i].file_path) != callee_project
})
.count() as u32;
}
}
}
0
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn load_all_source(&mut self) {
self.load_source_from_db();
self.load_source_from_filesystem();
}
fn load_source_from_db(&mut self) {
let db_path = match self.db_path {
Some(ref p) => p,
None => return,
};
let conn = match super::sqlite_backend::open_db(db_path) {
Ok(c) => c,
Err(_) => return,
};
let _ = super::sqlite_backend::load_source_into(&conn, &mut self.functions);
}
fn load_source_from_filesystem(&mut self) {
let mut files_to_read: HashMap<String, Vec<usize>> = HashMap::new();
for (idx, func) in self.functions.iter().enumerate() {
if func.source.is_empty() && func.end_line > 0 {
files_to_read.entry(func.file_path.clone()).or_default().push(idx);
}
}
for (file_path, indices) in &files_to_read {
let content = match std::fs::read_to_string(file_path) {
Ok(c) => c,
Err(_) => continue,
};
let lines: Vec<&str> = content.lines().collect();
for &idx in indices {
let start = self.functions[idx].start_line.saturating_sub(1);
let end = self.functions[idx].end_line.min(lines.len());
if start < end {
self.functions[idx].source = lines[start..end].join("\n");
}
}
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn ensure_call_graph(&mut self) {
if !self.calls.is_empty() {
return; }
if let Some(ref db_path) = self.db_path {
if let Ok(conn) = super::sqlite_backend::open_db(db_path) {
if let Ok((calls, called_by)) = super::sqlite_backend::load_call_graph(&conn) {
self.calls = calls;
self.called_by = called_by;
}
}
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub fn db_path(&self) -> Option<&Path> {
self.db_path.as_deref()
}
fn find_in_memory(&self, file_path: &str, start_line: usize) -> (Option<String>, usize) {
let indices = match self.file_index.get(file_path) {
Some(i) => i,
None => return (None, 0),
};
for &idx in indices {
if self.functions[idx].start_line != start_line {
continue;
}
if !self.functions[idx].source.is_empty() {
return (Some(self.functions[idx].source.clone()), self.functions[idx].end_line);
}
return (None, self.functions[idx].end_line);
}
(None, 0)
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "non_empty_index")]
pub fn load_source_for(&self, file_path: &str, start_line: usize) -> String {
let (in_memory, end_line) = self.find_in_memory(file_path, start_line);
if let Some(src) = in_memory {
return src;
}
if let Some(ref db_path) = self.db_path {
if let Some(src) = load_source_from_sqlite(db_path, file_path, start_line) {
return src;
}
}
load_source_from_file(file_path, start_line, end_line).unwrap_or_default()
}
}