Skip to main content

gwr_track/tracker/
aka.rs

1// Copyright (c) 2025 Graphcore Ltd. All rights reserved.
2
3//! Also Known As (AKA) - an alternative name manager.
4
5use std::collections::HashMap;
6use std::fmt::Display;
7use std::rc::Rc;
8
9use crate::entity::Entity;
10
11/// Helper function for creating local Aka derived from incoming Aka
12#[macro_export]
13macro_rules! build_aka {
14    ($aka:ident, $parent:expr, $renames:expr) => {{
15        let mut tmp_aka = gwr_track::tracker::aka::Aka::default();
16        gwr_track::tracker::aka::populate_aka($aka, Some(&mut tmp_aka), $parent, $renames);
17        tmp_aka
18    }};
19}
20
21/// Type alias for the optional list of alternative names
22pub type AlternativeNames<'a> = Option<&'a Vec<String>>;
23
24/// A structure to manage alternative names for entities
25#[derive(Default)]
26pub struct Aka {
27    names: HashMap<String, Vec<String>>,
28}
29
30impl Aka {
31    /// Get the list of alternative names for an entity
32    #[must_use]
33    pub fn get_alternative_names<'a>(&'a self, name: &str) -> AlternativeNames<'a> {
34        self.names.get(name)
35    }
36}
37
38impl Display for Aka {
39    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40        write!(f, "{:#?}", self.names)
41    }
42}
43
44/// Lookup the renames for a given port name
45#[must_use]
46pub fn get_alternative_names<'a>(aka: Option<&'a Aka>, name: &str) -> AlternativeNames<'a> {
47    if let Some(aka) = aka {
48        return aka.get_alternative_names(name);
49    }
50    None
51}
52
53/// Build up a new set of alternative names with a new set of renames
54pub fn populate_aka_from_string(
55    aka: Option<&Aka>,
56    new_aka: Option<&mut Aka>,
57    entity: &Rc<Entity>,
58    renames: &[(String, String)],
59) {
60    let ref_names: Vec<(&str, &str)> = renames
61        .iter()
62        .map(|(a, b)| (a.as_str(), b.as_str()))
63        .collect();
64    populate_aka(aka, new_aka, entity, &ref_names);
65}
66
67/// Build up a new set of alternative names with a new set of renames
68pub fn populate_aka(
69    aka: Option<&Aka>,
70    new_aka: Option<&mut Aka>,
71    entity: &Rc<Entity>,
72    renames: &[(&str, &str)],
73) {
74    if let Some(new_aka) = new_aka {
75        for (name_in_entity, name_in_child) in renames {
76            let renames = if let Some(aka) = aka.as_ref() {
77                match aka.names.get(*name_in_entity) {
78                    Some(existing_renames) => {
79                        let mut new_renames = existing_renames.clone();
80                        new_renames.push(format!("{}::{}", entity.full_name(), name_in_entity));
81                        new_renames
82                    }
83                    None => {
84                        vec![format!("{}::{}", entity.full_name(), name_in_entity)]
85                    }
86                }
87            } else {
88                vec![format!("{}::{}", entity.full_name(), name_in_entity)]
89            };
90            new_aka.names.insert((*name_in_child).to_string(), renames);
91        }
92    }
93}