From 9c1709e134b22971b5d97ac03d2b208079a20575 Mon Sep 17 00:00:00 2001 From: mars Date: Thu, 3 Mar 2022 20:04:03 -0700 Subject: [PATCH] NameVec support --- src/lib.rs | 3 +- src/namevec.rs | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 src/namevec.rs diff --git a/src/lib.rs b/src/lib.rs index 7af9e36..8ff542b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/src/namevec.rs b/src/namevec.rs new file mode 100644 index 0000000..d6ef345 --- /dev/null +++ b/src/namevec.rs @@ -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 { + 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")); + } +}