summaryrefslogtreecommitdiff
path: root/src/conversation/snapshot.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/conversation/snapshot.rs')
-rw-r--r--src/conversation/snapshot.rs43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/conversation/snapshot.rs b/src/conversation/snapshot.rs
new file mode 100644
index 0000000..da9eaae
--- /dev/null
+++ b/src/conversation/snapshot.rs
@@ -0,0 +1,43 @@
+use super::{
+ Id,
+ event::{Created, Event},
+};
+use crate::{clock::DateTime, event::Instant, name::Name};
+
+#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
+pub struct Conversation {
+ #[serde(flatten)]
+ pub created: Instant,
+ pub id: Id,
+ pub name: Name,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub deleted_at: Option<DateTime>,
+}
+
+impl Conversation {
+ fn apply(state: Option<Self>, event: Event) -> Option<Self> {
+ match (state, event) {
+ (None, Event::Created(event)) => Some(event.into()),
+ (Some(conversation), Event::Deleted(event)) if conversation.id == event.id => None,
+ (state, event) => panic!("invalid conversation event {event:#?} for state {state:#?}"),
+ }
+ }
+}
+
+impl FromIterator<Event> for Option<Conversation> {
+ fn from_iter<I: IntoIterator<Item = Event>>(events: I) -> Self {
+ events.into_iter().fold(None, Conversation::apply)
+ }
+}
+
+impl From<&Created> for Conversation {
+ fn from(event: &Created) -> Self {
+ event.conversation.clone()
+ }
+}
+
+impl From<Created> for Conversation {
+ fn from(event: Created) -> Self {
+ event.conversation
+ }
+}