
io.activej.serializer.stream.StreamInput Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of activej-serializer Show documentation
Show all versions of activej-serializer Show documentation
Extremely fast and space-efficient serializers. Implemented using bytecode engineering.
package io.activej.serializer.stream;
import io.activej.serializer.BinaryInput;
import io.activej.serializer.CorruptedDataException;
import org.jetbrains.annotations.Nullable;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import static java.lang.Math.max;
import static java.nio.charset.StandardCharsets.UTF_8;
public class StreamInput implements Closeable {
public static final int DEFAULT_BUFFER_SIZE = 16384;
private BinaryInput in;
private int limit;
private final InputStream inputStream;
private char[] charArray = new char[128];
private StreamInput(InputStream inputStream, BinaryInput binaryInput) {
this.inputStream = inputStream;
this.in = binaryInput;
this.limit = binaryInput.array.length;
}
private StreamInput(InputStream inputStream, int initialBufferSize) {
this.inputStream = inputStream;
this.in = new BinaryInput(allocate(initialBufferSize));
}
public static StreamInput create(InputStream inputStream) {
return new StreamInput(inputStream, DEFAULT_BUFFER_SIZE);
}
public static StreamInput create(InputStream inputStream, int bufferSize) {
return new StreamInput(inputStream, bufferSize);
}
public static StreamInput create(BinaryInput binaryInput) {
return new StreamInput(InputStream.nullInputStream(), binaryInput);
}
public static StreamInput create(InputStream inputStream, BinaryInput binaryInput) {
return new StreamInput(inputStream, binaryInput);
}
@Override
public final void close() throws IOException {
if (in != null) {
recycle(in.array());
in = null;
}
inputStream.close();
}
protected byte[] allocate(int size) {
return new byte[size];
}
protected void recycle(byte[] array) {
}
public BinaryInput in() {
return in;
}
public void in(BinaryInput in) {
this.in = in;
}
public int limit() {
return limit;
}
public int remaining() {
return limit - in.pos();
}
public void ensure(int bytes) throws IOException {
if (remaining() < bytes) {
doEnsureRead(bytes);
}
}
private void doEnsureRead(int size) throws IOException {
while (remaining() < size) {
ensureWriteRemaining(size);
int bytesRead = inputStream.read(in.array(), limit, in.array().length - limit);
if (bytesRead == -1) {
close();
throw new EOSException();
}
limit += bytesRead;
}
}
private void ensureWriteRemaining(int size) {
int writeRemaining = in.array().length - limit;
if (writeRemaining < size) {
int readRemaining = remaining();
if (in.array.length - readRemaining >= size) {
System.arraycopy(in.array(), in.pos(), in.array(), 0, readRemaining);
limit = readRemaining;
in.pos = 0;
} else {
byte[] bytes = allocate(max(in.array.length, size));
System.arraycopy(in.array(), in.pos(), bytes, 0, readRemaining);
limit -= in.pos();
recycle(in.array);
in = new BinaryInput(bytes);
}
}
}
public final boolean isEndOfStream() throws IOException {
if (remaining() != 0) return false;
ensureWriteRemaining(1);
int bytesRead = inputStream.read(in.array(), in.pos, 1);
if (bytesRead == -1) {
return true;
}
limit += bytesRead;
return false;
}
private char[] ensureCharArray(int length) {
if (charArray.length < length) {
charArray = new char[length + (length >>> 2)];
}
return charArray;
}
public final int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
public final int read(byte[] b, int off, int len) throws IOException {
if (in.pos < limit) {
int copy = Math.min(limit - in.pos, len);
in.read(b, off, copy);
off += copy;
len -= copy;
}
readBytes(b, off, len);
return len;
}
private void readBytes(byte[] b, int off, int len) throws IOException {
while (len > 0) {
int bytesRead = inputStream.read(b, off, len);
if (bytesRead == -1) {
close();
throw new EOSException();
}
off += bytesRead;
len -= bytesRead;
}
}
public final byte readByte() throws IOException {
return in.pos < limit ? in.readByte() : readByteImpl();
}
private byte readByteImpl() throws IOException {
doEnsureRead(1);
return in.readByte();
}
public final boolean readBoolean() throws IOException {
ensure(1);
return in.readBoolean();
}
public final short readShort() throws IOException {
ensure(2);
return in.readShort();
}
public final int readInt() throws IOException {
ensure(4);
return in.readInt();
}
public final long readLong() throws IOException {
ensure(8);
return in.readLong();
}
public final int readVarInt() throws IOException {
int result;
byte b = readByte();
if (b >= 0) {
result = b;
} else {
result = b & 0x7f;
if ((b = readByte()) >= 0) {
result |= b << 7;
} else {
result |= (b & 0x7f) << 7;
if ((b = readByte()) >= 0) {
result |= b << 14;
} else {
result |= (b & 0x7f) << 14;
if ((b = readByte()) >= 0) {
result |= b << 21;
} else {
result |= (b & 0x7f) << 21;
if ((b = readByte()) >= 0) {
result |= b << 28;
} else {
close();
throw new CorruptedDataException("VarInt value takes more than 5 bytes");
}
}
}
}
}
return result;
}
public final long readVarLong() throws IOException {
long result = 0;
for (int offset = 0; offset < 64; offset += 7) {
byte b = readByte();
result |= (long) (b & 0x7F) << offset;
if ((b & 0x80) == 0)
return result;
}
close();
throw new CorruptedDataException("VarLong value takes more than 10 bytes");
}
public final float readFloat() throws IOException {
ensure(4);
return in.readFloat();
}
public final double readDouble() throws IOException {
ensure(8);
return in.readDouble();
}
public final char readChar() throws IOException {
ensure(2);
return in.readChar();
}
public final String readString() throws IOException {
return readUTF8();
}
public final String readUTF8() throws IOException {
int length = readVarInt();
if (length == 0) return "";
ensure(length);
String str = new String(in.array(), in.pos(), length, UTF_8);
in.pos(in.pos() + length);
return str;
}
public final String readIso88591() throws IOException {
int length = readVarInt();
if (length == 0) return "";
ensure(length);
char[] chars = ensureCharArray(length);
for (int i = 0; i < length; i++) {
int c = readByte() & 0xff;
chars[i] = (char) c;
}
return new String(chars, 0, length);
}
public final String readUTF16() throws IOException {
int length = readVarInt();
if (length == 0) return "";
ensure(length * 2);
char[] chars = ensureCharArray(length);
for (int i = 0; i < length; i++) {
byte b1 = in.array()[in.pos];
byte b2 = in.array()[in.pos + 1];
in.pos += 2;
chars[i] = (char) (((b1 & 0xFF) << 8) + (b2 & 0xFF));
}
return new String(chars, 0, length);
}
public final @Nullable String readUTF8Nullable() throws IOException {
int length = readVarInt();
if (length-- == 0) return null;
if (length == 0) return "";
ensure(length);
String str = new String(in.array(), in.pos(), length, UTF_8);
in.pos(in.pos() + length);
return str;
}
public final @Nullable String readIso88591Nullable() throws IOException {
int length = readVarInt();
if (length-- == 0) return null;
if (length == 0) return "";
ensure(length);
char[] chars = ensureCharArray(length);
for (int i = 0; i < length; i++) {
int c = readByte() & 0xff;
chars[i] = (char) c;
}
return new String(chars, 0, length);
}
public final @Nullable String readUTF16Nullable() throws IOException {
int length = readVarInt();
if (length-- == 0) return null;
if (length == 0) return "";
ensure(length * 2);
char[] chars = ensureCharArray(length);
for (int i = 0; i < length; i++) {
byte b1 = in.array()[in.pos];
byte b2 = in.array()[in.pos + 1];
in.pos += 2;
chars[i] = (char) (((b1 & 0xFF) << 8) + (b2 & 0xFF));
}
return new String(chars, 0, length);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy