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