use crate::{
data_converters::{
GenericPayloadConverter, PayloadConversionError, PayloadConverter, SerializationContext,
SerializationContextData, TemporalDeserializable,
},
protos::temporal::api::common::v1::{Memo as ProtoMemo, Payload},
};
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct Memo {
raw: ProtoMemo,
payload_converter: PayloadConverter,
context: SerializationContextData,
}
impl Memo {
#[doc(hidden)]
pub fn from_raw(
raw: Option<ProtoMemo>,
payload_converter: PayloadConverter,
context: SerializationContextData,
) -> Self {
Self {
raw: raw.unwrap_or_default(),
payload_converter,
context,
}
}
pub fn get<T: TemporalDeserializable + 'static>(
&self,
key: &str,
) -> Result<Option<T>, PayloadConversionError> {
let Some(payload) = self.raw.fields.get(key) else {
return Ok(None);
};
self.payload_converter
.from_payload(
&SerializationContext {
data: &self.context,
converter: &self.payload_converter,
},
payload.clone(),
)
.map(Some)
}
pub fn contains_key(&self, key: &str) -> bool {
self.raw.fields.contains_key(key)
}
pub fn len(&self) -> usize {
self.raw.fields.len()
}
pub fn is_empty(&self) -> bool {
self.raw.fields.is_empty()
}
pub fn keys(&self) -> impl Iterator<Item = &str> {
self.raw.fields.keys().map(String::as_str)
}
pub fn raw_value(&self, key: &str) -> Option<&Payload> {
self.raw.fields.get(key)
}
pub fn raw(&self) -> &ProtoMemo {
&self.raw
}
pub fn into_raw(self) -> ProtoMemo {
self.raw
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
#[test]
fn memo_decodes_serialized_values() {
let payload_converter = PayloadConverter::default();
let context = SerializationContext {
data: &SerializationContextData::Workflow,
converter: &payload_converter,
};
let payload = payload_converter.to_payload(&context, &7_u32).unwrap();
let raw = ProtoMemo {
fields: HashMap::from([("count".to_owned(), payload.clone())]),
};
let memo = Memo::from_raw(
Some(raw.clone()),
payload_converter,
SerializationContextData::Workflow,
);
assert_eq!(memo.get::<u32>("count").unwrap(), Some(7));
assert_eq!(memo.get::<u32>("missing").unwrap(), None);
assert_eq!(memo.raw_value("count"), Some(&payload));
assert_eq!(memo.into_raw(), raw);
}
#[test]
fn memo_reports_deserialization_errors() {
let payload_converter = PayloadConverter::default();
let context = SerializationContext {
data: &SerializationContextData::Workflow,
converter: &payload_converter,
};
let payload = payload_converter.to_payload(&context, &7_u32).unwrap();
let memo = Memo::from_raw(
Some(ProtoMemo {
fields: HashMap::from([("count".to_owned(), payload)]),
}),
payload_converter,
SerializationContextData::Workflow,
);
assert!(memo.get::<String>("count").is_err());
}
}