falco_plugin/plugin/parse/
mod.rs

1use crate::parse::EventInput;
2use crate::plugin::base::Plugin;
3use crate::plugin::error::last_error::LastError;
4use crate::plugin::parse::wrappers::ParsePluginExported;
5use crate::plugin::tables::vtable::writer::LazyTableWriter;
6use crate::tables::LazyTableReader;
7use falco_event::events::{AnyEventPayload, RawEvent};
8use falco_plugin_api::ss_plugin_event_parse_input;
9
10#[doc(hidden)]
11pub mod wrappers;
12
13/// Support for event parse plugins
14pub trait ParsePlugin: Plugin + ParsePluginExported {
15    /// # Parsed event type
16    ///
17    /// Events will be parsed into this type before being passed to the plugin, so you can
18    /// work directly on the deserialized form and don't need to worry about validating
19    /// the events.
20    ///
21    /// If an event fails this conversion, an error will be returned from [`EventInput::event`],
22    /// which you can propagate directly to the caller.
23    ///
24    /// If you don't want any specific validation/conversion to be performed, specify the type as
25    /// ```
26    /// type Event<'a> = falco_event::events::RawEvent<'a>;
27    /// ```
28    type Event<'a>: AnyEventPayload + TryFrom<&'a RawEvent<'a>>
29    where
30        Self: 'a;
31
32    /// # Parse an event
33    ///
34    /// Receives an event from the current capture and parses its content.
35    /// The plugin is guaranteed to receive an event at most once, after any
36    /// operation related to the event sourcing capability, and before
37    /// any operation related to the field extraction capability.
38    fn parse_event(
39        &mut self,
40        event: &EventInput<Self::Event<'_>>,
41        parse_input: &ParseInput,
42    ) -> anyhow::Result<()>;
43}
44
45/// # The input to a parse plugin
46///
47/// It has two fields containing the vtables needed to access tables imported through
48/// the [tables API](`crate::tables`).
49///
50/// You will pass these vtables to all methods that read or write data from tables,
51/// but you won't interact with them otherwise. They're effectively tokens proving
52/// you're in the right context to read/write tables.
53#[derive(Debug)]
54pub struct ParseInput<'t> {
55    /// Accessors to read table entries
56    pub reader: LazyTableReader<'t>,
57    /// Accessors to modify table entries
58    pub writer: LazyTableWriter<'t>,
59}
60
61impl ParseInput<'_> {
62    pub(in crate::plugin::parse) unsafe fn try_from(
63        value: *const ss_plugin_event_parse_input,
64        last_error: LastError,
65    ) -> Result<Self, anyhow::Error> {
66        let input = unsafe {
67            value
68                .as_ref()
69                .ok_or_else(|| anyhow::anyhow!("Got null event parse input"))?
70        };
71
72        let reader = unsafe {
73            input
74                .table_reader_ext
75                .as_ref()
76                .ok_or_else(|| anyhow::anyhow!("Got null reader vtable"))?
77        };
78        let writer = unsafe {
79            input
80                .table_writer_ext
81                .as_ref()
82                .ok_or_else(|| anyhow::anyhow!("Got null writer vtable"))?
83        };
84
85        let reader = LazyTableReader::new(reader, last_error.clone());
86        let writer = LazyTableWriter::try_from(writer, last_error)?;
87
88        Ok(Self { reader, writer })
89    }
90}