falco_plugin/plugin/event/
json.rs1use crate::event::EventSource;
2use falco_event::fields::{FromBytes, FromBytesError, ToBytes};
3use serde::de::DeserializeOwned;
4use serde::Serialize;
5use std::cell::RefCell;
6use std::fmt::Debug;
7use std::io::Write;
8
9pub struct JsonPayload<T> {
44 inner: T,
45 serialized: RefCell<Option<Result<Vec<u8>, std::io::Error>>>,
46}
47
48impl<T> Debug for JsonPayload<T>
49where
50 T: Debug,
51{
52 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53 T::fmt(&self.inner, f)
54 }
55}
56
57impl<T> JsonPayload<T> {
58 pub fn new(inner: T) -> Self {
60 Self {
61 inner,
62 serialized: RefCell::new(None),
63 }
64 }
65
66 pub fn get_ref(&self) -> &T {
68 &self.inner
69 }
70
71 pub fn get_mut(&mut self) -> &mut T {
73 self.serialized.replace(None);
74 &mut self.inner
75 }
76
77 pub fn into_inner(self) -> T {
79 self.inner
80 }
81}
82
83impl<T> JsonPayload<T>
84where
85 T: Serialize,
86{
87 fn update_serialized(&self) {
88 if self.serialized.borrow().is_none() {
89 self.serialized.replace(Some(
90 serde_json::to_vec(&self.inner).map_err(std::io::Error::from),
91 ));
92 }
93 }
94}
95
96impl<'a, T> FromBytes<'a> for JsonPayload<T>
97where
98 T: DeserializeOwned,
99{
100 fn from_bytes(buf: &mut &'a [u8]) -> Result<Self, FromBytesError> {
101 let value: T = serde_json::from_slice(buf).map_err(|e| FromBytesError::Other(e.into()))?;
102 Ok(Self::new(value))
103 }
104}
105
106impl<T> ToBytes for JsonPayload<T>
107where
108 T: Serialize,
109{
110 fn binary_size(&self) -> usize {
111 self.update_serialized();
112 match self.serialized.borrow().as_ref().unwrap() {
113 Ok(v) => v.len(),
114 Err(_) => 0,
115 }
116 }
117
118 fn write<W: Write>(&self, writer: W) -> std::io::Result<()> {
119 self.update_serialized();
120 match self.serialized.take().unwrap() {
121 Ok(v) => {
122 let ret = v.as_slice().write(writer).map(|_| ());
123 self.serialized.replace(Some(Ok(v)));
124 ret
125 }
126 Err(e) => Err(e),
127 }
128 }
129
130 fn default_repr() -> impl ToBytes {
131 &[] as &[u8]
132 }
133}
134
135impl<T> EventSource for JsonPayload<T>
136where
137 T: EventSource,
138{
139 const SOURCE: Option<&'static str> = T::SOURCE;
140}