use crate::error::RpcError;
use core::error::Error;
use core::fmt::{self, Debug, Display};
use core::future::Future;
use core::pin::Pin;
use serde_json::Value;
use std::collections::BTreeMap;
use std::collections::btree_map::Entry;
use std::sync::Arc;
pub type Answer = Pin<Box<dyn Future<Output = Result<Value, RpcError>> + Send>>;
pub(crate) type Method = Arc<dyn Fn(Option<Value>) -> Answer + Send + Sync>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DuplicateMethod(pub &'static str);
impl Display for DuplicateMethod {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "method `{}` is declared twice", self.0)
}
}
impl Error for DuplicateMethod {}
#[derive(Clone, Default)]
pub struct MethodTable {
methods: BTreeMap<&'static str, Method>,
}
impl MethodTable {
pub fn names(&self) -> Vec<&'static str> {
self.methods.keys().copied().collect()
}
pub fn len(&self) -> usize {
self.methods.len()
}
pub fn is_empty(&self) -> bool {
self.methods.is_empty()
}
pub fn merge(mut self, other: Self) -> Result<Self, DuplicateMethod> {
for (name, method) in other.methods {
self.insert(name, method)?;
}
Ok(self)
}
pub(crate) fn insert(&mut self, name: &'static str, method: Method) -> Result<(), DuplicateMethod> {
match self.methods.entry(name) {
Entry::Occupied(_) => Err(DuplicateMethod(name)),
Entry::Vacant(entry) => {
entry.insert(method);
Ok(())
}
}
}
pub(crate) fn get(&self, name: &str) -> Option<&Method> {
self.methods.get(name)
}
}
impl Debug for MethodTable {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.debug_struct("MethodTable").field("methods", &self.names()).finish()
}
}