1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
//! A registry with plugin name

use anyhow::{anyhow, Result};
use rd_interface::{registry::FromConfig, Net, Server, Value};
use std::{collections::HashMap, fmt};

pub struct NetItem {
    pub plugin_name: String,
    pub factory: FromConfig<Net>,
}

pub struct ServerItem {
    pub plugin_name: String,
    pub factory: FromConfig<Server>,
}

impl NetItem {
    pub fn build(&self, nets: Vec<Net>, config: Value) -> rd_interface::Result<Net> {
        (self.factory)(nets, config)
    }
}

impl ServerItem {
    pub fn build(&self, listen_net: Net, net: Net, config: Value) -> rd_interface::Result<Server> {
        (self.factory)(vec![listen_net, net], config)
    }
}

pub struct Registry {
    pub net: HashMap<String, NetItem>,
    pub server: HashMap<String, ServerItem>,
}

impl fmt::Debug for NetItem {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("NetItem")
            .field("plugin_name", &self.plugin_name)
            .finish()
    }
}

impl fmt::Debug for ServerItem {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("ServerItem")
            .field("plugin_name", &self.plugin_name)
            .finish()
    }
}

impl fmt::Display for Registry {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(f, "Net")?;
        for (k, v) in self.net.iter() {
            writeln!(f, "\t{}: {}", k, v.plugin_name)?;
        }
        writeln!(f, "Server")?;
        for (k, v) in self.server.iter() {
            writeln!(f, "\t{}: {}", k, v.plugin_name)?;
        }
        Ok(())
    }
}

impl Registry {
    pub fn new() -> Registry {
        Registry {
            net: HashMap::new(),
            server: HashMap::new(),
        }
    }
    pub fn init_with_registry(
        &mut self,
        name: impl Into<String>,
        init: impl Fn(&mut rd_interface::Registry) -> rd_interface::Result<()>,
    ) -> rd_interface::Result<()> {
        let mut r = rd_interface::Registry::new();
        init(&mut r)?;
        self.add_registry(name.into(), r);
        Ok(())
    }
    fn add_registry(&mut self, plugin_name: String, registry: rd_interface::Registry) {
        for (k, v) in registry.net {
            self.net.insert(
                k,
                NetItem {
                    plugin_name: plugin_name.clone(),
                    factory: v,
                },
            );
        }
        for (k, v) in registry.server {
            self.server.insert(
                k,
                ServerItem {
                    plugin_name: plugin_name.clone(),
                    factory: v,
                },
            );
        }
    }
    pub fn get_net(&self, net_type: &str) -> Result<&NetItem> {
        self.net
            .get(net_type)
            .ok_or(anyhow!("Net type is not loaded: {}", net_type))
    }
    pub fn get_server(&self, server_type: &str) -> Result<&ServerItem> {
        self.server
            .get(server_type)
            .ok_or(anyhow!("Server type is not loaded: {}", server_type))
    }
}