use std::{fmt::Debug, sync::Arc};
#[derive(Debug, Clone)]
pub struct EntryBook<T>(Vec<EntryPair<T>>)
where
T: Clone;
impl<T> Default for EntryBook<T>
where
T: Clone,
{
fn default() -> Self {
EntryBook(Vec::new())
}
}
impl<T> EntryBook<T>
where
T: Clone,
{
pub fn insert(&mut self, key: Arc<str>, value: T) {
for piece in self.0.iter_mut() {
if piece.key == key {
*piece = EntryPair { key, value: Some(value) };
return;
}
}
self.0.push(EntryPair { key, value: Some(value) })
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn lookup(&self, key: &str) -> Option<(&T, u16)> {
for (idx, piece) in self.0.iter().enumerate() {
if &*piece.key == key {
match &piece.value {
Some(v) => {
return Some((v, idx as u16));
}
None => continue,
}
}
}
None
}
pub fn read_keys(&self) -> Vec<Arc<str>> {
self.0.iter().map(|piece| piece.key.to_owned()).collect()
}
pub fn load(&self, idx: u16) -> Result<(&T, &str), String> {
match self.0.get(idx as usize) {
Some(piece) => match &piece.value {
Some(v) => Ok((v, &*piece.key)),
None => Err(format!("given index {} is invalid in current book of size {}", idx, self.0.len())),
},
None => Err(format!("given index {} is invalid in current book of size {}", idx, self.0.len())),
}
}
pub fn check_name(&self, idx: usize, key: &str) -> Result<(), String> {
match self.0.get(idx) {
Some(piece) => {
if &*piece.key == key {
Ok(())
} else {
Err(format!("index {idx} is not for key {key}"))
}
}
None => Err(format!("index {} is invalid in current book of size {}", idx, self.0.len())),
}
}
pub fn clear(&mut self) {
self.0.clear();
}
pub fn iter(&self) -> impl Iterator<Item = (Arc<str>, &T)> {
self
.0
.iter()
.filter_map(|piece| piece.value.as_ref().map(|v| (piece.key.to_owned(), v)))
}
pub fn get_mut(&mut self, idx: usize) -> Option<&mut T> {
match self.0.get_mut(idx) {
Some(piece) => match &mut piece.value {
Some(v) => Some(v),
None => None,
},
None => None,
}
}
pub fn lookup_mut(&mut self, key: &str) -> Option<(&mut T, u16)> {
for (idx, piece) in self.0.iter_mut().enumerate() {
if &*piece.key == key {
match &mut piece.value {
Some(v) => return Some((v, idx as u16)),
None => return None,
}
}
}
None
}
pub fn remove(&mut self, key: &str) {
for piece in self.0.iter_mut() {
if &*piece.key == key {
piece.value = None;
}
}
}
pub fn keys(&self) -> impl Iterator<Item = &Arc<str>> {
self.0.iter().map(|x| &x.key)
}
pub fn to_hashmap(&self) -> std::collections::HashMap<Arc<str>, T> {
let mut res = std::collections::HashMap::with_capacity(self.0.len());
for piece in &self.0 {
if let Some(v) = &piece.value {
res.insert(piece.key.to_owned(), v.to_owned());
}
}
res
}
}
#[derive(Debug, Clone)]
pub struct EntryPair<T>
where
T: Clone,
{
pub key: Arc<str>,
pub value: Option<T>,
}