tangle


git clone https://radroots.dev/git/tangle.git
Log | Files | Refs | README | LICENSE

errors.rs (4592B)


      1 use core::fmt;
      2 
      3 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
      4 pub enum GroupReplyPrefix {
      5     Duplicate,
      6     Blocked,
      7     RateLimited,
      8     Invalid,
      9     Restricted,
     10     AuthRequired,
     11     Error,
     12 }
     13 
     14 impl GroupReplyPrefix {
     15     pub fn as_str(self) -> &'static str {
     16         match self {
     17             Self::Duplicate => "duplicate",
     18             Self::Blocked => "blocked",
     19             Self::RateLimited => "rate-limited",
     20             Self::Invalid => "invalid",
     21             Self::Restricted => "restricted",
     22             Self::AuthRequired => "auth-required",
     23             Self::Error => "error",
     24         }
     25     }
     26 }
     27 
     28 impl fmt::Display for GroupReplyPrefix {
     29     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
     30         formatter.write_str(self.as_str())
     31     }
     32 }
     33 
     34 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
     35 pub enum GroupErrorKind {
     36     InvalidGroupId,
     37     MalformedGroupTag,
     38     MissingGroupTag,
     39     ConflictingGroupTag,
     40     TooManyGroupTags,
     41     UnsupportedGroupKind,
     42     DirectRelayGeneratedSubmission,
     43     MissingTargetTag,
     44     MalformedTargetTag,
     45     MetadataTooLarge,
     46     TooManySupportedKinds,
     47     InvalidRole,
     48     MissingCapability,
     49     AuthenticationRequired,
     50     GroupUnavailable,
     51     GroupDeleted,
     52     GroupAlreadyExists,
     53     DuplicateMember,
     54     Internal,
     55 }
     56 
     57 #[derive(Debug, Clone, PartialEq, Eq)]
     58 pub struct GroupError {
     59     kind: GroupErrorKind,
     60     prefix: GroupReplyPrefix,
     61     message: String,
     62 }
     63 
     64 impl GroupError {
     65     pub fn new(kind: GroupErrorKind, prefix: GroupReplyPrefix, message: impl Into<String>) -> Self {
     66         Self {
     67             kind,
     68             prefix,
     69             message: message.into(),
     70         }
     71     }
     72 
     73     pub fn invalid(kind: GroupErrorKind, message: impl Into<String>) -> Self {
     74         Self::new(kind, GroupReplyPrefix::Invalid, message)
     75     }
     76 
     77     pub fn duplicate(kind: GroupErrorKind, message: impl Into<String>) -> Self {
     78         Self::new(kind, GroupReplyPrefix::Duplicate, message)
     79     }
     80 
     81     pub fn blocked(kind: GroupErrorKind, message: impl Into<String>) -> Self {
     82         Self::new(kind, GroupReplyPrefix::Blocked, message)
     83     }
     84 
     85     pub fn restricted(kind: GroupErrorKind, message: impl Into<String>) -> Self {
     86         Self::new(kind, GroupReplyPrefix::Restricted, message)
     87     }
     88 
     89     pub fn auth_required(message: impl Into<String>) -> Self {
     90         Self::new(
     91             GroupErrorKind::AuthenticationRequired,
     92             GroupReplyPrefix::AuthRequired,
     93             message,
     94         )
     95     }
     96 
     97     pub fn internal(message: impl Into<String>) -> Self {
     98         Self::new(GroupErrorKind::Internal, GroupReplyPrefix::Error, message)
     99     }
    100 
    101     pub fn kind(&self) -> GroupErrorKind {
    102         self.kind
    103     }
    104 
    105     pub fn reply_prefix(&self) -> GroupReplyPrefix {
    106         self.prefix
    107     }
    108 
    109     pub fn message(&self) -> &str {
    110         &self.message
    111     }
    112 
    113     pub fn prefixed_message(&self) -> String {
    114         format!("{}: {}", self.prefix.as_str(), self.message)
    115     }
    116 }
    117 
    118 impl fmt::Display for GroupError {
    119     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
    120         formatter.write_str(&self.prefixed_message())
    121     }
    122 }
    123 
    124 impl std::error::Error for GroupError {}
    125 
    126 #[cfg(test)]
    127 mod tests {
    128     use super::{GroupError, GroupErrorKind, GroupReplyPrefix};
    129 
    130     #[test]
    131     fn group_errors_map_to_nostr_reply_prefixes() {
    132         let cases = [
    133             (GroupReplyPrefix::Duplicate, "duplicate"),
    134             (GroupReplyPrefix::Blocked, "blocked"),
    135             (GroupReplyPrefix::RateLimited, "rate-limited"),
    136             (GroupReplyPrefix::Invalid, "invalid"),
    137             (GroupReplyPrefix::Restricted, "restricted"),
    138             (GroupReplyPrefix::AuthRequired, "auth-required"),
    139             (GroupReplyPrefix::Error, "error"),
    140         ];
    141 
    142         for (prefix, value) in cases {
    143             assert_eq!(prefix.as_str(), value);
    144             assert_eq!(prefix.to_string(), value);
    145         }
    146 
    147         let error = GroupError::restricted(
    148             GroupErrorKind::MissingCapability,
    149             "missing group capability manage_members",
    150         );
    151 
    152         assert_eq!(error.reply_prefix(), GroupReplyPrefix::Restricted);
    153         assert_eq!(
    154             error.prefixed_message(),
    155             "restricted: missing group capability manage_members"
    156         );
    157 
    158         let duplicate = GroupError::duplicate(
    159             GroupErrorKind::DuplicateMember,
    160             "group member already exists",
    161         );
    162 
    163         assert_eq!(duplicate.reply_prefix(), GroupReplyPrefix::Duplicate);
    164         assert_eq!(
    165             duplicate.prefixed_message(),
    166             "duplicate: group member already exists"
    167         );
    168     }
    169 }