如何根据清单设置注入代码?



如果我没有恰当地问这个问题,我道歉。我觉得问题的一部分是我很难用习惯用语来描述我正在做的事情。

我目前正试图弄清楚我是否可以注册在lib.rs中定义的处理程序函数到服务中,仅基于读取YAML清单文件。

我有一个清单文件config.yaml

event: count
handler: count_handler

我有一个lib.rs与以下定义:

// This is somewhat pseudo-code (has not been tested, but gives you the idea)
fn count_handler(d: Vec<u8>) -> Vec<u8> {
println!("count_handler was called!");
Vec::new()
}
type HandlerFn = fn(Vec<u8>) -> Vec<u8>;
struct Service {
handlers: HashMap<String, HandlerFn>,
}
impl Service {
fn new() -> Self {
let handlers: HashMap::new();
Self { handlers }
}
fn register_handler(&mut self, name: String, handler: HandlerFn) {
self.handlers.insert(name, handler);
}
fn start() {
println!("I'm doing some things with these handlers: {:?}", self.handlers);
}
}

我想弄明白的是:

  • 是否有任何方法可以使用清单文件在Service中自动注册我的count_handler?
    • 更新:似乎没有办法做到这一点使用只有manifest文件,所以让我进一步澄清
  • 是否有办法使用某种类型的宏来做到这一点?(proc宏?)
  • 我基本上需要任何映射生成发生而不需要用户手动注册处理程序

理想情况下,我将能够做到以下几点:

fn main() {
let manifest: Manifest = Manifest::from_file("config.yaml");
// assert_eq!(manifest.event, "count".to_owned());
// assert_eq!(manifest.handler, "count_handler".to_owned());
let service = Service::new();
service.start();
// "I'm doing some things with these handlers: HashMap{ "count": Function(count_handler) }"
}

一些约束和说明:

  • 假设清单中定义的handler总是存在于lib.rs
  • count_handler可以是任何满足HandlerFn
  • 的函数
  • 清单中的handler将始终由eventService中索引
    • 在本例中,<"count", count_handler()>Service
    • 中注册。

我不认为这在Rust中是可能的,但只是想弄清楚一些。

如果您想在运行时处理此问题,即在更改YAML文件时不重新编译应用程序,那么答案是:不,这是不可能的(不用再费力了)。这是因为Rust没有运行时反射的概念,因此函数的名称在编译时被擦除。根本没有办法查到。

作为用户EvilTak在评论中指出,你可以建立一个支持结构,这样你最终得到的某种从处理程序映射函数名(例如count_handler)对函数的引用可以在运行时调用,所以例如HashMap<String, fn(Vec<u8>) -> Vec<u8>>

然而,这似乎不符合您的"只使用清单文件"的标准。


也就是说,如果每次更改YAML文件时都可以重新编译应用程序,那么这是非常可能的。接下来的想法是在编译期间,在宏中读取YAML文件,并生成代码,如果您手动连接东西,您将自己编写这些代码。

最新更新