diff --git a/lib/net/imap/data_lite.rb b/lib/net/imap/data_lite.rb
index 5b96c873..2fafb7c4 100644
--- a/lib/net/imap/data_lite.rb
+++ b/lib/net/imap/data_lite.rb
@@ -1,34 +1,14 @@
# frozen_string_literal: true
-# Some of the code in this file was copied from the polyfill-data gem.
-#
-# MIT License
-#
-# Copyright (c) 2023 Jim Gay, Joel Drapper, Nicholas Evans
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-
module Net
class IMAP
- data_or_object = RUBY_VERSION >= "3.2.0" ? ::Data : Object
- class DataLite < data_or_object
+ # DataLite subclasses ruby's +Data+ class and is aliased as Net::IMAP::Data,
+ # so that code using it won't need to be updated when it is removed. It
+ # adds support for yaml encoding. When psych adds support for Data,
+ # DataLite _will_ be removed.
+ #
+ # Previously, DataLite served as a reimplementation of +Data+ for ruby 3.1.
+ class DataLite < ::Data
def encode_with(coder) coder.map = to_h.transform_keys(&:to_s) end
def init_with(coder) initialize(**coder.map.transform_keys(&:to_sym)) end
end
@@ -36,191 +16,3 @@ def init_with(coder) initialize(**coder.map.transform_keys(&:to_sym)) end
Data = DataLite
end
end
-
-# :nocov:
-# Need to skip test coverage for the rest, because it isn't loaded by ruby 3.2+.
-return if RUBY_VERSION >= "3.2.0"
-
-module Net
- class IMAP
- # DataLite is a temporary substitute for ruby 3.2's +Data+ class. DataLite
- # is aliased as Net::IMAP::Data, so that code using it won't need to be
- # updated when it is removed.
- #
- # See {ruby 3.2's documentation for Data}[https://docs.ruby-lang.org/en/3.2/Data.html].
- #
- # [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}[https://rubygems.org/gems/polyfill-data], by Jim Gay
- # and Joel Drapper, under the MIT license terms.
- class DataLite
- singleton_class.undef_method :new
-
- TYPE_ERROR = "%p is not a symbol nor a string"
- ATTRSET_ERROR = "invalid data member: %p"
- DUP_ERROR = "duplicate member: %p"
- ARITY_ERROR = "wrong number of arguments (given %d, expected %s)"
- private_constant :TYPE_ERROR, :ATTRSET_ERROR, :DUP_ERROR, :ARITY_ERROR
-
- # Defines a new Data class.
- #
- # _NOTE:_ Unlike ruby 3.2's +Data.define+, DataLite.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.
- 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
-
- ##
- # singleton-method: new
- # call-seq:
- # new(*args) -> instance
- # new(**kwargs) -> instance
- #
- # Constuctor for classes defined with ::define.
- #
- # Aliased as ::[].
-
- ##
- # singleton-method: []
- # call-seq:
- # ::[](*args) -> instance
- # ::[](**kwargs) -> instance
- #
- # Constuctor for classes defined with ::define.
- #
- # Alias for ::new
-
- ##
- def members; self.class.members end
- def to_h(&block) block ? __to_h__.to_h(&block) : __to_h__ end
- def hash; [self.class, __to_h__].hash end
- def ==(other) self.class == other.class && to_h == other.to_h end
- def eql?(other) self.class == other.class && hash == other.hash end
- def deconstruct; __to_h__.values end
-
- def deconstruct_keys(keys)
- raise TypeError unless keys.is_a?(Array) || keys.nil?
- return __to_h__ if keys&.first.nil?
- __to_h__.slice(*keys)
- end
-
- def with(**kwargs)
- return self if kwargs.empty?
- self.class.new(**__to_h__.merge(kwargs))
- end
-
- def inspect
- __inspect_guard__(self) do |seen|
- return "#" if seen
- attrs = __to_h__.map {|kv| "%s=%p" % kv }.join(", ")
- display = ["data", self.class.name, attrs].compact.join(" ")
- "#<#{display}>"
- end
- end
- alias_method :to_s, :inspect
-
- private
-
- def initialize_copy(source) super.freeze end
- def marshal_dump; __to_h__ end
-
- def __to_h__; Hash[members.map {|m| [m, send(m)] }] end
-
- # 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.
- 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
-
- end
-
- end
-end
-# :nocov: