obby_proto/lib.rs
1//! IRCv3 wire format.
2//!
3//! This crate holds no connection and no client state. It turns bytes into a [`Message`] and back,
4//! and it knows the rules that depend only on the line itself: tag escaping, casemapping, ISUPPORT
5//! token grammar, mode argument arity.
6//!
7//! ```
8//! use obby_proto::Message;
9//!
10//! let msg = Message::parse("@time=2026-09-06T10:00:00.000Z :nick!u@h PRIVMSG #chan :hello")?;
11//! assert_eq!(msg.command, "PRIVMSG");
12//! assert_eq!(msg.params, ["#chan", "hello"]);
13//! assert_eq!(msg.tag("time"), Some("2026-09-06T10:00:00.000Z"));
14//! # Ok::<(), obby_proto::ParseError>(())
15//! ```
16
17#![cfg_attr(not(feature = "std"), no_std)]
18
19extern crate alloc;
20
21mod casemap;
22mod format;
23mod isupport;
24mod message;
25mod mode;
26mod servertime;
27mod tags;
28
29pub use casemap::{CaseFolded, Casemapping};
30pub use format::{Colour, Ctcp, Emphasis, Span, Style, parse_ctcp, parse_spans, strip_formatting};
31pub use isupport::{ChanModes, Isupport, Prefix, Token};
32pub use message::{Message, ParseError, Source};
33pub use mode::{ModeChange, parse_channel_modes, parse_user_modes};
34pub use servertime::{format as format_server_time, parse as parse_server_time};
35pub use tags::{Tag, Tags};
36
37/// The byte budget for everything after the tags, including the trailing CRLF.
38///
39/// RFC 1459 sets this and IRCv3 leaves it alone; only the tag section grew.
40pub const MAX_LINE_BYTES: usize = 512;
41
42/// The byte budget for the tag section, excluding the leading `@` and the separating space.
43///
44/// The `message-tags` capability raises the total line budget by this much.
45pub const MAX_TAG_BYTES: usize = 8191;
46
47/// The byte budget a client may spend on its own `+`-prefixed tags.
48///
49/// A server may raise this, and no ISUPPORT token advertises it, so a client cannot discover the
50/// real ceiling and has to be told. ObbyIRCd allows 8191 for general client tags so one TAGMSG can
51/// carry a whole escaped WebRTC SDP, while holding the e2ee tag to this value on the same
52/// connection. Treat this as the floor to assume, not the limit to use.
53pub const MAX_CLIENT_TAG_BYTES: usize = 4094;