Skip to content

Commit 2ca4dbc

Browse files
authored
🔀 Merge pull request #436 from ruby/backport/v0.4-refactor-config-and-response_reader
♻️ Refactoring (backports)
2 parents c4a1c79 + 9279f8a commit 2ca4dbc

File tree

4 files changed

+40
-30
lines changed

4 files changed

+40
-30
lines changed

lib/net/imap/config.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,6 @@ def self.[](config)
242242
# Use +SASL-IR+ when it is supported by the server and the mechanism.
243243
attr_accessor :sasl_ir, type: :boolean
244244

245-
246245
# Controls the behavior of Net::IMAP#responses when called without any
247246
# arguments (+type+ or +block+).
248247
#
@@ -269,7 +268,7 @@ def self.[](config)
269268
# Raise an ArgumentError with the deprecation warning.
270269
#
271270
# Note: #responses_without_args is an alias for #responses_without_block.
272-
attr_accessor :responses_without_block, type: [
271+
attr_accessor :responses_without_block, type: Enum[
273272
:silence_deprecation_warning, :warn, :frozen_dup, :raise,
274273
]
275274

@@ -314,7 +313,7 @@ def self.[](config)
314313
#
315314
# [+false+ <em>(planned default for +v0.6+)</em>]
316315
# ResponseParser _only_ uses AppendUIDData and CopyUIDData.
317-
attr_accessor :parser_use_deprecated_uidplus_data, type: [
316+
attr_accessor :parser_use_deprecated_uidplus_data, type: Enum[
318317
true, :up_to_max_size, false
319318
]
320319

lib/net/imap/config/attr_type_coercion.rb

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,34 @@ def self.included(mod)
2626
end
2727
private_class_method :included
2828

29-
def self.attr_accessor(attr, type: nil)
30-
return unless type
31-
if :boolean == type then boolean attr
32-
elsif Integer == type then integer attr
33-
elsif Array === type then enum attr, type
34-
else raise ArgumentError, "unknown type coercion %p" % [type]
35-
end
29+
if defined?(Ractor.make_shareable)
30+
def self.safe(...) Ractor.make_shareable nil.instance_eval(...).freeze end
31+
else
32+
def self.safe(...) nil.instance_eval(...).freeze end
3633
end
34+
private_class_method :safe
3735

38-
def self.boolean(attr)
39-
define_method :"#{attr}=" do |val| super !!val end
40-
define_method :"#{attr}?" do send attr end
36+
Types = Hash.new do |h, type|
37+
type.nil? || Proc === type or raise TypeError, "type not nil or Proc"
38+
safe{type}
4139
end
40+
Types[:boolean] = Boolean = safe{-> {!!_1}}
41+
Types[Integer] = safe{->{Integer(_1)}}
4242

43-
def self.integer(attr)
44-
define_method :"#{attr}=" do |val| super Integer val end
43+
def self.attr_accessor(attr, type: nil)
44+
type = Types[type] or return
45+
define_method :"#{attr}=" do |val| super type[val] end
46+
define_method :"#{attr}?" do send attr end if type == Boolean
4547
end
4648

47-
def self.enum(attr, enum)
48-
enum = enum.dup.freeze
49+
Enum = ->(*enum) {
50+
enum = safe{enum}
4951
expected = -"one of #{enum.map(&:inspect).join(", ")}"
50-
define_method :"#{attr}=" do |val|
51-
unless enum.include?(val)
52-
raise ArgumentError, "expected %s, got %p" % [expected, val]
53-
end
54-
super val
55-
end
56-
end
52+
safe{->val {
53+
return val if enum.include?(val)
54+
raise ArgumentError, "expected %s, got %p" % [expected, val]
55+
}}
56+
}
5757

5858
end
5959
end

lib/net/imap/response_reader.rb

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,34 @@ def initialize(client, sock)
1111
end
1212

1313
def read_response_buffer
14-
buff = String.new
14+
@buff = String.new
1515
catch :eof do
1616
while true
17-
read_line(buff)
18-
break unless /\{(\d+)\}\r\n\z/n =~ buff
19-
read_literal(buff, $1.to_i)
17+
read_line
18+
break unless (@literal_size = get_literal_size)
19+
read_literal
2020
end
2121
end
2222
buff
23+
ensure
24+
@buff = nil
2325
end
2426

2527
private
2628

27-
def read_line(buff)
29+
attr_reader :buff, :literal_size
30+
31+
def get_literal_size; /\{(\d+)\}\r\n\z/n =~ buff && $1.to_i end
32+
33+
def read_line
2834
buff << (@sock.gets(CRLF) or throw :eof)
2935
end
3036

31-
def read_literal(buff, literal_size)
37+
def read_literal
3238
literal = String.new(capacity: literal_size)
3339
buff << (@sock.read(literal_size, literal) or throw :eof)
40+
ensure
41+
@literal_size = nil
3442
end
3543

3644
end

test/net/imap/test_response_reader.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ def literal(str) "{#{str.bytesize}}\r\n#{str}" end
2424
long_line = "tag ok #{aaaaaaaaa} #{aaaaaaaaa}\r\n"
2525
literal_aaaa = "* fake #{literal aaaaaaaaa}\r\n"
2626
literal_crlf = "tag ok #{literal many_crlfs} #{literal many_crlfs}\r\n"
27+
zero_literal = "tag ok #{literal ""} #{literal ""}\r\n"
2728
illegal_crs = "tag ok #{many_crs} #{many_crs}\r\n"
2829
illegal_lfs = "tag ok #{literal "\r"}\n#{literal "\r"}\n\r\n"
2930
io = StringIO.new([
3031
simple,
3132
long_line,
3233
literal_aaaa,
3334
literal_crlf,
35+
zero_literal,
3436
illegal_crs,
3537
illegal_lfs,
3638
simple,
@@ -40,6 +42,7 @@ def literal(str) "{#{str.bytesize}}\r\n#{str}" end
4042
assert_equal long_line, rcvr.read_response_buffer.to_str
4143
assert_equal literal_aaaa, rcvr.read_response_buffer.to_str
4244
assert_equal literal_crlf, rcvr.read_response_buffer.to_str
45+
assert_equal zero_literal, rcvr.read_response_buffer.to_str
4346
assert_equal illegal_crs, rcvr.read_response_buffer.to_str
4447
assert_equal illegal_lfs, rcvr.read_response_buffer.to_str
4548
assert_equal simple, rcvr.read_response_buffer.to_str

0 commit comments

Comments
 (0)