1use strum::{Display, EnumIter, EnumString, IntoEnumIterator};
2
3// An integer indicating a type of notification. The variants' numerical
4// values are stored in the database, so they should never be removed
5// or changed.
6#[repr(i32)]
7#[derive(Copy, Clone, Debug, EnumIter, EnumString, Display)]
8pub enum NotificationKind {
9 ContactRequest = 0,
10 ContactRequestAccepted = 1,
11 ChannelInvitation = 2,
12 ChannelMessageMention = 3,
13}
14
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub enum Notification {
17 ContactRequest {
18 requester_id: u64,
19 },
20 ContactRequestAccepted {
21 contact_id: u64,
22 },
23 ChannelInvitation {
24 inviter_id: u64,
25 channel_id: u64,
26 },
27 ChannelMessageMention {
28 sender_id: u64,
29 channel_id: u64,
30 message_id: u64,
31 },
32}
33
34impl Notification {
35 /// Load this notification from its generic representation, which is
36 /// used to represent it in the database, and in the wire protocol.
37 ///
38 /// The order in which a given notification type's fields are listed must
39 /// match the order they're listed in the `to_parts` method, and it must
40 /// not change, because they're stored in that order in the database.
41 pub fn from_parts(kind: NotificationKind, entity_ids: [Option<u64>; 3]) -> Option<Self> {
42 use NotificationKind::*;
43 Some(match kind {
44 ContactRequest => Self::ContactRequest {
45 requester_id: entity_ids[0]?,
46 },
47
48 ContactRequestAccepted => Self::ContactRequest {
49 requester_id: entity_ids[0]?,
50 },
51
52 ChannelInvitation => Self::ChannelInvitation {
53 inviter_id: entity_ids[0]?,
54 channel_id: entity_ids[1]?,
55 },
56
57 ChannelMessageMention => Self::ChannelMessageMention {
58 sender_id: entity_ids[0]?,
59 channel_id: entity_ids[1]?,
60 message_id: entity_ids[2]?,
61 },
62 })
63 }
64
65 /// Convert this notification into its generic representation, which is
66 /// used to represent it in the database, and in the wire protocol.
67 ///
68 /// The order in which a given notification type's fields are listed must
69 /// match the order they're listed in the `from_parts` method, and it must
70 /// not change, because they're stored in that order in the database.
71 pub fn to_parts(&self) -> (NotificationKind, [Option<u64>; 3]) {
72 use NotificationKind::*;
73 match self {
74 Self::ContactRequest { requester_id } => {
75 (ContactRequest, [Some(*requester_id), None, None])
76 }
77
78 Self::ContactRequestAccepted { contact_id } => {
79 (ContactRequest, [Some(*contact_id), None, None])
80 }
81
82 Self::ChannelInvitation {
83 inviter_id,
84 channel_id,
85 } => (
86 ChannelInvitation,
87 [Some(*inviter_id), Some(*channel_id), None],
88 ),
89
90 Self::ChannelMessageMention {
91 sender_id,
92 channel_id,
93 message_id,
94 } => (
95 ChannelMessageMention,
96 [Some(*sender_id), Some(*channel_id), Some(*message_id)],
97 ),
98 }
99 }
100}
101
102impl NotificationKind {
103 pub fn all() -> impl Iterator<Item = Self> {
104 Self::iter()
105 }
106
107 pub fn from_i32(i: i32) -> Option<Self> {
108 Self::iter().find(|kind| *kind as i32 == i)
109 }
110}