1use std::cell::UnsafeCell;
8use std::convert::TryInto;
9use std::mem;
10use std::ops::Deref;
11
12pub use pluginop_common::quic;
13use pluginop_common::APIResult;
14pub use pluginop_common::PluginOp;
15use pluginop_common::WASMLen;
16use pluginop_common::WASMPtr;
17
18use pluginop_common::quic::Registration;
19pub use pluginop_common::Bytes;
20pub use pluginop_common::PluginVal;
21use serde::{Deserialize, Serialize};
22use std::convert::TryFrom;
23pub use std::time::Duration;
24pub use unix_time::Instant as UnixInstant;
25
26const SIZE: usize = 1500;
28
29#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
31pub enum Error {
32 APICallError,
34 BadBytes,
36 BadType,
38 ShortInternalBuffer,
40 SerializeError,
42}
43
44pub type Result<T> = std::result::Result<T, Error>;
45
46extern "C" {
47 fn save_output_from_plugin(ptr: WASMPtr, len: WASMLen) -> APIResult;
49 fn save_outputs_from_plugin(ptr: WASMPtr, len: WASMLen) -> APIResult;
51 fn print_from_plugin(ptr: WASMPtr, len: WASMLen);
54 fn get_connection_from_plugin(
56 field_ptr: WASMPtr,
57 field_len: WASMLen,
58 res_ptr: WASMPtr,
59 res_len: WASMLen,
60 ) -> APIResult;
61 fn set_connection_from_plugin(
63 field_ptr: WASMPtr,
64 field_len: WASMLen,
65 value_ptr: WASMPtr,
66 value_len: WASMLen,
67 ) -> APIResult;
68 fn get_input_from_plugin(index: u32, res_ptr: WASMPtr, res_len: WASMLen) -> APIResult;
70 fn get_inputs_from_plugin(res_ptr: WASMPtr, res_len: WASMLen) -> APIResult;
72 fn get_bytes_from_plugin(tag: u64, len: u64, res_ptr: WASMPtr, res_len: WASMLen) -> i64;
74 fn put_bytes_from_plugin(tag: u64, ptr: WASMPtr, len: WASMLen) -> i64;
76 fn register_from_plugin(ptr: WASMPtr, len: WASMLen) -> i64;
78 fn set_timer_from_plugin(ts_ptr: WASMPtr, ts_len: WASMLen, id: u64, timer_id: u64)
80 -> APIResult;
81 fn cancel_timer_from_plugin(id: u64) -> APIResult;
83 fn get_unix_instant_from_plugin(res_ptr: WASMPtr, res_len: WASMLen) -> APIResult;
85 fn enable_from_plugin();
87 fn get_recovery_from_plugin(
89 field_ptr: WASMPtr,
90 field_len: WASMLen,
91 res_ptr: WASMPtr,
92 res_len: WASMLen,
93 ) -> APIResult;
94 fn set_recovery_from_plugin(
96 field_ptr: WASMPtr,
97 field_len: WASMLen,
98 value_ptr: WASMPtr,
99 value_len: WASMLen,
100 ) -> APIResult;
101 fn poctl_from_plugin(
103 id: u64,
104 input_ptr: WASMPtr,
105 input_len: WASMLen,
106 res_ptr: WASMPtr,
107 res_len: WASMLen,
108 ) -> APIResult;
109}
110
111#[repr(C)]
114pub struct PluginEnv(WASMPtr);
115
116impl PluginEnv {
117 pub fn save_output(&self, v: PluginVal) -> Result<()> {
119 let serialized_value = postcard::to_allocvec(&v).map_err(|_| Error::SerializeError)?;
120 match unsafe {
121 save_output_from_plugin(
122 serialized_value.as_ptr() as WASMPtr,
123 serialized_value.len() as WASMLen,
124 )
125 } {
126 0 => Ok(()),
127 _ => Err(Error::APICallError),
128 }
129 }
130
131 pub fn save_outputs(&self, v: &[PluginVal]) -> Result<()> {
133 let serialized_value = postcard::to_allocvec(&v).map_err(|_| Error::SerializeError)?;
134 match unsafe {
135 save_outputs_from_plugin(
136 serialized_value.as_ptr() as WASMPtr,
137 serialized_value.len() as WASMLen,
138 )
139 } {
140 0 => Ok(()),
141 _ => Err(Error::APICallError),
142 }
143 }
144
145 pub fn print(&self, s: &str) {
147 unsafe { print_from_plugin(s.as_ptr() as WASMPtr, s.len() as WASMLen) }
148 }
149
150 pub fn get_connection<T>(&self, field: quic::ConnectionField) -> Result<T>
152 where
153 T: TryFrom<PluginVal>,
154 {
155 let serialized_field = postcard::to_allocvec(&field).map_err(|_| Error::SerializeError)?;
156 let mut res = Vec::<u8>::with_capacity(SIZE).into_boxed_slice();
157 let err = unsafe {
158 get_connection_from_plugin(
159 serialized_field.as_ptr() as WASMPtr,
160 serialized_field.len() as WASMLen,
161 res.as_mut_ptr() as WASMPtr,
162 SIZE as WASMLen,
163 )
164 };
165 if err != 0 {
166 return Err(Error::APICallError);
167 }
168 let slice = unsafe { std::slice::from_raw_parts(res.as_ptr(), SIZE) };
169 let plugin_val: PluginVal =
170 postcard::from_bytes(slice).map_err(|_| Error::SerializeError)?;
171 plugin_val.try_into().map_err(|_| Error::BadType)
172 }
173
174 pub fn set_connection<T>(&mut self, field: quic::ConnectionField, v: T) -> Result<()>
176 where
177 T: Into<PluginVal>,
178 {
179 let serialized_field = postcard::to_allocvec(&field).map_err(|_| Error::SerializeError)?;
180 let serialized_value =
181 postcard::to_allocvec(&v.into()).map_err(|_| Error::SerializeError)?;
182 match unsafe {
183 set_connection_from_plugin(
184 serialized_field.as_ptr() as WASMPtr,
185 serialized_field.len() as WASMLen,
186 serialized_value.as_ptr() as WASMPtr,
187 serialized_value.len() as WASMLen,
188 )
189 } {
190 0 => Ok(()),
191 _ => Err(Error::APICallError),
192 }
193 }
194
195 pub fn get_recovery<'de, T>(&self, field: quic::RecoveryField) -> T
197 where
198 T: Deserialize<'de>,
199 {
200 let serialized_field = postcard::to_allocvec(&field).expect("serialized field");
201 let mut res = Vec::<u8>::with_capacity(SIZE).into_boxed_slice();
202 unsafe {
203 get_recovery_from_plugin(
204 serialized_field.as_ptr() as WASMPtr,
205 serialized_field.len() as WASMLen,
206 res.as_mut_ptr() as WASMPtr,
207 SIZE as WASMLen,
208 );
209 }
210 let slice = unsafe { std::slice::from_raw_parts(res.as_ptr(), SIZE) };
211 postcard::from_bytes(slice).expect("no error")
212 }
213
214 pub fn set_recovery<T>(&mut self, field: quic::RecoveryField, v: T) -> Result<()>
216 where
217 T: Into<PluginVal>,
218 {
219 let serialized_field = postcard::to_allocvec(&field).map_err(|_| Error::SerializeError)?;
220 let serialized_value =
221 postcard::to_allocvec(&v.into()).map_err(|_| Error::SerializeError)?;
222 match unsafe {
223 set_recovery_from_plugin(
224 serialized_field.as_ptr() as WASMPtr,
225 serialized_field.len() as WASMLen,
226 serialized_value.as_ptr() as WASMPtr,
227 serialized_value.len() as WASMLen,
228 )
229 } {
230 0 => Ok(()),
231 _ => Err(Error::APICallError),
232 }
233 }
234
235 pub fn get_input<T>(&self, index: u32) -> Result<T>
237 where
238 T: TryFrom<PluginVal>,
239 <T as TryFrom<PluginVal>>::Error: std::fmt::Debug,
240 {
241 let mut res = Vec::<u8>::with_capacity(SIZE).into_boxed_slice();
242 if unsafe { get_input_from_plugin(index, res.as_mut_ptr() as WASMPtr, SIZE as WASMLen) }
243 != 0
244 {
245 return Err(Error::ShortInternalBuffer);
246 }
247 let slice = unsafe { std::slice::from_raw_parts(res.as_ptr(), SIZE) };
248 let input: PluginVal = match postcard::from_bytes(slice) {
249 Ok(i) => i,
250 Err(_) => return Err(Error::SerializeError),
251 };
252 input.try_into().map_err(|_| Error::SerializeError)
253 }
254
255 pub fn get_inputs(&self) -> Result<Vec<PluginVal>> {
257 let mut res = Vec::<u8>::with_capacity(SIZE).into_boxed_slice();
258 if unsafe { get_inputs_from_plugin(res.as_mut_ptr() as WASMPtr, SIZE as WASMLen) } != 0 {
259 return Err(Error::ShortInternalBuffer);
260 }
261 let slice = unsafe { std::slice::from_raw_parts(res.as_ptr(), SIZE) };
262 postcard::from_bytes(slice).map_err(|_| Error::SerializeError)
263 }
264
265 pub fn get_bytes(&mut self, tag: u64, len: u64) -> Result<Vec<u8>> {
267 let mut res = Vec::<u8>::with_capacity(len as usize).into_boxed_slice();
268 let len =
269 unsafe { get_bytes_from_plugin(tag, len, res.as_mut_ptr() as WASMPtr, len as WASMLen) };
270 if len < 0 {
271 return Err(Error::BadBytes);
272 }
273 let slice = unsafe { std::slice::from_raw_parts(res.as_ptr(), len as usize) };
274 Ok(slice.to_vec())
275 }
276
277 pub fn put_bytes(&mut self, tag: u64, b: &[u8]) -> Result<usize> {
279 let written =
280 unsafe { put_bytes_from_plugin(tag, b.as_ptr() as WASMPtr, b.len() as WASMLen) };
281 if written < 0 {
282 return Err(Error::BadBytes);
283 }
284 Ok(written as usize)
285 }
286
287 pub fn register(&mut self, r: Registration) -> Result<()> {
290 let serialized = postcard::to_allocvec(&r).map_err(|_| Error::SerializeError)?;
291 match unsafe {
292 register_from_plugin(serialized.as_ptr() as WASMPtr, serialized.len() as WASMLen)
293 } {
294 0 => Ok(()),
295 _ => Err(Error::APICallError),
296 }
297 }
298
299 pub fn set_timer(&mut self, ts: UnixInstant, id: u64, timer_id: u64) -> Result<()> {
304 let serialized_ts = postcard::to_allocvec(&ts).map_err(|_| Error::SerializeError)?;
305 match unsafe {
306 set_timer_from_plugin(
307 serialized_ts.as_ptr() as WASMPtr,
308 serialized_ts.len() as WASMLen,
309 id,
310 timer_id,
311 )
312 } {
313 0 => Ok(()),
314 _ => Err(Error::APICallError),
315 }
316 }
317
318 pub fn cancel_timer(&mut self, id: u64) -> Result<()> {
320 match unsafe { cancel_timer_from_plugin(id) } {
321 0 => Ok(()),
322 _ => Err(Error::APICallError),
323 }
324 }
325
326 pub fn get_unix_instant(&self) -> Result<UnixInstant> {
328 let size = mem::size_of::<UnixInstant>();
329 let mut res = Vec::<u8>::with_capacity(size).into_boxed_slice();
330 let err =
331 unsafe { get_unix_instant_from_plugin(res.as_mut_ptr() as WASMPtr, size as WASMLen) };
332 if err != 0 {
333 return Err(Error::APICallError);
334 }
335 let slice = unsafe { std::slice::from_raw_parts(res.as_ptr(), size) };
336 postcard::from_bytes(slice).map_err(|_| Error::SerializeError)
337 }
338
339 pub fn enable(&self) {
343 unsafe { enable_from_plugin() };
344 }
345
346 pub fn poctl(&mut self, id: u64, params: &[PluginVal]) -> Result<Vec<PluginVal>> {
348 let serialized_inputs =
349 postcard::to_allocvec(¶ms).map_err(|_| Error::SerializeError)?;
350 let mut res = Vec::<u8>::with_capacity(SIZE).into_boxed_slice();
351 let err = unsafe {
352 poctl_from_plugin(
353 id,
354 serialized_inputs.as_ptr() as WASMPtr,
355 serialized_inputs.len() as WASMLen,
356 res.as_mut_ptr() as WASMPtr,
357 SIZE as WASMLen,
358 )
359 };
360 if err != 0 {
361 return Err(Error::APICallError);
362 }
363 let slice = unsafe { std::slice::from_raw_parts(res.as_ptr(), SIZE) };
364 postcard::from_bytes(slice).map_err(|_| Error::SerializeError)
365 }
366}
367
368pub struct PluginCell<T>(UnsafeCell<T>);
370
371impl<T> PluginCell<T> {
372 pub fn new(v: T) -> Self {
373 Self(UnsafeCell::new(v))
374 }
375
376 #[allow(clippy::mut_from_ref)]
379 pub fn get_mut(&self) -> &mut T {
380 unsafe { &mut *self.0.get() }
382 }
383}
384
385impl<T: Sync + Send> Deref for PluginCell<T> {
386 type Target = T;
387
388 fn deref(&self) -> &Self::Target {
389 unsafe { &*self.0.get() }
391 }
392}
393
394unsafe impl<T: Send> Send for PluginCell<T> {}
396unsafe impl<T: Sync> Sync for PluginCell<T> {}
398
399pub mod fd;