1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use crateEventSource;
use ;
use CStr;
use ;
/// Asynchronous event
///
/// This is the event type generated by [async event](`crate::async_event`) plugins.
/// This differs from the autogenerated `falco_event_schema::types::PPME_ASYNCEVENT_E` type
/// in the following ways:
/// - none of the fields are `Option`s
/// - the name is just a `&CStr`
/// - serde serialization/deserialization is not supported
/// - does not depend on the whole `falco_event_schema` crate
///
/// It handles encoding and decoding the payload automatically, so you can use any type that can be
/// converted from/to a byte buffer (including a raw `&[u8]`) as the payload.
///
/// To store an arbitrary type inside the payload, make sure the data implements [`FromBytes`],
/// [`ToBytes`] and [`EventSource`], for example:
/// ```
/// use std::io::Write;
/// use falco_event::events::{AnyEventPayload, RawEvent};
/// use falco_event::fields::{FromBytes, FromBytesError, ToBytes};
/// use falco_plugin::event::{EventSource, AsyncEvent};
/// use falco_plugin::event::events::Event;
///
/// struct MyEvent {
/// param1: u32,
/// param2: u32,
/// }
///
/// impl EventSource for MyEvent {
/// const SOURCE: Option<&'static str> = Some("my_plugin");
/// }
///
/// impl FromBytes<'_> for MyEvent {
/// fn from_bytes(buf: &mut &[u8]) -> Result<Self, FromBytesError> {
/// if buf.len() < 2 * size_of::<u32>() {
/// return Err(FromBytesError::InvalidLength);
/// }
///
/// let param1 = u32::from_le_bytes(buf[..size_of::<u32>()].try_into().unwrap());
/// let param2 = u32::from_le_bytes(buf[size_of::<u32>()..].try_into().unwrap());
/// *buf = &buf[2 * size_of::<u32>()..];
/// Ok(MyEvent { param1, param2 })
/// }
/// }
///
/// impl ToBytes for MyEvent {
/// fn binary_size(&self) -> usize {
/// 2 * size_of::<u32>()
/// }
///
/// fn write<W: Write>(&self, mut writer: W) -> std::io::Result<()> {
/// writer.write_all(&self.param1.to_le_bytes())?;
/// writer.write_all(&self.param2.to_le_bytes())?;
/// Ok(())
/// }
///
/// fn default_repr() -> impl ToBytes {
/// MyEvent { param1: 0, param2: 0 }
/// }
/// }
///
///# trait FakePluginTrait {
///# type Event<'a>: AnyEventPayload + TryFrom<&'a RawEvent<'a>> where Self: 'a;
///# }
///# struct FakePlugin;
///# impl FakePluginTrait for FakePlugin {
/// // in a plugin trait implementation:
/// type Event<'a> = Event<AsyncEvent<'a, MyEvent>>;
///# }
/// ```
///
/// *Note*: this SDK also provides support for [JSON-encoded payloads](`crate::event::JsonPayload`)
/// since it's already necessary to talk to the Falco Plugin API. JSON is not a good choice
/// for high-volume events, as it takes a lot of space and is pretty slow, compared to binary
/// formats. See the source of `plugin::event:json` for what is needed to support a different
/// serialization format and consider using e.g. [bincode](https://crates.io/crates/bincode) instead.