1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/// An invalid message was either provided, or could not be parsed

#[derive(Debug)]
#[non_exhaustive]
pub enum MessageError {
    /// Invalid command

    InvalidCommand {
        /// Expected this command

        expected: String,
        /// But got this command

        got: String,
    },

    /// Expected a nickname attached to that message

    ExpectedNick,

    /// Expected an argument at position `pos`

    ExpectedArg {
        /// 'index' of the argument (e.g. 0)

        pos: usize,
    },

    /// expected data attached to that message

    ExpectedData,

    /// Expected a specific tag

    ExpectedTag {
        /// The tag name

        name: String,
    },

    /// Cannot parse a specific tag

    CannotParseTag {
        /// The tag name

        name: String,
        /// The parse error

        error: Box<dyn std::error::Error + Send + Sync>,
    },

    /// An empty key in the tags was provided

    MissingTagKey(
        /// Tag pair index this key was expected to be at

        usize,
    ),

    /// A value wasn't provided for a tag pair

    ///

    /// This usually means the tag was 'key;' and not 'key=val'. 'key=' is allowed.

    MissingTagValue(
        /// Tag pair index this key was expected to be at

        usize,
    ),

    /// An incomplete message was provided

    IncompleteMessage {
        /// At index `pos`

        pos: usize,
    },

    /// An empty message was provided

    EmptyMessage,

    /// A custom error message

    Custom {
        /// The inner error

        error: Box<dyn std::error::Error + Send + Sync>,
    },
}

impl std::fmt::Display for MessageError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::InvalidCommand { expected, got } => {
                write!(f, "invalid command. expected '{}' got '{}'", expected, got)
            }
            Self::ExpectedNick => write!(f, "expected a nickname attached to that message"),
            Self::ExpectedArg { pos } => write!(f, "expected arg at position: {}", pos),
            Self::ExpectedData => write!(f, "expected a data segment in the message"),
            Self::ExpectedTag { name } => write!(f, "expected tag '{}'", name),
            Self::CannotParseTag { name, error } => write!(f, "cannot parse '{}': {}", name, error),
            Self::MissingTagKey(index) => write!(f, "missing tag key at pair index: {}", index),
            Self::MissingTagValue(index) => write!(f, "missing tag value at pair index: {}", index),
            Self::IncompleteMessage { pos } => write!(f, "incomplete message starting at: {}", pos),
            Self::EmptyMessage => write!(f, "no message could be parsed"),
            Self::Custom { error } => write!(f, "custom error: {}", error),
        }
    }
}

impl std::error::Error for MessageError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Self::CannotParseTag { error, .. } => Some(&**error),
            Self::Custom { error } => Some(&**error),
            _ => None,
        }
    }
}