package ru.gravit.launcher.serialize; import java.io.ByteArrayInputStream; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; import java.util.Objects; import java.util.UUID; import ru.gravit.launcher.LauncherAPI; import ru.gravit.utils.helper.IOHelper; public final class HInput implements AutoCloseable { @LauncherAPI public final InputStream stream; @LauncherAPI public HInput(byte[] bytes) { stream = new ByteArrayInputStream(bytes); } @LauncherAPI public HInput(InputStream stream) { this.stream = Objects.requireNonNull(stream, "stream"); } @Override public void close() throws IOException { stream.close(); } @LauncherAPI public String readASCII(int maxBytes) throws IOException { return IOHelper.decodeASCII(readByteArray(maxBytes)); } @LauncherAPI public BigInteger readBigInteger(int maxBytes) throws IOException { return new BigInteger(readByteArray(maxBytes)); } @LauncherAPI public boolean readBoolean() throws IOException { int b = readUnsignedByte(); switch (b) { case 0b0: return false; case 0b1: return true; default: throw new IOException("Invalid boolean state: " + b); } } @LauncherAPI public byte[] readByteArray(int max) throws IOException { byte[] bytes = new byte[readLength(max)]; IOHelper.read(stream, bytes); return bytes; } @LauncherAPI public int readInt() throws IOException { return (readUnsignedByte() << 24) + (readUnsignedByte() << 16) + (readUnsignedByte() << 8) + readUnsignedByte(); } @LauncherAPI public int readLength(int max) throws IOException { if (max < 0) return -max; return IOHelper.verifyLength(readVarInt(), max); } @LauncherAPI public long readLong() throws IOException { return (long) readInt() << 32 | readInt() & 0xFFFFFFFFL; } @LauncherAPI public short readShort() throws IOException { return (short) ((readUnsignedByte() << 8) + readUnsignedByte()); } @LauncherAPI public String readString(int maxBytes) throws IOException { return IOHelper.decode(readByteArray(maxBytes)); } @LauncherAPI public int readUnsignedByte() throws IOException { int b = stream.read(); if (b < 0) throw new EOFException("readUnsignedByte"); return b; } @LauncherAPI public int readUnsignedShort() throws IOException { return Short.toUnsignedInt(readShort()); } @LauncherAPI public UUID readUUID() throws IOException { return new UUID(readLong(), readLong()); } @LauncherAPI public int readVarInt() throws IOException { int shift = 0; int result = 0; while (shift < Integer.SIZE) { int b = readUnsignedByte(); result |= (b & 0x7F) << shift; if ((b & 0x80) == 0) return result; shift += 7; } throw new IOException("VarInt too big"); } @LauncherAPI public long readVarLong() throws IOException { int shift = 0; long result = 0; while (shift < Long.SIZE) { int b = readUnsignedByte(); result |= (long) (b & 0x7F) << shift; if ((b & 0x80) == 0) return result; shift += 7; } throw new IOException("VarLong too big"); } }