haproxy_spoa_hub_plugin_api/
lib.rs1#![allow(non_camel_case_types, non_local_definitions)]
3
4pub mod plugin_trait;
5pub mod types;
6
7pub use abi_stable;
8pub use abi_stable::std_types::{RHashMap, RString, RVec, Tuple2};
9pub use plugin_trait::{PluginBox, PluginMod, PluginMod_Ref, SpoePlugin, SpoePlugin_TO};
10pub use types::{
11 ConfigValue, Diagnostic, DiagnosticSeverity, PluginContext, ProcessingResult, SpoeMessage,
12 SpoeValue, TxnVariable, VarScope,
13};
14
15#[doc(hidden)]
64#[macro_export]
65macro_rules! __plugin_present {
66 ($($tt:tt)*) => {};
67}
68
69#[macro_export]
70macro_rules! define_plugin {
71 ($plugin_ty:ty, {
77 fn new() -> Self $new_body:block
78
79 fn init(&mut self, $ctx_param:ident : &PluginContext $(,)?) -> Result<(), Box<dyn std::error::Error + Send + Sync>> $init_body:block
80
81 fn name(&self) -> &str $name_body:block
82
83 fn version(&self) -> &str $version_body:block
84
85 fn process(
86 &self,
87 $msg_param:ident : &SpoeMessage $(,)?
88 ) -> Result<ProcessingResult, Box<dyn std::error::Error + Send + Sync>> $process_body:block
89
90 $(fn config_schema(&self) -> Option<&str> $schema_body:block)?
91
92 $(fn validate(&self, $vctx_param:ident : &PluginContext $(,)?) -> Vec<Diagnostic> $validate_body:block)?
93 }) => {
94 mod __plugin_impl {
95 use super::*;
96 use $crate::abi_stable::std_types::{
97 RBoxError, ROption, RResult, RStr, RString, RVec,
98 };
99 use $crate::abi_stable::sabi_trait::prelude::TD_Opaque;
100
101 impl $plugin_ty {
102 pub fn __new() -> Self $new_body
103 #[allow(clippy::unnecessary_wraps)]
104 pub fn __init(
105 &mut self,
106 $ctx_param: &$crate::PluginContext,
107 ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> $init_body
108 pub fn __name(&self) -> &str $name_body
109 pub fn __version(&self) -> &str $version_body
110 #[allow(clippy::unnecessary_wraps)]
111 pub fn __process(
112 &self,
113 $msg_param: &$crate::SpoeMessage,
114 ) -> Result<$crate::ProcessingResult, Box<dyn std::error::Error + Send + Sync>> $process_body
115
116 $(
117 #[allow(clippy::unnecessary_wraps)]
118 pub fn __config_schema(&self) -> Option<&str> $schema_body
119 )?
120
121 $(
122 #[allow(clippy::unnecessary_wraps)]
123 pub fn __validate(
124 &self,
125 $vctx_param: &$crate::PluginContext,
126 ) -> Vec<$crate::Diagnostic> $validate_body
127 )?
128 }
129
130 impl $crate::SpoePlugin for $plugin_ty {
131 fn init(
132 &mut self,
133 context: &$crate::PluginContext,
134 ) -> RResult<(), RBoxError> {
135 self.__init(context).map_err(RBoxError::from_box).into()
136 }
137
138 fn process(
139 &self,
140 message: &$crate::SpoeMessage,
141 ) -> RResult<$crate::ProcessingResult, RBoxError> {
142 match std::panic::catch_unwind(
143 std::panic::AssertUnwindSafe(|| self.__process(message)),
144 ) {
145 Ok(res) => res.map_err(RBoxError::from_box).into(),
146 Err(_) => {
147 RResult::RErr(RBoxError::new(
148 $crate::PluginPanicError,
149 ))
150 }
151 }
152 }
153
154 fn name(&self) -> RStr<'_> {
155 self.__name().into()
156 }
157
158 fn version(&self) -> RStr<'_> {
159 self.__version().into()
160 }
161
162 fn shutdown(&self) {}
163
164 $(
165 fn config_schema(&self) -> ROption<RString> {
166 $crate::__plugin_present!($schema_body);
167 self.__config_schema().map(RString::from).into()
168 }
169 )?
170
171 $(
172 fn validate(
173 &self,
174 context: &$crate::PluginContext,
175 ) -> RVec<$crate::Diagnostic> {
176 $crate::__plugin_present!($validate_body);
177 self.__validate(context).into()
178 }
179 )?
180 }
181
182 #[$crate::abi_stable::export_root_module]
183 pub fn get_root_module() -> $crate::PluginMod_Ref {
184 use $crate::abi_stable::prefix_type::PrefixTypeTrait;
185 $crate::PluginMod {
186 new: __create_plugin,
187 }
188 .leak_into_prefix()
189 }
190
191 extern "C" fn __create_plugin() -> RResult<$crate::PluginBox, RBoxError> {
192 let plugin = <$plugin_ty>::__new();
193 RResult::ROk($crate::SpoePlugin_TO::from_value(plugin, TD_Opaque))
194 }
195 }
196 };
197}
198
199#[derive(Debug)]
201pub struct PluginPanicError;
202
203impl std::fmt::Display for PluginPanicError {
204 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205 write!(f, "plugin panicked during message processing")
206 }
207}
208
209impl std::error::Error for PluginPanicError {}