use std::{
collections::HashMap,
ops::{Add, AddAssign, Mul, MulAssign},
};
use crate::public::traits::CheckedType;
#[derive(Debug)]
pub struct AtomDict<T: CheckedType> {
dict: HashMap<String, T>,
}
impl<T: CheckedType> AtomDict<T> {
pub fn new() -> Self {
Self {
dict: HashMap::new(),
}
}
pub fn insert(&mut self, k: String, v: T) {
self.dict.insert(k, v);
}
pub fn get_dict(&self) -> &HashMap<String, T> {
&self.dict
}
}
impl<T: CheckedType> Add for AtomDict<T> {
type Output = Self;
fn add(mut self, rhs: Self) -> Self::Output {
self += rhs;
self
}
}
impl<T: CheckedType> Mul<T> for AtomDict<T> {
type Output = Self;
fn mul(mut self, rhs: T) -> Self::Output {
self *= rhs;
self
}
}
impl<T: CheckedType> AddAssign for AtomDict<T> {
fn add_assign(&mut self, rhs: Self) {
rhs.dict
.into_iter()
.for_each(|(k, v)| *self.dict.entry(k).or_insert_with(T::zero) += v);
}
}
impl<T: CheckedType> MulAssign<T> for AtomDict<T> {
fn mul_assign(&mut self, rhs: T) {
self.dict.iter_mut().for_each(|(_, v)| *v *= rhs);
}
}
#[cfg(test)]
mod tests {
use super::AtomDict;
use std::collections::HashMap;
#[test]
fn add_test() {
let mut a = AtomDict::<i32>::new(); let mut b = AtomDict::<i32>::new(); a.insert("C".to_string(), 1);
a.insert("H".to_string(), 4);
b.insert("H".to_string(), 2);
b.insert("O".to_string(), 1);
let c = a + b;
assert_eq!(
c.dict,
[
("H".to_string(), 6),
("O".to_string(), 1),
("C".to_string(), 1)
]
.iter()
.cloned()
.collect::<HashMap<String, i32>>()
);
}
#[test]
fn mul_test() {
let mut a = AtomDict::<i32>::new(); a.insert("C".to_string(), 1);
a.insert("H".to_string(), 4);
let c = a * 2;
assert_eq!(
c.get_dict(),
&[("H".to_string(), 8), ("C".to_string(), 2)]
.iter()
.cloned()
.collect::<HashMap<String, i32>>()
);
}
}