Skip to content

Commit 02c93b8

Browse files
authored
Merge pull request #1640 from squidowl/read-marker-fix
Multiline Fixes
2 parents 6c8019d + b2aad4c commit 02c93b8

File tree

9 files changed

+499
-117
lines changed

9 files changed

+499
-117
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Fixed:
1919
Thanks:
2020

2121
- Contributions: @KaiKorla, @englut
22-
- Bug reports: chmod222, @whitequark, @englut, sebbu, @ascarion
22+
- Bug reports: chmod222, @whitequark, @englut, sebbu, @ascarion, @4e554c4c
2323
- Feature requests: @gAlleb, @jtbx, @cyrneko, @englut
2424

2525
# 2026.4 (2026-03-03)

data/src/capabilities.rs

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use std::collections::HashSet;
22
use std::str::FromStr;
3+
use std::string::ToString;
34

4-
use crate::config;
5+
use irc::proto::{self, Tags, command, format};
6+
7+
use crate::{Target, User, config, message};
58

69
// This is not an exhaustive list of IRCv3 capabilities, just the ones that
710
// Halloy will request when available. When adding new IRCv3 capabilities to
@@ -62,11 +65,78 @@ impl FromStr for Capability {
6265
}
6366

6467
#[derive(Debug, Clone, Copy)]
65-
pub struct Multiline {
68+
pub struct MultilineLimits {
6669
pub max_bytes: usize,
6770
pub max_lines: Option<usize>,
6871
}
6972

73+
impl MultilineLimits {
74+
pub fn concat_bytes(
75+
&self,
76+
relay_bytes: usize,
77+
batch_kind: MultilineBatchKind,
78+
target: &Target,
79+
) -> usize {
80+
// Message byte limit - relay bytes - space - command - space - target - message separator - crlf
81+
format::BYTE_LIMIT.saturating_sub(
82+
match batch_kind {
83+
MultilineBatchKind::PRIVMSG => 7,
84+
MultilineBatchKind::NOTICE => 6,
85+
} + target.as_str().len()
86+
+ relay_bytes
87+
+ 6,
88+
)
89+
}
90+
}
91+
92+
pub fn multiline_concat_lines(concat_bytes: usize, text: &str) -> Vec<&str> {
93+
let mut lines = Vec::new();
94+
let mut last_line_start = 0;
95+
let mut prev_char_index = 0;
96+
97+
for (char_index, _) in text.char_indices() {
98+
if char_index.saturating_sub(last_line_start) > concat_bytes {
99+
lines.push(&text[last_line_start..prev_char_index]);
100+
last_line_start = prev_char_index;
101+
}
102+
103+
prev_char_index = char_index;
104+
}
105+
106+
lines.push(&text[last_line_start..]);
107+
108+
lines
109+
}
110+
111+
pub fn multiline_encoded(
112+
user: Option<&User>,
113+
batch_kind: MultilineBatchKind,
114+
target: &Target,
115+
text: &str,
116+
tags: Tags,
117+
) -> message::Encoded {
118+
let mut encoded = command!(
119+
match batch_kind {
120+
MultilineBatchKind::PRIVMSG => "PRIVMSG",
121+
MultilineBatchKind::NOTICE => "NOTICE",
122+
},
123+
target.as_str(),
124+
text,
125+
);
126+
127+
if let Some(user) = user {
128+
encoded.source = Some(proto::Source::User(proto::User {
129+
nickname: user.nickname().to_string(),
130+
username: user.username().map(ToString::to_string),
131+
hostname: user.hostname().map(ToString::to_string),
132+
}));
133+
}
134+
135+
encoded.tags = tags;
136+
137+
message::Encoded(encoded)
138+
}
139+
70140
#[derive(Debug, Clone, Copy, PartialEq)]
71141
pub enum MultilineBatchKind {
72142
PRIVMSG,
@@ -78,7 +148,7 @@ pub struct Capabilities {
78148
listed: HashSet<String>,
79149
pending: HashSet<String>,
80150
acknowledged: HashSet<Capability>,
81-
multiline: Option<Multiline>,
151+
multiline: Option<MultilineLimits>,
82152
}
83153

84154
impl Capabilities {
@@ -234,7 +304,7 @@ impl Capabilities {
234304
.strip_prefix("max-bytes=")
235305
.and_then(|value| value.parse::<usize>().ok())
236306
}) {
237-
self.multiline = Some(Multiline {
307+
self.multiline = Some(MultilineLimits {
238308
max_bytes,
239309
max_lines: dictionary.iter().find_map(|key_value| {
240310
key_value
@@ -272,7 +342,7 @@ impl Capabilities {
272342
}
273343
}
274344

275-
pub fn multiline(&self) -> Option<Multiline> {
345+
pub fn multiline_limits(&self) -> Option<MultilineLimits> {
276346
if self.acknowledged(Capability::Multiline) {
277347
self.multiline
278348
} else {

0 commit comments

Comments
 (0)