notification.rs

  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    ChannelInvitation = 1,
 11    ChannelMessageMention = 2,
 12}
 13
 14pub enum Notification {
 15    ContactRequest {
 16        requester_id: u64,
 17    },
 18    ChannelInvitation {
 19        inviter_id: u64,
 20        channel_id: u64,
 21    },
 22    ChannelMessageMention {
 23        sender_id: u64,
 24        channel_id: u64,
 25        message_id: u64,
 26    },
 27}
 28
 29#[derive(Copy, Clone)]
 30pub enum NotificationEntityKind {
 31    User,
 32    Channel,
 33    ChannelMessage,
 34}
 35
 36impl Notification {
 37    /// Load this notification from its generic representation, which is
 38    /// used to represent it in the database, and in the wire protocol.
 39    ///
 40    /// The order in which a given notification type's fields are listed must
 41    /// match the order they're listed in the `to_parts` method, and it must
 42    /// not change, because they're stored in that order in the database.
 43    pub fn from_parts(kind: NotificationKind, entity_ids: [Option<u64>; 3]) -> Option<Self> {
 44        use NotificationKind::*;
 45
 46        Some(match kind {
 47            ContactRequest => Self::ContactRequest {
 48                requester_id: entity_ids[0]?,
 49            },
 50            ChannelInvitation => Self::ChannelInvitation {
 51                inviter_id: entity_ids[0]?,
 52                channel_id: entity_ids[1]?,
 53            },
 54            ChannelMessageMention => Self::ChannelMessageMention {
 55                sender_id: entity_ids[0]?,
 56                channel_id: entity_ids[1]?,
 57                message_id: entity_ids[2]?,
 58            },
 59        })
 60    }
 61
 62    /// Convert this notification into its generic representation, which is
 63    /// used to represent it in the database, and in the wire protocol.
 64    ///
 65    /// The order in which a given notification type's fields are listed must
 66    /// match the order they're listed in the `from_parts` method, and it must
 67    /// not change, because they're stored in that order in the database.
 68    ///
 69    /// Along with each field, provide the kind of entity that the field refers
 70    /// to. This is used to load the associated entities for a batch of
 71    /// notifications from the database.
 72    pub fn to_parts(&self) -> (NotificationKind, [Option<(u64, NotificationEntityKind)>; 3]) {
 73        use NotificationKind::*;
 74
 75        match self {
 76            Self::ContactRequest { requester_id } => (
 77                ContactRequest,
 78                [
 79                    Some((*requester_id, NotificationEntityKind::User)),
 80                    None,
 81                    None,
 82                ],
 83            ),
 84
 85            Self::ChannelInvitation {
 86                inviter_id,
 87                channel_id,
 88            } => (
 89                ChannelInvitation,
 90                [
 91                    Some((*inviter_id, NotificationEntityKind::User)),
 92                    Some((*channel_id, NotificationEntityKind::User)),
 93                    None,
 94                ],
 95            ),
 96
 97            Self::ChannelMessageMention {
 98                sender_id,
 99                channel_id,
100                message_id,
101            } => (
102                ChannelMessageMention,
103                [
104                    Some((*sender_id, NotificationEntityKind::User)),
105                    Some((*channel_id, NotificationEntityKind::ChannelMessage)),
106                    Some((*message_id, NotificationEntityKind::Channel)),
107                ],
108            ),
109        }
110    }
111}
112
113impl NotificationKind {
114    pub fn all() -> impl Iterator<Item = Self> {
115        Self::iter()
116    }
117
118    pub fn from_i32(i: i32) -> Option<Self> {
119        Self::iter().find(|kind| *kind as i32 == i)
120    }
121}