Provide encode buffer hint
This commit is contained in:
@@ -32,13 +32,18 @@ public interface MinecraftPacket {
|
||||
|
||||
boolean handle(MinecraftSessionHandler handler);
|
||||
|
||||
default int expectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
default int decodeExpectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
ProtocolVersion version) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
default int expectedMinLength(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
default int decodeExpectedMinLength(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
ProtocolVersion version) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
default int encodeSizeHint(ProtocolUtils.Direction direction,
|
||||
ProtocolVersion version) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,6 +292,17 @@ public enum ProtocolUtils {
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the size of the written {@code str} if encoded as a VarInt-prefixed UTF-8 string.
|
||||
*
|
||||
* @param str the string to write
|
||||
* @return the encoded size
|
||||
*/
|
||||
public static int stringSizeHint(CharSequence str) {
|
||||
int size = ByteBufUtil.utf8Bytes(str);
|
||||
return varIntBytes(size) + size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the specified {@code str} to the {@code buf} with a VarInt prefix.
|
||||
*
|
||||
|
||||
@@ -96,8 +96,8 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
|
||||
private void doLengthSanityChecks(ByteBuf buf, MinecraftPacket packet) throws Exception {
|
||||
int expectedMinLen = packet.expectedMinLength(buf, direction, registry.version);
|
||||
int expectedMaxLen = packet.expectedMaxLength(buf, direction, registry.version);
|
||||
int expectedMinLen = packet.decodeExpectedMinLength(buf, direction, registry.version);
|
||||
int expectedMaxLen = packet.decodeExpectedMaxLength(buf, direction, registry.version);
|
||||
if (expectedMaxLen != -1 && buf.readableBytes() > expectedMaxLen) {
|
||||
throw handleOverflow(packet, expectedMaxLen, buf.readableBytes());
|
||||
}
|
||||
|
||||
@@ -54,6 +54,19 @@ public class MinecraftEncoder extends MessageToByteEncoder<MinecraftPacket> {
|
||||
msg.encode(out, direction, registry.version);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, MinecraftPacket msg,
|
||||
boolean preferDirect) throws Exception {
|
||||
int hint = msg.encodeSizeHint(direction, registry.version);
|
||||
if (hint < 0) {
|
||||
return super.allocateBuffer(ctx, msg, preferDirect);
|
||||
}
|
||||
|
||||
int packetId = this.registry.getPacketId(msg);
|
||||
int totalHint = ProtocolUtils.varIntBytes(packetId) + hint;
|
||||
return preferDirect ? ctx.alloc().ioBuffer(totalHint) : ctx.alloc().heapBuffer(totalHint);
|
||||
}
|
||||
|
||||
public void setProtocolVersion(final ProtocolVersion protocolVersion) {
|
||||
this.registry = state.getProtocolRegistry(direction, protocolVersion);
|
||||
}
|
||||
|
||||
@@ -131,8 +131,8 @@ public class MinecraftVarintFrameDecoder extends ByteToMessageDecoder {
|
||||
|
||||
// We 'technically' have the incoming bytes of a payload here, and so, these can actually parse
|
||||
// the packet if needed, so, we'll take advantage of the existing methods
|
||||
int expectedMinLen = packet.expectedMinLength(in, direction, registry.version);
|
||||
int expectedMaxLen = packet.expectedMaxLength(in, direction, registry.version);
|
||||
int expectedMinLen = packet.decodeExpectedMinLength(in, direction, registry.version);
|
||||
int expectedMaxLen = packet.decodeExpectedMaxLength(in, direction, registry.version);
|
||||
if (expectedMaxLen != -1 && payloadLength > expectedMaxLen) {
|
||||
throw handleOverflow(packet, expectedMaxLen, in.readableBytes());
|
||||
}
|
||||
|
||||
@@ -362,4 +362,12 @@ public class AvailableCommandsPacket implements MinecraftPacket {
|
||||
return builder.buildFuture();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeSizeHint(Direction direction, ProtocolVersion version) {
|
||||
// This is a very complex packet to encode. Paper 1.21.10 + Velocity with Spark has a size of
|
||||
// 30,334, but this is likely on the lower side. We'll use 128KiB as a more realistically-sized
|
||||
// amount.
|
||||
return 128 * 1024;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ public class EncryptionResponsePacket implements MinecraftPacket {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||
public int decodeExpectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||
// It turns out these come out to the same length, whether we're talking >=1.8 or not.
|
||||
// The length prefix always winds up being 2 bytes.
|
||||
int base = 256 + 2 + 2;
|
||||
@@ -123,8 +123,8 @@ public class EncryptionResponsePacket implements MinecraftPacket {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expectedMinLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||
int base = expectedMaxLength(buf, direction, version);
|
||||
public int decodeExpectedMinLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||
int base = decodeExpectedMaxLength(buf, direction, version);
|
||||
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19)) {
|
||||
// These are "optional"
|
||||
base -= 128 + 8;
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class HandshakePacket implements MinecraftPacket {
|
||||
@@ -108,14 +109,21 @@ public class HandshakePacket implements MinecraftPacket {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expectedMinLength(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
public int decodeExpectedMinLength(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
ProtocolVersion version) {
|
||||
return 7;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
public int decodeExpectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
ProtocolVersion version) {
|
||||
return 9 + (MAXIMUM_HOSTNAME_LENGTH * 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeSizeHint(Direction direction, ProtocolVersion version) {
|
||||
// We could compute an exact size, but 4KiB ought to be enough to encode all reasonable
|
||||
// sizes of this packet.
|
||||
return 4 * 1024;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public class LoginAcknowledgedPacket implements MinecraftPacket {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
public int decodeExpectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
ProtocolVersion version) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||
import com.velocitypowered.proxy.protocol.util.DeferredByteBufHolder;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
@@ -86,4 +87,9 @@ public class LoginPluginMessagePacket extends DeferredByteBufHolder implements M
|
||||
public boolean handle(MinecraftSessionHandler handler) {
|
||||
return handler.handle(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeSizeHint(Direction direction, ProtocolVersion version) {
|
||||
return content().readableBytes();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||
import com.velocitypowered.proxy.protocol.util.DeferredByteBufHolder;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
@@ -88,4 +89,9 @@ public class LoginPluginResponsePacket extends DeferredByteBufHolder implements
|
||||
public boolean handle(MinecraftSessionHandler handler) {
|
||||
return handler.handle(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeSizeHint(Direction direction, ProtocolVersion version) {
|
||||
return content().readableBytes();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||
import com.velocitypowered.proxy.protocol.util.DeferredByteBufHolder;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
@@ -143,4 +144,9 @@ public class PluginMessagePacket extends DeferredByteBufHolder implements Minecr
|
||||
public PluginMessagePacket touch(Object hint) {
|
||||
return (PluginMessagePacket) super.touch(hint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeSizeHint(Direction direction, ProtocolVersion version) {
|
||||
return content().readableBytes();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.velocitypowered.api.util.Favicon;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -121,4 +122,9 @@ public class ServerDataPacket implements MinecraftPacket {
|
||||
public void setSecureChatEnforced(boolean secureChatEnforced) {
|
||||
this.secureChatEnforced = secureChatEnforced;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeSizeHint(Direction direction, ProtocolVersion version) {
|
||||
return 8 * 1024;
|
||||
}
|
||||
}
|
||||
@@ -150,7 +150,7 @@ public class ServerLoginPacket implements MinecraftPacket {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||
public int decodeExpectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||
// Accommodate the rare (but likely malicious) use of UTF-8 usernames, since it is technically
|
||||
// legal on the protocol level.
|
||||
int base = 1 + (16 * 3);
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.velocitypowered.api.util.UuidUtils;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||
import com.velocitypowered.proxy.util.VelocityProperties;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.util.List;
|
||||
@@ -132,4 +133,11 @@ public class ServerLoginSuccessPacket implements MinecraftPacket {
|
||||
public boolean handle(MinecraftSessionHandler handler) {
|
||||
return handler.handle(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeSizeHint(Direction direction, ProtocolVersion version) {
|
||||
// We could compute an exact size, but 4KiB ought to be enough to encode all reasonable
|
||||
// sizes of this packet.
|
||||
return 4 * 1024;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||
import com.velocitypowered.proxy.protocol.util.DeferredByteBufHolder;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
@@ -45,4 +46,8 @@ public class ServerboundCustomClickActionPacket extends DeferredByteBufHolder im
|
||||
return handler.handle(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeSizeHint(Direction direction, ProtocolVersion version) {
|
||||
return content().readableBytes();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,12 +44,12 @@ public class StatusPingPacket implements MinecraftPacket {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||
public int decodeExpectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expectedMinLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||
public int decodeExpectedMinLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public class StatusRequestPacket implements MinecraftPacket {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||
public int decodeExpectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
@@ -66,4 +67,9 @@ public class StatusResponsePacket implements MinecraftPacket {
|
||||
public boolean handle(MinecraftSessionHandler handler) {
|
||||
return handler.handle(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeSizeHint(Direction direction, ProtocolVersion version) {
|
||||
return ProtocolUtils.stringSizeHint(this.status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class UpsertPlayerInfoPacket implements MinecraftPacket {
|
||||
|
||||
private static final Action[] ALL_ACTIONS = Action.class.getEnumConstants();
|
||||
|
||||
private final EnumSet<Action> actions;
|
||||
private final List<Entry> entries;
|
||||
|
||||
@@ -85,14 +87,13 @@ public class UpsertPlayerInfoPacket implements MinecraftPacket {
|
||||
@Override
|
||||
public void decode(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
ProtocolVersion protocolVersion) {
|
||||
Action[] actions = Action.class.getEnumConstants();
|
||||
byte[] bytes = new byte[-Math.floorDiv(-actions.length, 8)];
|
||||
byte[] bytes = new byte[-Math.floorDiv(-ALL_ACTIONS.length, 8)];
|
||||
buf.readBytes(bytes);
|
||||
BitSet actionSet = BitSet.valueOf(bytes);
|
||||
|
||||
for (int idx = 0; idx < actions.length; idx++) {
|
||||
for (int idx = 0; idx < ALL_ACTIONS.length; idx++) {
|
||||
if (actionSet.get(idx)) {
|
||||
addAction(actions[idx]);
|
||||
addAction(ALL_ACTIONS[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,14 +110,13 @@ public class UpsertPlayerInfoPacket implements MinecraftPacket {
|
||||
@Override
|
||||
public void encode(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
ProtocolVersion protocolVersion) {
|
||||
Action[] actions = Action.class.getEnumConstants();
|
||||
BitSet set = new BitSet(actions.length);
|
||||
for (int idx = 0; idx < actions.length; idx++) {
|
||||
set.set(idx, this.actions.contains(actions[idx]));
|
||||
BitSet set = new BitSet(ALL_ACTIONS.length);
|
||||
for (int idx = 0; idx < ALL_ACTIONS.length; idx++) {
|
||||
set.set(idx, this.actions.contains(ALL_ACTIONS[idx]));
|
||||
}
|
||||
|
||||
byte[] bytes = set.toByteArray();
|
||||
buf.writeBytes(Arrays.copyOf(bytes, -Math.floorDiv(-actions.length, 8)));
|
||||
buf.writeBytes(Arrays.copyOf(bytes, -Math.floorDiv(-ALL_ACTIONS.length, 8)));
|
||||
|
||||
ProtocolUtils.writeVarInt(buf, this.entries.size());
|
||||
for (Entry entry : this.entries) {
|
||||
@@ -133,12 +133,6 @@ public class UpsertPlayerInfoPacket implements MinecraftPacket {
|
||||
return handler.handle(this);
|
||||
}
|
||||
|
||||
public BitSet readFixedBitSet(ByteBuf buf, int param0) {
|
||||
byte[] var0 = new byte[-Math.floorDiv(-param0, 8)];
|
||||
buf.readBytes(var0);
|
||||
return BitSet.valueOf(var0);
|
||||
}
|
||||
|
||||
public enum Action {
|
||||
ADD_PLAYER((ignored, buf, info) -> { // read
|
||||
info.profile = new GameProfile(
|
||||
|
||||
@@ -44,4 +44,9 @@ public class CodeOfConductPacket extends DeferredByteBufHolder implements Minecr
|
||||
public boolean handle(MinecraftSessionHandler handler) {
|
||||
return handler.handle(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeSizeHint(Direction direction, ProtocolVersion version) {
|
||||
return content().readableBytes();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public class FinishedUpdatePacket implements MinecraftPacket {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
public int decodeExpectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
ProtocolVersion version) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||
import com.velocitypowered.proxy.protocol.util.DeferredByteBufHolder;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
@@ -47,4 +48,9 @@ public class RegistrySyncPacket extends DeferredByteBufHolder implements Minecra
|
||||
public boolean handle(MinecraftSessionHandler handler) {
|
||||
return handler.handle(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeSizeHint(Direction direction, ProtocolVersion version) {
|
||||
return content().readableBytes();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public class StartUpdatePacket implements MinecraftPacket {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
public int decodeExpectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction,
|
||||
ProtocolVersion version) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -79,4 +80,22 @@ public class TagsUpdatePacket implements MinecraftPacket {
|
||||
public boolean handle(MinecraftSessionHandler handler) {
|
||||
return handler.handle(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeSizeHint(Direction direction, ProtocolVersion version) {
|
||||
int size = ProtocolUtils.varIntBytes(tags.size());
|
||||
for (Map.Entry<String, Map<String, int[]>> entry : tags.entrySet()) {
|
||||
size += ProtocolUtils.stringSizeHint(entry.getKey());
|
||||
size += ProtocolUtils.varIntBytes(entry.getValue().size());
|
||||
for (Map.Entry<String, int[]> innerEntry : entry.getValue().entrySet()) {
|
||||
size += ProtocolUtils.stringSizeHint(innerEntry.getKey());
|
||||
size += ProtocolUtils.varIntBytes(innerEntry.getValue().length);
|
||||
for (int innerEntryValue : innerEntry.getValue()) {
|
||||
size += ProtocolUtils.varIntBytes(innerEntryValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user