1use crate::plugin::tables::data::{seal, FieldTypeId, Key, TableData, Value};
2use crate::plugin::tables::field::Field;
3use crate::plugin::tables::runtime::NoMetadata;
4use crate::plugin::tables::runtime_table_validator::RuntimeTableValidator;
5use crate::plugin::tables::table::raw::RawTable;
6use crate::plugin::tables::traits::{Entry, TableAccess, TableMetadata};
7use crate::plugin::tables::vtable::fields::TableFields;
8use crate::plugin::tables::vtable::reader::TableReader;
9use crate::plugin::tables::vtable::writer::TableWriter;
10use crate::plugin::tables::vtable::TablesInput;
11use anyhow::Error;
12use falco_plugin_api::{ss_plugin_state_data, ss_plugin_table_field_t, ss_plugin_table_fieldinfo};
13use std::ffi::CStr;
14use std::marker::PhantomData;
15use std::ops::ControlFlow;
16
17pub(in crate::plugin::tables) mod raw;
18
19#[derive(Debug)]
21pub struct Table<K, E = super::entry::Entry<NoMetadata<()>>, M = <E as Entry>::Metadata> {
22 pub(in crate::plugin::tables) raw_table: RawTable,
23 pub(in crate::plugin::tables) metadata: M,
24 pub(in crate::plugin::tables) is_nested: bool,
25 pub(in crate::plugin::tables) key_type: PhantomData<K>,
26 pub(in crate::plugin::tables) entry_type: PhantomData<E>,
27}
28
29impl<K, E, M> TableAccess for Table<K, E, M>
30where
31 K: Key,
32 E: Entry<Metadata = M>,
33 M: TableMetadata + Clone,
34{
35 type Key = K;
36 type Entry = E;
37 type Metadata = M;
38
39 fn new(raw_table: RawTable, metadata: Self::Metadata, is_nested: bool) -> Self {
40 Self {
41 raw_table,
42 metadata,
43 is_nested,
44 key_type: PhantomData,
45 entry_type: PhantomData,
46 }
47 }
48
49 fn get_entry(
50 &self,
51 reader_vtable: &impl TableReader,
52 key: &Self::Key,
53 ) -> Result<Self::Entry, Error>
54 where
55 Self::Key: Key,
56 Self::Entry: Entry,
57 {
58 Table::get_entry(self, reader_vtable, key)
59 }
60}
61
62impl<K, E, M> Table<K, E, M>
63where
64 K: Key,
65 E: Entry<Metadata = M>,
66 M: TableMetadata + Clone,
67{
68 pub fn get_entry(&self, reader_vtable: &impl TableReader, key: &K) -> Result<E, Error> {
70 let raw_entry = self.raw_table.get_entry(reader_vtable, key)?;
71 Ok(E::new(
72 raw_entry,
73 self.raw_table.table,
74 self.metadata.clone(),
75 ))
76 }
77
78 pub fn erase(&self, writer_vtable: &impl TableWriter, key: &K) -> Result<(), Error> {
80 unsafe { self.raw_table.erase(writer_vtable, key) }
81 }
82
83 pub fn insert(
85 &self,
86 reader_vtable: &impl TableReader,
87 writer_vtable: &impl TableWriter,
88 key: &K,
89 entry: E,
90 ) -> Result<E, Error> {
91 let raw_entry = unsafe {
92 self.raw_table
93 .insert(reader_vtable, writer_vtable, key, entry.into_raw())
94 }?;
95 Ok(E::new(
96 raw_entry,
97 self.raw_table.table,
98 self.metadata.clone(),
99 ))
100 }
101}
102
103impl<K, E, M> Table<K, E, M>
104where
105 E: Entry<Metadata = M>,
106 M: TableMetadata + Clone,
107{
108 pub(in crate::plugin::tables) fn new_without_key(
109 raw_table: RawTable,
110 metadata: E::Metadata,
111 is_nested: bool,
112 ) -> Self {
113 Self {
114 raw_table,
115 metadata,
116 is_nested,
117 key_type: PhantomData,
118 entry_type: PhantomData,
119 }
120 }
121
122 pub(in crate::plugin::tables) fn table_validator(&self) -> RuntimeTableValidator {
123 let ptr = if self.is_nested {
124 std::ptr::null_mut()
125 } else {
126 self.raw_table.table
127 };
128 RuntimeTableValidator::new(ptr)
129 }
130
131 pub fn create_entry(&self, writer_vtable: &impl TableWriter) -> Result<E, Error> {
133 let raw_entry = self.raw_table.create_entry(writer_vtable)?;
134 Ok(E::new(
135 raw_entry,
136 self.raw_table.table,
137 self.metadata.clone(),
138 ))
139 }
140
141 pub fn clear(&self, writer_vtable: &impl TableWriter) -> Result<(), Error> {
143 self.raw_table.clear(writer_vtable)
144 }
145
146 pub fn list_fields(&self, fields_vtable: &TableFields) -> &[ss_plugin_table_fieldinfo] {
152 self.raw_table.list_fields(fields_vtable)
153 }
154
155 pub fn get_field<V: Value + ?Sized>(
165 &self,
166 tables_input: &TablesInput,
167 name: &CStr,
168 ) -> Result<Field<V, E>, Error> {
169 let field = self.raw_table.get_field(tables_input, name)?;
170 Ok(Field::new(field, self.table_validator()))
171 }
172
173 pub fn get_table_field<NK, V, U, F, R>(
196 &self,
197 tables_input: &TablesInput,
198 name: &CStr,
199 func: F,
200 ) -> Result<(Field<V, E>, R), Error>
201 where
202 NK: Key,
203 for<'a> V::AssocData: From<&'a M>,
204 V: Value + ?Sized,
205 U: Entry,
206 U::Metadata: for<'a> From<&'a V::AssocData>,
207 F: FnOnce(&Table<(), U>) -> Result<R, Error>,
208 {
209 let field = self.raw_table.get_field::<V>(tables_input, name)?;
210 let metadata = U::Metadata::from(&field.assoc_data);
211
212 let fields = unsafe {
213 self.raw_table
214 .with_subtable::<NK, _, _>(field.field, tables_input, |subtable| {
215 let owned = RawTable {
216 table: subtable.table,
217 };
218 let table = Table::new_without_key(owned, metadata, true);
219 func(&table)
220 })??
221 };
222
223 let field = Field::new(field, self.table_validator());
224 Ok((field, fields))
225 }
226
227 pub fn add_field<V: Value<AssocData = ()> + ?Sized>(
236 &self,
237 tables_input: &TablesInput,
238 name: &CStr,
239 ) -> Result<Field<V, E>, Error> {
240 let field = self.raw_table.add_field(tables_input, name)?;
241 Ok(Field::new(field, self.table_validator()))
242 }
243
244 pub fn get_name(&self, reader_vtable: &impl TableReader) -> anyhow::Result<&str> {
248 self.raw_table.get_name(reader_vtable)
249 }
250
251 pub fn get_size(&self, reader_vtable: &impl TableReader) -> anyhow::Result<usize> {
255 self.raw_table.get_size(reader_vtable)
256 }
257
258 pub fn iter_entries_mut<F>(
266 &self,
267 reader_vtable: &impl TableReader,
268 mut func: F,
269 ) -> anyhow::Result<ControlFlow<()>>
270 where
271 F: FnMut(&mut E) -> ControlFlow<()>,
272 {
273 self.raw_table.iter_entries_mut(reader_vtable, move |raw| {
274 let mut entry = E::new(raw, self.raw_table.table, self.metadata.clone());
275 func(&mut entry)
276 })
277 }
278}
279
280impl<K, E, M> seal::Sealed for Table<K, E, M> {}
281
282impl<K, E, M> TableData for Table<K, E, M> {
283 const TYPE_ID: FieldTypeId = FieldTypeId::Table;
284
285 fn to_data(&self) -> ss_plugin_state_data {
286 ss_plugin_state_data {
287 table: self.raw_table.table,
288 }
289 }
290}
291
292impl<K, E, M> Value for Table<K, E, M>
293where
294 K: Key + 'static,
295 E: Entry<Metadata = M> + 'static,
296 M: TableMetadata + Clone + 'static,
297{
298 type AssocData = M;
299 type Value<'a>
300 = Self
301 where
302 Self: 'a;
303
304 unsafe fn from_data_with_assoc<'a>(
305 data: &ss_plugin_state_data,
306 assoc: &Self::AssocData,
307 ) -> Self::Value<'a> {
308 let table = unsafe { RawTable { table: data.table } };
309 Table::new(table, assoc.clone(), true)
310 }
311
312 unsafe fn get_assoc_from_raw_table(
313 table: &RawTable,
314 field: *mut ss_plugin_table_field_t,
315 tables_input: &TablesInput,
316 ) -> Result<Self::AssocData, Error> {
317 table.with_subtable::<K, _, _>(field, tables_input, |subtable| {
318 M::new(subtable, tables_input)
319 })?
320 }
321}