falco_plugin/plugin/extract/
schema.rs1use crate::plugin::extract::extractor_fn::{ExtractLambda, ExtractorFn};
2use crate::plugin::extract::fields::{Extract, ExtractFieldTypeId};
3use crate::plugin::extract::ExtractPlugin;
4use serde::ser::SerializeStruct;
5use serde::{Serialize, Serializer};
6use std::fmt::{Debug, Formatter};
7
8#[derive(Clone, Copy, Debug)]
14pub enum ExtractArgType {
15 None,
17 OptionalIndex,
19 OptionalKey,
21 RequiredIndex,
23 RequiredKey,
25}
26
27impl Serialize for ExtractArgType {
28 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
29 where
30 S: Serializer,
31 {
32 match self {
33 ExtractArgType::None => serializer.serialize_none(),
34 ExtractArgType::OptionalIndex => {
35 let mut ss = serializer.serialize_struct("arg", 1)?;
36 ss.serialize_field("isIndex", &true)?;
37 ss.end()
38 }
39 ExtractArgType::OptionalKey => {
40 let mut ss = serializer.serialize_struct("arg", 1)?;
41 ss.serialize_field("isKey", &true)?;
42 ss.end()
43 }
44 ExtractArgType::RequiredIndex => {
45 let mut ss = serializer.serialize_struct("arg", 2)?;
46 ss.serialize_field("isIndex", &true)?;
47 ss.serialize_field("isRequired", &true)?;
48 ss.end()
49 }
50 ExtractArgType::RequiredKey => {
51 let mut ss = serializer.serialize_struct("arg", 2)?;
52 ss.serialize_field("isKey", &true)?;
53 ss.serialize_field("isRequired", &true)?;
54 ss.end()
55 }
56 }
57 }
58}
59
60pub fn serialize_field_type<S: Serializer>(
61 f: &ExtractFieldTypeId,
62 serializer: S,
63) -> Result<S::Ok, S::Error> {
64 match f {
65 ExtractFieldTypeId::U64 => serializer.serialize_str("uint64"),
66 ExtractFieldTypeId::String => serializer.serialize_str("string"),
67 ExtractFieldTypeId::RelTime => serializer.serialize_str("reltime"),
68 ExtractFieldTypeId::AbsTime => serializer.serialize_str("abstime"),
69 ExtractFieldTypeId::Bool => serializer.serialize_str("bool"),
70 ExtractFieldTypeId::IpAddr => serializer.serialize_str("ipaddr"),
71 ExtractFieldTypeId::IpNet => serializer.serialize_str("ipnet"),
72 }
73}
74
75fn is_false(b: &bool) -> bool {
76 !*b
77}
78
79#[derive(Serialize)]
85pub struct ExtractFieldInfo<P: ExtractPlugin> {
86 pub name: &'static str,
88 #[serde(rename = "type")]
89 #[serde(serialize_with = "serialize_field_type")]
90 pub field_type: ExtractFieldTypeId,
92 #[serde(rename = "isList")]
93 pub is_list: bool,
95 pub arg: ExtractArgType,
97 #[serde(rename = "display")]
98 pub display_name: Option<&'static str>,
100 #[serde(rename = "desc")]
101 pub description: &'static str,
103 #[serde(rename = "addOutput")]
104 #[serde(skip_serializing_if = "is_false")]
105 pub add_output: bool,
107 #[serde(skip)]
108 pub func: ExtractLambda<P>,
110}
111
112impl<P: ExtractPlugin> Debug for ExtractFieldInfo<P> {
113 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
114 let json = serde_json::to_string_pretty(self).map_err(|_| std::fmt::Error)?;
115 f.write_str(&json)
116 }
117}
118
119impl<P: ExtractPlugin> ExtractFieldInfo<P> {
120 pub const fn with_display(mut self, display_name: &'static str) -> Self {
122 self.display_name = Some(display_name);
123 self
124 }
125
126 pub const fn with_description(mut self, description: &'static str) -> Self {
128 self.description = description;
129 self
130 }
131
132 pub const fn add_output(mut self) -> Self {
134 self.add_output = true;
135 self
136 }
137}
138
139pub const fn field<P, R, F, A>(name: &'static str, func: &'static F) -> ExtractFieldInfo<P>
143where
144 P: ExtractPlugin,
145 R: Extract + 'static,
146 F: ExtractorFn<P, R, A>,
147 A: 'static,
148{
149 ExtractFieldInfo {
150 name,
151 field_type: <R as Extract>::TYPE_ID,
152 is_list: <R as Extract>::IS_LIST,
153 arg: F::ARG_TYPE,
154 display_name: None,
155 description: name,
156 add_output: false,
157 func: ExtractLambda {
158 obj: func as *const _ as *const (),
159 func: F::extract,
160 },
161 }
162}