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
use std::borrow::Cow;
use crate::Parse;
/// An IRC-styled prefix.
///
/// A prefix is attached to certain messages denoting whom sent it.
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
pub enum Prefix<'a> {
/// A user prefix.
///
/// This is attached for messages sent by a user
///
/// Currently, with Twitch, only `name` is is relevant
User {
/// Their (nick) name
name: Cow<'a, str>,
/// Their user name
user: Cow<'a, str>,
/// Their host
host: Cow<'a, str>,
},
/// A server prefix.
///
/// This is attached for messages sent by the server
Server {
/// The host of the server
host: Cow<'a, str>,
},
/// No prefix was attached
#[default]
None,
}
impl<'a> Prefix<'a> {
/// Is this a [User](Self::User) prefix?
pub const fn is_user(&self) -> bool {
matches!(self, Self::User { .. })
}
/// Is this a [Server](Self::Server) prefix?
pub const fn is_server(&self) -> bool {
matches!(self, Self::Server { .. })
}
/// Get the prefix as a `&str` (the user name, or the server host name)
pub fn as_name_str(&self) -> Option<&str> {
match self {
Self::User { name, .. } | Self::Server { host: name } => Some(name),
_ => None,
}
}
}
impl<'a> Parse<'a> for Prefix<'a> {
type Output = Self;
fn parse(input: &mut &'a str) -> Self::Output {
if !input.starts_with(':') {
return Self::None;
}
let (head, tail) = match input[1..].split_once(' ') {
Some(val) => val,
None => return Self::None,
};
*input = tail;
let prefix = match head.find('!') {
Some(bang) => {
let name = &head[..bang];
let (user, host) = match head[bang + 1..].split_once('@').map(|(k, v)| (k, v)) {
Some(val) => val,
None => return Self::None,
};
Self::User {
name: Cow::from(name),
user: Cow::from(user),
host: Cow::from(host),
}
}
None => Self::Server {
host: Cow::from(head),
},
};
prefix
}
}