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 Box, 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<Box<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 mut table = Box::new(table);
31        let table_ptr = table.as_mut() as *mut Table<K, E>;
32
33        // Note: we lend the ss_plugin_table_input to the FFI api and do not need
34        // to hold on to it (everything is copied out), but the name field is copied
35        // as a pointer, so the name we receive must be a 'static ref
36        let table_input = ss_plugin_table_input {
37            name: table.name().as_ptr(),
38            key_type: K::TYPE_ID as ss_plugin_state_type,
39            table: table_ptr.cast(),
40            reader: ss_plugin_table_reader_vtable {
41                get_table_name: reader_vtable_ext.get_table_name,
42                get_table_size: reader_vtable_ext.get_table_size,
43                get_table_entry: reader_vtable_ext.get_table_entry,
44                read_entry_field: reader_vtable_ext.read_entry_field,
45            },
46            writer: ss_plugin_table_writer_vtable {
47                clear_table: writer_vtable_ext.clear_table,
48                erase_table_entry: writer_vtable_ext.erase_table_entry,
49                create_table_entry: writer_vtable_ext.create_table_entry,
50                destroy_table_entry: writer_vtable_ext.destroy_table_entry,
51                add_table_entry: writer_vtable_ext.add_table_entry,
52                write_entry_field: writer_vtable_ext.write_entry_field,
53            },
54            fields: ss_plugin_table_fields_vtable {
55                list_table_fields: fields_vtable_ext.list_table_fields,
56                get_table_field: fields_vtable_ext.get_table_field,
57                add_table_field: fields_vtable_ext.add_table_field,
58            },
59            reader_ext: &mut reader_vtable_ext as *mut _,
60            writer_ext: &mut writer_vtable_ext as *mut _,
61            fields_ext: &mut fields_vtable_ext as *mut _,
62        };
63
64        unsafe { (self.add_table)(self.owner, &table_input as *const _) }
65            .as_result()
66            .with_last_error(&self.last_error)?;
67        Ok(table)
68    }
69}