Crate ircv3_parse

Crate ircv3_parse 

Source
Expand description

Zero-copy IRC message parser with IRCv3 support.

§Quick Start

use ircv3_parse::FromMessage;

#[derive(FromMessage)]
#[irc(command = "PRIVMSG")]
struct PrivMsg<'a> {
    #[irc(source = "name")]
    nick: &'a str,
    #[irc(trailing)]
    message: &'a str
}

let input = ":nick!user@example.com PRIVMSG #channel :Hello everyone!";
let msg: PrivMsg = ircv3_parse::from_str(input)?;

println!("From: {}", msg.nick);
println!("Message: {}", msg.message);

§FromMessage Derive Attributes

The FromMessage derive macro supports both &str and String field types.

§Struct-Level Attributes

  • #[irc(command = "COMMAND")] - Validates that the command matches (case-insensitive)

§Field-Level Attributes

  • #[irc(tag = "key")] - Extract tag value
  • #[irc(tag_flag = "key")] - Extract tag flag
  • #[irc(source = "component")] - Extract source component (name, user, or host)
  • #[irc(param = N)] - Extract parameter by index
  • #[irc(params)] - Extract all parameters into a Vec
  • #[irc(trailing)] - Extract trailing parameter
  • #[irc(command)] - Extract command
  • #[irc(with = "function")] - Custom extraction

§Manual FromMessage Implementation

For more complex parsing logic, implement the FromMessage trait manually.

§Understanding Message Structure

The Message struct provides access to IRC message components:

§Example Implementation

use ircv3_parse::{message::de::FromMessage, DeError, Message};

struct PrivMsg<'a> {
    color: Option<&'a str>,
    channel: &'a str,
    nick: &'a str,
    message: &'a str,
}

impl<'a> FromMessage<'a> for PrivMsg<'a> {
    fn from_message(msg: &Message<'a>) -> Result<Self, DeError> {
        // Validate command
        let command = msg.command();
        if !command.is_privmsg() {
            return Err(DeError::invalid_command("PRIVMSG", command.as_str()));
        }

        // Extract tags (optional)
        let color = msg.tags()
            .and_then(|tags| tags.get("color"))
            .map(|v| v.as_str());

        // Extract source (required)
        let source = msg.source()
            .ok_or_else(|| DeError::missing_source())?;
        let nick = source.name;

        // Extract parameters
        let params = msg.params();
        let channel = params.middles.first()
            .ok_or_else(|| DeError::missing_param_field("channel", 0))?;
        let message = params.trailing.as_str();

        Ok(Self {
            color,
            channel,
            nick,
            message,
        })
    }
}

§Error Handling

use ircv3_parse::FromMessage;

#[derive(FromMessage)]
#[irc(command = "PRIVMSG")]
struct PrivMsg {
    #[irc(trailing)]
    message: String
}

let input = "NOTICE all :hi";
let result = ircv3_parse::from_str::<PrivMsg>(input);

if let Err(e) = result {
    if e.is_parse_error() {
        println!("Invalid IRC message format: {e}");
    }

    if e.is_invalid_command() {
        println!("Expected PRIVMSG, got {input}");
    }

    if e.is_missing_tags() {
        println!("Message has no tags component");
    }

    if e.is_missing_source() {
        println!("Message has no source component");
    }

    if e.is_missing_param() {
        println!("Message has no parameters");
    }

    if e.is_missing_tag() {
        println!("Specific tag not found");
    }
}

§Building Messages

use ircv3_parse::{builder::legacy::MessageBuilder, components::Commands};

let message = MessageBuilder::new(Commands::PRIVMSG)
    .with_tags(|tags| {
        tags.add("id", Some("123"))?
            .add("color", None)?
            .add_flag("subscriber")
    })?
    .with_source("nick", |source| {
        source.with_user("user")?.with_host("example.com")
    })?
    .with_params(|params| params.add("#channel"))?
    .with_trailing("hi")?
    .finish();

let bytes = message.to_bytes();
// Result: @id=123;color=;subscriber :nick!user@example.com PRIVMSG #channel :hi\r\n

§Builder Order

Components must be added in the correct order:

  1. Command (required) - MessageBuilder::new() with Commands
  2. Tags (optional) - with_tags()
  3. Source (optional) - with_source()
  4. Middle parameters (optional) - with_params()
  5. Trailing parameter (optional) - with_trailing()

§Feature Flags

  • derive - Enables the FromMessage derive macro
  • serde - Enables Serialize implementation for Message

Re-exports§

pub use components::Commands;
pub use error::DeError;
pub use error::IRCError;
pub use message::Message;
pub use message::MessageBuilder;

Modules§

builder
components
error
message
validators

Functions§

from_message
Serialize the custom data structure as a Bytes.
from_str
Parse an IRC message into a type implementing message::de::FromMessage.
parse
Parse an IRC message from a string.
unescape
Unescapes an IRCv3 tag value according to the specification.

Derive Macros§

FromMessagederive
Derives FromMessage implementation for structs