All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.core.io.buffer.Netty5DataBuffer Maven / Gradle / Ivy

There is a newer version: 6.1.6
Show newest version
/*
 * Copyright 2002-2023 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.core.io.buffer;

import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.NoSuchElementException;
import java.util.function.IntPredicate;

import io.netty5.buffer.Buffer;
import io.netty5.buffer.BufferComponent;
import io.netty5.buffer.ComponentIterator;

import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

/**
 * Implementation of the {@code DataBuffer} interface that wraps a Netty 5
 * {@link Buffer}. Typically constructed with {@link Netty5DataBufferFactory}.
 *
 * @author Violeta Georgieva
 * @author Arjen Poutsma
 * @since 6.0
 */
public final class Netty5DataBuffer implements CloseableDataBuffer, TouchableDataBuffer {

	private final Buffer buffer;

	private final Netty5DataBufferFactory dataBufferFactory;


	/**
	 * Create a new {@code Netty5DataBuffer} based on the given {@code Buffer}.
	 * @param buffer the buffer to base this buffer on
	 */
	Netty5DataBuffer(Buffer buffer, Netty5DataBufferFactory dataBufferFactory) {
		Assert.notNull(buffer, "Buffer must not be null");
		Assert.notNull(dataBufferFactory, "Netty5DataBufferFactory must not be null");
		this.buffer = buffer;
		this.dataBufferFactory = dataBufferFactory;
	}

	/**
	 * Directly exposes the native {@code Buffer} that this buffer is based on.
	 * @return the wrapped buffer
	 */
	public Buffer getNativeBuffer() {
		return this.buffer;
	}

	@Override
	public DataBufferFactory factory() {
		return this.dataBufferFactory;
	}

	@Override
	public int indexOf(IntPredicate predicate, int fromIndex) {
		Assert.notNull(predicate, "IntPredicate must not be null");
		if (fromIndex < 0) {
			fromIndex = 0;
		}
		else if (fromIndex >= this.buffer.writerOffset()) {
			return -1;
		}
		int length = this.buffer.writerOffset() - fromIndex;
		int bytes = this.buffer.openCursor(fromIndex, length).process(predicate.negate()::test);
		return bytes == -1 ? -1 : fromIndex + bytes;
	}

	@Override
	public int lastIndexOf(IntPredicate predicate, int fromIndex) {
		Assert.notNull(predicate, "IntPredicate must not be null");
		if (fromIndex < 0) {
			return -1;
		}
		fromIndex = Math.min(fromIndex, this.buffer.writerOffset() - 1);
		return this.buffer.openCursor(0, fromIndex + 1).process(predicate.negate()::test);
	}

	@Override
	public int readableByteCount() {
		return this.buffer.readableBytes();
	}

	@Override
	public int writableByteCount() {
		return this.buffer.writableBytes();
	}

	@Override
	public int readPosition() {
		return this.buffer.readerOffset();
	}

	@Override
	public Netty5DataBuffer readPosition(int readPosition) {
		this.buffer.readerOffset(readPosition);
		return this;
	}

	@Override
	public int writePosition() {
		return this.buffer.writerOffset();
	}

	@Override
	public Netty5DataBuffer writePosition(int writePosition) {
		this.buffer.writerOffset(writePosition);
		return this;
	}

	@Override
	public byte getByte(int index) {
		return this.buffer.getByte(index);
	}

	@Override
	public int capacity() {
		return this.buffer.capacity();
	}

	@Override
	@Deprecated
	public Netty5DataBuffer capacity(int capacity) {
		if (capacity <= 0) {
			throw new IllegalArgumentException(String.format("'newCapacity' %d must be higher than 0", capacity));
		}
		int diff = capacity - capacity();
		if (diff > 0) {
			this.buffer.ensureWritable(this.buffer.writableBytes() + diff);
		}
		return this;
	}

	@Override
	public DataBuffer ensureWritable(int capacity) {
		Assert.isTrue(capacity >= 0, "Capacity must be >= 0");
		this.buffer.ensureWritable(capacity);
		return this;
	}

	@Override
	public byte read() {
		return this.buffer.readByte();
	}

	@Override
	public Netty5DataBuffer read(byte[] destination) {
		return read(destination, 0, destination.length);
	}

	@Override
	public Netty5DataBuffer read(byte[] destination, int offset, int length) {
		this.buffer.readBytes(destination, offset, length);
		return this;
	}

	@Override
	public Netty5DataBuffer write(byte b) {
		this.buffer.writeByte(b);
		return this;
	}

	@Override
	public Netty5DataBuffer write(byte[] source) {
		this.buffer.writeBytes(source);
		return this;
	}

	@Override
	public Netty5DataBuffer write(byte[] source, int offset, int length) {
		this.buffer.writeBytes(source, offset, length);
		return this;
	}

	@Override
	public Netty5DataBuffer write(DataBuffer... dataBuffers) {
		if (!ObjectUtils.isEmpty(dataBuffers)) {
			if (hasNetty5DataBuffers(dataBuffers)) {
				Buffer[] nativeBuffers = new Buffer[dataBuffers.length];
				for (int i = 0; i < dataBuffers.length; i++) {
					nativeBuffers[i] = ((Netty5DataBuffer) dataBuffers[i]).getNativeBuffer();
				}
				return write(nativeBuffers);
			}
			else {
				ByteBuffer[] byteBuffers = new ByteBuffer[dataBuffers.length];
				for (int i = 0; i < dataBuffers.length; i++) {
					byteBuffers[i] = ByteBuffer.allocate(dataBuffers[i].readableByteCount());
					dataBuffers[i].toByteBuffer(byteBuffers[i]);
				}
				return write(byteBuffers);
			}
		}
		return this;
	}

	private static boolean hasNetty5DataBuffers(DataBuffer[] buffers) {
		for (DataBuffer buffer : buffers) {
			if (!(buffer instanceof Netty5DataBuffer)) {
				return false;
			}
		}
		return true;
	}

	@Override
	public Netty5DataBuffer write(ByteBuffer... buffers) {
		if (!ObjectUtils.isEmpty(buffers)) {
			for (ByteBuffer buffer : buffers) {
				this.buffer.writeBytes(buffer);
			}
		}
		return this;
	}

	/**
	 * Writes one or more Netty 5 {@link Buffer Buffers} to this buffer,
	 * starting at the current writing position.
	 * @param buffers the buffers to write into this buffer
	 * @return this buffer
	 */
	public Netty5DataBuffer write(Buffer... buffers) {
		if (!ObjectUtils.isEmpty(buffers)) {
			for (Buffer buffer : buffers) {
				this.buffer.writeBytes(buffer);
			}
		}
		return this;
	}

	@Override
	public DataBuffer write(CharSequence charSequence, Charset charset) {
		Assert.notNull(charSequence, "CharSequence must not be null");
		Assert.notNull(charset, "Charset must not be null");

		this.buffer.writeCharSequence(charSequence, charset);
		return this;
	}

	/**
	 * {@inheritDoc}
	 * 

Note that due to the lack of a {@code slice} method * in Netty 5's {@link Buffer}, this implementation returns a copy that * does not share its contents with this buffer. */ @Override @Deprecated public DataBuffer slice(int index, int length) { Buffer copy = this.buffer.copy(index, length); return new Netty5DataBuffer(copy, this.dataBufferFactory); } @Override public DataBuffer split(int index) { Buffer split = this.buffer.split(index); return new Netty5DataBuffer(split, this.dataBufferFactory); } @Override @Deprecated public ByteBuffer asByteBuffer() { return toByteBuffer(); } @Override @Deprecated public ByteBuffer asByteBuffer(int index, int length) { return toByteBuffer(index, length); } @Override @Deprecated public ByteBuffer toByteBuffer(int index, int length) { ByteBuffer copy = this.buffer.isDirect() ? ByteBuffer.allocateDirect(length) : ByteBuffer.allocate(length); this.buffer.copyInto(index, copy, 0, length); return copy; } @Override public void toByteBuffer(int srcPos, ByteBuffer dest, int destPos, int length) { this.buffer.copyInto(srcPos, dest, destPos, length); } @Override public ByteBufferIterator readableByteBuffers() { return new BufferComponentIterator<>(this.buffer.forEachComponent(), true); } @Override public ByteBufferIterator writableByteBuffers() { return new BufferComponentIterator<>(this.buffer.forEachComponent(), false); } @Override public String toString(Charset charset) { Assert.notNull(charset, "Charset must not be null"); return this.buffer.toString(charset); } @Override public String toString(int index, int length, Charset charset) { Assert.notNull(charset, "Charset must not be null"); byte[] data = new byte[length]; this.buffer.copyInto(index, data, 0, length); return new String(data, 0, length, charset); } @Override public Netty5DataBuffer touch(Object hint) { this.buffer.touch(hint); return this; } @Override public void close() { this.buffer.close(); } @Override public boolean equals(@Nullable Object obj) { return (this == obj || (obj instanceof Netty5DataBuffer that && this.buffer.equals(that.buffer))); } @Override public int hashCode() { return this.buffer.hashCode(); } @Override public String toString() { return this.buffer.toString(); } private static final class BufferComponentIterator implements ByteBufferIterator { private final ComponentIterator delegate; private final boolean readable; @Nullable private T next; public BufferComponentIterator(ComponentIterator delegate, boolean readable) { Assert.notNull(delegate, "Delegate must not be null"); this.delegate = delegate; this.readable = readable; this.next = readable ? this.delegate.firstReadable() : this.delegate.firstWritable(); } @Override public boolean hasNext() { return this.next != null; } @Override public ByteBuffer next() { if (this.next != null) { ByteBuffer result; if (this.readable) { result = this.next.readableBuffer(); this.next = this.next.nextReadable(); } else { result = this.next.writableBuffer(); this.next = this.next.nextWritable(); } return result; } else { throw new NoSuchElementException(); } } @Override public void close() { this.delegate.close(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy