1 /* 2 * Copyright 2021 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.util.Resource; 19 import io.netty5.util.Send; 20 21 import java.nio.ByteBuffer; 22 import java.nio.charset.Charset; 23 24 /** 25 * The {@code CompositeBuffer} is a concrete {@link Buffer} implementation that make a number of other buffers appear 26 * as one. A composite buffer behaves the same as a normal, non-composite buffer in every way, so you normally don't 27 * need to handle them specially. 28 * <p> 29 * A composite buffer is constructed using one of the {@code compose} methods: 30 * <ul> 31 * <li> 32 * {@link BufferAllocator#compose(Iterable)} creates a composite buffer from the buffers that are sent to it via 33 * the passed in send objects. Since {@link Send#receive()} transfers ownership, the resulting composite buffer 34 * will have ownership, because it is guaranteed that there are no other references to its constituent buffers. 35 * </li> 36 * <li> 37 * {@link BufferAllocator#compose(Send)} creates a composite buffer with a single component. 38 * Since {@link Send#receive()} transfers ownership, the resulting composite buffer 39 * will have ownership, because it is guaranteed that there are no other references to its constituent buffer. 40 * </li> 41 * <li> 42 * {@link BufferAllocator#compose()} creates an empty, zero capacity, composite buffer. Such empty buffers may 43 * change their {@linkplain #readOnly() read-only} states when they gain their first component. 44 * </li> 45 * </ul> 46 * Composite buffers can later be extended with internally allocated components, with {@link #ensureWritable(int)}, 47 * or with externally allocated buffers, using {@link #extendWith(Send)}. 48 * 49 * <h3>How buffers compose</h3> 50 * 51 * A buffer can be thought of as having three distinct regions, in order: 52 * <ol> 53 * <li>Memory that have been read.</li> 54 * <li>Memory that is readable.</li> 55 * <li>Memory that can be written to.</li> 56 * </ol> 57 * 58 * A composite buffer must present itself similarly, but may be composed of buffers where their offsets don't line up, 59 * and thus end up producing "gaps" in the composite buffer. 60 * The solution is that the composite buffer hide these gaps from view. 61 * <p> 62 * For example, if we compose two buffers that both have non-zero read-offset, then the composite buffer will get the 63 * read-offset of the first buffer, followed by a concatenation of the readable memory from both. 64 * Similarly, the write-offset of the composite buffer will come from the last buffer with a non-zero write-offset, 65 * and any writable memory prior to the last readable memory region will be hidden: 66 * 67 * <pre> 68 * First buffer Second buffer 69 * +----------------------+ +--------------------+ 70 * 0| |r/o |w/o | 0| |r/o |w/o | 71 * +----+---------+-------+ +----+--------+------+ 72 * \ \ \ ,____________/ ,___________/ 73 * \ \ \/ / 74 * +----+---------+--------+------+ 75 * 0| |r/o : |w/o | Composite buffer 76 * +------------------------------+ 77 * </pre> 78 * 79 * Components in the middle can have both their end-regions hidden in the same way, so only their readable memory is 80 * included in the composite buffer. 81 * Buffers that consist entirely of memory that has already been read, or memory that is writable, can also concatenate 82 * onto those regions at the ends. 83 * The final capacity of the composite buffer, will be the sum of all the visible regions. 84 * <p> 85 * Reads and writes to the composite buffer that modifies the read or write offsets, will also modify the relevant 86 * offsets in the constituent buffers. 87 * 88 * <h3>Constituent buffer requirements</h3> 89 * 90 * The buffers that are being composed must all have the same writability. 91 * Either all components must be {@linkplain Buffer#readOnly() read-only}, or they must all be writable. 92 * <p> 93 * It is not a requirement that the buffers have the same size. 94 * <p> 95 * It is not a requirement that the buffers are allocated by this allocator, but if 96 * {@link Buffer#ensureWritable(int)} is called on the composed buffer, and the composed buffer needs to be 97 * expanded, then this allocator instance will be used for allocation the extra memory. 98 * 99 * <h3>Ownership and Send</h3> 100 * 101 * {@linkplain Resource#send() Sending} a composite buffer implies sending all of its constituent buffers. 102 * For sending to be possible, both the composite buffer itself, and all of its constituent buffers, must be in a 103 * state that permits them being sent. This should be the case by default, as it shouldn't be possible to create 104 * composite buffers that can't be sent. 105 */ 106 public interface CompositeBuffer extends Buffer { 107 108 /** 109 * Create an empty composite buffer, that has no components. The buffer can be extended with components using either 110 * {@link #ensureWritable(int)} or {@link #extendWith(Send)}. 111 * 112 * @param allocator The allocator for the composite buffer. This allocator will be used e.g. to service 113 * {@link #ensureWritable(int)} calls. 114 * @return A composite buffer that has no components, and has a capacity of zero. 115 */ 116 static CompositeBuffer compose(BufferAllocator allocator) { 117 return DefaultCompositeBuffer.compose(allocator); 118 } 119 120 /** 121 * Check if the given buffer is a composite buffer or not. 122 * @param composite The buffer to check. 123 * @return {@code true} if the given buffer was created with {@link BufferAllocator#compose()}, 124 * {@link BufferAllocator#compose(Send)} or {@link BufferAllocator#compose(Iterable)}, {@code false} otherwise. 125 */ 126 static boolean isComposite(Buffer composite) { 127 return composite instanceof CompositeBuffer; 128 } 129 130 /** 131 * Extend this composite buffer with the given extension buffer. 132 * This works as if the extension had originally been included at the end of the list of constituent buffers when 133 * the composite buffer was created. 134 * The extension buffer is added to the end of this composite buffer, which is modified in-place. 135 * 136 * @see BufferAllocator#compose(Send) 137 * @param extension The buffer to extend the composite buffer with. 138 * @return This composite buffer instance. 139 */ 140 CompositeBuffer extendWith(Send<Buffer> extension); 141 142 /** 143 * Split this buffer at a component boundary that is less than or equal to the given offset. 144 * <p> 145 * This method behaves the same as {@link #split(int)}, except no components are split. 146 * 147 * @param splitOffset The maximum split offset. The real split offset will be at a component boundary that is less 148 * than or equal to this offset. 149 * @return A new buffer with independent and exclusive ownership over the bytes from the beginning to a component 150 * boundary less than or equal to the given offset of this buffer. 151 */ 152 CompositeBuffer splitComponentsFloor(int splitOffset); 153 154 /** 155 * Split this buffer at a component boundary that is greater than or equal to the given offset. 156 * <p> 157 * This method behaves the same as {@link #split(int)}, except no components are split. 158 * 159 * @param splitOffset The minimum split offset. The real split offset will be at a component boundary that is 160 * greater than or equal to this offset. 161 * @return A new buffer with independent and exclusive ownership over the bytes from the beginning to a component 162 * boundary greater than or equal to the given offset of this buffer. 163 */ 164 CompositeBuffer splitComponentsCeil(int splitOffset); 165 166 /** 167 * Break a composite buffer into its constituent components. 168 * <p> 169 * This "consumes" the composite buffer, leaving the composite buffer instance as if it had been closed. 170 * The buffers in the returned array are not closed, and become owned by the caller. 171 * 172 * @return An array of the constituent buffer components. 173 */ 174 Buffer[] decomposeBuffer(); 175 176 @Override 177 CompositeBuffer readerOffset(int offset); 178 179 @Override 180 CompositeBuffer writerOffset(int offset); 181 182 @Override 183 default CompositeBuffer skipReadableBytes(int delta) { 184 return (CompositeBuffer) Buffer.super.skipReadableBytes(delta); 185 } 186 187 @Override 188 default CompositeBuffer skipWritableBytes(int delta) { 189 return (CompositeBuffer) Buffer.super.skipWritableBytes(delta); 190 } 191 192 @Override 193 CompositeBuffer fill(byte value); 194 195 @Override 196 CompositeBuffer makeReadOnly(); 197 198 @Override 199 default CompositeBuffer writeBytes(Buffer source) { 200 return (CompositeBuffer) Buffer.super.writeBytes(source); 201 } 202 203 @Override 204 default CompositeBuffer writeBytes(byte[] source) { 205 return (CompositeBuffer) Buffer.super.writeBytes(source); 206 } 207 208 @Override 209 default CompositeBuffer writeBytes(byte[] source, int srcPos, int length) { 210 return (CompositeBuffer) Buffer.super.writeBytes(source, srcPos, length); 211 } 212 213 @Override 214 default CompositeBuffer writeCharSequence(CharSequence source, Charset charset) { 215 return (CompositeBuffer) Buffer.super.writeCharSequence(source, charset); 216 } 217 218 @Override 219 default CompositeBuffer readBytes(byte[] destination, int destPos, int length) { 220 return (CompositeBuffer) Buffer.super.readBytes(destination, destPos, length); 221 } 222 223 @Override 224 default CompositeBuffer writeBoolean(boolean value) { 225 return (CompositeBuffer) Buffer.super.writeBoolean(value); 226 } 227 228 @Override 229 default CompositeBuffer setBoolean(int woff, boolean value) { 230 return (CompositeBuffer) Buffer.super.setBoolean(woff, value); 231 } 232 233 @Override 234 default CompositeBuffer writeBytes(ByteBuffer source) { 235 return (CompositeBuffer) Buffer.super.writeBytes(source); 236 } 237 238 @Override 239 default CompositeBuffer readBytes(ByteBuffer destination) { 240 return (CompositeBuffer) Buffer.super.readBytes(destination); 241 } 242 243 @Override 244 default CompositeBuffer resetOffsets() { 245 return (CompositeBuffer) Buffer.super.resetOffsets(); 246 } 247 248 @Override 249 default CompositeBuffer ensureWritable(int size) { 250 return (CompositeBuffer) Buffer.super.ensureWritable(size); 251 } 252 253 @Override 254 CompositeBuffer ensureWritable(int size, int minimumGrowth, boolean allowCompaction); 255 256 @Override 257 default CompositeBuffer copy() { 258 return (CompositeBuffer) Buffer.super.copy(); 259 } 260 261 @Override 262 default CompositeBuffer copy(int offset, int length) { 263 return (CompositeBuffer) Buffer.super.copy(offset, length); 264 } 265 266 @Override 267 CompositeBuffer copy(int offset, int length, boolean readOnly); 268 269 @Override 270 default CompositeBuffer split() { 271 return (CompositeBuffer) Buffer.super.split(); 272 } 273 274 @Override 275 CompositeBuffer split(int splitOffset); 276 277 @Override 278 CompositeBuffer compact(); 279 280 @Override 281 CompositeBuffer writeByte(byte value); 282 283 @Override 284 CompositeBuffer setByte(int woff, byte value); 285 286 @Override 287 CompositeBuffer writeUnsignedByte(int value); 288 289 @Override 290 CompositeBuffer setUnsignedByte(int woff, int value); 291 292 @Override 293 CompositeBuffer writeChar(char value); 294 295 @Override 296 CompositeBuffer setChar(int woff, char value); 297 298 @Override 299 CompositeBuffer writeShort(short value); 300 301 @Override 302 CompositeBuffer setShort(int woff, short value); 303 304 @Override 305 CompositeBuffer writeUnsignedShort(int value); 306 307 @Override 308 CompositeBuffer setUnsignedShort(int woff, int value); 309 310 @Override 311 CompositeBuffer writeMedium(int value); 312 313 @Override 314 CompositeBuffer setMedium(int woff, int value); 315 316 @Override 317 CompositeBuffer writeUnsignedMedium(int value); 318 319 @Override 320 CompositeBuffer setUnsignedMedium(int woff, int value); 321 322 @Override 323 CompositeBuffer writeInt(int value); 324 325 @Override 326 CompositeBuffer setInt(int woff, int value); 327 328 @Override 329 CompositeBuffer writeUnsignedInt(long value); 330 331 @Override 332 CompositeBuffer setUnsignedInt(int woff, long value); 333 334 @Override 335 CompositeBuffer writeFloat(float value); 336 337 @Override 338 CompositeBuffer setFloat(int woff, float value); 339 340 @Override 341 CompositeBuffer writeLong(long value); 342 343 @Override 344 CompositeBuffer setLong(int woff, long value); 345 346 @Override 347 CompositeBuffer writeDouble(double value); 348 349 @Override 350 CompositeBuffer setDouble(int woff, double value); 351 352 @Override 353 CompositeBuffer implicitCapacityLimit(int limit); 354 }