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::generate().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<'a, D> {
event: &'a crate::Event,
pub data: D,
}
impl<D> Deref for Event<'_, D> {
type Target = crate::Event;
fn deref(&self) -> &Self::Target {
self.event
}
}
impl<'a, D> TryFrom<&'a crate::Event> for Event<'a, D>
where
D: bitcode::DecodeOwned,
{
type Error = bitcode::Error;
fn try_from(value: &'a crate::Event) -> Result<Self, Self::Error> {
let data = bitcode::decode::<D>(&value.data)?;
Ok(Event { data, event: value })
}
}
pub struct RawEvent<'a, D>(pub &'a crate::Event, pub PhantomData<D>);
impl<D> Deref for RawEvent<'_, D> {
type Target = crate::Event;
fn deref(&self) -> &Self::Target {
self.0
}
}