1use std::{collections::HashMap, fmt};
2
3use crate::{INet, IServer, IntoDyn, Net, Result, Server};
4use serde::de::DeserializeOwned;
5use serde_json::Value;
6
7pub type FromConfig<T> = Box<dyn Fn(Vec<Net>, Value) -> Result<T>>;
8
9#[derive(Debug, Default, serde_derive::Deserialize)]
10pub struct EmptyConfig(Value);
11
12pub struct Registry {
13 pub net: HashMap<String, FromConfig<Net>>,
14 pub server: HashMap<String, FromConfig<Server>>,
15}
16
17impl fmt::Debug for Registry {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 f.debug_struct("Registry")
20 .field("net", &self.net.keys())
21 .field("server", &self.server.keys())
22 .finish()
23 }
24}
25
26impl Registry {
27 pub fn new() -> Registry {
28 Registry {
29 net: HashMap::new(),
30 server: HashMap::new(),
31 }
32 }
33 pub fn add_net<N: NetFactory>(&mut self) {
34 self.net.insert(N::NAME.into(), N::into_dyn());
35 }
36 pub fn add_server<S: ServerFactory>(&mut self) {
37 self.server.insert(S::NAME.into(), S::into_dyn());
38 }
39}
40
41pub trait NetFactory {
42 const NAME: &'static str;
43 type Config: DeserializeOwned;
44 type Net: INet + Sized + 'static;
45
46 fn new(nets: Vec<Net>, config: Self::Config) -> Result<Self::Net>;
47 fn into_dyn() -> FromConfig<Net> {
48 Box::new(move |nets, cfg| {
49 serde_json::from_value(cfg)
50 .map_err(Into::<crate::Error>::into)
51 .and_then(|cfg| Self::new(nets, cfg))
52 .map(|n| n.into_dyn())
53 })
54 }
55}
56
57pub trait ServerFactory {
58 const NAME: &'static str;
59 type Config: DeserializeOwned;
60 type Server: IServer + Sized + 'static;
61
62 fn new(listen_net: Net, net: Net, config: Self::Config) -> Result<Self::Server>;
63 fn into_dyn() -> FromConfig<Server> {
64 Box::new(move |mut nets, cfg| {
65 serde_json::from_value(cfg)
66 .map_err(Into::<crate::Error>::into)
67 .and_then(|cfg| {
68 if nets.len() != 2 {
69 return Err(crate::Error::Other(
70 "Server must have listen_net and net".to_string().into(),
71 ));
72 }
73 let listen_net = nets.remove(0);
74 let net = nets.remove(0);
75
76 Self::new(listen_net, net, cfg)
77 })
78 .map(|n| n.into_dyn())
79 })
80 }
81}