// Copyright (c) 2022 Marceline Cramer // SPDX-License-Identifier: GPL-3.0-or-later use std::collections::HashMap; pub trait Named { fn name<'a>(&'a self) -> &'a str; } impl Named for String { fn name<'a>(&'a self) -> &'a str { use std::borrow::Borrow; self.borrow() } } impl Named for &str { fn name<'a>(&'a self) -> &'a str { self } } #[derive(Clone, Debug, Eq, PartialEq)] pub struct DuplicationError { pub original_index: usize, pub original_key: String, pub new_index: usize, pub new_val: T, } #[derive(Default, Clone, Debug, Eq, PartialEq)] pub struct NameVec { pub vals: Vec, pub keys: HashMap, } impl NameVec { pub fn push(&mut self, val: T) -> Result { let name = val.name(); if let Some(old_index) = self.keys.get(name) { Err(*old_index) } else { let new_index = self.vals.len(); self.keys.insert(name.to_string(), new_index); self.vals.push(val); Ok(new_index) } } pub fn contains(&self, name: &str) -> bool { self.keys.contains_key(name) } pub fn get(&self, name: &str) -> Option<&T> { if let Some(idx) = self.get_idx(name) { self.vals.get(idx) } else { None } } pub fn get_idx(&self, name: &str) -> Option { self.keys.get(name).map(|x| *x) } } // TODO implement and write unit tests! // impl FromIterator for Result, DuplicationError> {} #[cfg(test)] pub mod tests { use super::*; #[test] fn basic_usage() { let mut nv = NameVec::default(); assert_eq!(Ok(0), nv.push("val0")); assert_eq!(Ok(1), nv.push("val1")); assert_eq!(Ok(2), nv.push("val2")); assert_eq!(true, nv.contains("val0")); assert_eq!(false, nv.contains("not in set")); assert_eq!(Some(&"val0"), nv.get("val0")); assert_eq!(Some(&"val2"), nv.get("val2")); assert_eq!(None, nv.get("val3")); assert_eq!(Some(1), nv.get_idx("val1")); assert_eq!(None, nv.get_idx("val4")); } #[test] fn deduplicate() { let mut nv = NameVec::default(); assert_eq!(Ok(0), nv.push("original")); assert_eq!(Ok(1), nv.push("next")); assert_eq!(Err(0), nv.push("original")); } }