ankurah_core/
changes.rs

1use crate::{
2    model::{Entity, View},
3    resultset::ResultSet,
4};
5use ankurah_proto::Event;
6use std::sync::Arc;
7
8#[derive(Debug, Clone)]
9pub struct EntityChange {
10    pub entity: Arc<Entity>,
11    pub events: Vec<Event>,
12}
13
14#[derive(Debug, Clone)]
15pub enum ItemChange<I> {
16    /// Initial retrieval of an item upon subscription
17    Initial { item: I },
18    /// A new item was added OR changed such that it now matches the subscription
19    Add { item: I, events: Vec<Event> },
20    /// A item that previously matched the subscription has changed in a way that has not changed the matching condition
21    Update { item: I, events: Vec<Event> },
22    /// A item that previously matched the subscription has changed in a way that no longer matches the subscription
23    Remove { item: I, events: Vec<Event> },
24}
25
26impl<I> ItemChange<I> {
27    pub fn entity(&self) -> &I {
28        match self {
29            ItemChange::Initial { item }
30            | ItemChange::Add { item, .. }
31            | ItemChange::Update { item, .. }
32            | ItemChange::Remove { item, .. } => item,
33        }
34    }
35
36    pub fn events(&self) -> &[Event] {
37        match self {
38            ItemChange::Add { events, .. } | ItemChange::Update { events, .. } | ItemChange::Remove { events, .. } => events,
39            _ => &[],
40        }
41    }
42    pub fn kind(&self) -> ChangeKind { ChangeKind::from(self) }
43}
44
45impl<I> std::fmt::Display for ItemChange<I>
46where I: View
47{
48    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49        match self {
50            ItemChange::Initial { item } => {
51                write!(f, "Initial {}/{}", I::collection(), item.id())
52            }
53            ItemChange::Add { item, .. } => {
54                write!(f, "Add {}/{}", I::collection(), item.id())
55            }
56            ItemChange::Update { item, .. } => {
57                write!(f, "Update {}/{}", I::collection(), item.id())
58            }
59            ItemChange::Remove { item, .. } => {
60                write!(f, "Remove {}/{}", I::collection(), item.id())
61            }
62        }
63    }
64}
65
66impl std::fmt::Display for EntityChange {
67    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68        write!(f, "EntityChange {}/{}", self.entity.collection, self.entity.id)
69    }
70}
71
72#[derive(Debug)]
73pub struct ChangeSet<R> {
74    pub resultset: crate::resultset::ResultSet<R>,
75    pub changes: Vec<ItemChange<R>>,
76}
77
78impl<I> std::fmt::Display for ChangeSet<I>
79where I: View
80{
81    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82        // print the number of results in the resultset, and then display each change
83        let results = self.resultset.items.len();
84        write!(f, "ChangeSet({results} results): {}", self.changes.iter().map(|c| c.to_string()).collect::<Vec<_>>().join(", "))
85    }
86}
87
88impl<I> From<ChangeSet<Arc<Entity>>> for ChangeSet<I>
89where I: View
90{
91    fn from(val: ChangeSet<Arc<Entity>>) -> Self {
92        ChangeSet {
93            resultset: ResultSet { items: val.resultset.iter().map(|item| I::from_entity(item.clone())).collect() },
94            changes: val.changes.into_iter().map(|change| change.into()).collect(),
95        }
96    }
97}
98
99impl<I> From<ItemChange<Arc<Entity>>> for ItemChange<I>
100where I: View
101{
102    fn from(change: ItemChange<Arc<Entity>>) -> Self {
103        match change {
104            ItemChange::Initial { item } => ItemChange::Initial { item: I::from_entity(item) },
105            ItemChange::Add { item, events } => ItemChange::Add { item: I::from_entity(item), events },
106            ItemChange::Update { item, events } => ItemChange::Update { item: I::from_entity(item), events },
107            ItemChange::Remove { item, events } => ItemChange::Remove { item: I::from_entity(item), events },
108        }
109    }
110}
111
112#[derive(Debug, Clone, PartialEq)]
113pub enum ChangeKind {
114    Initial,
115    Add,
116    Remove,
117    Update,
118}
119
120impl<R> From<&ItemChange<R>> for ChangeKind {
121    fn from(change: &ItemChange<R>) -> Self {
122        match change {
123            ItemChange::Initial { .. } => ChangeKind::Initial,
124            ItemChange::Add { .. } => ChangeKind::Add,
125            ItemChange::Remove { .. } => ChangeKind::Remove,
126            ItemChange::Update { .. } => ChangeKind::Update,
127        }
128    }
129}