use crate::event::EventSource;
use falco_event::fields::{FromBytes, FromBytesError, ToBytes};
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::cell::RefCell;
use std::fmt::Debug;
use std::io::Write;
pub struct JsonPayload<T> {
inner: T,
serialized: RefCell<Option<Result<Vec<u8>, std::io::Error>>>,
}
impl<T> Debug for JsonPayload<T>
where
T: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
T::fmt(&self.inner, f)
}
}
impl<T> JsonPayload<T> {
pub fn new(inner: T) -> Self {
Self {
inner,
serialized: RefCell::new(None),
}
}
pub fn get_ref(&self) -> &T {
&self.inner
}
pub fn get_mut(&mut self) -> &mut T {
self.serialized.replace(None);
&mut self.inner
}
pub fn into_inner(self) -> T {
self.inner
}
}
impl<T> JsonPayload<T>
where
T: Serialize,
{
fn update_serialized(&self) {
if self.serialized.borrow().is_none() {
self.serialized.replace(Some(
serde_json::to_vec(&self.inner).map_err(std::io::Error::from),
));
}
}
}
impl<'a, T> FromBytes<'a> for JsonPayload<T>
where
T: DeserializeOwned,
{
fn from_bytes(buf: &mut &'a [u8]) -> Result<Self, FromBytesError> {
let value: T = serde_json::from_slice(buf).map_err(|e| FromBytesError::Other(e.into()))?;
Ok(Self::new(value))
}
}
impl<T> ToBytes for JsonPayload<T>
where
T: Serialize,
{
fn binary_size(&self) -> usize {
self.update_serialized();
match self.serialized.borrow().as_ref().unwrap() {
Ok(v) => v.len(),
Err(_) => 0,
}
}
fn write<W: Write>(&self, writer: W) -> std::io::Result<()> {
self.update_serialized();
match self.serialized.take().unwrap() {
Ok(v) => {
let ret = v.as_slice().write(writer).map(|_| ());
self.serialized.replace(Some(Ok(v)));
ret
}
Err(e) => Err(e),
}
}
fn default_repr() -> impl ToBytes {
&[] as &[u8]
}
}
impl<T> EventSource for JsonPayload<T>
where
T: EventSource,
{
const SOURCE: Option<&'static str> = T::SOURCE;
}