Class: Net::IMAP::DataLite
Relationships & Source Files | |
Inherits: | Object |
Defined in: | lib/net/imap/data_lite.rb, lib/net/imap/data_lite.rb |
Overview
DataLite
is a temporary substitute for ruby 3.2’s Data class. DataLite
is aliased as Data, so that code using it won’t need to be updated when it is removed.
See ruby 3.2’s documentation for Data.
- When running ruby 3.1
-
This class reimplements the API for ruby 3.2’s Data, and should be compatible for nearly all use-cases. This reimplementation will be removed in
net-imap
0.6, when support for ruby 3.1 is dropped.NOTE:
net-imap
no longer supports ruby versions prior to 3.1. - When running ruby >= 3.2
-
This class inherits from Data and only defines the methods needed for YAML serialization. This will be dropped when
psych
adds support for Data.
Some of the code in this class was copied or adapted from the polyfill-data gem, by Jim Gay and Joel Drapper, under the MIT license terms.
Constant Summary
-
ARITY_ERROR =
private
# File 'lib/net/imap/data_lite.rb', line 72"wrong number of arguments (given %d, expected %s)"
-
ATTRSET_ERROR =
private
# File 'lib/net/imap/data_lite.rb', line 70"invalid data member: %p"
-
DUP_ERROR =
private
# File 'lib/net/imap/data_lite.rb', line 71"duplicate member: %p"
-
TYPE_ERROR =
private
# File 'lib/net/imap/data_lite.rb', line 69"%p is not a symbol nor a string"
Class Method Summary
-
.define(*args, &block)
Defines a new Data class.
Instance Method Summary
- #==(other)
- #deconstruct
- #deconstruct_keys(keys)
- #encode_with(coder)
- #eql?(other) ⇒ Boolean
- #hash
- #init_with(coder)
- #inspect (also: #to_s)
- #members
- #to_h(&block)
-
#to_s
Alias for #inspect.
- #with(**kwargs)
-
#__inspect_guard__(obj)
private
Yields
true
ifobj
has been seen already,false
if it hasn’t. - #__to_h__ private
- #initialize_copy(source) private
- #marshal_dump private
Class Method Details
.define(*args, &block)
Defines a new Data class.
NOTE: Unlike ruby 3.2’s Data.define
, .define
only supports member names which are valid local variable names. Member names can’t be keywords (e.g: next
or class
) or start with capital letters, “@”, etc.
# File 'lib/net/imap/data_lite.rb', line 81
def self.define(*args, &block) members = args.each_with_object({}) do |arg, members| arg = arg.to_str unless arg in Symbol | String if arg.respond_to?(:to_str) arg = arg.to_sym if arg in String arg in Symbol or raise TypeError, TYPE_ERROR % [arg] arg in %r{=} and raise ArgumentError, ATTRSET_ERROR % [arg] members.key?(arg) and raise ArgumentError, DUP_ERROR % [arg] members[arg] = true end members = members.keys.freeze klass = ::Class.new(self) klass.singleton_class.undef_method :define klass.define_singleton_method(:members) { members } def klass.new(*args, **kwargs, &block) if kwargs.size.positive? if args.size.positive? raise ArgumentError, ARITY_ERROR % [args.size, 0] end elsif members.size < args.size expected = members.size.zero? ? 0 : 0..members.size raise ArgumentError, ARITY_ERROR % [args.size, expected] else kwargs = Hash[members.take(args.size).zip(args)] end allocate.tap do |instance| instance.__send__(:initialize, **kwargs, &block) end.freeze end klass.singleton_class.alias_method :[], :new klass.attr_reader(*members) # Dynamically defined initializer methods are in an included module, # rather than directly on DataLite (like in ruby 3.2+): # * simpler to handle required kwarg ArgumentErrors # * easier to ensure consistent ivar assignment order (object shape) # * faster than instance_variable_set klass.include(Module.new do if members.any? kwargs = members.map{"#{_1.name}:"}.join(", ") params = members.map(&:name).join(", ") ivars = members.map{"@#{_1.name}"}.join(", ") attrs = members.map{"attrs[:#{_1.name}]"}.join(", ") module_eval <<~RUBY, __FILE__, __LINE__ + 1 protected def initialize(#{kwargs}) #{ivars} = #{params}; freeze end def marshal_load(attrs) #{ivars} = #{attrs}; freeze end RUBY end end) klass.module_eval do _1.module_eval(&block) end if block_given? klass end
Instance Method Details
#==(other)
[ GitHub ]#__inspect_guard__(obj) (private)
Yields true
if obj
has been seen already, false
if it hasn’t. Marks obj
as seen inside the block, so circuler references don’t recursively trigger a SystemStackError (stack level too deep).
Making circular references inside a Data object should be very uncommon, but we’ll support them for the sake of completeness.
# File 'lib/net/imap/data_lite.rb', line 202
def __inspect_guard__(obj) preexisting = Thread.current[:__net_imap_data__inspect__] Thread.current[:__net_imap_data__inspect__] ||= {}.compare_by_identity inspect_guard = Thread.current[:__net_imap_data__inspect__] if inspect_guard.include?(obj) yield true else begin inspect_guard[obj] = true yield false ensure inspect_guard.delete(obj) end end ensure unless preexisting.equal?(inspect_guard) Thread.current[:__net_imap_data__inspect__] = preexisting end end
#__to_h__ (private)
[ GitHub ]# File 'lib/net/imap/data_lite.rb', line 194
def __to_h__; Hash[members.map {|m| [m, send(m)] }] end
#deconstruct
[ GitHub ]# File 'lib/net/imap/data_lite.rb', line 166
def deconstruct; __to_h__.values end
#deconstruct_keys(keys)
#encode_with(coder)
[ GitHub ]
#eql?(other) ⇒ Boolean
#hash
[ GitHub ]# File 'lib/net/imap/data_lite.rb', line 163
def hash; [self.class, __to_h__].hash end
#init_with(coder)
[ GitHub ]# File 'lib/net/imap/data_lite.rb', line 33
def init_with(coder) initialize(**coder.map.transform_keys(&:to_sym)) end
#initialize_copy(source) (private)
[ GitHub ]# File 'lib/net/imap/data_lite.rb', line 191
def initialize_copy(source) super.freeze end
#inspect Also known as: #to_s
[ GitHub ]# File 'lib/net/imap/data_lite.rb', line 179
def inspect __inspect_guard__(self) do |seen| return "#<data #{self.class}:...>" if seen attrs = __to_h__.map {|kv| "%s=%p" % kv }.join(", ") display = ["data", self.class.name, attrs].compact.join(" ") "#<#{display}>" end end
#marshal_dump (private)
[ GitHub ]# File 'lib/net/imap/data_lite.rb', line 192
def marshal_dump; __to_h__ end
#members
[ GitHub ]# File 'lib/net/imap/data_lite.rb', line 161
def members; self.class.members end
#to_h(&block)
[ GitHub ]#to_s
Alias for #inspect.
# File 'lib/net/imap/data_lite.rb', line 187
alias_method :to_s, :inspect