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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use std::collections::hash_map::{Iter, RandomState, Values};
use std::collections::HashMap;
use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;

use crate::models::{FromDirective, HasAliases, HasName};
use crate::LedgerError;

#[derive(Debug, Clone)]
pub struct List<T> {
    aliases: HashMap<String, String>,
    list: HashMap<String, Rc<T>>,
}

impl<T> Into<HashMap<String, Rc<T>>> for List<T> {
    fn into(self) -> HashMap<String, Rc<T>, RandomState> {
        self.list
    }
}

impl<'a, T: Eq + Hash + HasName + Clone + FromDirective + HasAliases + Debug> List<T> {
    pub fn new() -> Self {
        let aliases: HashMap<String, String> = HashMap::new();
        let list: HashMap<String, Rc<T>> = HashMap::new();
        List { aliases, list }
    }

    pub fn insert(&mut self, element: T) {
        let found = self.list.get(element.get_name());
        match found {
            Some(_) => (), // do nothing
            None => {
                let name = element.get_name().to_string();
                for alias in element.get_aliases().iter() {
                    self.aliases.insert(alias.clone(), name.clone());
                }
                self.list.insert(name.clone(), Rc::new(element));
            }
        }
    }
    pub fn add_alias(&mut self, alias: String, for_element: &'a T) {
        let element = self.aliases.get(&alias);
        match element {
            Some(x) => panic!(
                "Repeated alias {} for {} and {}",
                alias,
                for_element.get_name(),
                x
            ),
            None => {
                self.aliases
                    .insert(alias, for_element.get_name().to_string());
            }
        }
        ()
    }

    pub fn element_in_list(&self, element: &T) -> bool {
        match self.aliases.get(element.get_name()) {
            None => false,
            Some(_) => true,
        }
    }
    pub fn get(&self, index: &str) -> Result<&Rc<T>, LedgerError> {
        match self.list.get(index) {
            None => match self.aliases.get(index) {
                None => Err(LedgerError::AliasNotInList(format!(
                    "{} {:?} not found",
                    std::any::type_name::<T>(),
                    index
                ))),
                Some(x) => Ok(self.list.get(x).unwrap()),
            },
            Some(x) => Ok(x),
        }
    }

    pub fn iter(&self) -> Iter<'_, String, Rc<T>> {
        self.list.iter()
    }
    pub fn values(&self) -> Values<'_, String, Rc<T>> {
        self.list.values()
    }
    pub fn len(&self) -> usize {
        self.list.len()
    }
    pub fn len_alias(&self) -> usize {
        self.aliases.len() + self.len()
    }
}

impl<T: Clone> List<T> {
    pub fn append(&mut self, other: &List<T>) {
        self.list.extend(other.to_owned().list.into_iter());
        self.aliases.extend(other.to_owned().aliases.into_iter());
    }
}