falco_plugin/tables/export/mod.rs
1//! Exporting tables to other plugins
2//!
3//! Exporting a table to other plugins is done using the [`Entry`] derive macro.
4//! It lets you use a struct type as a parameter to [`Table`]. You can then create
5//! a new table using [`TablesInput::add_table`](crate::tables::TablesInput::add_table).
6//!
7//! Every field in the entry struct must be wrapped in [`Public`](`crate::tables::export::Public`),
8//! [`Private`](`crate::tables::export::Private`) or [`Readonly`](`crate::tables::export::Readonly`),
9//! except for nested tables. These just need to be a `Box<Table<K, E>>`, as it makes no sense
10//! to have a private nested table and the distinction between writable and readonly is meaningless
11//! for tables (they have no setter to replace the whole table and you can always add/remove
12//! entries from the nested table).
13//!
14//! # Example
15//!
16//! ```
17//! use std::ffi::{CStr, CString};
18//! use falco_plugin::base::Plugin;
19//!# use falco_plugin::plugin;
20//! use falco_plugin::tables::TablesInput;
21//! use falco_plugin::tables::export;
22//!
23//! // define the struct representing each table entry
24//! #[derive(export::Entry)]
25//! struct ExportedTable {
26//! int_field: export::Readonly<u64>, // do not allow writes via the plugin API
27//! string_field: export::Public<CString>, // allow writes via the plugin API
28//! secret: export::Private<Vec<u8>>, // do not expose over the plugin API at all
29//! }
30//!
31//! // define the type holding the plugin state
32//! struct MyPlugin {
33//! // you can use methods on this instance to access fields bypassing the Falco table API
34//! // (for performance within your own plugin)
35//! exported_table: Box<export::Table<u64, ExportedTable>>,
36//! }
37//!
38//! // implement the base::Plugin trait
39//! impl Plugin for MyPlugin {
40//! // ...
41//!# const NAME: &'static CStr = c"sample-plugin-rs";
42//!# const PLUGIN_VERSION: &'static CStr = c"0.0.1";
43//!# const DESCRIPTION: &'static CStr = c"A sample Falco plugin that does nothing";
44//!# const CONTACT: &'static CStr = c"you@example.com";
45//!# type ConfigType = ();
46//!
47//! fn new(input: Option<&TablesInput>, config: Self::ConfigType)
48//! -> Result<Self, anyhow::Error> {
49//!
50//! let Some(input) = input else {
51//! anyhow::bail!("Did not get tables input");
52//! };
53//!
54//! // create a new table called "exported"
55//! //
56//! // The concrete type is inferred from the field type the result is stored in.
57//! let exported_table = input.add_table(export::Table::new(c"exported")?)?;
58//!
59//! Ok(MyPlugin { exported_table })
60//! }
61//! }
62//!# plugin!(#[no_capabilities] MyPlugin);
63//! ```
64
65mod entry;
66mod field;
67mod field_descriptor;
68mod field_value;
69mod macros;
70mod metadata;
71mod ref_shared;
72mod static_field_specialization;
73mod table;
74mod tables_input;
75mod vtable;
76mod wrappers;
77
78pub use field::private::Private;
79pub use field::public::Public;
80pub use field::readonly::Readonly;
81pub use table::Table;
82
83// for macro use only
84#[doc(hidden)]
85pub mod traits {
86 pub use super::entry::table_metadata::traits::TableMetadata;
87 pub use super::entry::traits::Entry;
88}
89
90// for macro use only
91#[doc(hidden)]
92pub use field_descriptor::{FieldDescriptor, FieldId, FieldRef};
93
94// for macro use only
95#[doc(hidden)]
96pub use field_value::dynamic::DynamicFieldValue;
97
98// for macro use only
99#[doc(hidden)]
100pub use metadata::{HasMetadata, Metadata};
101
102// for macro use only
103#[doc(hidden)]
104pub use ref_shared::RefShared;
105
106// for macro use only
107#[doc(hidden)]
108pub use static_field_specialization::{
109 StaticFieldCheck, StaticFieldFallback, StaticFieldGet, StaticFieldGetFallback, StaticFieldSet,
110 StaticFieldSetFallback,
111};
112
113/// Mark a struct type as a table value
114///
115/// See the [module documentation](`crate::tables::export`) for details.
116pub use falco_plugin_derive::Entry;