use std::collections::HashMap;
use std::convert::TryFrom;
use std::fmt::Debug;
use std::borrow::{Cow,ToOwned,Borrow};
use std::ops::Deref;
use crate::common::*;
use crate::types::*;
use crate::error::*;
use crate::element::*;
use crate::document::*;
pub trait Storable<Key> {
fn maybe_id(&self) -> Option<Cow<str>> {
None
}
fn encodable(&self) -> bool {
false
}
fn key(&self) -> Option<Key> {
None
}
fn assign_key(&mut self, _key: Key) {
}
}
pub trait Store<T,Key> where T: Storable<Key>,
Key: TryFrom<usize> + Copy + Debug,
usize: std::convert::TryFrom<Key>,
<usize as std::convert::TryFrom<Key>>::Error : std::fmt::Debug {
fn items_mut(&mut self) -> &mut Vec<Option<Box<T>>>;
fn index_mut(&mut self) -> &mut HashMap<String,Key>;
fn items(&self) -> &Vec<Option<Box<T>>>;
fn iter(&self) -> std::slice::Iter<Option<Box<T>>>;
fn index(&self) -> &HashMap<String,Key>;
fn encode(&mut self, item: T, _context: Option<Key>) -> Result<T,FoliaError> {
Ok(item) }
fn add(&mut self, mut item: T, context: Option<Key>) -> Result<Key,FoliaError> {
if item.encodable() {
item = self.encode(item, context)?;
}
if let Some(key) = self.get_key(&item) {
return Ok(key);
}
let id: Option<String> = item.maybe_id().map(|x| x.to_owned().to_string());
let mut boxed = Box::new(item);
if let Ok(key) = Key::try_from(self.items().len()) {
boxed.assign_key(key); self.items_mut().push( Some(boxed) );
if let Some(id) = id {
self.index_mut().insert(id,key);
}
Ok(key)
} else {
Err(FoliaError::InternalError(format!("Store.add(). Index out of bounds (e.g. integer overflow)")))
}
}
fn get_key(&self, item: &T) -> Option<Key> {
let id: &Option<Cow<str>> = &item.maybe_id();
if let Some(id) = id.as_ref() {
let id: &str = id; self.index().get(id).map(|k| k.to_owned())
} else {
None
}
}
fn is_empty(&self) -> bool {
self.items().is_empty()
}
fn len(&self) -> usize {
self.items().len()
}
fn get(&self, key: Key) -> Option<&T> {
if let Some(item) = self.items().get(usize::try_from(key).expect("conversion to usize")) { item.as_ref().map(|item| item.as_ref())
} else {
None
}
}
fn get_mut(&mut self, key: Key) -> Option<&mut T> {
if let Some(item) = self.items_mut().get_mut(usize::try_from(key).expect("conversion to usize")) { item.as_mut().map(|item| item.as_mut())
} else {
None
}
}
fn id_to_key(&self, id: &str) -> Option<Key> {
self.index().get(id).map( |&key| key )
}
fn get_by_id(&self, id: &str) -> Option<&T> {
self.id_to_key(id).map( |key| {
self.get(key)
}).map(|o| o.unwrap())
}
fn get_mut_by_id(&mut self, id: &str) -> Option<&mut T> {
self.id_to_key(id).map( move |key| {
self.get_mut(key)
}).map(|o| o.unwrap())
}
}
pub trait StringStore<Key> where Key: TryFrom<usize> + Copy + Debug,
usize: std::convert::TryFrom<Key>,
<usize as std::convert::TryFrom<Key>>::Error : std::fmt::Debug {
fn items_mut(&mut self) -> &mut Vec<Option<String>>;
fn index_mut(&mut self) -> &mut HashMap<String,Key>;
fn items(&self) -> &Vec<Option<String>>;
fn iter(&self) -> std::slice::Iter<Option<String>>;
fn index(&self) -> &HashMap<String,Key>;
fn add(&mut self, item: Cow<str>) -> Result<Key,FoliaError> {
if let Some(key) = self.get_key(&item) {
return Ok(key);
}
if let Ok(key) = Key::try_from(self.items().len()) {
self.items_mut().push( Some(item.clone().to_owned().to_string()) );
self.index_mut().insert( item.to_owned().to_string() ,key);
Ok(key)
} else {
Err(FoliaError::InternalError(format!("Store.add(). Index out of bounds (e.g. integer overflow)")))
}
}
fn get_key(&self, item: &str) -> Option<Key> {
self.index().get(item).map(|k| k.to_owned())
}
fn is_empty(&self) -> bool {
self.items().is_empty()
}
fn len(&self) -> usize {
self.items().len()
}
fn get(&self, key: Key) -> Option<&str> {
if let Some(item) = self.items().get(usize::try_from(key).expect("conversion to usize")) { item.as_ref().map(|item| item.as_ref())
} else {
None
}
}
fn get_mut(&mut self, key: Key) -> Option<&mut String> {
if let Some(item) = self.items_mut().get_mut(usize::try_from(key).expect("conversion to usize")) { item.as_mut()
} else {
None
}
}
}