Skip to main content

falco_plugin/tables/export/
tables_input.rs

1use crate::error::as_result::{AsResult, WithLastError};
2use crate::tables::export::traits::{Entry, TableMetadata};
3use crate::tables::export::wrappers::{fields_vtable, reader_vtable, writer_vtable};
4use crate::tables::export::Table;
5use crate::tables::{Key, TablesInput};
6use falco_plugin_api::{
7    ss_plugin_state_type, ss_plugin_table_fields_vtable, ss_plugin_table_input,
8    ss_plugin_table_reader_vtable, ss_plugin_table_writer_vtable,
9};
10use std::borrow::Borrow;
11
12impl TablesInput<'_> {
13    /// # Export a table to the Falco plugin API
14    ///
15    /// This method returns a [`Table`], which you need to store in your plugin instance
16    /// even if you don't intend to use the table yourself (the table is destroyed when
17    /// going out of scope, which will lead to crashes in plugins using your table).
18    pub fn add_table<K, E>(&self, table: Table<K, E>) -> Result<Table<K, E>, anyhow::Error>
19    where
20        K: Key + Ord,
21        K: Borrow<<K as Key>::Borrowed>,
22        <K as Key>::Borrowed: Ord + ToOwned<Owned = K>,
23        E: Entry,
24        E::Metadata: TableMetadata,
25    {
26        let mut reader_vtable_ext = reader_vtable::<K, E>();
27        let mut writer_vtable_ext = writer_vtable::<K, E>();
28        let mut fields_vtable_ext = fields_vtable::<K, E>();
29
30        let table_ptr = Table::as_mut_ptr(&table);
31
32        // Note: we lend the ss_plugin_table_input to the FFI api and do not need
33        // to hold on to it (everything is copied out), but the name field is copied
34        // as a pointer, so the name we receive must be a 'static ref
35        let table_input = ss_plugin_table_input {
36            name: table.name().as_ptr(),
37            key_type: K::TYPE_ID as ss_plugin_state_type,
38            table: table_ptr.cast(),
39            reader: ss_plugin_table_reader_vtable {
40                get_table_name: reader_vtable_ext.get_table_name,
41                get_table_size: reader_vtable_ext.get_table_size,
42                get_table_entry: reader_vtable_ext.get_table_entry,
43                read_entry_field: reader_vtable_ext.read_entry_field,
44            },
45            writer: ss_plugin_table_writer_vtable {
46                clear_table: writer_vtable_ext.clear_table,
47                erase_table_entry: writer_vtable_ext.erase_table_entry,
48                create_table_entry: writer_vtable_ext.create_table_entry,
49                destroy_table_entry: writer_vtable_ext.destroy_table_entry,
50                add_table_entry: writer_vtable_ext.add_table_entry,
51                write_entry_field: writer_vtable_ext.write_entry_field,
52            },
53            fields: ss_plugin_table_fields_vtable {
54                list_table_fields: fields_vtable_ext.list_table_fields,
55                get_table_field: fields_vtable_ext.get_table_field,
56                add_table_field: fields_vtable_ext.add_table_field,
57            },
58            reader_ext: &mut reader_vtable_ext as *mut _,
59            writer_ext: &mut writer_vtable_ext as *mut _,
60            fields_ext: &mut fields_vtable_ext as *mut _,
61        };
62
63        unsafe { (self.add_table)(self.owner, &table_input as *const _) }
64            .as_result()
65            .with_last_error(&self.last_error)?;
66        Ok(table)
67    }
68}