Skip to content

Commit 2b1aa63

Browse files
authored
🔀 Merge pull request #679 from ruby/raw_data-improvements
♻️ Improve `RawData.new`, Add `RawData.split`
2 parents b796780 + 257e51d commit 2b1aa63

2 files changed

Lines changed: 30 additions & 5 deletions

File tree

lib/net/imap/command_data.rb

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,12 @@ def send_data(imap, tag) = imap.__send__(:put_string, data)
198198

199199
class RawData < CommandData # :nodoc:
200200
def initialize(data:)
201-
data = split_parts(data)
201+
case data
202+
in String then data = self.class.split(data)
203+
in Array if data.all? { _1 in RawText | Literal }
204+
else
205+
raise TypeError, "expected String or Array[#{RawText} | #{Literal}]"
206+
end
202207
super
203208
validate
204209
end
@@ -212,9 +217,11 @@ def validate
212217
end
213218
end
214219

215-
private
216-
217-
def split_parts(data)
220+
# Splits an input +string+ into an array of RawText and Literal/Literal8.
221+
#
222+
# NOTE: unlike RawData#validate, this does not prevent the final RawText
223+
# from ending with a literal prefix.
224+
def self.split(data)
218225
data = data.b # dups and ensures BINARY encoding
219226
parts = []
220227
while data.match(/(~)?\{(0|[1-9]\d*)(\+)?\}\r\n/n)
@@ -228,14 +235,15 @@ def split_parts(data)
228235
parts
229236
end
230237

231-
def extract_literal(data, binary:, bytesize:, non_sync:)
238+
def self.extract_literal(data, binary:, bytesize:, non_sync:)
232239
if data.bytesize < bytesize
233240
raise DataFormatError, "Too few bytes in string for literal, " \
234241
"expected: %s, remaining: %s" % [bytesize, data.bytesize]
235242
end
236243
literal = data.byteslice(0, bytesize)
237244
(binary ? Literal8 : Literal).new(data: literal, non_sync:)
238245
end
246+
private_class_method :extract_literal
239247
end
240248

241249
class Atom < CommandData # :nodoc:

test/net/imap/test_command_data.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,23 @@ class RawDataTest < CommandDataTest
365365
raw = RawData.new(data: " {123} ")
366366
assert_equal [RawText[" {123} "]], raw.data
367367
end
368+
369+
data(
370+
"simple raw text" => 'hello "world"',
371+
"text, literal, text" => "OK {5}\r\nhello {5}\r\nworld",
372+
"empty literals" => "{0}\r\n{0+}\r\n~{0}\r\n~{0+}\r\n",
373+
"binary and regular" => "foo ~{7}\r\n\0bar\r\nbaz {4}\r\nquux",
374+
)
375+
test ".split" do |string|
376+
assert_equal(RawData[string].data, RawData.split(string))
377+
end
378+
379+
test ".split allows final literal prefix" do
380+
assert_equal [RawText["text {123}"]], RawData.split("text {123}")
381+
assert_equal [RawText["text+ {123+}"]], RawData.split("text+ {123+}")
382+
assert_equal [RawText["~text ~{123}"]], RawData.split("~text ~{123}")
383+
assert_equal [RawText["~text+ ~{123+}"]], RawData.split("~text+ ~{123+}")
384+
end
368385
end
369386

370387
end

0 commit comments

Comments
 (0)