falco_plugin 0.5.1

High level bindings for the Falco plugin API
Documentation
use crate::plugin::event::EventSource;
use falco_event::fields::{FromBytes, ToBytes};
use std::fmt::{Debug, Formatter};

/// Plugin event
///
/// This is the event type generated by [source](`crate::source`) plugins. This differs
/// from the autogenerated `falco_event_schema::types::PPME_PLUGINEVENT_E` type in the following
/// ways:
/// - none of the fields are `Option`s
/// - 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, PluginEvent};
/// 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<PluginEvent<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.
#[derive(falco_event::EventPayload)]
#[event_payload(
    source = <T as EventSource>::SOURCE,
    code = 322,
    length_type = u32,
    from_bytes_bound(where T: FromBytes<'raw_event>),
    to_bytes_bound(where T: ToBytes))]
pub struct PluginEvent<T>
where
    T: EventSource,
{
    /// ID of the plugin that generated this event
    pub plugin_id: u32,
    /// Payload, as a custom type
    pub event_data: T,
}

impl<T> Debug for PluginEvent<T>
where
    T: EventSource + Debug,
{
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "> pluginevent plugin_id={} data={:?}",
            self.plugin_id, self.event_data
        )
    }
}