use std::{collections::HashMap, marker::PhantomData, ops::Deref};
use thiserror::Error;
use ulid::Ulid;
const REQUESTED_BY: &str = "EVENTO_REQUESTED_BY";
const REQUESTED_AS: &str = "EVENTO_REQUESTED_AS";
#[derive(Debug, Error)]
pub enum MetadataError {
#[error("not found")]
NotFound,
#[error("decode: {0}")]
Decode(#[from] bitcode::Error),
}
#[derive(Clone, PartialEq, Debug, bitcode::Encode, bitcode::Decode)]
pub struct Metadata {
pub id: String,
meta: HashMap<String, Vec<u8>>,
}
impl Metadata {
pub(crate) fn insert_enc<V: bitcode::Encode>(
&mut self,
key: impl Into<String>,
value: &V,
) -> &mut Self {
self.meta.insert(key.into(), bitcode::encode(value));
self
}
pub fn try_get<D: bitcode::DecodeOwned>(&self, key: &str) -> Result<D, MetadataError> {
let Some(value) = self.meta.get(key) else {
return Err(MetadataError::NotFound);
};
Ok(bitcode::decode(value)?)
}
pub fn set_requested_as(&mut self, value: impl Into<String>) -> &mut Self {
let value = value.into();
self.insert_enc(REQUESTED_AS, &value);
self
}
pub fn requested_as(&self) -> Result<String, MetadataError> {
self.try_get(REQUESTED_AS)
}
pub fn set_requested_by(&mut self, value: impl Into<String>) -> &mut Self {
let value = value.into();
self.insert_enc(REQUESTED_BY, &value);
self
}
pub fn requested_by(&self) -> Result<String, MetadataError> {
self.try_get(REQUESTED_BY)
}
}
impl Default for Metadata {
fn default() -> Self {
Self {
id: Ulid::new().to_string(),
meta: Default::default(),
}
}
}
impl Deref for Metadata {
type Target = HashMap<String, Vec<u8>>;
fn deref(&self) -> &Self::Target {
&self.meta
}
}
impl From<&Metadata> for Metadata {
fn from(value: &Metadata) -> Self {
value.clone()
}
}
pub struct Event<D> {
event: crate::Event,
pub data: D,
}
impl<D> Deref for Event<D> {
type Target = crate::Event;
fn deref(&self) -> &Self::Target {
&self.event
}
}
impl<D> TryFrom<&crate::Event> for Event<D>
where
D: bitcode::DecodeOwned,
{
type Error = bitcode::Error;
fn try_from(value: &crate::Event) -> Result<Self, Self::Error> {
let data = bitcode::decode::<D>(&value.data)?;
Ok(Event {
data,
event: value.clone(),
})
}
}
pub struct RawEvent<D>(pub crate::Event, pub PhantomData<D>);
impl<D> Deref for RawEvent<D> {
type Target = crate::Event;
fn deref(&self) -> &Self::Target {
&self.0
}
}