diff options
Diffstat (limited to 'mrbgems/mruby-enum-chain')
| -rw-r--r-- | mrbgems/mruby-enum-chain/mrbgem.rake | 6 | ||||
| -rw-r--r-- | mrbgems/mruby-enum-chain/mrblib/chain.rb | 57 | ||||
| -rw-r--r-- | mrbgems/mruby-enum-chain/test/enum_chain.rb | 97 |
3 files changed, 160 insertions, 0 deletions
diff --git a/mrbgems/mruby-enum-chain/mrbgem.rake b/mrbgems/mruby-enum-chain/mrbgem.rake new file mode 100644 index 000000000..7294f2644 --- /dev/null +++ b/mrbgems/mruby-enum-chain/mrbgem.rake @@ -0,0 +1,6 @@ +MRuby::Gem::Specification.new('mruby-enum-chain') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'Enumerator::Chain class' + spec.add_dependency('mruby-enumerator', :core => 'mruby-enumerator') +end diff --git a/mrbgems/mruby-enum-chain/mrblib/chain.rb b/mrbgems/mruby-enum-chain/mrblib/chain.rb new file mode 100644 index 000000000..55474eb92 --- /dev/null +++ b/mrbgems/mruby-enum-chain/mrblib/chain.rb @@ -0,0 +1,57 @@ +## +# chain.rb Enumerator::Chain class +# See Copyright Notice in mruby.h + +module Enumerable + def chain(*args) + Enumerator::Chain.new(self, *args) + end +end + +class Enumerator + def +(other) + Chain.new(self, other) + end + + class Chain + include Enumerable + + def initialize(*args) + @enums = args + end + + def each(&block) + return to_enum unless block_given? + + @enums.each { |e| e.each(&block) } + + self + end + + def size + @enums.reduce(0) do |a, e| + return nil unless e.respond_to?(:size) + a + e.size + end + end + + def rewind + i = @enums.size - 1 + while 0 <= i + e = @enums[i] + e.rewind if e.respond_to?(:rewind) + i -= 1 + end + + self + end + + def +(other) + self.class.new(self, other) + end + + def inspect + "#<#{self.class}: #{@enums.inspect}>" + end + end +end diff --git a/mrbgems/mruby-enum-chain/test/enum_chain.rb b/mrbgems/mruby-enum-chain/test/enum_chain.rb new file mode 100644 index 000000000..1d3d691ca --- /dev/null +++ b/mrbgems/mruby-enum-chain/test/enum_chain.rb @@ -0,0 +1,97 @@ +## +# Enumerator::Chain test + +assert("Enumerable#chain") do + a = [] + b = {} + c = Object.new # not has #each method + + assert_kind_of Enumerator::Chain, a.chain + assert_kind_of Enumerator::Chain, a.chain(b) + assert_kind_of Enumerator::Chain, a.chain(b, c) + assert_raise(NoMethodError) { c.chain } +end + +assert("Enumerator#+") do + a = [].each + b = {}.each + c = Object.new # not has #each method + + assert_kind_of Enumerator::Chain, a + b + assert_kind_of Enumerator::Chain, a + c + assert_kind_of Enumerator::Chain, b + a + assert_kind_of Enumerator::Chain, b + c + assert_raise(NoMethodError) { c + a } +end + +assert("Enumerator::Chain.new") do + a = [] + b = {} + c = Object.new # not has #each method + + assert_kind_of Enumerator::Chain, Enumerator::Chain.new + assert_kind_of Enumerator::Chain, Enumerator::Chain.new(a, a) + assert_kind_of Enumerator::Chain, Enumerator::Chain.new(a, b) + assert_kind_of Enumerator::Chain, Enumerator::Chain.new(a, c) + assert_kind_of Enumerator::Chain, Enumerator::Chain.new(b, a) + assert_kind_of Enumerator::Chain, Enumerator::Chain.new(b, b) + assert_kind_of Enumerator::Chain, Enumerator::Chain.new(b, c) + assert_kind_of Enumerator::Chain, Enumerator::Chain.new(c, a) +end + +assert("Enumerator::Chain#each") do + a = [1, 2, 3] + + aa = a.chain(a) + assert_kind_of Enumerator, aa.each + assert_equal [1, 2, 3, 1, 2, 3], aa.each.to_a + + aa = a.chain(6..9) + assert_kind_of Enumerator, aa.each + assert_equal [1, 2, 3, 6, 7, 8, 9], aa.each.to_a + + aa = a.chain((-3..-2).each_with_index, a) + assert_kind_of Enumerator, aa.each + assert_equal [1, 2, 3, [-3, 0], [-2, 1], 1, 2, 3], aa.each.to_a + + aa = a.chain(Object.new) + assert_kind_of Enumerator, aa.each + assert_raise(NoMethodError) { aa.each.to_a } +end + +assert("Enumerator::Chain#size") do + a = [1, 2, 3] + + aa = a.chain(a) + assert_equal 6, aa.size + + aa = a.chain(3..4) + assert_nil aa.size + + aa = a.chain(3..4, a) + assert_nil aa.size + + aa = a.chain(Object.new) + assert_nil aa.size +end + +assert("Enumerator::Chain#rewind") do + rewound = [] + e1 = [1, 2] + e2 = (4..6) + (class << e1; self end).define_method(:rewind) { rewound << __id__ } + (class << e2; self end).define_method(:rewind) { rewound << __id__ } + c = e1.chain(e2).each{}.rewind + assert_equal [e2.__id__, e1.__id__], rewound +end + +assert("Enumerator::Chain#+") do + a = [].chain + b = {}.chain + c = Object.new # not has #each method + + assert_kind_of Enumerator::Chain, a + b + assert_kind_of Enumerator::Chain, a + c + assert_kind_of Enumerator::Chain, b + a + assert_kind_of Enumerator::Chain, b + c +end |
