summaryrefslogtreecommitdiff
path: root/src/conversation/history.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/conversation/history.rs')
-rw-r--r--src/conversation/history.rs69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/conversation/history.rs b/src/conversation/history.rs
new file mode 100644
index 0000000..601614c
--- /dev/null
+++ b/src/conversation/history.rs
@@ -0,0 +1,69 @@
+use itertools::Itertools as _;
+
+use super::{
+ Conversation, Id,
+ event::{Created, Deleted, Event},
+};
+use crate::event::{Instant, Sequence};
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct History {
+ pub conversation: Conversation,
+ pub deleted: Option<Instant>,
+}
+
+// State interface
+impl History {
+ pub fn id(&self) -> &Id {
+ &self.conversation.id
+ }
+
+ // Snapshot of this conversation as it was when created. (Note to the future:
+ // it's okay if this returns a redacted or modified version of the conversation.
+ // If we implement renames by redacting the original name, then this should
+ // return the renamed conversation, not the original, even if that's not how
+ // it was "as created.")
+ pub fn as_created(&self) -> Conversation {
+ self.conversation.clone()
+ }
+
+ pub fn as_of<S>(&self, sequence: S) -> Option<Conversation>
+ where
+ S: Into<Sequence>,
+ {
+ self.events()
+ .filter(Sequence::up_to(sequence.into()))
+ .collect()
+ }
+
+ // Snapshot of this conversation as of all events recorded in this history.
+ pub fn as_snapshot(&self) -> Option<Conversation> {
+ self.events().collect()
+ }
+}
+
+// Event factories
+impl History {
+ pub fn events(&self) -> impl Iterator<Item = Event> + use<> {
+ [self.created()]
+ .into_iter()
+ .merge_by(self.deleted(), Sequence::merge)
+ }
+
+ fn created(&self) -> Event {
+ Created {
+ conversation: self.conversation.clone(),
+ }
+ .into()
+ }
+
+ fn deleted(&self) -> Option<Event> {
+ self.deleted.map(|instant| {
+ Deleted {
+ instant,
+ id: self.conversation.id.clone(),
+ }
+ .into()
+ })
+ }
+}