100 lines
2.4 KiB
Rust
100 lines
2.4 KiB
Rust
// 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<T> {
|
|
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<T: Named> {
|
|
pub vals: Vec<T>,
|
|
pub keys: HashMap<String, usize>,
|
|
}
|
|
|
|
impl<T: Named> NameVec<T> {
|
|
pub fn push(&mut self, val: T) -> Result<usize, usize> {
|
|
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<usize> {
|
|
self.keys.get(name).map(|x| *x)
|
|
}
|
|
}
|
|
|
|
// TODO implement and write unit tests!
|
|
// impl<T: Named> FromIterator<T> for Result<NameVec<T>, DuplicationError<T>> {}
|
|
|
|
#[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"));
|
|
}
|
|
}
|