Skip to content

Commit 053c89e

Browse files
committed
🏷️ Add number64 and nz-number64 to NumValidator
This uses the uint63 definition, from RFC9051. This isn't used by any internal Net::IMAP code, _yet_.
1 parent f3b7417 commit 053c89e

2 files changed

Lines changed: 119 additions & 7 deletions

File tree

lib/net/imap/data_encoding.rb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,22 @@ def valid_nz_number?(num)
174174
0 < num && num <= 0xffff_ffff
175175
end
176176

177+
# Check if argument is a valid 'number64' according to RFC 9051
178+
# number64 = 1*DIGIT
179+
# ; Unsigned 63-bit integer
180+
# ; (0 <= n <= 9,223,372,036,854,775,807)
181+
def valid_number64?(num)
182+
0 <= num && num <= 0x7fff_ffff_ffff_ffff
183+
end
184+
185+
# Check if argument is a valid 'number64' according to RFC 9051
186+
# number64 = 1*DIGIT
187+
# ; Unsigned 63-bit integer
188+
# ; (0 <= n <= 9,223,372,036,854,775,807)
189+
def valid_nz_number64?(num)
190+
0 < num && num <= 0x7fff_ffff_ffff_ffff
191+
end
192+
177193
# Check if argument is a valid 'mod-sequence-value' according to RFC 4551
178194
# mod-sequence-value = 1*DIGIT
179195
# ; Positive unsigned 64-bit integer
@@ -203,6 +219,20 @@ def ensure_nz_number(num)
203219
"nz-number must be non-zero unsigned 32-bit integer: #{num}"
204220
end
205221

222+
# Ensure argument is 'number64' or raise DataFormatError
223+
def ensure_number64(num)
224+
return num if valid_number64?(num)
225+
raise DataFormatError,
226+
"number64 must be unsigned 63-bit integer: #{num}"
227+
end
228+
229+
# Ensure argument is 'nz-number64' or raise DataFormatError
230+
def ensure_nz_number64(num)
231+
return num if valid_nz_number64?(num)
232+
raise DataFormatError,
233+
"nz-number64 must be non-zero unsigned 63-bit integer: #{num}"
234+
end
235+
206236
# Ensure argument is 'mod-sequence-value' or raise DataFormatError
207237
def ensure_mod_sequence_value(num)
208238
return num if valid_mod_sequence_value?(num)
@@ -237,6 +267,26 @@ def coerce_nz_number(num)
237267
end
238268
end
239269

270+
# Like #ensure_number64, but usable with numeric String input.
271+
def coerce_number64(num)
272+
case num
273+
when Integer then ensure_number64 num
274+
when NUMBER_RE then ensure_number64 Integer num
275+
else
276+
raise DataFormatError, "%p is not a valid number64" % [num]
277+
end
278+
end
279+
280+
# Like #ensure_nz_number64, but usable with numeric String input.
281+
def coerce_nz_number64(num)
282+
case num
283+
when Integer then ensure_nz_number64 num
284+
when NUMBER_RE then ensure_nz_number64 Integer num
285+
else
286+
raise DataFormatError, "%p is not a valid nz-number64" % [num]
287+
end
288+
end
289+
240290
# Like #ensure_mod_sequence_value, but usable with numeric String input.
241291
def coerce_mod_sequence_value(num)
242292
case num

test/net/imap/test_num_validator.rb

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ class NumValidatorTest < Net::IMAP::TestCase
99
TEST_VALUES = {
1010
-1 => %i[invalid],
1111

12-
0 => %i[number mod-sequence-valzer],
13-
1 => %i[number nz-number mod-sequence-value mod-sequence-valzer],
14-
0x0000_ffff => %i[number nz-number mod-sequence-value mod-sequence-valzer],
15-
0xffff_ffff => %i[number nz-number mod-sequence-value mod-sequence-valzer],
16-
0x0000_0001_0000_0000 => %i[ mod-sequence-value mod-sequence-valzer],
17-
0x0000_ffff_ffff_ffff => %i[ mod-sequence-value mod-sequence-valzer],
18-
0xffff_ffff_ffff_fffe => %i[ mod-sequence-value mod-sequence-valzer],
12+
0 => %i[number number64 mod-sequence-valzer],
13+
1 => %i[number nz-number number64 nz-number64 mod-sequence-value mod-sequence-valzer],
14+
0x0000_ffff => %i[number nz-number number64 nz-number64 mod-sequence-value mod-sequence-valzer],
15+
0xffff_ffff => %i[number nz-number number64 nz-number64 mod-sequence-value mod-sequence-valzer],
16+
0x0000_0001_0000_0000 => %i[ number64 nz-number64 mod-sequence-value mod-sequence-valzer],
17+
0x0000_ffff_ffff_ffff => %i[ number64 nz-number64 mod-sequence-value mod-sequence-valzer],
18+
0x7fff_ffff_ffff_ffff => %i[ number64 nz-number64 mod-sequence-value mod-sequence-valzer],
19+
0x8000_0000_0000_0000 => %i[ mod-sequence-value mod-sequence-valzer],
20+
0xffff_ffff_ffff_fffe => %i[ mod-sequence-value mod-sequence-valzer],
1921

2022
0xffff_ffff_ffff_ffff => %i[invalid],
2123
}
@@ -40,6 +42,18 @@ def self.using_test_values_for(type)
4042
end
4143
end
4244

45+
using_test_values_for :number64 do |label, value, valid|
46+
test "#valid_number64?(%s) => %p" % [label, valid] do
47+
assert_equal valid, NumValidator.valid_number64?(value)
48+
end
49+
end
50+
51+
using_test_values_for :"nz-number64" do |label, value, valid|
52+
test "#valid_nz_number64?(%s) => %p" % [label, valid] do
53+
assert_equal valid, NumValidator.valid_nz_number64?(value)
54+
end
55+
end
56+
4357
using_test_values_for :"mod-sequence-value" do |label, value, valid|
4458
test "#valid_mod_sequence_value?(%s) => %p" % [label, valid] do
4559
assert_equal valid, NumValidator.valid_mod_sequence_value?(value)
@@ -80,6 +94,28 @@ def assert_format_error
8094
end
8195
end
8296

97+
using_test_values_for :number64 do |label, value, valid|
98+
result = valid ? "=> #{label}" : "raises DataFormatError"
99+
test "#ensure_number64(%s) %s" % [label, result] do
100+
if valid
101+
assert_equal value, NumValidator.ensure_number64(value)
102+
else
103+
assert_format_error do NumValidator.ensure_number64(value) end
104+
end
105+
end
106+
end
107+
108+
using_test_values_for :"nz-number64" do |label, value, valid|
109+
result = valid ? "=> #{label}" : "raises DataFormatError"
110+
test "#ensure_nz_number64(%s) %s" % [label, result] do
111+
if valid
112+
assert_equal value, NumValidator.ensure_nz_number64(value)
113+
else
114+
assert_format_error do NumValidator.ensure_nz_number64(value) end
115+
end
116+
end
117+
end
118+
83119
using_test_values_for :"mod-sequence-value" do |label, value, valid|
84120
result = valid ? "=> #{label}" : "raises DataFormatError"
85121
test "#ensure_mod_sequence_value(%s) %s" % [label, result] do
@@ -128,6 +164,32 @@ def assert_format_error
128164
end
129165
end
130166

167+
using_test_values_for :number64 do |label, value, valid|
168+
result = valid ? "=> #{value}" : "raises DataFormatError"
169+
[value, value.to_s].each do |input|
170+
test "#coerce_number64(%p) %s" % [input, result] do
171+
if valid
172+
assert_equal value, NumValidator.coerce_number64(input)
173+
else
174+
assert_format_error do NumValidator.coerce_number64(input) end
175+
end
176+
end
177+
end
178+
end
179+
180+
using_test_values_for :"nz-number64" do |label, value, valid|
181+
result = valid ? "=> #{value}" : "raises DataFormatError"
182+
[value, value.to_s].each do |input|
183+
test "#coerce_nz_number64(%p) %s" % [input, result] do
184+
if valid
185+
assert_equal value, NumValidator.coerce_nz_number64(input)
186+
else
187+
assert_format_error do NumValidator.coerce_nz_number64(input) end
188+
end
189+
end
190+
end
191+
end
192+
131193
using_test_values_for :"mod-sequence-value" do |label, value, valid|
132194
result = valid ? "=> #{value}" : "raises DataFormatError"
133195
[value, value.to_s].each do |input|

0 commit comments

Comments
 (0)