temporalio_workflow/
memo.rs1use std::{collections::BTreeMap, rc::Rc};
2
3use temporalio_common_wasm::{
4 data_converters::{
5 GenericPayloadConverter, PayloadConversionError, PayloadConverter, SerializationContext,
6 SerializationContextData, TemporalSerializable,
7 },
8 protos::temporal::api::common::v1::Payload,
9};
10
11trait SerializableMemoValue {
12 fn to_payload(
13 &self,
14 payload_converter: &PayloadConverter,
15 ) -> Result<Payload, PayloadConversionError>;
16}
17
18impl<T> SerializableMemoValue for T
19where
20 T: TemporalSerializable + 'static,
21{
22 fn to_payload(
23 &self,
24 payload_converter: &PayloadConverter,
25 ) -> Result<Payload, PayloadConversionError> {
26 payload_converter.to_payload(
27 &SerializationContext {
28 data: &SerializationContextData::Workflow,
29 converter: payload_converter,
30 },
31 self,
32 )
33 }
34}
35
36#[derive(Clone, derive_more::Debug)]
38#[non_exhaustive]
39pub struct MemoValue {
40 #[debug(skip)]
41 value: Rc<dyn SerializableMemoValue>,
42}
43
44impl MemoValue {
45 pub fn new<T: TemporalSerializable + 'static>(value: T) -> Self {
47 Self {
48 value: Rc::new(value),
49 }
50 }
51
52 pub(crate) fn to_payload(
53 &self,
54 payload_converter: &PayloadConverter,
55 ) -> Result<Payload, PayloadConversionError> {
56 self.value.to_payload(payload_converter)
57 }
58}
59
60#[derive(Clone, Debug, Default)]
62#[non_exhaustive]
63pub struct MemoValues {
64 values: BTreeMap<String, MemoValue>,
65}
66
67impl MemoValues {
68 pub fn new() -> Self {
70 Self::default()
71 }
72
73 pub fn insert<T>(&mut self, key: impl Into<String>, value: T) -> &mut Self
75 where
76 T: TemporalSerializable + 'static,
77 {
78 self.values.insert(key.into(), MemoValue::new(value));
79 self
80 }
81
82 pub(crate) fn encode(
83 &self,
84 payload_converter: &PayloadConverter,
85 ) -> Result<std::collections::HashMap<String, Payload>, PayloadConversionError> {
86 self.values
87 .iter()
88 .map(|(key, value)| {
89 value
90 .to_payload(payload_converter)
91 .map(|payload| (key.clone(), payload))
92 })
93 .collect()
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100 use temporalio_common_wasm::{Memo, protos::temporal::api::common::v1::Memo as ProtoMemo};
101
102 #[test]
103 fn memo_values_serialize_heterogeneous_values() {
104 let payload_converter = PayloadConverter::default();
105 let mut values = MemoValues::new();
106 values
107 .insert("count", 7_u32)
108 .insert("label", "hello".to_string());
109
110 let memo = Memo::from_raw(
111 Some(ProtoMemo {
112 fields: values.encode(&payload_converter).unwrap(),
113 }),
114 payload_converter,
115 SerializationContextData::Workflow,
116 );
117
118 assert_eq!(memo.get::<u32>("count").unwrap(), Some(7));
119 assert_eq!(
120 memo.get::<String>("label").unwrap(),
121 Some("hello".to_string())
122 );
123 }
124}