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
use std::collections::HashMap;

use super::Function;

/// A type that maps functions to their assigned names.
#[derive(Clone, Debug)]
pub struct FunctionsStore {
    dict: HashMap<Function, String>,
}

impl FunctionsStore {
    pub fn new<T>(functions: T) -> Self
    where
        T: IntoIterator<Item = Function>,
    {
        let mut dict = HashMap::new();
        for function in functions {
            Self::_insert(function, &mut dict);
        }
        Self { dict }
    }

    pub fn insert(&mut self, function: Function) {
        Self::_insert(function, &mut self.dict);
    }

    pub fn assigned_name(&self, function: &Function) -> Option<&str> {
        self.dict.get(function).map(|name| name.as_str())
    }

    pub fn name(&self, function: &Function) -> String {
        self.assigned_name(function)
            .map(|name| name.to_string())
            .unwrap_or_else(|| function.name())
    }

    pub fn name_for_function(function: &Function, functions: Option<&Self>) -> String {
        functions
            .and_then(|functions| functions.assigned_name(function))
            .map(|name| name.to_string())
            .unwrap_or_else(|| function.name())
    }

    fn _insert(function: Function, dict: &mut HashMap<Function, String>) {
        match function {
            Function::Known(_, _) => {
                let name = function.name();
                dict.insert(function, name);
            }
            _ => panic!(),
        }
    }
}

impl Default for FunctionsStore {
    fn default() -> Self {
        Self::new([])
    }
}