git_bug/entities/identity/snapshot/
timeline.rs1use super::history_step::{
15 AvatarUrlHistoryStep, EmailHistoryStep, IdentityHistoryStep, LoginNameHistoryStep,
16 MetadataHistoryStep, NameHistoryStep,
17};
18use crate::{
19 entities::identity::{Identity, identity_operation::IdentityOperationData},
20 replica::entity::{Entity, operation::Operation, snapshot::timeline::Timeline},
21};
22
23#[derive(Debug, Clone)]
25pub struct IdentityTimeline {
26 history: Vec<IdentityHistoryStep>,
27}
28
29impl Timeline<Identity> for IdentityTimeline {
30 fn new() -> Self {
31 Self { history: vec![] }
32 }
33
34 fn from_root_operation(operation: &Operation<Identity>) -> Self {
35 let mut me = Self::new();
36
37 let IdentityOperationData::Create { name } = operation.operation_data() else {
38 unreachable!("This should only be called with the root operation.");
39 };
40 me.add_name_history(NameHistoryStep {
41 author: operation.author(),
42 name: name.to_owned(),
43 at: operation.creation_time(),
44 });
45
46 me
47 }
48
49 fn add(&mut self, op: &Operation<Identity>) {
50 match op.operation_data() {
51 IdentityOperationData::Create { .. } => unreachable!("Already processed."),
52 IdentityOperationData::SetName { name } => self.add_name_history(NameHistoryStep {
53 author: op.author(),
54 name: name.to_owned(),
55 at: op.creation_time(),
56 }),
57 IdentityOperationData::SetEmail { email } => self.add_email_history(EmailHistoryStep {
58 author: op.author(),
59 email: email.to_owned(),
60 at: op.creation_time(),
61 }),
62 IdentityOperationData::SetLoginName { login_name } => {
63 self.add_login_name_history(LoginNameHistoryStep {
64 author: op.author(),
65 login_name: login_name.to_owned(),
66 at: op.creation_time(),
67 });
68 }
69 IdentityOperationData::SetAvatarUrl { url } => {
70 self.add_avatar_url_history(AvatarUrlHistoryStep {
71 author: op.author(),
72 avatar_url: url.to_owned(),
73 at: op.creation_time(),
74 });
75 }
76 IdentityOperationData::SetMetadata { metadata } => {
77 self.add_metadata_history(MetadataHistoryStep {
78 author: op.author(),
79 metadata: metadata.to_owned(),
80 at: op.creation_time(),
81 });
82 }
83 }
84 }
85
86 fn history(&self) -> &[<Identity as Entity>::HistoryStep] {
87 &self.history
88 }
89}
90
91macro_rules! filter_history {
92 ($history:expr, $type_name:ident) => {
93 filter_history!(@iter $history, $type_name)
94 };
95 (@$mode:ident $history:expr, $type_name:ident) => {
96 $history.$mode().filter_map(|h| {
97 if let IdentityHistoryStep::$type_name(a) = h {
98 Some(a)
99 } else {
100 None
101 }
102 })
103 };
104}
105
106impl IdentityTimeline {
107 pub fn name_history(&self) -> impl Iterator<Item = &NameHistoryStep> {
109 filter_history!(self.history, Name)
110 }
111
112 pub fn email_history(&self) -> impl Iterator<Item = &EmailHistoryStep> {
114 filter_history!(self.history, Email)
115 }
116
117 pub fn login_name_history(&self) -> impl Iterator<Item = &LoginNameHistoryStep> {
120 filter_history!(self.history, LoginName)
121 }
122
123 pub fn avatar_url_history(&self) -> impl Iterator<Item = &AvatarUrlHistoryStep> {
126 filter_history!(self.history, AvatarUrl)
127 }
128
129 pub fn metadata_history(&self) -> impl Iterator<Item = &MetadataHistoryStep> {
132 filter_history!(self.history, Metadata)
133 }
134
135 pub fn add_name_history(&mut self, item: NameHistoryStep) {
139 self.history.push(IdentityHistoryStep::Name(item));
140 }
141
142 pub fn add_email_history(&mut self, item: EmailHistoryStep) {
144 self.history.push(IdentityHistoryStep::Email(item));
145 }
146
147 pub fn add_login_name_history(&mut self, item: LoginNameHistoryStep) {
149 self.history.push(IdentityHistoryStep::LoginName(item));
150 }
151
152 pub fn add_avatar_url_history(&mut self, item: AvatarUrlHistoryStep) {
154 self.history.push(IdentityHistoryStep::AvatarUrl(item));
155 }
156
157 pub fn add_metadata_history(&mut self, item: MetadataHistoryStep) {
159 self.history.push(IdentityHistoryStep::Metadata(item));
160 }
161}