use crate::plugin::tables::table::raw::RawTable;
use crate::tables::TablesInput;
use falco_plugin_api::{
ss_plugin_bool, ss_plugin_field_type_FTYPE_UINT64, ss_plugin_state_data,
ss_plugin_state_type_SS_PLUGIN_ST_BOOL, ss_plugin_state_type_SS_PLUGIN_ST_INT16,
ss_plugin_state_type_SS_PLUGIN_ST_INT32, ss_plugin_state_type_SS_PLUGIN_ST_INT64,
ss_plugin_state_type_SS_PLUGIN_ST_INT8, ss_plugin_state_type_SS_PLUGIN_ST_STRING,
ss_plugin_state_type_SS_PLUGIN_ST_TABLE, ss_plugin_state_type_SS_PLUGIN_ST_UINT16,
ss_plugin_state_type_SS_PLUGIN_ST_UINT32, ss_plugin_state_type_SS_PLUGIN_ST_UINT8,
ss_plugin_table_field_t,
};
use num_derive::FromPrimitive;
use std::borrow::Borrow;
use std::ffi::{CStr, CString};
use std::fmt::{Debug, Formatter};
pub(in crate::plugin::tables) mod seal {
pub trait Sealed {}
}
#[non_exhaustive]
#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive)]
pub enum FieldTypeId {
I8 = ss_plugin_state_type_SS_PLUGIN_ST_INT8,
I16 = ss_plugin_state_type_SS_PLUGIN_ST_INT16,
I32 = ss_plugin_state_type_SS_PLUGIN_ST_INT32,
I64 = ss_plugin_state_type_SS_PLUGIN_ST_INT64,
U8 = ss_plugin_state_type_SS_PLUGIN_ST_UINT8,
U16 = ss_plugin_state_type_SS_PLUGIN_ST_UINT16,
U32 = ss_plugin_state_type_SS_PLUGIN_ST_UINT32,
U64 = ss_plugin_field_type_FTYPE_UINT64,
String = ss_plugin_state_type_SS_PLUGIN_ST_STRING,
Table = ss_plugin_state_type_SS_PLUGIN_ST_TABLE,
Bool = ss_plugin_state_type_SS_PLUGIN_ST_BOOL,
}
pub trait TableData: seal::Sealed {
const TYPE_ID: FieldTypeId;
fn to_data(&self) -> ss_plugin_state_data;
}
pub trait Key: TableData {
type Borrowed: ?Sized;
unsafe fn from_data(data: &ss_plugin_state_data) -> &Self::Borrowed
where
Self: Borrow<Self::Borrowed>;
}
pub trait Value: TableData {
type AssocData;
type Value<'a>
where
Self: 'a;
unsafe fn from_data_with_assoc<'a>(
data: &ss_plugin_state_data,
assoc: &Self::AssocData,
) -> Self::Value<'a>;
unsafe fn get_assoc_from_raw_table(
table: &RawTable,
field: *mut ss_plugin_table_field_t,
tables_input: &TablesInput,
) -> Result<Self::AssocData, anyhow::Error>;
}
macro_rules! impl_table_data_direct {
($ty:ty => $field:ident: $type_id:expr) => {
impl seal::Sealed for $ty {}
impl TableData for $ty {
const TYPE_ID: FieldTypeId = $type_id;
fn to_data(&self) -> ss_plugin_state_data {
ss_plugin_state_data { $field: *self }
}
}
impl Key for $ty {
type Borrowed = $ty;
unsafe fn from_data(data: &ss_plugin_state_data) -> &Self {
unsafe { &data.$field }
}
}
impl Value for $ty {
type AssocData = ();
type Value<'a> = $ty;
unsafe fn from_data_with_assoc<'a>(
data: &ss_plugin_state_data,
_assoc: &Self::AssocData,
) -> Self::Value<'a> {
unsafe { data.$field }
}
unsafe fn get_assoc_from_raw_table(
_table: &RawTable,
_field: *mut ss_plugin_table_field_t,
_tables_input: &TablesInput,
) -> Result<Self::AssocData, anyhow::Error> {
Ok(())
}
}
};
}
impl_table_data_direct!(u8 => u8_: FieldTypeId::U8);
impl_table_data_direct!(i8 => s8: FieldTypeId::I8);
impl_table_data_direct!(u16 => u16_: FieldTypeId::U16);
impl_table_data_direct!(i16 => s16: FieldTypeId::I16);
impl_table_data_direct!(u32 => u32_: FieldTypeId::U32);
impl_table_data_direct!(i32 => s32: FieldTypeId::I32);
impl_table_data_direct!(u64 => u64_: FieldTypeId::U64);
impl_table_data_direct!(i64 => s64: FieldTypeId::I64);
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct Bool(pub(crate) ss_plugin_bool);
impl Debug for Bool {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Bool").field(&bool::from(*self)).finish()
}
}
impl From<bool> for Bool {
fn from(value: bool) -> Self {
Self(value as ss_plugin_bool)
}
}
impl From<Bool> for bool {
fn from(value: Bool) -> Self {
value.0 != 0
}
}
impl seal::Sealed for Bool {}
impl TableData for Bool {
const TYPE_ID: FieldTypeId = FieldTypeId::Bool;
fn to_data(&self) -> ss_plugin_state_data {
ss_plugin_state_data { b: self.0 }
}
}
impl Value for Bool {
type AssocData = ();
type Value<'a> = bool;
unsafe fn from_data_with_assoc<'a>(
data: &ss_plugin_state_data,
_assoc: &Self::AssocData,
) -> Self::Value<'a> {
unsafe { data.b != 0 }
}
unsafe fn get_assoc_from_raw_table(
_table: &RawTable,
_field: *mut ss_plugin_table_field_t,
_tables_input: &TablesInput,
) -> Result<Self::AssocData, anyhow::Error> {
Ok(())
}
}
impl Key for Bool {
type Borrowed = Bool;
unsafe fn from_data(data: &ss_plugin_state_data) -> &Self {
unsafe { std::mem::transmute(&data.b) }
}
}
impl seal::Sealed for CString {}
impl TableData for CString {
const TYPE_ID: FieldTypeId = FieldTypeId::String;
fn to_data(&self) -> ss_plugin_state_data {
ss_plugin_state_data {
str_: self.as_ptr(),
}
}
}
impl Key for CString {
type Borrowed = CStr;
unsafe fn from_data(data: &ss_plugin_state_data) -> &CStr {
unsafe { CStr::from_ptr(data.str_) }
}
}
impl seal::Sealed for CStr {}
impl TableData for CStr {
const TYPE_ID: FieldTypeId = FieldTypeId::String;
fn to_data(&self) -> ss_plugin_state_data {
ss_plugin_state_data {
str_: self.as_ptr(),
}
}
}
impl Value for CStr {
type AssocData = ();
type Value<'a> = &'a CStr;
unsafe fn from_data_with_assoc<'a>(
data: &ss_plugin_state_data,
_assoc: &Self::AssocData,
) -> Self::Value<'a> {
unsafe { CStr::from_ptr(data.str_) }
}
unsafe fn get_assoc_from_raw_table(
_table: &RawTable,
_field: *mut ss_plugin_table_field_t,
_tables_input: &TablesInput,
) -> Result<Self::AssocData, anyhow::Error> {
Ok(())
}
}