1use crate::cache::{Cache, DomainEntry, FileEntry, SymbolEntry};
9
10pub struct Query<'a> {
12 cache: &'a Cache,
13}
14
15impl<'a> Query<'a> {
16 pub fn new(cache: &'a Cache) -> Self {
17 Self { cache }
18 }
19
20 pub fn symbol(&self, name: &str) -> Option<&SymbolEntry> {
22 self.cache.get_symbol(name)
23 }
24
25 pub fn file(&self, path: &str) -> Option<&FileEntry> {
32 self.cache.get_file(path)
33 }
34
35 pub fn callers(&self, symbol: &str) -> Vec<&str> {
37 self.cache
38 .get_callers(symbol)
39 .map(|v| v.iter().map(|s| s.as_str()).collect())
40 .unwrap_or_default()
41 }
42
43 pub fn callees(&self, symbol: &str) -> Vec<&str> {
45 self.cache
46 .get_callees(symbol)
47 .map(|v| v.iter().map(|s| s.as_str()).collect())
48 .unwrap_or_default()
49 }
50
51 pub fn domain(&self, name: &str) -> Option<&DomainEntry> {
53 self.cache.domains.get(name)
54 }
55
56 pub fn domains(&self) -> impl Iterator<Item = &DomainEntry> {
58 self.cache.domains.values()
59 }
60
61 pub fn files_in_domain(&self, domain: &str) -> Vec<&str> {
63 self.cache
64 .get_domain_files(domain)
65 .map(|v| v.iter().map(|s| s.as_str()).collect())
66 .unwrap_or_default()
67 }
68
69 pub fn files_in_layer(&self, layer: &str) -> Vec<&str> {
71 self.cache
72 .files
73 .values()
74 .filter(|f| f.layer.as_deref() == Some(layer))
75 .map(|f| f.path.as_str())
76 .collect()
77 }
78
79 pub fn search_symbols(&self, pattern: &str) -> Vec<&SymbolEntry> {
81 let p = pattern.to_lowercase();
82 self.cache
83 .symbols
84 .values()
85 .filter(|s| s.name.to_lowercase().contains(&p))
86 .collect()
87 }
88
89 pub fn hotpaths(&self) -> impl Iterator<Item = &str> {
91 self.cache
93 .graph
94 .as_ref()
95 .map(|g| {
96 let mut callee_counts: Vec<(&String, usize)> =
97 g.reverse.iter().map(|(k, v)| (k, v.len())).collect();
98 callee_counts.sort_by(|a, b| b.1.cmp(&a.1));
99 callee_counts
100 .into_iter()
101 .take(10)
102 .map(|(k, _)| k.as_str())
103 .collect::<Vec<_>>()
104 })
105 .unwrap_or_default()
106 .into_iter()
107 }
108}