use std::collections::HashMap;
use std::sync::Arc;
use serde_json::Value;
pub type DefaultData = HashMap<String, Value>;
pub type DataFactory<T> = Arc<dyn Fn() -> T + Send + Sync>;
#[derive(Clone)]
pub struct ContextTypes<UD = DefaultData, CD = DefaultData, BD = DefaultData> {
user_data_factory: DataFactory<UD>,
chat_data_factory: DataFactory<CD>,
bot_data_factory: DataFactory<BD>,
}
impl Default for ContextTypes<DefaultData, DefaultData, DefaultData> {
fn default() -> Self {
Self {
user_data_factory: Arc::new(HashMap::<String, serde_json::Value>::new),
chat_data_factory: Arc::new(HashMap::<String, serde_json::Value>::new),
bot_data_factory: Arc::new(HashMap::<String, serde_json::Value>::new),
}
}
}
impl<UD, CD, BD> ContextTypes<UD, CD, BD>
where
UD: Send + Sync + 'static,
CD: Send + Sync + 'static,
BD: Send + Sync + 'static,
{
#[must_use]
pub fn new(
user_data_factory: DataFactory<UD>,
chat_data_factory: DataFactory<CD>,
bot_data_factory: DataFactory<BD>,
) -> Self {
Self {
user_data_factory,
chat_data_factory,
bot_data_factory,
}
}
#[must_use]
pub fn user_data(&self) -> UD {
(self.user_data_factory)()
}
#[must_use]
pub fn chat_data(&self) -> CD {
(self.chat_data_factory)()
}
#[must_use]
pub fn bot_data(&self) -> BD {
(self.bot_data_factory)()
}
#[must_use]
pub fn user_data_factory(&self) -> &DataFactory<UD> {
&self.user_data_factory
}
#[must_use]
pub fn chat_data_factory(&self) -> &DataFactory<CD> {
&self.chat_data_factory
}
#[must_use]
pub fn bot_data_factory(&self) -> &DataFactory<BD> {
&self.bot_data_factory
}
}
impl<UD, CD, BD> std::fmt::Debug for ContextTypes<UD, CD, BD> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ContextTypes")
.field("user_data_factory", &"<fn>")
.field("chat_data_factory", &"<fn>")
.field("bot_data_factory", &"<fn>")
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_context_types_produce_empty_hashmaps() {
let ct = ContextTypes::default();
let ud: DefaultData = ct.user_data();
let cd: DefaultData = ct.chat_data();
let bd: DefaultData = ct.bot_data();
assert!(ud.is_empty());
assert!(cd.is_empty());
assert!(bd.is_empty());
}
#[test]
fn custom_context_types() {
#[derive(Debug, Default)]
struct MyUserData {
score: i32,
}
let ct = ContextTypes::new(
Arc::new(|| MyUserData { score: 100 }),
Arc::new(HashMap::<String, serde_json::Value>::new),
Arc::new(HashMap::<String, serde_json::Value>::new),
);
let ud = ct.user_data();
assert_eq!(ud.score, 100);
}
#[test]
fn factory_is_repeatable() {
let ct = ContextTypes::default();
let a: DefaultData = ct.user_data();
let b: DefaultData = ct.user_data();
assert!(a.is_empty());
assert!(b.is_empty());
}
#[test]
fn debug_impl() {
let ct = ContextTypes::default();
let s = format!("{ct:?}");
assert!(s.contains("ContextTypes"));
}
}