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