Remove code comments
This commit is contained in:
parent
a5e58493d8
commit
52d7c13013
17 changed files with 18 additions and 335 deletions
|
|
@ -1,11 +1,7 @@
|
|||
//! Parsing of the IRC wire format into [`Message`] / [`Prefix`] values.
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// The source of a message: `nick!user@host`, or a bare nick / server name.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Prefix {
|
||||
/// The full, unparsed prefix as received.
|
||||
pub raw: String,
|
||||
pub nick: Option<String>,
|
||||
pub user: Option<String>,
|
||||
|
|
@ -13,7 +9,6 @@ pub struct Prefix {
|
|||
}
|
||||
|
||||
impl Prefix {
|
||||
/// Parse a prefix per the grammar `servername / (nick [ [ "!" user ] "@" host ])`.
|
||||
fn parse(raw: &str) -> Prefix {
|
||||
let (nick, user, host) = if let Some((n, rest)) = raw.split_once('!') {
|
||||
match rest.split_once('@') {
|
||||
|
|
@ -23,7 +18,6 @@ impl Prefix {
|
|||
} else if let Some((n, h)) = raw.split_once('@') {
|
||||
(Some(n), None, Some(h))
|
||||
} else {
|
||||
// A bare nick or a server name — keep it as the nick for convenience.
|
||||
(Some(raw), None, None)
|
||||
};
|
||||
|
||||
|
|
@ -35,36 +29,26 @@ impl Prefix {
|
|||
}
|
||||
}
|
||||
|
||||
/// Best display name for the sender: the nick if we have one, else the raw prefix.
|
||||
pub fn name(&self) -> &str {
|
||||
self.nick.as_deref().unwrap_or(&self.raw)
|
||||
}
|
||||
}
|
||||
|
||||
/// A parsed IRC message.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Message {
|
||||
/// IRCv3 message tags (already unescaped). Empty when none were present.
|
||||
pub tags: HashMap<String, String>,
|
||||
/// The message source, if the server included one.
|
||||
pub prefix: Option<Prefix>,
|
||||
/// The command, upper-cased (e.g. `PRIVMSG`) or a 3-digit numeric (e.g. `001`).
|
||||
pub command: String,
|
||||
/// Command parameters; the last one may be a "trailing" value containing spaces.
|
||||
pub params: Vec<String>,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
/// Parse a single line of IRC (the trailing CRLF may be present or not).
|
||||
///
|
||||
/// Returns `None` for blank or structurally invalid lines.
|
||||
pub fn parse(line: &str) -> Option<Message> {
|
||||
let mut rest = line.trim_end_matches(['\r', '\n']).trim_start();
|
||||
if rest.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// 1. Tags: `@key=value;key2 ` (optional, space-terminated).
|
||||
let mut tags = HashMap::new();
|
||||
if let Some(stripped) = rest.strip_prefix('@') {
|
||||
let (tag_str, r) = stripped.split_once(' ')?;
|
||||
|
|
@ -77,7 +61,6 @@ impl Message {
|
|||
}
|
||||
}
|
||||
|
||||
// 2. Source / prefix: `:nick!user@host ` (optional, space-terminated).
|
||||
let mut prefix = None;
|
||||
if let Some(stripped) = rest.strip_prefix(':') {
|
||||
let (p, r) = stripped.split_once(' ')?;
|
||||
|
|
@ -85,7 +68,6 @@ impl Message {
|
|||
rest = r.trim_start();
|
||||
}
|
||||
|
||||
// 3. Command (required).
|
||||
let (command, mut rest) = match rest.split_once(' ') {
|
||||
Some((c, r)) => (c, r.trim_start()),
|
||||
None => (rest, ""),
|
||||
|
|
@ -94,8 +76,6 @@ impl Message {
|
|||
return None;
|
||||
}
|
||||
|
||||
// 4. Parameters. A parameter beginning with ':' is the trailing param and
|
||||
// consumes the remainder of the line verbatim (spaces included).
|
||||
let mut params = Vec::new();
|
||||
while !rest.is_empty() {
|
||||
if let Some(trailing) = rest.strip_prefix(':') {
|
||||
|
|
@ -124,28 +104,23 @@ impl Message {
|
|||
})
|
||||
}
|
||||
|
||||
/// Get the parameter at `index`, if present.
|
||||
pub fn param(&self, index: usize) -> Option<&str> {
|
||||
self.params.get(index).map(String::as_str)
|
||||
}
|
||||
|
||||
/// The last parameter — for `PRIVMSG`/`NOTICE`/`PING` this is the message text.
|
||||
pub fn trailing(&self) -> Option<&str> {
|
||||
self.params.last().map(String::as_str)
|
||||
}
|
||||
|
||||
/// The sender's nick, if the message carried a `nick!user@host` prefix.
|
||||
pub fn nick(&self) -> Option<&str> {
|
||||
self.prefix.as_ref().and_then(|p| p.nick.as_deref())
|
||||
}
|
||||
|
||||
/// The value of an IRCv3 message tag (e.g. `time`, `batch`), if present.
|
||||
pub fn tag(&self, key: &str) -> Option<&str> {
|
||||
self.tags.get(key).map(String::as_str)
|
||||
}
|
||||
}
|
||||
|
||||
/// Unescape an IRCv3 tag value per <https://ircv3.net/specs/extensions/message-tags>.
|
||||
fn unescape_tag_value(value: &str) -> String {
|
||||
let mut out = String::with_capacity(value.len());
|
||||
let mut chars = value.chars();
|
||||
|
|
@ -160,8 +135,8 @@ fn unescape_tag_value(value: &str) -> String {
|
|||
Some('\\') => out.push('\\'),
|
||||
Some('r') => out.push('\r'),
|
||||
Some('n') => out.push('\n'),
|
||||
Some(other) => out.push(other), // unknown escape: drop the backslash
|
||||
None => {} // trailing backslash: ignore
|
||||
Some(other) => out.push(other),
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
out
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue