Skip to content

Commit b848e71

Browse files
authored
🔀 Merge pull request #417 from ruby/refactor-config-attr-coercion
♻️ Refactor Config attr type coercion
2 parents 27d0cb6 + 9579675 commit b848e71

File tree

2 files changed

+19
-26
lines changed

2 files changed

+19
-26
lines changed

lib/net/imap/config.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ def self.[](config)
245245
# present. When capabilities are unknown, Net::IMAP will automatically
246246
# send a +CAPABILITY+ command first before sending +LOGIN+.
247247
#
248-
attr_accessor :enforce_logindisabled, type: [
248+
attr_accessor :enforce_logindisabled, type: Enum[
249249
false, :when_capabilities_cached, true
250250
]
251251

@@ -275,7 +275,7 @@ def self.[](config)
275275
# Raise an ArgumentError with the deprecation warning.
276276
#
277277
# Note: #responses_without_args is an alias for #responses_without_block.
278-
attr_accessor :responses_without_block, type: [
278+
attr_accessor :responses_without_block, type: Enum[
279279
:silence_deprecation_warning, :warn, :frozen_dup, :raise,
280280
]
281281

@@ -320,7 +320,7 @@ def self.[](config)
320320
#
321321
# [+false+ <em>(planned default for +v0.6+)</em>]
322322
# ResponseParser _only_ uses AppendUIDData and CopyUIDData.
323-
attr_accessor :parser_use_deprecated_uidplus_data, type: [
323+
attr_accessor :parser_use_deprecated_uidplus_data, type: Enum[
324324
true, :up_to_max_size, false
325325
]
326326

lib/net/imap/config/attr_type_coercion.rb

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,27 @@ 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
36-
end
29+
def self.safe(...) = Ractor.make_shareable nil.instance_eval(...).freeze
30+
private_class_method :safe
3731

38-
def self.boolean(attr)
39-
define_method :"#{attr}=" do |val| super !!val end
40-
define_method :"#{attr}?" do send attr end
41-
end
32+
Types = Hash.new do |h, type| type => Proc | nil; safe{type} end
33+
Types[:boolean] = Boolean = safe{-> {!!_1}}
34+
Types[Integer] = safe{->{Integer(_1)}}
4235

43-
def self.integer(attr)
44-
define_method :"#{attr}=" do |val| super Integer val end
36+
def self.attr_accessor(attr, type: nil)
37+
type = Types[type] or return
38+
define_method :"#{attr}=" do |val| super type[val] end
39+
define_method :"#{attr}?" do send attr end if type == Boolean
4540
end
4641

47-
def self.enum(attr, enum)
48-
enum = enum.dup.freeze
42+
Enum = ->(*enum) {
43+
enum = safe{enum}
4944
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
45+
safe{->val {
46+
return val if enum.include?(val)
47+
raise ArgumentError, "expected %s, got %p" % [expected, val]
48+
}}
49+
}
5750

5851
end
5952
end

0 commit comments

Comments
 (0)