diff --git a/lib/json.rb b/lib/json.rb index 807488ff..ad605bb3 100644 --- a/lib/json.rb +++ b/lib/json.rb @@ -408,6 +408,7 @@ # - Complex: require 'json/add/complex' # - Date: require 'json/add/date' # - DateTime: require 'json/add/date_time' +# - Enumerator::ArithmeticSequence: require 'json/add/arithmetic_sequence' # - Exception: require 'json/add/exception' # - OpenStruct: require 'json/add/ostruct' # - Range: require 'json/add/range' diff --git a/lib/json/add/arithmetic_sequence.rb b/lib/json/add/arithmetic_sequence.rb new file mode 100644 index 00000000..784006fa --- /dev/null +++ b/lib/json/add/arithmetic_sequence.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require 'json' unless defined?(JSON::JSON_LOADED) && JSON::JSON_LOADED + +class Enumerator + class ArithmeticSequence + # See #as_json. + def self.json_create(object) + Range.new(*object.values_at('b', 'e', 'x')) % object['s'] + end + + # Methods Enumerator::ArithmeticSequence#as_json and + # +Enumerator::ArithmeticSequence.json_create+ can be used to serialize and + # deserialize an \ArithmeticSequence object. See Marshal[rdoc-ref:Marshal]. + # + # \Method Enumerator::ArithmeticSequence#as_json serializes +self+, + # returning a 5-element hash representing +self+: + # + # require 'json/add/arithmetic_sequence' + # + # x = 42.step(by: 3, to: 72).as_json + # # => {"json_class"=>"Enumerator::ArithmeticSequence", "b"=>42, "e"=>72, "x"=>false, "s"=>3} + # + # y = ((42...72) % 4).as_json + # # => {"json_class"=>"Enumerator::ArithmeticSequence", "b"=>42, "e"=>72, "x"=>true, "s"=>4} + # + # \Method +JSON.create+ deserializes such a hash, returning an + # \ArithmeticSequence object: + # + # Enumerator::ArithmeticSequence.json_create(x) # => ((42..72).%(3)) + # Enumerator::ArithmeticSequence.json_create(y) # => ((42...72).%(4)) + # + def as_json(*) + { + JSON.create_id => self.class.name, + 'b' => self.begin, + 'e' => self.end, + 'x' => exclude_end?, + 's' => step + } + end + + # Returns a JSON string representing +self+: + # + # require 'json/add/arithmetic_sequence' + # + # puts 42.step(by: 3, to: 72).to_json + # puts ((42...72) % 4).to_json + # + # Output: + # + # {"json_class":"Enumerator::ArithmeticSequence","b":42,"e":72,"x":false,"s":3} + # {"json_class":"Enumerator::ArithmeticSequence","b":42,"e":72,"x":true,"s":4} + # + def to_json(*args) + as_json.to_json(*args) + end + end +end diff --git a/tests/json_addition_test.rb b/tests/json_addition_test.rb index 3a7a5817..70cb8252 100644 --- a/tests/json_addition_test.rb +++ b/tests/json_addition_test.rb @@ -1,5 +1,6 @@ #frozen_string_literal: false require_relative 'test_helper' +require 'json/add/arithmetic_sequence' require 'json/add/core' require 'json/add/complex' require 'json/add/rational' @@ -196,4 +197,11 @@ def test_set s = Set.new([:a, :b, :c, :a]) assert_equal s, JSON.parse(JSON(s), :create_additions => true) end + + def test_arithmetic_sequence + include_end = 42.step(by: 3, to: 72) + assert_equal include_end, JSON.parse(JSON(include_end), :create_additions => true) + exclude_end = ((42...72) % 4) + assert_equal exclude_end, JSON.parse(JSON(exclude_end), :create_additions => true) + end end