NameVec support

This commit is contained in:
mars 2022-03-03 20:04:03 -07:00
parent 4fa03f2891
commit 9c1709e134
2 changed files with 101 additions and 1 deletions

View File

@ -3,9 +3,10 @@
use console::Style;
pub mod symbols;
pub mod lexer;
pub mod namevec;
pub mod parse;
pub mod symbols;
use lexer::Token;

99
src/namevec.rs Normal file
View File

@ -0,0 +1,99 @@
// 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"));
}
}