use std::collections::HashMap;
use std::sync::Mutex;
use serde::{Deserialize, Serialize};
use crate::protocol::FnType;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FnDef {
pub name: String,
pub fn_type: FnType,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub args_schema: Option<serde_json::Value>,
}
pub struct FnRegistry {
fns: Mutex<HashMap<String, FnDef>>,
}
impl FnRegistry {
pub fn new() -> Self {
Self {
fns: Mutex::new(HashMap::new()),
}
}
pub fn register(&self, def: FnDef) {
self.fns.lock().unwrap().insert(def.name.clone(), def);
}
pub fn register_all(&self, defs: Vec<FnDef>) {
let mut fns = self.fns.lock().unwrap();
for def in defs {
fns.insert(def.name.clone(), def);
}
}
pub fn replace_all(&self, defs: Vec<FnDef>) {
let mut fns = self.fns.lock().unwrap();
fns.clear();
for def in defs {
fns.insert(def.name.clone(), def);
}
}
pub fn get(&self, name: &str) -> Option<FnDef> {
self.fns.lock().unwrap().get(name).cloned()
}
pub fn list(&self) -> Vec<FnDef> {
self.fns.lock().unwrap().values().cloned().collect()
}
pub fn list_by_type(&self, fn_type: FnType) -> Vec<FnDef> {
self.fns
.lock()
.unwrap()
.values()
.filter(|f| f.fn_type == fn_type)
.cloned()
.collect()
}
pub fn exists(&self, name: &str) -> bool {
self.fns.lock().unwrap().contains_key(name)
}
pub fn count(&self) -> usize {
self.fns.lock().unwrap().len()
}
}
impl Default for FnRegistry {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn register_and_lookup() {
let reg = FnRegistry::new();
reg.register(FnDef {
name: "placeBid".into(),
fn_type: FnType::Mutation,
args_schema: None,
});
reg.register(FnDef {
name: "getLots".into(),
fn_type: FnType::Query,
args_schema: None,
});
assert_eq!(reg.count(), 2);
assert!(reg.exists("placeBid"));
assert!(!reg.exists("nonexistent"));
let def = reg.get("placeBid").unwrap();
assert_eq!(def.fn_type, FnType::Mutation);
}
#[test]
fn list_by_type() {
let reg = FnRegistry::new();
reg.register_all(vec![
FnDef {
name: "a".into(),
fn_type: FnType::Mutation,
args_schema: None,
},
FnDef {
name: "b".into(),
fn_type: FnType::Query,
args_schema: None,
},
FnDef {
name: "c".into(),
fn_type: FnType::Mutation,
args_schema: None,
},
FnDef {
name: "d".into(),
fn_type: FnType::Action,
args_schema: None,
},
]);
assert_eq!(reg.list_by_type(FnType::Mutation).len(), 2);
assert_eq!(reg.list_by_type(FnType::Query).len(), 1);
assert_eq!(reg.list_by_type(FnType::Action).len(), 1);
}
}