Skip to content

Commit

Permalink
new(plugin): introduce ValidatedTableWriter
Browse files Browse the repository at this point in the history
This adds a .validate() method to LazyTableWriter, which returns another
TableWriter implementation with all the NULL checks handled once.

Signed-off-by: Grzegorz Nosek <[email protected]>
  • Loading branch information
gnosek authored and poiana committed Oct 21, 2024
1 parent 21a0a83 commit ca2ca6d
Showing 1 changed file with 132 additions and 0 deletions.
132 changes: 132 additions & 0 deletions falco_plugin/src/plugin/tables/vtable/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use falco_plugin_api::{
ss_plugin_rc, ss_plugin_state_data, ss_plugin_table_entry_t, ss_plugin_table_field_t,
ss_plugin_table_t, ss_plugin_table_writer_vtable_ext,
};
use std::marker::PhantomData;

/// A vtable containing table write access methods
///
Expand Down Expand Up @@ -86,9 +87,48 @@ impl<'t> LazyTableWriter<'t> {
last_error,
})
}

/// Validate all vtable entries and skip further NULL checks
///
/// This method validates all possible vtable methods to make future
/// table accesses faster. If your plugin method does more than a few
/// (say, 10) calls to methods that take a `TableWriter`, it might be
/// faster to get a `ValidatedTableWriter`
pub fn validate(&self) -> Result<ValidatedTableWriter, TableError> {
Ok(ValidatedTableWriter {
clear_table: self
.writer_ext
.clear_table
.ok_or(BadVtable("clear_table"))?,
erase_table_entry: self
.writer_ext
.erase_table_entry
.ok_or(BadVtable("erase_table_entry"))?,
create_table_entry: self
.writer_ext
.create_table_entry
.ok_or(BadVtable("create_table_entry"))?,
destroy_table_entry: self
.writer_ext
.destroy_table_entry
.ok_or(BadVtable("destroy_table_entry"))?,
add_table_entry: self
.writer_ext
.add_table_entry
.ok_or(BadVtable("add_table_entry"))?,
write_entry_field: self
.writer_ext
.write_entry_field
.ok_or(BadVtable("write_entry_field"))?,
last_error: self.last_error.clone(),
lifetime: PhantomData,
})
}
}

impl<'t> private::TableWriterImpl for LazyTableWriter<'t> {
type Error = TableError;

unsafe fn clear_table(&self, t: *mut ss_plugin_table_t) -> Result<ss_plugin_rc, TableError> {
unsafe {
Ok(self
Expand Down Expand Up @@ -182,3 +222,95 @@ impl<'t> private::TableWriterImpl for LazyTableWriter<'t> {
&self.last_error
}
}

/// A vtable containing table write access methods
///
/// It's used as a token to prove you're allowed to write tables in a particular context
#[derive(Debug)]
pub struct ValidatedTableWriter<'t> {
clear_table: unsafe extern "C-unwind" fn(t: *mut ss_plugin_table_t) -> ss_plugin_rc,
erase_table_entry: unsafe extern "C-unwind" fn(
t: *mut ss_plugin_table_t,
key: *const ss_plugin_state_data,
) -> ss_plugin_rc,
create_table_entry:
unsafe extern "C-unwind" fn(t: *mut ss_plugin_table_t) -> *mut ss_plugin_table_entry_t,
destroy_table_entry:
unsafe extern "C-unwind" fn(t: *mut ss_plugin_table_t, e: *mut ss_plugin_table_entry_t),
add_table_entry: unsafe extern "C-unwind" fn(
t: *mut ss_plugin_table_t,
key: *const ss_plugin_state_data,
entry: *mut ss_plugin_table_entry_t,
) -> *mut ss_plugin_table_entry_t,
write_entry_field: unsafe extern "C-unwind" fn(
t: *mut ss_plugin_table_t,
e: *mut ss_plugin_table_entry_t,
f: *const ss_plugin_table_field_t,
in_: *const ss_plugin_state_data,
) -> ss_plugin_rc,

pub(in crate::plugin::tables) last_error: LastError,
lifetime: PhantomData<&'t ()>,
}

impl<'t> private::TableWriterImpl for ValidatedTableWriter<'t> {
type Error = std::convert::Infallible;

unsafe fn clear_table(&self, t: *mut ss_plugin_table_t) -> Result<ss_plugin_rc, Self::Error> {
unsafe { Ok((self.clear_table)(t)) }
}

unsafe fn erase_table_entry(
&self,
t: *mut ss_plugin_table_t,
key: *const ss_plugin_state_data,
) -> Result<ss_plugin_rc, Self::Error> {
unsafe { Ok((self.erase_table_entry)(t, key)) }
}

unsafe fn create_table_entry(
&self,
t: *mut ss_plugin_table_t,
) -> Result<*mut ss_plugin_table_entry_t, Self::Error> {
unsafe { Ok((self.create_table_entry)(t)) }
}

unsafe fn destroy_table_entry(
&self,
t: *mut ss_plugin_table_t,
e: *mut ss_plugin_table_entry_t,
) {
unsafe { (self.destroy_table_entry)(t, e) }
}

fn destroy_table_entry_fn(
&self,
) -> Option<
unsafe extern "C-unwind" fn(t: *mut ss_plugin_table_t, e: *mut ss_plugin_table_entry_t),
> {
Some(self.destroy_table_entry)
}

unsafe fn add_table_entry(
&self,
t: *mut ss_plugin_table_t,
key: *const ss_plugin_state_data,
entry: *mut ss_plugin_table_entry_t,
) -> Result<*mut ss_plugin_table_entry_t, Self::Error> {
unsafe { Ok((self.add_table_entry)(t, key, entry)) }
}

unsafe fn write_entry_field(
&self,
t: *mut ss_plugin_table_t,
e: *mut ss_plugin_table_entry_t,
f: *const ss_plugin_table_field_t,
in_: *const ss_plugin_state_data,
) -> Result<ss_plugin_rc, Self::Error> {
unsafe { Ok((self.write_entry_field)(t, e, f, in_)) }
}

fn last_error(&self) -> &LastError {
&self.last_error
}
}

0 comments on commit ca2ca6d

Please sign in to comment.