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

com.github.netty.protocol.mysql.CodecUtils Maven / Gradle / Ivy

/*
 * Copyright 2016 The Netty Project
 *
 * The Netty Project licenses this file to you 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:
 *
 *   http://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 com.github.netty.protocol.mysql;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.util.AsciiString;

import java.nio.charset.Charset;
import java.util.EnumSet;
import java.util.Set;

public final class CodecUtils {
    private static final byte TERMINAL = 0x00;
    private static final int NULL_VALUE = 0xFB;
    private static final int SHORT_VALUE = 0xFC;
    private static final int MEDIUM_VALUE = 0xFD;
    private static final int LONG_VALUE = 0xFE;

    public static long readLengthEncodedInteger(ByteBuf buf) {
        return readLengthEncodedInteger(buf, buf.readUnsignedByte());
    }

    // https://dev.mysql.com/doc/internals/en/integer.html
    public static long readLengthEncodedInteger(ByteBuf buffer, int firstUnsignedByte) {
        switch (firstUnsignedByte) {
            case NULL_VALUE:
                return -1;
            case SHORT_VALUE:
                return buffer.readUnsignedShortLE();
            case MEDIUM_VALUE:
                return buffer.readUnsignedMediumLE();
            case LONG_VALUE:
                return buffer.readLongLE();
            default:
                return firstUnsignedByte;
        }
    }

    public static AsciiString readNullTerminatedString(ByteBuf buffer) {
        int len = buffer.bytesBefore(TERMINAL);
        byte[] bytes = new byte[len];
        buffer.readBytes(bytes);
        buffer.readByte();
        return new AsciiString(bytes, false);
    }

    public static String readNullTerminatedString(ByteBuf buffer, Charset charset) {
        int len = buffer.bytesBefore(TERMINAL);
        String s = buffer.readCharSequence(len, charset).toString();
        buffer.readByte();
        return s;
    }

    public static int findNullTermLen(ByteBuf buf) {
        int termIdx = buf.indexOf(buf.readerIndex(), buf.capacity(), (byte) 0);
        if (termIdx < 0) {
            return -1;
        }
        return termIdx - buf.readerIndex();
    }

    public static String readFixedLengthString(ByteBuf buf, int length, Charset charset) {
        if (length < 0) {
            return null;
        }
        String s = buf.toString(buf.readerIndex(), length, charset);
        buf.readerIndex(buf.readerIndex() + length);
        return s;
    }

    public static String readLengthEncodedString(ByteBuf buf, Charset charset) {
        long len = readLengthEncodedInteger(buf);
        return readFixedLengthString(buf, (int) len, charset);
    }

    public static String readLengthEncodedString(ByteBuf buf, int firstByte, Charset charset) {
        long len = readLengthEncodedInteger(buf, firstByte);
        return readFixedLengthString(buf, (int) len, charset);
    }

    public static > EnumSet readShortEnumSet(ByteBuf buf, Class enumClass) {
        return toEnumSet(enumClass, buf.readUnsignedShortLE());
    }

    public static > EnumSet readIntEnumSet(ByteBuf buf, Class enumClass) {
        return toEnumSet(enumClass, buf.readUnsignedIntLE());
    }

    public static > EnumSet toEnumSet(Class enumClass, long vector) {
        EnumSet set = EnumSet.noneOf(enumClass);
        for (E e : enumClass.getEnumConstants()) {
            long mask = 1 << e.ordinal();
            if ((mask & vector) != 0) {
                set.add(e);
            }
        }
        return set;
    }

//    private static  E toEnum(Class enumClass, int i) {
//        E[] enumConstants = enumClass.getEnumConstants();
//        if (i > enumConstants.length) {
//            throw new IndexOutOfBoundsException(String.format(
//                    "%d is too large of an ordinal to convert to the enum %s",
//                    i, enumClass.getName()));
//        }
//        return enumConstants[i];
//    }

    public static > long toLong(Set set) {
        long vector = 0;
        for (E e : set) {
            if (e.ordinal() >= Long.SIZE) {
                throw new IllegalArgumentException("The enum set is too large to fit in a bit vector: " + set);
            }
            vector |= 1L << e.ordinal();
        }
        return vector;
    }

    public static void writeLengthEncodedInt(ByteBuf buf, Long n) {
        if (n == null) {
            buf.writeByte(NULL_VALUE);
        } else if (n < 0) {
            throw new IllegalArgumentException("Cannot encode a negative length: " + n);
        } else if (n < NULL_VALUE) {
            buf.writeByte(n.intValue());
        } else if (n < 0xFFFF) {
            buf.writeByte(SHORT_VALUE);
            buf.writeShortLE(n.intValue());
        } else if (n < 0xFFFFFF) {
            buf.writeByte(MEDIUM_VALUE);
            buf.writeMediumLE(n.intValue());
        } else {
            buf.writeByte(LONG_VALUE);
            buf.writeLongLE(n);
        }
    }

    public static void writeUB2(ByteBuf buffer, int i) {
        buffer.writeByte((byte) (i & 0xff));
        buffer.writeByte((byte) (i >>> 8));
    }

    public static void writeUB3(ByteBuf buffer, int i) {
        buffer.writeByte((byte) (i & 0xff));
        buffer.writeByte((byte) (i >>> 8));
        buffer.writeByte((byte) (i >>> 16));
    }

    public static void writeLengthEncodedString(ByteBuf buf, CharSequence sequence, Charset charset) {
        ByteBuf tmpBuf = Unpooled.buffer();
        try {
            tmpBuf.writeCharSequence(sequence, charset);
            writeLengthEncodedInt(buf, (long) tmpBuf.readableBytes());
            buf.writeBytes(tmpBuf);
        } finally {
            tmpBuf.release();
        }
    }

    public static void writeNullTerminatedString(ByteBuf buf, CharSequence sequence, Charset charset) {
        if (sequence != null) {
            buf.writeCharSequence(sequence, charset);
        }
        buf.writeByte(0);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy