1use dashmap::DashMap;
2use std::collections::{HashMap, HashSet};
3
4use crate::block::{BlockId, BlockKind, BlockRelation};
5
6#[derive(Debug, Default, Clone)]
8pub struct BlockRelationMap {
9 relations: DashMap<BlockId, HashMap<BlockRelation, Vec<BlockId>>>,
11}
12
13impl BlockRelationMap {
14 pub fn add_relation_impl(&self, from: BlockId, relation: BlockRelation, to: BlockId) {
16 self.relations
17 .entry(from)
18 .or_default()
19 .entry(relation)
20 .or_default()
21 .push(to);
22 }
23
24 pub fn add_relation_impls(&self, from: BlockId, relation: BlockRelation, targets: &[BlockId]) {
26 let mut entry = self.relations.entry(from).or_default();
27 let relation_vec = entry.entry(relation).or_default();
28 relation_vec.extend_from_slice(targets);
29 }
30
31 pub fn remove_relation_impl(
33 &self,
34 from: BlockId,
35 relation: BlockRelation,
36 to: BlockId,
37 ) -> bool {
38 let mut removed = false;
39 if let Some(mut block_relations) = self.relations.get_mut(&from) {
40 if let Some(targets) = block_relations.get_mut(&relation)
41 && let Some(pos) = targets.iter().position(|&x| x == to)
42 {
43 targets.remove(pos);
44 removed = true;
45 if targets.is_empty() {
47 block_relations.remove(&relation);
48 }
49 }
50 if block_relations.is_empty() {
52 drop(block_relations);
53 self.relations.remove(&from);
54 }
55 }
56 removed
57 }
58
59 pub fn remove_all_relations(&self, from: BlockId, relation: BlockRelation) -> Vec<BlockId> {
61 let mut result = Vec::new();
62 if let Some(mut block_relations) = self.relations.get_mut(&from) {
63 if let Some(targets) = block_relations.remove(&relation) {
64 result = targets;
65 }
66 if block_relations.is_empty() {
68 drop(block_relations);
69 self.relations.remove(&from);
70 }
71 }
72 result
73 }
74
75 pub fn remove_block_relations(&self, block_id: BlockId) {
77 self.relations.remove(&block_id);
78 }
79
80 pub fn get_related(&self, from: BlockId, relation: BlockRelation) -> Vec<BlockId> {
82 self.relations
83 .get(&from)
84 .and_then(|block_relations| block_relations.get(&relation).cloned())
85 .unwrap_or_default()
86 }
87
88 pub fn get_all_relations(&self, from: BlockId) -> HashMap<BlockRelation, Vec<BlockId>> {
90 self.relations
91 .get(&from)
92 .map(|r| r.clone())
93 .unwrap_or_default()
94 }
95
96 pub fn has_relation(&self, from: BlockId, relation: BlockRelation, to: BlockId) -> bool {
98 self.relations
99 .get(&from)
100 .and_then(|block_relations| block_relations.get(&relation).map(|t| t.contains(&to)))
101 .unwrap_or(false)
102 }
103
104 pub fn add_relation_if_not_exists(&self, from: BlockId, relation: BlockRelation, to: BlockId) {
106 let mut entry = self.relations.entry(from).or_default();
107 let targets = entry.entry(relation).or_default();
108 if !targets.contains(&to) {
109 targets.push(to);
110 }
111 }
112
113 pub fn add_bidirectional_if_not_exists(&self, caller: BlockId, callee: BlockId) {
115 {
117 let mut caller_entry = self.relations.entry(caller).or_default();
118 let caller_targets = caller_entry.entry(BlockRelation::Calls).or_default();
119 if !caller_targets.contains(&callee) {
120 caller_targets.push(callee);
121 }
122 }
123
124 {
126 let mut callee_entry = self.relations.entry(callee).or_default();
127 let callee_targets = callee_entry.entry(BlockRelation::CalledBy).or_default();
128 if !callee_targets.contains(&caller) {
129 callee_targets.push(caller);
130 }
131 }
132 }
133
134 pub fn has_relation_type(&self, from: BlockId, relation: BlockRelation) -> bool {
136 self.relations
137 .get(&from)
138 .and_then(|block_relations| block_relations.get(&relation).map(|t| !t.is_empty()))
139 .unwrap_or(false)
140 }
141
142 pub fn get_connected_blocks(&self) -> Vec<BlockId> {
144 self.relations.iter().map(|r| *r.key()).collect()
145 }
146
147 pub fn get_all_related_blocks(&self, from: BlockId) -> HashSet<BlockId> {
149 let mut result = HashSet::new();
150 if let Some(block_relations) = self.relations.get(&from) {
151 for targets in block_relations.values() {
152 result.extend(targets.iter().copied());
153 }
154 }
155 result
156 }
157
158 pub fn find_reverse_relations(&self, to: BlockId, relation: BlockRelation) -> Vec<BlockId> {
160 let mut result = Vec::new();
161 for entry in self.relations.iter() {
162 let from_block = *entry.key();
163 let block_relations = entry.value();
164 if let Some(targets) = block_relations.get(&relation)
165 && targets.contains(&to)
166 {
167 result.push(from_block);
168 }
169 }
170 result
171 }
172
173 pub fn stats(&self) -> RelationStats {
175 let mut total_relations = 0;
176 let mut by_relation: HashMap<BlockRelation, usize> = HashMap::new();
177
178 for entry in self.relations.iter() {
179 let block_relations = entry.value();
180 for (&relation, targets) in block_relations.iter() {
181 by_relation
182 .entry(relation)
183 .and_modify(|count| *count += targets.len())
184 .or_insert_with(|| targets.len());
185 total_relations += targets.len();
186 }
187 }
188
189 RelationStats {
190 total_blocks: self.relations.len(),
191 total_relations,
192 by_relation,
193 }
194 }
195
196 pub fn clear(&self) {
198 self.relations.clear();
199 }
200
201 pub fn is_empty(&self) -> bool {
203 self.relations.is_empty()
204 }
205
206 pub fn len(&self) -> usize {
208 self.relations.len()
209 }
210}
211
212pub struct RelationBuilder<'a> {
214 map: &'a BlockRelationMap,
215 from: BlockId,
216}
217
218impl<'a> RelationBuilder<'a> {
219 fn new(map: &'a BlockRelationMap, from: BlockId) -> Self {
220 Self { map, from }
221 }
222
223 pub fn calls(self, to: BlockId) -> Self {
225 self.map
226 .add_relation_impl(self.from, BlockRelation::Calls, to);
227 self
228 }
229
230 pub fn called_by(self, to: BlockId) -> Self {
232 self.map
233 .add_relation_impl(self.from, BlockRelation::CalledBy, to);
234 self
235 }
236
237 pub fn contains(self, to: BlockId) -> Self {
239 self.map
240 .add_relation_impl(self.from, BlockRelation::Contains, to);
241 self
242 }
243
244 pub fn contained_by(self, to: BlockId) -> Self {
246 self.map
247 .add_relation_impl(self.from, BlockRelation::ContainedBy, to);
248 self
249 }
250
251 pub fn relation(self, relation: BlockRelation, to: BlockId) -> Self {
253 self.map.add_relation_impl(self.from, relation, to);
254 self
255 }
256
257 pub fn relations(self, relation: BlockRelation, targets: &[BlockId]) -> Self {
259 self.map.add_relation_impls(self.from, relation, targets);
260 self
261 }
262}
263
264impl BlockRelationMap {
265 pub fn from_block(&self, from: BlockId) -> RelationBuilder<'_> {
267 RelationBuilder::new(self, from)
268 }
269}
270
271#[derive(Debug, Default, Clone)]
273pub struct RelationStats {
274 pub total_blocks: usize,
275 pub total_relations: usize,
276 pub by_relation: HashMap<BlockRelation, usize>,
277}
278
279impl std::fmt::Display for RelationStats {
280 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
281 writeln!(f, "Relation Stats:")?;
282 writeln!(f, " Total blocks with relations: {}", self.total_blocks)?;
283 writeln!(f, " Total relationships: {}", self.total_relations)?;
284 writeln!(f, " By type:")?;
285 for (&relation, &count) in &self.by_relation {
286 writeln!(f, " {relation}: {count}")?;
287 }
288 Ok(())
289 }
290}
291
292impl BlockRelationMap {
294 pub fn add_call_relation(&self, caller: BlockId, callee: BlockId) {
296 self.add_relation_impl(caller, BlockRelation::Calls, callee);
297 self.add_relation_impl(callee, BlockRelation::CalledBy, caller);
298 }
299
300 pub fn remove_call_relation(&self, caller: BlockId, callee: BlockId) {
302 self.remove_relation_impl(caller, BlockRelation::Calls, callee);
303 self.remove_relation_impl(callee, BlockRelation::CalledBy, caller);
304 }
305
306 pub fn get_callers(&self, block: BlockId) -> Vec<BlockId> {
307 self.get_related(block, BlockRelation::CalledBy)
308 }
309
310 pub fn get_callees(&self, block: BlockId) -> Vec<BlockId> {
311 self.get_related(block, BlockRelation::Calls)
312 }
313
314 pub fn get_children(&self, block: BlockId) -> Vec<BlockId> {
316 self.get_related(block, BlockRelation::Unknown)
317 }
318
319 pub fn get_parent(&self, block: BlockId) -> Option<BlockId> {
321 self.find_reverse_relations(block, BlockRelation::Unknown)
322 .into_iter()
323 .next()
324 }
325
326 pub fn get_ancestors(&self, mut block: BlockId) -> Vec<BlockId> {
328 let mut ancestors = Vec::new();
329 let mut visited = HashSet::new();
330
331 while let Some(parent) = self.get_parent(block) {
332 if visited.contains(&parent) {
333 break;
335 }
336 visited.insert(parent);
337 ancestors.push(parent);
338 block = parent;
339 }
340
341 ancestors
342 }
343
344 pub fn get_descendants(&self, block: BlockId) -> Vec<BlockId> {
346 let mut descendants = Vec::new();
347 let mut visited = HashSet::new();
348 let mut queue = vec![block];
349
350 while let Some(current) = queue.pop() {
351 if visited.contains(¤t) {
352 continue;
353 }
354 visited.insert(current);
355
356 let children = self.get_children(current);
357 descendants.extend(&children);
358 queue.extend(children);
359 }
360
361 descendants
362 }
363}
364
365pub struct BlockIndexMaps {
379 block_name_index: DashMap<String, Vec<(usize, BlockKind, BlockId)>>,
382
383 unit_index_map: DashMap<usize, Vec<(Option<String>, BlockKind, BlockId)>>,
386
387 block_kind_index: DashMap<BlockKind, Vec<(usize, Option<String>, BlockId)>>,
390
391 block_id_index: DashMap<BlockId, (usize, Option<String>, BlockKind)>,
394}
395
396impl Default for BlockIndexMaps {
397 fn default() -> Self {
398 Self::new()
399 }
400}
401
402impl BlockIndexMaps {
403 pub fn new() -> Self {
405 Self {
406 block_name_index: DashMap::new(),
407 unit_index_map: DashMap::new(),
408 block_kind_index: DashMap::new(),
409 block_id_index: DashMap::new(),
410 }
411 }
412
413 pub fn insert_block(
421 &self,
422 block_id: BlockId,
423 block_name: Option<String>,
424 block_kind: BlockKind,
425 unit_index: usize,
426 ) {
427 self.block_id_index
429 .insert(block_id, (unit_index, block_name.clone(), block_kind));
430
431 if let Some(ref name) = block_name {
433 self.block_name_index
434 .entry(name.clone())
435 .or_default()
436 .push((unit_index, block_kind, block_id));
437 }
438
439 self.unit_index_map.entry(unit_index).or_default().push((
441 block_name.clone(),
442 block_kind,
443 block_id,
444 ));
445
446 self.block_kind_index
448 .entry(block_kind)
449 .or_default()
450 .push((unit_index, block_name, block_id));
451 }
452
453 pub fn find_by_name(&self, name: &str) -> Vec<(usize, BlockKind, BlockId)> {
457 self.block_name_index
458 .get(name)
459 .map(|v| v.clone())
460 .unwrap_or_default()
461 }
462
463 pub fn find_by_unit(&self, unit_index: usize) -> Vec<(Option<String>, BlockKind, BlockId)> {
467 self.unit_index_map
468 .get(&unit_index)
469 .map(|v| v.clone())
470 .unwrap_or_default()
471 }
472
473 pub fn find_by_kind(&self, block_kind: BlockKind) -> Vec<(usize, Option<String>, BlockId)> {
477 self.block_kind_index
478 .get(&block_kind)
479 .map(|v| v.clone())
480 .unwrap_or_default()
481 }
482
483 pub fn find_by_kind_and_unit(&self, block_kind: BlockKind, unit_index: usize) -> Vec<BlockId> {
487 let by_kind = self.find_by_kind(block_kind);
488 by_kind
489 .into_iter()
490 .filter(|(unit, _, _)| *unit == unit_index)
491 .map(|(_, _, block_id)| block_id)
492 .collect()
493 }
494
495 pub fn get_block_info(&self, block_id: BlockId) -> Option<(usize, Option<String>, BlockKind)> {
499 self.block_id_index.get(&block_id).map(|v| v.clone())
500 }
501
502 pub fn block_count(&self) -> usize {
504 self.block_id_index.len()
505 }
506
507 pub fn unique_names_count(&self) -> usize {
509 self.block_name_index.len()
510 }
511
512 pub fn contains_block(&self, block_id: BlockId) -> bool {
514 self.block_id_index.contains_key(&block_id)
515 }
516
517 pub fn iter_all_blocks(&self) -> Vec<(BlockId, usize, Option<String>, BlockKind)> {
520 self.block_id_index
521 .iter()
522 .map(|entry| {
523 let block_id = *entry.key();
524 let (unit_index, name, kind) = entry.value();
525 (block_id, *unit_index, name.clone(), *kind)
526 })
527 .collect()
528 }
529
530 pub fn clear(&self) {
532 self.block_name_index.clear();
533 self.unit_index_map.clear();
534 self.block_kind_index.clear();
535 self.block_id_index.clear();
536 }
537}