1use serde::{Deserialize, Deserializer, Serialize, Serializer};
9
10use std::{fmt, hash, ops::Deref};
11
12#[derive(Debug, Clone, PartialEq, Eq, Hash)]
68pub struct Forgettable<T>(Option<T>);
69
70impl<T> Default for Forgettable<T> {
71 fn default() -> Self {
73 Forgettable(None)
74 }
75}
76
77impl<T> From<T> for Forgettable<T> {
78 fn from(value: T) -> Self {
79 Forgettable(Some(value))
80 }
81}
82
83impl<T> Forgettable<T> {
84 pub fn new(value: T) -> Self {
86 Forgettable(Some(value))
87 }
88
89 pub fn forgotten() -> Self {
91 Forgettable(None)
92 }
93
94 pub fn value(&self) -> Option<ForgettableRef<'_, T>> {
99 self.0.as_ref().map(ForgettableRef)
100 }
101
102 pub fn is_set(&self) -> bool {
104 self.0.is_some()
105 }
106
107 pub fn is_forgotten(&self) -> bool {
109 self.0.is_none()
110 }
111}
112
113impl<T: Serialize> Forgettable<T> {
114 #[doc(hidden)]
117 pub fn __extract_payload_value(&self) -> Option<serde_json::Value> {
118 self.0
119 .as_ref()
120 .map(|v| serde_json::to_value(v).expect("Failed to serialize forgettable field"))
121 }
122}
123
124impl<T: Serialize> Serialize for Forgettable<T> {
125 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
126 serializer.serialize_none()
127 }
128}
129
130impl<'de, T: Deserialize<'de>> Deserialize<'de> for Forgettable<T> {
131 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
132 let value = Option::<T>::deserialize(deserializer)?;
133 match value {
134 Some(v) => Ok(Forgettable(Some(v))),
135 None => Ok(Forgettable(None)),
136 }
137 }
138}
139
140pub struct ForgettableRef<'a, T>(&'a T);
146
147impl<T: fmt::Debug> fmt::Debug for ForgettableRef<'_, T> {
148 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149 self.0.fmt(f)
150 }
151}
152
153impl<T: fmt::Display> fmt::Display for ForgettableRef<'_, T> {
154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155 self.0.fmt(f)
156 }
157}
158
159impl<T> Deref for ForgettableRef<'_, T> {
160 type Target = T;
161
162 fn deref(&self) -> &T {
163 self.0
164 }
165}
166
167impl<T: PartialEq> PartialEq<T> for ForgettableRef<'_, T> {
168 fn eq(&self, other: &T) -> bool {
169 self.0 == other
170 }
171}
172
173impl<T: PartialEq> PartialEq for ForgettableRef<'_, T> {
174 fn eq(&self, other: &Self) -> bool {
175 self.0 == other.0
176 }
177}
178
179impl<T: Eq> Eq for ForgettableRef<'_, T> {}
180
181impl<T: hash::Hash> hash::Hash for ForgettableRef<'_, T> {
182 fn hash<H: hash::Hasher>(&self, state: &mut H) {
183 self.0.hash(state);
184 }
185}
186
187#[doc(hidden)]
192pub fn inject_forgettable_payload(event_json: &mut serde_json::Value, payload: serde_json::Value) {
193 if let (Some(event_obj), serde_json::Value::Object(payload_obj)) =
194 (event_json.as_object_mut(), payload)
195 {
196 for (key, value) in payload_obj {
197 event_obj.insert(key, value);
198 }
199 }
200}
201
202#[cfg(test)]
203mod tests {
204 use super::*;
205
206 #[test]
207 fn serialize_set_emits_null() {
208 let value: Forgettable<String> = Forgettable::new("Alice".to_string());
209 let json = serde_json::to_value(&value).unwrap();
210 assert_eq!(json, serde_json::json!(null));
211 }
212
213 #[test]
214 fn serialize_forgotten_emits_null() {
215 let value: Forgettable<String> = Forgettable::forgotten();
216 let json = serde_json::to_value(&value).unwrap();
217 assert_eq!(json, serde_json::json!(null));
218 }
219
220 #[test]
221 fn deserialize_value() {
222 let json = serde_json::json!("Alice");
223 let value: Forgettable<String> = serde_json::from_value(json).unwrap();
224 assert_eq!(value, Forgettable::new("Alice".to_string()));
225 }
226
227 #[test]
228 fn deserialize_null() {
229 let json = serde_json::json!(null);
230 let value: Forgettable<String> = serde_json::from_value(json).unwrap();
231 assert_eq!(value, Forgettable::forgotten());
232 }
233
234 #[test]
235 fn serialize_struct_with_forgettable_emits_null() {
236 #[derive(Serialize, Deserialize, Debug, PartialEq)]
237 struct Event {
238 #[serde(rename = "type")]
239 kind: String,
240 name: Forgettable<String>,
241 email: String,
242 }
243
244 let event = Event {
245 kind: "initialized".to_string(),
246 name: Forgettable::new("Alice".to_string()),
247 email: "alice@test.com".to_string(),
248 };
249 let json = serde_json::to_value(&event).unwrap();
250 assert_eq!(json["name"], serde_json::json!(null));
252 assert_eq!(json["email"], serde_json::json!("alice@test.com"));
253
254 let deserialized: Event = serde_json::from_value(json).unwrap();
256 assert_eq!(deserialized.name, Forgettable::forgotten());
257
258 let event_forgotten = Event {
260 kind: "initialized".to_string(),
261 name: Forgettable::forgotten(),
262 email: "alice@test.com".to_string(),
263 };
264 let json = serde_json::to_value(&event_forgotten).unwrap();
265 assert_eq!(json["name"], serde_json::json!(null));
266
267 let deserialized: Event = serde_json::from_value(json).unwrap();
268 assert_eq!(deserialized, event_forgotten);
269 }
270
271 #[test]
272 fn inject_payload() {
273 let mut json = serde_json::json!({
274 "type": "initialized",
275 "id": "uuid",
276 "name": null,
277 "email": "alice@test.com"
278 });
279
280 let payload = serde_json::json!({"name": "Alice"});
281 inject_forgettable_payload(&mut json, payload);
282
283 assert_eq!(json["name"], serde_json::json!("Alice"));
284 assert_eq!(json["email"], serde_json::json!("alice@test.com"));
285 }
286
287 #[test]
288 fn value_helpers() {
289 let set: Forgettable<String> = Forgettable::new("test".to_string());
290 assert!(set.is_set());
291 assert!(!set.is_forgotten());
292 assert_eq!(&*set.value().unwrap(), "test");
293
294 let forgotten: Forgettable<String> = Forgettable::forgotten();
295 assert!(!forgotten.is_set());
296 assert!(forgotten.is_forgotten());
297 assert!(forgotten.value().is_none());
298 }
299
300 #[test]
301 fn extract_payload_value() {
302 let set: Forgettable<String> = Forgettable::new("Alice".to_string());
303 assert_eq!(
304 set.__extract_payload_value(),
305 Some(serde_json::json!("Alice"))
306 );
307
308 let forgotten: Forgettable<String> = Forgettable::forgotten();
309 assert_eq!(forgotten.__extract_payload_value(), None);
310 }
311
312 #[test]
313 fn forgettable_ref_deref() {
314 let f = Forgettable::new("hello".to_string());
315 let r = f.value().unwrap();
316 assert_eq!(r.len(), 5);
318 assert_eq!(&*r, "hello");
319 }
320
321 #[test]
322 fn forgettable_ref_display() {
323 let f = Forgettable::new("Alice".to_string());
324 let r = f.value().unwrap();
325 assert_eq!(format!("{r}"), "Alice");
326 }
327
328 #[test]
329 fn forgettable_ref_partial_eq() {
330 let f = Forgettable::new("Alice".to_string());
331 let r = f.value().unwrap();
332 assert_eq!(r, "Alice".to_string());
333 }
334
335 #[test]
336 fn default_is_forgotten() {
337 let f: Forgettable<String> = Default::default();
338 assert!(f.is_forgotten());
339 assert!(f.value().is_none());
340 }
341
342 #[test]
343 fn from_value() {
344 let f: Forgettable<String> = "Alice".to_string().into();
345 assert!(f.is_set());
346 assert_eq!(&*f.value().unwrap(), "Alice");
347 }
348}