1 /*
2 * Copyright 2022 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 package io.netty5.buffer.api;
17
18 import io.netty5.buffer.api.ComponentIterator.Next;
19 import io.netty5.util.SafeCloseable;
20
21 /**
22 * A facade for iterating the readable or writable components of a {@link Buffer}.
23 *
24 * <strong>Note:</strong> the {@linkplain ComponentIterator iterator object} must be
25 * {@linkplain ComponentIterator#close() closed} after use.
26 * The easiest way to ensure this, is to use a try-with-resources clause.
27 * <p>
28 * The typical code pattern for using this API looks like the following:
29 * <pre>{@code
30 * try (var iteration = buffer.forEachReadable()) {
31 * for (var c = iteration.first(); c != null; c = c.next()) {
32 * ByteBuffer componentBuffer = c.readableBuffer();
33 * // ...
34 * }
35 * }
36 * }</pre>
37 * Note the use of the {@code var} keyword for local variables, which are required for correctly expressing the
38 * generic types used in the iteration.
39 * Following this code pattern will ensure that the components, and their parent buffer, will be correctly
40 * life-cycled.
41 *
42 * @param <T> A type that implements {@link Next}, and either {@link ReadableComponent} or {@link WritableComponent}.
43 * @see Buffer#forEachReadable()
44 * @see Buffer#forEachWritable()
45 */
46 public interface ComponentIterator<T extends Next> extends SafeCloseable {
47 /**
48 * Get the first component of the iteration, or {@code null} if there are no components.
49 * <p>
50 * The object returned will implement both {@link Next}, and one of the {@link ReadableComponent} or
51 * {@link WritableComponent} interfaces.
52 *
53 * @return The first component of the iteration, or {@code null} if there are no components.
54 */
55 T first();
56
57 /**
58 * This interface exposes external iteration on components.
59 */
60 interface Next {
61 /**
62 * Get the next component of the iteration, or {@code null} if there are no more components.
63 * <p>
64 * The returned object, if any, will be of the same type as this object, and would typically be assigned to the
65 * same variable.
66 * <p>
67 * Iteration is only valid while the {@link ComponentIterator} is open.
68 * Calling this method after the associated component iterator has been
69 * {@linkplain ComponentIterator#close() closed} may result in undefined behaviour.
70 *
71 * @return The next component in the iteration, or {@code null} if there are no more components.
72 * @param <N> A type that implements {@link Next}, and one of the {@link ReadableComponent} or
73 * {@link WritableComponent} interfaces.
74 */
75 <N extends Next> N next();
76 }
77 }