runtime.rs

 1// use std::Error;
 2
 3use serde::{de::DeserializeOwned, Serialize};
 4
 5/// Represents a handle to a constant or function in the Runtime.
 6/// Should be constructed by calling [`Runtime::handle_for`].
 7#[derive(Debug, Clone, Hash, PartialEq, Eq)]
 8pub struct Handle(String);
 9
10impl Handle {
11    pub fn inner(&self) -> &str {
12        &self.0
13    }
14}
15
16/// Represents an interface that can be implemented by a plugin.
17pub trait Interface
18where
19    Self: Sized,
20{
21    /// Create an interface from a given runtime.
22    /// All handles to be used by the interface should be registered and stored in `Self`.
23    fn from_runtime<T: Runtime>(runtime: &mut T) -> Option<Self>;
24}
25
26pub trait Runtime
27where
28    Self: Sized,
29{
30    /// Represents a plugin to be loaded by the runtime,
31    /// e.g. some source code + anything else needed to set up.
32    type Plugin;
33
34    /// The error type for this module.
35    /// Ideally should implement the [`std::err::Error`] trait.
36    type Error;
37
38    /// Initializes a plugin, returning a [`Runtime`] that can be queried.
39    /// Note that if you have any configuration,
40    fn init(plugin: Self::Plugin) -> Result<Self, Self::Error>;
41
42    /// Returns a top-level constant from the module.
43    /// This can be used to extract configuration information from the module, for example.
44    /// Before calling this function, get a handle into the runtime using [`handle_for`].
45    fn constant<T: DeserializeOwned>(&mut self, handle: &Handle) -> Result<T, Self::Error>;
46
47    /// Call a function defined in the module.
48    fn call<A: Serialize, R: DeserializeOwned>(
49        &mut self,
50        handle: &Handle,
51        arg: A,
52    ) -> Result<R, Self::Error>;
53
54    /// Registers a handle with the runtime.
55    /// This is a mutable item if needed, but generally
56    /// this should be an immutable operation.
57    /// Returns whether the handle exists/was successfully registered.
58    fn register_handle<T: AsRef<str>>(&mut self, name: T) -> bool;
59
60    /// Returns the handle for a given name if the handle is defined.
61    /// Will only return an error if there was an error while trying to register the handle.
62    /// This function uses [`register_handle`], no need to implement this one.
63    fn handle_for<T: AsRef<str>>(&mut self, name: T) -> Option<Handle> {
64        if self.register_handle(&name) {
65            Some(Handle(name.as_ref().to_string()))
66        } else {
67            None
68        }
69    }
70
71    /// Creates the given interface from the current module.
72    /// Returns [`Error`] if the provided plugin does not match the expected interface.
73    /// Essentially wraps the [`Interface`] trait.
74    fn as_interface<T: Interface>(&mut self) -> Option<T> {
75        Interface::from_runtime(self)
76    }
77}