use std::{collections::HashMap, mem};
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct StringMap {
pub(super) indices: HashMap<String, usize>,
pub(super) entries: Vec<Option<String>>,
}
impl StringMap {
pub fn get_index(&self, i: usize) -> Option<&str> {
self.entries.get(i).and_then(|entry| entry.as_deref())
}
pub fn get_index_of(&self, value: &str) -> Option<usize> {
self.indices.get(value).copied()
}
pub(super) fn get_full(&self, value: &str) -> Option<(usize, &str)> {
self.get_index_of(value)
.and_then(|i| self.get_index(i).map(|entry| (i, entry)))
}
#[doc(hidden)]
pub fn insert(&mut self, value: String) -> Option<String> {
self.insert_full(value).1
}
fn insert_full(&mut self, value: String) -> (usize, Option<String>) {
match self.get_index_of(&value) {
Some(i) => {
let entry = mem::replace(&mut self.entries[i], Some(value));
(i, entry)
}
None => {
let i = self.push(value);
(i, None)
}
}
}
pub(super) fn insert_at(&mut self, i: usize, value: String) -> Option<String> {
if i >= self.entries.len() {
self.entries.resize(i + 1, None);
}
self.indices.insert(value.clone(), i);
mem::replace(&mut self.entries[i], Some(value))
}
fn push(&mut self, value: String) -> usize {
let i = self.entries.len();
self.indices.insert(value.clone(), i);
self.entries.push(Some(value));
i
}
}