1ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin/*
2ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
5ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * This code is free software; you can redistribute it and/or modify it
6ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * under the terms of the GNU General Public License version 2 only, as
7ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * published by the Free Software Foundation.  Oracle designates this
8ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * particular file as subject to the "Classpath" exception as provided
9ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * by Oracle in the LICENSE file that accompanied this code.
10ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
11ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * This code is distributed in the hope that it will be useful, but WITHOUT
12ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * version 2 for more details (a copy is included in the LICENSE file that
15ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * accompanied this code).
16ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
17ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * You should have received a copy of the GNU General Public License version
18ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * 2 along with this work; if not, write to the Free Software Foundation,
19ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
21ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * or visit www.oracle.com if you need additional information or have any
23ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * questions.
24ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin */
25ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinpackage java.util.stream;
26ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
27ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.Comparator;
28ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.Objects;
29ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.Spliterator;
30ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.concurrent.ConcurrentHashMap;
31ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.concurrent.atomic.AtomicLong;
32ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.BooleanSupplier;
33ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.Consumer;
34ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.DoubleConsumer;
35ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.DoubleSupplier;
36ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.IntConsumer;
37ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.IntSupplier;
38ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.LongConsumer;
39ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.LongSupplier;
40ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.Supplier;
41ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
42ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin/**
43ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * Spliterator implementations for wrapping and delegating spliterators, used
44ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * in the implementation of the {@link Stream#spliterator()} method.
45ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
46ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * @since 1.8
47ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin */
48ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinclass StreamSpliterators {
49ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
50ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
51ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Abstract wrapping spliterator that binds to the spliterator of a
52ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * pipeline helper on first operation.
53ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
54ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>This spliterator is not late-binding and will bind to the source
55ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * spliterator when first operated on.
56ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
57ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>A wrapping spliterator produced from a sequential stream
58ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * cannot be split if there are stateful operations present.
59ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
60ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static abstract class AbstractWrappingSpliterator<P_IN, P_OUT,
61ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              T_BUFFER extends AbstractSpinedBuffer>
62ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Spliterator<P_OUT> {
63ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
64ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // @@@ Detect if stateful operations are present or not
65ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        //     If not then can split otherwise cannot
66ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
67ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
68ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * True if this spliterator supports splitting
69ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
70ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        final boolean isParallel;
71ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
72ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        final PipelineHelper<P_OUT> ph;
73ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
74ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
75ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * Supplier for the source spliterator.  Client provides either a
76ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * spliterator or a supplier.
77ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
78ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private Supplier<Spliterator<P_IN>> spliteratorSupplier;
79ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
80ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
81ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * Source spliterator.  Either provided from client or obtained from
82ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * supplier.
83ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
84ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        Spliterator<P_IN> spliterator;
85ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
86ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
87ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * Sink chain for the downstream stages of the pipeline, ultimately
88ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * leading to the buffer. Used during partial traversal.
89ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
90ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        Sink<P_IN> bufferSink;
91ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
92ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
93ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * A function that advances one element of the spliterator, pushing
94ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * it to bufferSink.  Returns whether any elements were processed.
95ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * Used during partial traversal.
96ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
97ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        BooleanSupplier pusher;
98ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
99ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /** Next element to consume from the buffer, used during partial traversal */
100ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        long nextToConsume;
101ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
102ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /** Buffer into which elements are pushed.  Used during partial traversal. */
103ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        T_BUFFER buffer;
104ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
105ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
106ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * True if full traversal has occurred (with possible cancelation).
107ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * If doing a partial traversal, there may be still elements in buffer.
108ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
109ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        boolean finished;
110ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
111ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
112ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * Construct an AbstractWrappingSpliterator from a
113ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * {@code Supplier<Spliterator>}.
114ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
115ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        AbstractWrappingSpliterator(PipelineHelper<P_OUT> ph,
116ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                    Supplier<Spliterator<P_IN>> spliteratorSupplier,
117ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                    boolean parallel) {
118ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.ph = ph;
119ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.spliteratorSupplier = spliteratorSupplier;
120ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.spliterator = null;
121ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.isParallel = parallel;
122ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
123ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
124ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
125ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * Construct an AbstractWrappingSpliterator from a
126ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * {@code Spliterator}.
127ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
128ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        AbstractWrappingSpliterator(PipelineHelper<P_OUT> ph,
129ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                    Spliterator<P_IN> spliterator,
130ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                    boolean parallel) {
131ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.ph = ph;
132ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.spliteratorSupplier = null;
133ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.spliterator = spliterator;
134ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.isParallel = parallel;
135ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
136ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
137ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
138ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * Called before advancing to set up spliterator, if needed.
139ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
140ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        final void init() {
141ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (spliterator == null) {
142ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                spliterator = spliteratorSupplier.get();
143ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                spliteratorSupplier = null;
144ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
145ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
146ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
147ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
148ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * Get an element from the source, pushing it into the sink chain,
149ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * setting up the buffer if needed
150ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * @return whether there are elements to consume from the buffer
151ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
152ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        final boolean doAdvance() {
153ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (buffer == null) {
154ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (finished)
155ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return false;
156ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
157ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                init();
158ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                initPartialTraversalState();
159ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                nextToConsume = 0;
160ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                bufferSink.begin(spliterator.getExactSizeIfKnown());
161ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return fillBuffer();
162ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
163ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            else {
164ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                ++nextToConsume;
165ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                boolean hasNext = nextToConsume < buffer.count();
166ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (!hasNext) {
167ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    nextToConsume = 0;
168ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    buffer.clear();
169ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    hasNext = fillBuffer();
170ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
171ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return hasNext;
172ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
173ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
174ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
175ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
176ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * Invokes the shape-specific constructor with the provided arguments
177ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * and returns the result.
178ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
179ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        abstract AbstractWrappingSpliterator<P_IN, P_OUT, ?> wrap(Spliterator<P_IN> s);
180ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
181ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
182ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * Initializes buffer, sink chain, and pusher for a shape-specific
183ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * implementation.
184ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
185ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        abstract void initPartialTraversalState();
186ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
187ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
188ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Spliterator<P_OUT> trySplit() {
189ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (isParallel && !finished) {
190ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                init();
191ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
192ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Spliterator<P_IN> split = spliterator.trySplit();
193ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return (split == null) ? null : wrap(split);
194ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
195ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            else
196ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return null;
197ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
198ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
199ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
200ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * If the buffer is empty, push elements into the sink chain until
201ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * the source is empty or cancellation is requested.
202ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * @return whether there are elements to consume from the buffer
203ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
204ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private boolean fillBuffer() {
205ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            while (buffer.count() == 0) {
206ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (bufferSink.cancellationRequested() || !pusher.getAsBoolean()) {
207ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    if (finished)
208ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        return false;
209ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    else {
210ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        bufferSink.end(); // might trigger more elements
211ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        finished = true;
212ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
213ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
214ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
215ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return true;
216ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
217ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
218ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
219ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public final long estimateSize() {
220ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            init();
221ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // Use the estimate of the wrapped spliterator
222ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // Note this may not be accurate if there are filter/flatMap
223ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // operations filtering or adding elements to the stream
224ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return spliterator.estimateSize();
225ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
226ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
227ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
228ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public final long getExactSizeIfKnown() {
229ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            init();
230ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return StreamOpFlag.SIZED.isKnown(ph.getStreamAndOpFlags())
231ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                   ? spliterator.getExactSizeIfKnown()
232ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                   : -1;
233ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
234ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
235ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
236ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public final int characteristics() {
237ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            init();
238ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
239ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // Get the characteristics from the pipeline
240ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            int c = StreamOpFlag.toCharacteristics(StreamOpFlag.toStreamFlags(ph.getStreamAndOpFlags()));
241ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
242ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // Mask off the size and uniform characteristics and replace with
243ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // those of the spliterator
244ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // Note that a non-uniform spliterator can change from something
245ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // with an exact size to an estimate for a sub-split, for example
246ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // with HashSet where the size is known at the top level spliterator
247ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // but for sub-splits only an estimate is known
248ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if ((c & Spliterator.SIZED) != 0) {
249ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                c &= ~(Spliterator.SIZED | Spliterator.SUBSIZED);
250ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                c |= (spliterator.characteristics() & (Spliterator.SIZED | Spliterator.SUBSIZED));
251ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
252ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
253ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return c;
254ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
255ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
256ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
257ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Comparator<? super P_OUT> getComparator() {
258ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (!hasCharacteristics(SORTED))
259ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException();
260ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return null;
261ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
262ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
263ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
264ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public final String toString() {
265ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return String.format("%s[%s]", getClass().getName(), spliterator);
266ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
267ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
268ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
269ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static final class WrappingSpliterator<P_IN, P_OUT>
270ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends AbstractWrappingSpliterator<P_IN, P_OUT, SpinedBuffer<P_OUT>> {
271ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
272ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        WrappingSpliterator(PipelineHelper<P_OUT> ph,
273ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            Supplier<Spliterator<P_IN>> supplier,
274ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            boolean parallel) {
275ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(ph, supplier, parallel);
276ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
277ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
278ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        WrappingSpliterator(PipelineHelper<P_OUT> ph,
279ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            Spliterator<P_IN> spliterator,
280ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            boolean parallel) {
281ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(ph, spliterator, parallel);
282ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
283ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
284ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
285ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        WrappingSpliterator<P_IN, P_OUT> wrap(Spliterator<P_IN> s) {
286ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return new WrappingSpliterator<>(ph, s, isParallel);
287ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
288ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
289ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
290ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        void initPartialTraversalState() {
291ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            SpinedBuffer<P_OUT> b = new SpinedBuffer<>();
292ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            buffer = b;
293ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            bufferSink = ph.wrapSink(b::accept);
294ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            pusher = () -> spliterator.tryAdvance(bufferSink);
295ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
296ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
297ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
298ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public boolean tryAdvance(Consumer<? super P_OUT> consumer) {
299ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            Objects.requireNonNull(consumer);
300ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            boolean hasNext = doAdvance();
301ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (hasNext)
302ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                consumer.accept(buffer.get(nextToConsume));
303ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return hasNext;
304ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
305ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
306ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
307ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEachRemaining(Consumer<? super P_OUT> consumer) {
308ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (buffer == null && !finished) {
309ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(consumer);
310ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                init();
311ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
312ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                ph.wrapAndCopyInto((Sink<P_OUT>) consumer::accept, spliterator);
313ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                finished = true;
314ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
315ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            else {
316ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                do { } while (tryAdvance(consumer));
317ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
318ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
319ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
320ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
321ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static final class IntWrappingSpliterator<P_IN>
322ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends AbstractWrappingSpliterator<P_IN, Integer, SpinedBuffer.OfInt>
323ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Spliterator.OfInt {
324ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
325ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        IntWrappingSpliterator(PipelineHelper<Integer> ph,
326ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                               Supplier<Spliterator<P_IN>> supplier,
327ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                               boolean parallel) {
328ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(ph, supplier, parallel);
329ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
330ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
331ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        IntWrappingSpliterator(PipelineHelper<Integer> ph,
332ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                               Spliterator<P_IN> spliterator,
333ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                               boolean parallel) {
334ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(ph, spliterator, parallel);
335ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
336ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
337ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
338ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        AbstractWrappingSpliterator<P_IN, Integer, ?> wrap(Spliterator<P_IN> s) {
339ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return new IntWrappingSpliterator<>(ph, s, isParallel);
340ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
341ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
342ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
343ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        void initPartialTraversalState() {
344ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            SpinedBuffer.OfInt b = new SpinedBuffer.OfInt();
345ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            buffer = b;
346ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            bufferSink = ph.wrapSink((Sink.OfInt) b::accept);
347ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            pusher = () -> spliterator.tryAdvance(bufferSink);
348ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
349ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
350ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
351ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Spliterator.OfInt trySplit() {
352ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return (Spliterator.OfInt) super.trySplit();
353ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
354ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
355ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
356ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public boolean tryAdvance(IntConsumer consumer) {
357ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            Objects.requireNonNull(consumer);
358ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            boolean hasNext = doAdvance();
359ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (hasNext)
360ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                consumer.accept(buffer.get(nextToConsume));
361ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return hasNext;
362ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
363ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
364ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
365ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEachRemaining(IntConsumer consumer) {
366ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (buffer == null && !finished) {
367ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(consumer);
368ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                init();
369ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
370ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                ph.wrapAndCopyInto((Sink.OfInt) consumer::accept, spliterator);
371ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                finished = true;
372ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
373ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            else {
374ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                do { } while (tryAdvance(consumer));
375ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
376ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
377ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
378ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
379ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static final class LongWrappingSpliterator<P_IN>
380ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends AbstractWrappingSpliterator<P_IN, Long, SpinedBuffer.OfLong>
381ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Spliterator.OfLong {
382ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
383ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        LongWrappingSpliterator(PipelineHelper<Long> ph,
384ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                Supplier<Spliterator<P_IN>> supplier,
385ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                boolean parallel) {
386ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(ph, supplier, parallel);
387ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
388ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
389ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        LongWrappingSpliterator(PipelineHelper<Long> ph,
390ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                Spliterator<P_IN> spliterator,
391ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                boolean parallel) {
392ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(ph, spliterator, parallel);
393ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
394ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
395ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
396ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        AbstractWrappingSpliterator<P_IN, Long, ?> wrap(Spliterator<P_IN> s) {
397ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return new LongWrappingSpliterator<>(ph, s, isParallel);
398ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
399ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
400ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
401ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        void initPartialTraversalState() {
402ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            SpinedBuffer.OfLong b = new SpinedBuffer.OfLong();
403ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            buffer = b;
404ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            bufferSink = ph.wrapSink((Sink.OfLong) b::accept);
405ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            pusher = () -> spliterator.tryAdvance(bufferSink);
406ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
407ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
408ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
409ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Spliterator.OfLong trySplit() {
410ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return (Spliterator.OfLong) super.trySplit();
411ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
412ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
413ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
414ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public boolean tryAdvance(LongConsumer consumer) {
415ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            Objects.requireNonNull(consumer);
416ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            boolean hasNext = doAdvance();
417ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (hasNext)
418ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                consumer.accept(buffer.get(nextToConsume));
419ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return hasNext;
420ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
421ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
422ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
423ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEachRemaining(LongConsumer consumer) {
424ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (buffer == null && !finished) {
425ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(consumer);
426ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                init();
427ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
428ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                ph.wrapAndCopyInto((Sink.OfLong) consumer::accept, spliterator);
429ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                finished = true;
430ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
431ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            else {
432ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                do { } while (tryAdvance(consumer));
433ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
434ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
435ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
436ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
437ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static final class DoubleWrappingSpliterator<P_IN>
438ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends AbstractWrappingSpliterator<P_IN, Double, SpinedBuffer.OfDouble>
439ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Spliterator.OfDouble {
440ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
441ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        DoubleWrappingSpliterator(PipelineHelper<Double> ph,
442ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                  Supplier<Spliterator<P_IN>> supplier,
443ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                  boolean parallel) {
444ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(ph, supplier, parallel);
445ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
446ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
447ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        DoubleWrappingSpliterator(PipelineHelper<Double> ph,
448ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                  Spliterator<P_IN> spliterator,
449ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                  boolean parallel) {
450ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(ph, spliterator, parallel);
451ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
452ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
453ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
454ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        AbstractWrappingSpliterator<P_IN, Double, ?> wrap(Spliterator<P_IN> s) {
455ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return new DoubleWrappingSpliterator<>(ph, s, isParallel);
456ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
457ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
458ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
459ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        void initPartialTraversalState() {
460ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            SpinedBuffer.OfDouble b = new SpinedBuffer.OfDouble();
461ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            buffer = b;
462ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            bufferSink = ph.wrapSink((Sink.OfDouble) b::accept);
463ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            pusher = () -> spliterator.tryAdvance(bufferSink);
464ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
465ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
466ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
467ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Spliterator.OfDouble trySplit() {
468ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return (Spliterator.OfDouble) super.trySplit();
469ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
470ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
471ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
472ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public boolean tryAdvance(DoubleConsumer consumer) {
473ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            Objects.requireNonNull(consumer);
474ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            boolean hasNext = doAdvance();
475ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (hasNext)
476ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                consumer.accept(buffer.get(nextToConsume));
477ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return hasNext;
478ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
479ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
480ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
481ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEachRemaining(DoubleConsumer consumer) {
482ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (buffer == null && !finished) {
483ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(consumer);
484ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                init();
485ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
486ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                ph.wrapAndCopyInto((Sink.OfDouble) consumer::accept, spliterator);
487ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                finished = true;
488ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
489ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            else {
490ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                do { } while (tryAdvance(consumer));
491ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
492ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
493ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
494ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
495ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
496ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Spliterator implementation that delegates to an underlying spliterator,
497ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * acquiring the spliterator from a {@code Supplier<Spliterator>} on the
498ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * first call to any spliterator method.
499ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param <T>
500ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
501ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static class DelegatingSpliterator<T, T_SPLITR extends Spliterator<T>>
502ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Spliterator<T> {
503ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private final Supplier<? extends T_SPLITR> supplier;
504ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
505ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private T_SPLITR s;
506ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
507ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        DelegatingSpliterator(Supplier<? extends T_SPLITR> supplier) {
508ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.supplier = supplier;
509ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
510ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
511ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        T_SPLITR get() {
512ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (s == null) {
513ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                s = supplier.get();
514ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
515ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return s;
516ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
517ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
518ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
519ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("unchecked")
520ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public T_SPLITR trySplit() {
521ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return (T_SPLITR) get().trySplit();
522ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
523ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
524ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
525ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public boolean tryAdvance(Consumer<? super T> consumer) {
526ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return get().tryAdvance(consumer);
527ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
528ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
529ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
530ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEachRemaining(Consumer<? super T> consumer) {
531ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            get().forEachRemaining(consumer);
532ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
533ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
534ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
535ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public long estimateSize() {
536ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return get().estimateSize();
537ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
538ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
539ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
540ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public int characteristics() {
541ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return get().characteristics();
542ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
543ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
544ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
545ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Comparator<? super T> getComparator() {
546ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return get().getComparator();
547ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
548ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
549ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
550ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public long getExactSizeIfKnown() {
551ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return get().getExactSizeIfKnown();
552ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
553ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
554ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
555ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public String toString() {
556ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return getClass().getName() + "[" + get() + "]";
557ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
558ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
559ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static class OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
560ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends DelegatingSpliterator<T, T_SPLITR>
561ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Spliterator.OfPrimitive<T, T_CONS, T_SPLITR> {
562ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfPrimitive(Supplier<? extends T_SPLITR> supplier) {
563ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(supplier);
564ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
565ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
566ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
567ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public boolean tryAdvance(T_CONS consumer) {
568ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return get().tryAdvance(consumer);
569ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
570ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
571ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
572ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void forEachRemaining(T_CONS consumer) {
573ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                get().forEachRemaining(consumer);
574ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
575ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
576ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
577ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfInt
578ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends OfPrimitive<Integer, IntConsumer, Spliterator.OfInt>
579ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfInt {
580ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
581ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfInt(Supplier<Spliterator.OfInt> supplier) {
582ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(supplier);
583ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
584ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
585ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
586ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfLong
587ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends OfPrimitive<Long, LongConsumer, Spliterator.OfLong>
588ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfLong {
589ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
590ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfLong(Supplier<Spliterator.OfLong> supplier) {
591ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(supplier);
592ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
593ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
594ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
595ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfDouble
596ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends OfPrimitive<Double, DoubleConsumer, Spliterator.OfDouble>
597ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfDouble {
598ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
599ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfDouble(Supplier<Spliterator.OfDouble> supplier) {
600ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(supplier);
601ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
602ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
603ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
604ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
605ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
606ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A slice Spliterator from a source Spliterator that reports
607ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * {@code SUBSIZED}.
608ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
609ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
610ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static abstract class SliceSpliterator<T, T_SPLITR extends Spliterator<T>> {
611ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // The start index of the slice
612ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        final long sliceOrigin;
613ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // One past the last index of the slice
614ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        final long sliceFence;
615ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
616ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // The spliterator to slice
617ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        T_SPLITR s;
618ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // current (absolute) index, modified on advance/split
619ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        long index;
620ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // one past last (absolute) index or sliceFence, which ever is smaller
621ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        long fence;
622ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
623ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        SliceSpliterator(T_SPLITR s, long sliceOrigin, long sliceFence, long origin, long fence) {
624ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert s.hasCharacteristics(Spliterator.SUBSIZED);
625ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.s = s;
626ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.sliceOrigin = sliceOrigin;
627ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.sliceFence = sliceFence;
628ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.index = origin;
629ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.fence = fence;
630ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
631ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
632ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected abstract T_SPLITR makeSpliterator(T_SPLITR s, long sliceOrigin, long sliceFence, long origin, long fence);
633ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
634ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public T_SPLITR trySplit() {
635ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (sliceOrigin >= fence)
636ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return null;
637ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
638ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (index >= fence)
639ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return null;
640ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
641ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // Keep splitting until the left and right splits intersect with the slice
642ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // thereby ensuring the size estimate decreases.
643ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // This also avoids creating empty spliterators which can result in
644ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // existing and additionally created F/J tasks that perform
645ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // redundant work on no elements.
646ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            while (true) {
647ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                @SuppressWarnings("unchecked")
648ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                T_SPLITR leftSplit = (T_SPLITR) s.trySplit();
649ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (leftSplit == null)
650ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return null;
651ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
652ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                long leftSplitFenceUnbounded = index + leftSplit.estimateSize();
653ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                long leftSplitFence = Math.min(leftSplitFenceUnbounded, sliceFence);
654ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (sliceOrigin >= leftSplitFence) {
655ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // The left split does not intersect with, and is to the left of, the slice
656ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // The right split does intersect
657ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // Discard the left split and split further with the right split
658ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    index = leftSplitFence;
659ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
660ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                else if (leftSplitFence >= sliceFence) {
661ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // The right split does not intersect with, and is to the right of, the slice
662ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // The left split does intersect
663ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // Discard the right split and split further with the left split
664ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    s = leftSplit;
665ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    fence = leftSplitFence;
666ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
667ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                else if (index >= sliceOrigin && leftSplitFenceUnbounded <= sliceFence) {
668ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // The left split is contained within the slice, return the underlying left split
669ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // Right split is contained within or intersects with the slice
670ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    index = leftSplitFence;
671ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return leftSplit;
672ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                } else {
673ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // The left split intersects with the slice
674ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // Right split is contained within or intersects with the slice
675ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return makeSpliterator(leftSplit, sliceOrigin, sliceFence, index, index = leftSplitFence);
676ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
677ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
678ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
679ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
680ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public long estimateSize() {
681ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return (sliceOrigin < fence)
682ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                   ? fence - Math.max(sliceOrigin, index) : 0;
683ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
684ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
685ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public int characteristics() {
686ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return s.characteristics();
687ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
688ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
689ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfRef<T>
690ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends SliceSpliterator<T, Spliterator<T>>
691ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator<T> {
692ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
693ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfRef(Spliterator<T> s, long sliceOrigin, long sliceFence) {
694ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this(s, sliceOrigin, sliceFence, 0, Math.min(s.estimateSize(), sliceFence));
695ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
696ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
697ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private OfRef(Spliterator<T> s,
698ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                          long sliceOrigin, long sliceFence, long origin, long fence) {
699ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, sliceOrigin, sliceFence, origin, fence);
700ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
701ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
702ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
703ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected Spliterator<T> makeSpliterator(Spliterator<T> s,
704ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                     long sliceOrigin, long sliceFence,
705ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                     long origin, long fence) {
706ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new OfRef<>(s, sliceOrigin, sliceFence, origin, fence);
707ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
708ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
709ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
710ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public boolean tryAdvance(Consumer<? super T> action) {
711ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(action);
712ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
713ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (sliceOrigin >= fence)
714ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return false;
715ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
716ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                while (sliceOrigin > index) {
717ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    s.tryAdvance(e -> {});
718ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    index++;
719ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
720ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
721ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (index >= fence)
722ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return false;
723ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
724ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                index++;
725ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return s.tryAdvance(action);
726ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
727ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
728ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
729ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void forEachRemaining(Consumer<? super T> action) {
730ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(action);
731ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
732ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (sliceOrigin >= fence)
733ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return;
734ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
735ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (index >= fence)
736ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return;
737ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
738ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (index >= sliceOrigin && (index + s.estimateSize()) <= sliceFence) {
739ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // The spliterator is contained within the slice
740ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    s.forEachRemaining(action);
741ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    index = fence;
742ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                } else {
743ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // The spliterator intersects with the slice
744ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    while (sliceOrigin > index) {
745ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        s.tryAdvance(e -> {});
746ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        index++;
747ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
748ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // Traverse elements up to the fence
749ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    for (;index < fence; index++) {
750ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        s.tryAdvance(action);
751ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
752ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
753ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
754ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
755ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
756ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static abstract class OfPrimitive<T,
757ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>,
758ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                T_CONS>
759ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends SliceSpliterator<T, T_SPLITR>
760ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfPrimitive<T, T_CONS, T_SPLITR> {
761ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
762ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfPrimitive(T_SPLITR s, long sliceOrigin, long sliceFence) {
763ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this(s, sliceOrigin, sliceFence, 0, Math.min(s.estimateSize(), sliceFence));
764ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
765ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
766ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private OfPrimitive(T_SPLITR s,
767ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                long sliceOrigin, long sliceFence, long origin, long fence) {
768ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, sliceOrigin, sliceFence, origin, fence);
769ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
770ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
771ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
772ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public boolean tryAdvance(T_CONS action) {
773ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(action);
774ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
775ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (sliceOrigin >= fence)
776ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return false;
777ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
778ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                while (sliceOrigin > index) {
779ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    s.tryAdvance(emptyConsumer());
780ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    index++;
781ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
782ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
783ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (index >= fence)
784ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return false;
785ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
786ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                index++;
787ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return s.tryAdvance(action);
788ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
789ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
790ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
791ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void forEachRemaining(T_CONS action) {
792ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(action);
793ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
794ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (sliceOrigin >= fence)
795ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return;
796ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
797ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (index >= fence)
798ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return;
799ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
800ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (index >= sliceOrigin && (index + s.estimateSize()) <= sliceFence) {
801ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // The spliterator is contained within the slice
802ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    s.forEachRemaining(action);
803ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    index = fence;
804ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                } else {
805ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // The spliterator intersects with the slice
806ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    while (sliceOrigin > index) {
807ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        s.tryAdvance(emptyConsumer());
808ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        index++;
809ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
810ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // Traverse elements up to the fence
811ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    for (;index < fence; index++) {
812ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        s.tryAdvance(action);
813ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
814ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
815ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
816ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
817ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected abstract T_CONS emptyConsumer();
818ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
819ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
820ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfInt extends OfPrimitive<Integer, Spliterator.OfInt, IntConsumer>
821ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfInt {
822ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfInt(Spliterator.OfInt s, long sliceOrigin, long sliceFence) {
823ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, sliceOrigin, sliceFence);
824ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
825ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
826ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfInt(Spliterator.OfInt s,
827ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                  long sliceOrigin, long sliceFence, long origin, long fence) {
828ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, sliceOrigin, sliceFence, origin, fence);
829ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
830ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
831ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
832ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected Spliterator.OfInt makeSpliterator(Spliterator.OfInt s,
833ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                        long sliceOrigin, long sliceFence,
834ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                        long origin, long fence) {
835ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new SliceSpliterator.OfInt(s, sliceOrigin, sliceFence, origin, fence);
836ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
837ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
838ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
839ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected IntConsumer emptyConsumer() {
840ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return e -> {};
841ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
842ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
843ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
844ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfLong extends OfPrimitive<Long, Spliterator.OfLong, LongConsumer>
845ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfLong {
846ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfLong(Spliterator.OfLong s, long sliceOrigin, long sliceFence) {
847ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, sliceOrigin, sliceFence);
848ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
849ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
850ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfLong(Spliterator.OfLong s,
851ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                   long sliceOrigin, long sliceFence, long origin, long fence) {
852ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, sliceOrigin, sliceFence, origin, fence);
853ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
854ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
855ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
856ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected Spliterator.OfLong makeSpliterator(Spliterator.OfLong s,
857ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                         long sliceOrigin, long sliceFence,
858ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                         long origin, long fence) {
859ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new SliceSpliterator.OfLong(s, sliceOrigin, sliceFence, origin, fence);
860ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
861ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
862ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
863ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected LongConsumer emptyConsumer() {
864ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return e -> {};
865ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
866ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
867ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
868ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfDouble extends OfPrimitive<Double, Spliterator.OfDouble, DoubleConsumer>
869ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfDouble {
870ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfDouble(Spliterator.OfDouble s, long sliceOrigin, long sliceFence) {
871ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, sliceOrigin, sliceFence);
872ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
873ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
874ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfDouble(Spliterator.OfDouble s,
875ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                     long sliceOrigin, long sliceFence, long origin, long fence) {
876ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, sliceOrigin, sliceFence, origin, fence);
877ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
878ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
879ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
880ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected Spliterator.OfDouble makeSpliterator(Spliterator.OfDouble s,
881ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                           long sliceOrigin, long sliceFence,
882ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                           long origin, long fence) {
883ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new SliceSpliterator.OfDouble(s, sliceOrigin, sliceFence, origin, fence);
884ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
885ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
886ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
887ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected DoubleConsumer emptyConsumer() {
888ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return e -> {};
889ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
890ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
891ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
892ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
893ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
894ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A slice Spliterator that does not preserve order, if any, of a source
895ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Spliterator.
896ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
897ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Note: The source spliterator may report {@code ORDERED} since that
898ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * spliterator be the result of a previous pipeline stage that was
899ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * collected to a {@code Node}. It is the order of the pipeline stage
900ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * that governs whether the this slice spliterator is to be used or not.
901ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
902ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static abstract class UnorderedSliceSpliterator<T, T_SPLITR extends Spliterator<T>> {
903ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final int CHUNK_SIZE = 1 << 7;
904ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
905ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // The spliterator to slice
906ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final T_SPLITR s;
907ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final boolean unlimited;
908ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private final long skipThreshold;
909ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private final AtomicLong permits;
910ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
911ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        UnorderedSliceSpliterator(T_SPLITR s, long skip, long limit) {
912ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.s = s;
913ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.unlimited = limit < 0;
914ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.skipThreshold = limit >= 0 ? limit : 0;
915ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.permits = new AtomicLong(limit >= 0 ? skip + limit : skip);
916ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
917ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
918ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        UnorderedSliceSpliterator(T_SPLITR s,
919ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                  UnorderedSliceSpliterator<T, T_SPLITR> parent) {
920ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.s = s;
921ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.unlimited = parent.unlimited;
922ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.permits = parent.permits;
923ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.skipThreshold = parent.skipThreshold;
924ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
925ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
926ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
927ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * Acquire permission to skip or process elements.  The caller must
928ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * first acquire the elements, then consult this method for guidance
929ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * as to what to do with the data.
930ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         *
931ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * <p>We use an {@code AtomicLong} to atomically maintain a counter,
932ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * which is initialized as skip+limit if we are limiting, or skip only
933ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * if we are not limiting.  The user should consult the method
934ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * {@code checkPermits()} before acquiring data elements.
935ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         *
936ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * @param numElements the number of elements the caller has in hand
937ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * @return the number of elements that should be processed; any
938ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * remaining elements should be discarded.
939ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
940ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final long acquirePermits(long numElements) {
941ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            long remainingPermits;
942ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            long grabbing;
943ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // permits never increase, and don't decrease below zero
944ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert numElements > 0;
945ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            do {
946ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                remainingPermits = permits.get();
947ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (remainingPermits == 0)
948ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return unlimited ? numElements : 0;
949ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                grabbing = Math.min(remainingPermits, numElements);
950ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            } while (grabbing > 0 &&
951ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                     !permits.compareAndSet(remainingPermits, remainingPermits - grabbing));
952ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
953ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (unlimited)
954ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return Math.max(numElements - grabbing, 0);
955ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            else if (remainingPermits > skipThreshold)
956ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return Math.max(grabbing - (remainingPermits - skipThreshold), 0);
957ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            else
958ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return grabbing;
959ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
960ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
961ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        enum PermitStatus { NO_MORE, MAYBE_MORE, UNLIMITED }
962ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
963ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /** Call to check if permits might be available before acquiring data */
964ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final PermitStatus permitStatus() {
965ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (permits.get() > 0)
966ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return PermitStatus.MAYBE_MORE;
967ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            else
968ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return unlimited ?  PermitStatus.UNLIMITED : PermitStatus.NO_MORE;
969ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
970ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
971ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public final T_SPLITR trySplit() {
972ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // Stop splitting when there are no more limit permits
973ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (permits.get() == 0)
974ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return null;
975ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @SuppressWarnings("unchecked")
976ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            T_SPLITR split = (T_SPLITR) s.trySplit();
977ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return split == null ? null : makeSpliterator(split);
978ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
979ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
980ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected abstract T_SPLITR makeSpliterator(T_SPLITR s);
981ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
982ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public final long estimateSize() {
983ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return s.estimateSize();
984ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
985ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
986ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public final int characteristics() {
987ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return s.characteristics() &
988ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                   ~(Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED);
989ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
990ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
991ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfRef<T> extends UnorderedSliceSpliterator<T, Spliterator<T>>
992ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator<T>, Consumer<T> {
993ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            T tmpSlot;
994ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
995ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfRef(Spliterator<T> s, long skip, long limit) {
996ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, skip, limit);
997ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
998ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
999ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfRef(Spliterator<T> s, OfRef<T> parent) {
1000ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, parent);
1001ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1002ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1003ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1004ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public final void accept(T t) {
1005ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                tmpSlot = t;
1006ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1007ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1008ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1009ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public boolean tryAdvance(Consumer<? super T> action) {
1010ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(action);
1011ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1012ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                while (permitStatus() != PermitStatus.NO_MORE) {
1013ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    if (!s.tryAdvance(this))
1014ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        return false;
1015ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    else if (acquirePermits(1) == 1) {
1016ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        action.accept(tmpSlot);
1017ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        tmpSlot = null;
1018ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        return true;
1019ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
1020ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1021ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return false;
1022ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1023ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1024ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1025ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void forEachRemaining(Consumer<? super T> action) {
1026ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(action);
1027ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1028ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                ArrayBuffer.OfRef<T> sb = null;
1029ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                PermitStatus permitStatus;
1030ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                while ((permitStatus = permitStatus()) != PermitStatus.NO_MORE) {
1031ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    if (permitStatus == PermitStatus.MAYBE_MORE) {
1032ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        // Optimistically traverse elements up to a threshold of CHUNK_SIZE
1033ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        if (sb == null)
1034ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            sb = new ArrayBuffer.OfRef<>(CHUNK_SIZE);
1035ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        else
1036ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            sb.reset();
1037ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        long permitsRequested = 0;
1038ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        do { } while (s.tryAdvance(sb) && ++permitsRequested < CHUNK_SIZE);
1039ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        if (permitsRequested == 0)
1040ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            return;
1041ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        sb.forEach(action, acquirePermits(permitsRequested));
1042ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
1043ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    else {
1044ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        // Must be UNLIMITED; let 'er rip
1045ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        s.forEachRemaining(action);
1046ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        return;
1047ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
1048ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1049ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1050ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1051ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1052ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected Spliterator<T> makeSpliterator(Spliterator<T> s) {
1053ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new UnorderedSliceSpliterator.OfRef<>(s, this);
1054ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1055ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1056ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1057ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
1058ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * Concrete sub-types must also be an instance of type {@code T_CONS}.
1059ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         *
1060ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * @param  the type of the spined buffer. Must also be a type of
1061ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         *        {@code T_CONS}.
1062ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
1063ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static abstract class OfPrimitive<
1064ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                T,
1065ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                T_CONS,
1066ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                T_BUFF extends ArrayBuffer.OfPrimitive<T_CONS>,
1067ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
1068ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends UnorderedSliceSpliterator<T, T_SPLITR>
1069ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfPrimitive<T, T_CONS, T_SPLITR> {
1070ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfPrimitive(T_SPLITR s, long skip, long limit) {
1071ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, skip, limit);
1072ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1073ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1074ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfPrimitive(T_SPLITR s, UnorderedSliceSpliterator.OfPrimitive<T, T_CONS, T_BUFF, T_SPLITR> parent) {
1075ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, parent);
1076ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1077ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1078ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1079ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public boolean tryAdvance(T_CONS action) {
1080ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(action);
1081ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                @SuppressWarnings("unchecked")
1082ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                T_CONS consumer = (T_CONS) this;
1083ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1084ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                while (permitStatus() != PermitStatus.NO_MORE) {
1085ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    if (!s.tryAdvance(consumer))
1086ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        return false;
1087ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    else if (acquirePermits(1) == 1) {
1088ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        acceptConsumed(action);
1089ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        return true;
1090ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
1091ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1092ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return false;
1093ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1094ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1095ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected abstract void acceptConsumed(T_CONS action);
1096ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1097ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1098ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void forEachRemaining(T_CONS action) {
1099ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(action);
1100ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1101ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                T_BUFF sb = null;
1102ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                PermitStatus permitStatus;
1103ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                while ((permitStatus = permitStatus()) != PermitStatus.NO_MORE) {
1104ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    if (permitStatus == PermitStatus.MAYBE_MORE) {
1105ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        // Optimistically traverse elements up to a threshold of CHUNK_SIZE
1106ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        if (sb == null)
1107ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            sb = bufferCreate(CHUNK_SIZE);
1108ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        else
1109ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            sb.reset();
1110ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        @SuppressWarnings("unchecked")
1111ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        T_CONS sbc = (T_CONS) sb;
1112ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        long permitsRequested = 0;
1113ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        do { } while (s.tryAdvance(sbc) && ++permitsRequested < CHUNK_SIZE);
1114ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        if (permitsRequested == 0)
1115ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            return;
1116ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        sb.forEach(action, acquirePermits(permitsRequested));
1117ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
1118ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    else {
1119ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        // Must be UNLIMITED; let 'er rip
1120ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        s.forEachRemaining(action);
1121ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        return;
1122ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
1123ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1124ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1125ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1126ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected abstract T_BUFF bufferCreate(int initialCapacity);
1127ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1128ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1129ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfInt
1130ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends OfPrimitive<Integer, IntConsumer, ArrayBuffer.OfInt, Spliterator.OfInt>
1131ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfInt, IntConsumer {
1132ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1133ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            int tmpValue;
1134ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1135ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfInt(Spliterator.OfInt s, long skip, long limit) {
1136ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, skip, limit);
1137ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1138ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1139ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfInt(Spliterator.OfInt s, UnorderedSliceSpliterator.OfInt parent) {
1140ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, parent);
1141ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1142ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1143ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1144ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void accept(int value) {
1145ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                tmpValue = value;
1146ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1147ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1148ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1149ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected void acceptConsumed(IntConsumer action) {
1150ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                action.accept(tmpValue);
1151ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1152ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1153ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1154ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected ArrayBuffer.OfInt bufferCreate(int initialCapacity) {
1155ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new ArrayBuffer.OfInt(initialCapacity);
1156ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1157ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1158ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1159ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected Spliterator.OfInt makeSpliterator(Spliterator.OfInt s) {
1160ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new UnorderedSliceSpliterator.OfInt(s, this);
1161ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1162ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1163ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1164ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfLong
1165ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends OfPrimitive<Long, LongConsumer, ArrayBuffer.OfLong, Spliterator.OfLong>
1166ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfLong, LongConsumer {
1167ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1168ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            long tmpValue;
1169ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1170ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfLong(Spliterator.OfLong s, long skip, long limit) {
1171ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, skip, limit);
1172ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1173ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1174ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfLong(Spliterator.OfLong s, UnorderedSliceSpliterator.OfLong parent) {
1175ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, parent);
1176ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1177ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1178ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1179ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void accept(long value) {
1180ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                tmpValue = value;
1181ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1182ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1183ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1184ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected void acceptConsumed(LongConsumer action) {
1185ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                action.accept(tmpValue);
1186ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1187ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1188ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1189ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected ArrayBuffer.OfLong bufferCreate(int initialCapacity) {
1190ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new ArrayBuffer.OfLong(initialCapacity);
1191ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1192ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1193ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1194ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected Spliterator.OfLong makeSpliterator(Spliterator.OfLong s) {
1195ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new UnorderedSliceSpliterator.OfLong(s, this);
1196ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1197ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1198ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1199ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfDouble
1200ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends OfPrimitive<Double, DoubleConsumer, ArrayBuffer.OfDouble, Spliterator.OfDouble>
1201ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfDouble, DoubleConsumer {
1202ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1203ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            double tmpValue;
1204ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1205ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfDouble(Spliterator.OfDouble s, long skip, long limit) {
1206ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, skip, limit);
1207ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1208ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1209ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfDouble(Spliterator.OfDouble s, UnorderedSliceSpliterator.OfDouble parent) {
1210ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(s, parent);
1211ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1212ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1213ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1214ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void accept(double value) {
1215ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                tmpValue = value;
1216ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1217ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1218ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1219ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected void acceptConsumed(DoubleConsumer action) {
1220ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                action.accept(tmpValue);
1221ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1222ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1223ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1224ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected ArrayBuffer.OfDouble bufferCreate(int initialCapacity) {
1225ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new ArrayBuffer.OfDouble(initialCapacity);
1226ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1227ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1228ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1229ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            protected Spliterator.OfDouble makeSpliterator(Spliterator.OfDouble s) {
1230ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new UnorderedSliceSpliterator.OfDouble(s, this);
1231ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1232ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1233ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1234ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1235ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
1236ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A wrapping spliterator that only reports distinct elements of the
1237ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * underlying spliterator. Does not preserve size and encounter order.
1238ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
1239ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static final class DistinctSpliterator<T> implements Spliterator<T>, Consumer<T> {
1240ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1241ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // The value to represent null in the ConcurrentHashMap
1242ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final Object NULL_VALUE = new Object();
1243ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1244ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // The underlying spliterator
1245ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private final Spliterator<T> s;
1246ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1247ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // ConcurrentHashMap holding distinct elements as keys
1248ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private final ConcurrentHashMap<T, Boolean> seen;
1249ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1250ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // Temporary element, only used with tryAdvance
1251ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private T tmpSlot;
1252ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1253ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        DistinctSpliterator(Spliterator<T> s) {
1254ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this(s, new ConcurrentHashMap<>());
1255ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1256ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1257ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private DistinctSpliterator(Spliterator<T> s, ConcurrentHashMap<T, Boolean> seen) {
1258ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.s = s;
1259ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.seen = seen;
1260ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1261ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1262ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1263ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void accept(T t) {
1264ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.tmpSlot = t;
1265ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1266ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1267ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("unchecked")
1268ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private T mapNull(T t) {
1269ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return t != null ? t : (T) NULL_VALUE;
1270ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1271ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1272ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1273ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public boolean tryAdvance(Consumer<? super T> action) {
1274ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            while (s.tryAdvance(this)) {
1275ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (seen.putIfAbsent(mapNull(tmpSlot), Boolean.TRUE) == null) {
1276ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    action.accept(tmpSlot);
1277ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    tmpSlot = null;
1278ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return true;
1279ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1280ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1281ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return false;
1282ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1283ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1284ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1285ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEachRemaining(Consumer<? super T> action) {
1286ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            s.forEachRemaining(t -> {
1287ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (seen.putIfAbsent(mapNull(t), Boolean.TRUE) == null) {
1288ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    action.accept(t);
1289ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1290ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            });
1291ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1292ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1293ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1294ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Spliterator<T> trySplit() {
1295ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            Spliterator<T> split = s.trySplit();
1296ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return (split != null) ? new DistinctSpliterator<>(split, seen) : null;
1297ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1298ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1299ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1300ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public long estimateSize() {
1301ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return s.estimateSize();
1302ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1303ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1304ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1305ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public int characteristics() {
1306ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return (s.characteristics() & ~(Spliterator.SIZED | Spliterator.SUBSIZED |
1307ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                            Spliterator.SORTED | Spliterator.ORDERED))
1308ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                   | Spliterator.DISTINCT;
1309ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1310ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1311ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1312ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Comparator<? super T> getComparator() {
1313ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return s.getComparator();
1314ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1315ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1316ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1317ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
1318ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A Spliterator that infinitely supplies elements in no particular order.
1319ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
1320ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>Splitting divides the estimated size in two and stops when the
1321ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * estimate size is 0.
1322ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
1323ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>The {@code forEachRemaining} method if invoked will never terminate.
1324ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The {@code tryAdvance} method always returns true.
1325ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
1326ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
1327ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static abstract class InfiniteSupplyingSpliterator<T> implements Spliterator<T> {
1328ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        long estimate;
1329ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1330ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected InfiniteSupplyingSpliterator(long estimate) {
1331ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.estimate = estimate;
1332ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1333ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1334ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1335ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public long estimateSize() {
1336ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return estimate;
1337ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1338ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1339ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1340ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public int characteristics() {
1341ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return IMMUTABLE;
1342ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1343ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1344ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfRef<T> extends InfiniteSupplyingSpliterator<T> {
1345ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            final Supplier<T> s;
1346ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1347ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfRef(long size, Supplier<T> s) {
1348ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(size);
1349ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.s = s;
1350ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1351ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1352ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1353ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public boolean tryAdvance(Consumer<? super T> action) {
1354ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(action);
1355ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1356ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                action.accept(s.get());
1357ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return true;
1358ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1359ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1360ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1361ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public Spliterator<T> trySplit() {
1362ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (estimate == 0)
1363ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return null;
1364ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new InfiniteSupplyingSpliterator.OfRef<>(estimate >>>= 1, s);
1365ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1366ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1367ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1368ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfInt extends InfiniteSupplyingSpliterator<Integer>
1369ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfInt {
1370ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            final IntSupplier s;
1371ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1372ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfInt(long size, IntSupplier s) {
1373ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(size);
1374ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.s = s;
1375ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1376ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1377ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1378ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public boolean tryAdvance(IntConsumer action) {
1379ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(action);
1380ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1381ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                action.accept(s.getAsInt());
1382ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return true;
1383ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1384ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1385ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1386ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public Spliterator.OfInt trySplit() {
1387ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (estimate == 0)
1388ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return null;
1389ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new InfiniteSupplyingSpliterator.OfInt(estimate = estimate >>> 1, s);
1390ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1391ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1392ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1393ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfLong extends InfiniteSupplyingSpliterator<Long>
1394ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfLong {
1395ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            final LongSupplier s;
1396ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1397ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfLong(long size, LongSupplier s) {
1398ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(size);
1399ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.s = s;
1400ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1401ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1402ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1403ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public boolean tryAdvance(LongConsumer action) {
1404ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(action);
1405ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1406ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                action.accept(s.getAsLong());
1407ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return true;
1408ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1409ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1410ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1411ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public Spliterator.OfLong trySplit() {
1412ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (estimate == 0)
1413ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return null;
1414ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new InfiniteSupplyingSpliterator.OfLong(estimate = estimate >>> 1, s);
1415ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1416ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1417ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1418ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfDouble extends InfiniteSupplyingSpliterator<Double>
1419ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfDouble {
1420ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            final DoubleSupplier s;
1421ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1422ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfDouble(long size, DoubleSupplier s) {
1423ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(size);
1424ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.s = s;
1425ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1426ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1427ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1428ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public boolean tryAdvance(DoubleConsumer action) {
1429ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                Objects.requireNonNull(action);
1430ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1431ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                action.accept(s.getAsDouble());
1432ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return true;
1433ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1434ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1435ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1436ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public Spliterator.OfDouble trySplit() {
1437ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (estimate == 0)
1438ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return null;
1439ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new InfiniteSupplyingSpliterator.OfDouble(estimate = estimate >>> 1, s);
1440ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1441ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1442ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1443ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1444ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // @@@ Consolidate with Node.Builder
1445ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static abstract class ArrayBuffer {
1446ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        int index;
1447ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1448ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        void reset() {
1449ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            index = 0;
1450ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1451ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1452ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfRef<T> extends ArrayBuffer implements Consumer<T> {
1453ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            final Object[] array;
1454ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1455ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfRef(int size) {
1456ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = new Object[size];
1457ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1458ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1459ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1460ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void accept(T t) {
1461ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                array[index++] = t;
1462ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1463ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1464ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void forEach(Consumer<? super T> action, long fence) {
1465ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                for (int i = 0; i < fence; i++) {
1466ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    @SuppressWarnings("unchecked")
1467ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    T t = (T) array[i];
1468ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    action.accept(t);
1469ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1470ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1471ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1472ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1473ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static abstract class OfPrimitive<T_CONS> extends ArrayBuffer {
1474ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            int index;
1475ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1476ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1477ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            void reset() {
1478ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                index = 0;
1479ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1480ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1481ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            abstract void forEach(T_CONS action, long fence);
1482ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1483ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1484ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfInt extends OfPrimitive<IntConsumer>
1485ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements IntConsumer {
1486ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            final int[] array;
1487ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1488ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfInt(int size) {
1489ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = new int[size];
1490ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1491ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1492ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1493ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void accept(int t) {
1494ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                array[index++] = t;
1495ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1496ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1497ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1498ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void forEach(IntConsumer action, long fence) {
1499ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                for (int i = 0; i < fence; i++) {
1500ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    action.accept(array[i]);
1501ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1502ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1503ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1504ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1505ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfLong extends OfPrimitive<LongConsumer>
1506ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements LongConsumer {
1507ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            final long[] array;
1508ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1509ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfLong(int size) {
1510ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = new long[size];
1511ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1512ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1513ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1514ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void accept(long t) {
1515ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                array[index++] = t;
1516ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1517ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1518ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1519ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void forEach(LongConsumer action, long fence) {
1520ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                for (int i = 0; i < fence; i++) {
1521ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    action.accept(array[i]);
1522ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1523ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1524ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1525ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1526ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfDouble extends OfPrimitive<DoubleConsumer>
1527ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements DoubleConsumer {
1528ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            final double[] array;
1529ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1530ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfDouble(int size) {
1531ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = new double[size];
1532ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1533ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1534ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1535ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void accept(double t) {
1536ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                array[index++] = t;
1537ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1538ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1539ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1540ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            void forEach(DoubleConsumer action, long fence) {
1541ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                for (int i = 0; i < fence; i++) {
1542ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    action.accept(array[i]);
1543ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1544ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1545ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1546ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1547ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin}
1548ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1549