use lockchain::traits::{AutoEncoder, Body, FileIO, Vault};
use std::collections::{HashMap, HashSet};
use std::marker::PhantomData;
use std::path::PathBuf;
pub struct ApiState<B, V>
where
B: Body,
V: Vault<B>,
{
#[doc(hidden)]
pub vaults: HashMap<String, Option<V>>,
#[doc(hidden)]
pub _phantom: PhantomData<B>,
#[doc(hidden)]
pub tokens: HashSet<String>,
pub bound_scope: bool,
pub working_dir: PathBuf,
pub administrative: bool,
}
impl<B, V> ApiState<B, V>
where
B: Body,
V: Vault<B>,
{
pub fn load(encoded: &str) -> Option<Self> {
SerializedState::decode(encoded).ok().map(|s| s.into())
}
pub fn store(&self) -> String {
SerializedState::from(self).encode().ok().unwrap()
}
pub fn vaults(&self) -> Vec<&str> {
self.vaults.iter().map(|(k, _)| k.as_str()).collect()
}
pub fn count(&self) -> usize {
self.vaults.len()
}
pub fn add_vault(&mut self, name: &str, vault: V) {
self.vaults.insert(name.into(), Some(vault));
}
pub fn get_vault(&mut self, name: &str) -> Option<&mut V> {
self.vaults.get_mut(name)?.as_mut()
}
}
impl<B, V> Default for ApiState<B, V>
where
B: Body,
V: Vault<B>,
{
#[allow(unconditional_recursion)]
fn default() -> Self {
Self {
_phantom: PhantomData,
bound_scope: true,
vaults: HashMap::new(),
tokens: HashSet::new(),
administrative: false,
..Default::default()
}
}
}
#[derive(Serialize, Deserialize)]
struct SerializedState {
vaults: Vec<String>,
}
impl AutoEncoder for SerializedState {}
impl FileIO for SerializedState {}
impl<'state, B, V> From<&'state ApiState<B, V>> for SerializedState
where
B: Body,
V: Vault<B>,
{
fn from(me: &'state ApiState<B, V>) -> Self {
Self {
vaults: me.vaults.iter().map(|(k, _)| k.clone()).collect(),
}
}
}
impl<B, V> From<SerializedState> for ApiState<B, V>
where
B: Body,
V: Vault<B>,
{
fn from(me: SerializedState) -> Self {
Self {
vaults: me.vaults.into_iter().map(|k| (k, None)).collect(),
_phantom: PhantomData,
..Default::default()
}
}
}