@@ -67,6 +67,8 @@ public class RubyEnumerator extends RubyObject {
6767
6868 /** Function object for lazily computing size (used for internally created enumerators) */
6969 private SizeFn sizeFn ;
70+
71+ private IRubyObject feedValue ;
7072
7173 public static void defineEnumerator (Ruby runtime ) {
7274 RubyModule enm = runtime .getClassFromPath ("Enumerable" );
@@ -255,14 +257,16 @@ private IRubyObject initialize(IRubyObject object, IRubyObject method, IRubyObje
255257 }
256258
257259 private IRubyObject initialize20 (IRubyObject object , IRubyObject method , IRubyObject [] methodArgs , IRubyObject size , SizeFn sizeFn ) {
260+ final Ruby runtime = getRuntime ();
258261 this .object = object ;
259262 this .method = method .asJavaString ();
260263 this .methodArgs = methodArgs ;
261264 this .size = size ;
262265 this .sizeFn = sizeFn ;
266+ this .feedValue = runtime .getNil ();
263267 setInstanceVariable ("@__object__" , object );
264268 setInstanceVariable ("@__method__" , method );
265- setInstanceVariable ("@__args__" , RubyArray .newArrayNoCopyLight (getRuntime () , methodArgs ));
269+ setInstanceVariable ("@__args__" , RubyArray .newArrayNoCopyLight (runtime , methodArgs ));
266270 return this ;
267271 }
268272
@@ -275,7 +279,8 @@ public IRubyObject dup() {
275279 copy .method = this .method ;
276280 copy .methodArgs = this .methodArgs ;
277281 copy .size = this .size ;
278- copy .sizeFn = this .sizeFn ;
282+ copy .sizeFn = this .sizeFn ;
283+ copy .feedValue = getRuntime ().getNil ();
279284 return copy ;
280285 }
281286
@@ -452,7 +457,7 @@ public IRubyObject with_index19(ThreadContext context, IRubyObject arg, final Bl
452457 @ JRubyMethod
453458 public synchronized IRubyObject next (ThreadContext context ) {
454459 ensureNexter (context );
455-
460+ if (! feedValue . isNil ()) feedValue = context . nil ;
456461 return nexter .next ();
457462 }
458463
@@ -485,10 +490,21 @@ public synchronized IRubyObject peekValues(ThreadContext context) {
485490 @ JRubyMethod (name = "next_values" )
486491 public synchronized IRubyObject nextValues (ThreadContext context ) {
487492 ensureNexter (context );
488-
493+ if (! feedValue . isNil ()) feedValue = context . nil ;
489494 return RubyArray .newArray (context .runtime , nexter .next ());
490495 }
491496
497+ @ JRubyMethod
498+ public IRubyObject feed (ThreadContext context , IRubyObject val ) {
499+ ensureNexter (context );
500+ if (!feedValue .isNil ()) {
501+ throw context .runtime .newTypeError ("feed value already set" );
502+ }
503+ feedValue = val ;
504+ nexter .setFeedValue (val );
505+ return context .nil ;
506+ }
507+
492508 private void ensureNexter (ThreadContext context ) {
493509 if (nexter == null ) {
494510 if (Options .ENUMERATOR_LIGHTWEIGHT .load ()) {
@@ -537,14 +553,24 @@ private static abstract class Nexter {
537553
538554 /** args to each method */
539555 protected final IRubyObject [] methodArgs ;
556+
557+ private IRubyObject feedValue ;
540558
541559 public Nexter (Ruby runtime , IRubyObject object , String method , IRubyObject [] methodArgs ) {
542560 this .object = object ;
543561 this .method = method ;
544562 this .methodArgs = methodArgs ;
545563 this .runtime = runtime ;
546564 }
547-
565+
566+ public void setFeedValue (IRubyObject feedValue ) {
567+ this .feedValue = feedValue ;
568+ }
569+
570+ public IRubyObject getFeedValue () {
571+ return feedValue ;
572+ }
573+
548574 public abstract IRubyObject next ();
549575
550576 public abstract void shutdown ();
@@ -616,8 +642,9 @@ private static class TerminateEnumeration extends RuntimeException implements Un
616642
617643 public ThreadedNexter (Ruby runtime , IRubyObject object , String method , IRubyObject [] methodArgs ) {
618644 super (runtime , object , method , methodArgs );
645+ setFeedValue (runtime .getNil ());
619646 }
620-
647+
621648 @ Override
622649 public synchronized IRubyObject next () {
623650 if (doneObject != null ) {
@@ -741,7 +768,9 @@ public IRubyObject call(ThreadContext context, IRubyObject[] args, Block block)
741768 throw terminateEnumeration ;
742769 }
743770
744- return context .nil ;
771+ IRubyObject feedValue = getFeedValue ();
772+ setFeedValue (context .nil );
773+ return feedValue ;
745774 }
746775 }, context ));
747776 } catch (TerminateEnumeration te ) {
0 commit comments