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

cn.wjybxx.dson.io.DsonInputs Maven / Gradle / Ivy

There is a newer version: 2.2.0
Show newest version
/*
 * Copyright 2023-2024 wjybxx([email protected])
 *
 * 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
 *
 *     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 cn.wjybxx.dson.io;

import cn.wjybxx.base.io.ByteBufferUtils;
import cn.wjybxx.base.mutable.MutableInt;
import cn.wjybxx.dson.internal.CodedUtils;

import java.nio.charset.StandardCharsets;

/**
 * 核心包去除了对Protobuf的支持,如果期望使用protobuf和netty读取数据,可引入相应的扩展包。
 *
 * @author wjybxx
 * date - 2023/4/22
 */
public class DsonInputs {

    public static DsonInput newInstance(byte[] buffer) {
        return new ArrayDsonInput(buffer, 0, buffer.length);
    }

    public static DsonInput newInstance(byte[] buffer, int offset, int length) {
        return new ArrayDsonInput(buffer, offset, length);
    }

    static class ArrayDsonInput implements DsonInput {

        private final byte[] buffer;
        private final int rawOffset;
        private final int rawLimit;

        private int bufferPos;
        private int bufferPosLimit;
        private final MutableInt newPos = new MutableInt();

        ArrayDsonInput(byte[] buffer, int offset, int length) {
            ByteBufferUtils.checkBuffer(buffer, offset, length);
            this.buffer = buffer;
            this.rawOffset = offset;
            this.rawLimit = offset + length;

            this.bufferPos = offset;
            this.bufferPosLimit = offset + length;
        }

        // region check

        private int checkNewBufferPos(int newBufferPos) {
            if (newBufferPos < rawOffset || newBufferPos > bufferPosLimit) {
                throw new DsonIOException("BytesLimited, LimitPos: %d, position: %d, newPosition: %d"
                        .formatted(bufferPosLimit, bufferPos, newBufferPos));
            }
            return newBufferPos;
        }

        //endregion

        // region basic

        @Override
        public byte readRawByte() {
            checkNewBufferPos(bufferPos + 1);
            return buffer[bufferPos++];
        }

        @Override
        public int readInt32() {
            try {
                int r = CodedUtils.readInt32(buffer, bufferPos, newPos);
                bufferPos = checkNewBufferPos(newPos.getValue());
                return r;
            } catch (Exception e) {
                throw DsonIOException.wrap(e, "buffer overflow");
            }
        }

        @Override
        public int readUint32() {
            try {
                int r = CodedUtils.readUint32(buffer, bufferPos, newPos);
                bufferPos = checkNewBufferPos(newPos.getValue());
                return r;
            } catch (Exception e) {
                throw DsonIOException.wrap(e, "buffer overflow");
            }
        }

        @Override
        public int readSint32() {
            try {
                int r = CodedUtils.readSint32(buffer, bufferPos, newPos);
                bufferPos = checkNewBufferPos(newPos.getValue());
                return r;
            } catch (Exception e) {
                throw DsonIOException.wrap(e, "buffer overflow");
            }
        }

        @Override
        public int readFixed32() {
            try {
                int r = CodedUtils.readFixed32(buffer, bufferPos, newPos);
                bufferPos = checkNewBufferPos(newPos.getValue());
                return r;
            } catch (Exception e) {
                throw DsonIOException.wrap(e, "buffer overflow");
            }
        }

        @Override
        public long readInt64() {
            try {
                long r = CodedUtils.readInt64(buffer, bufferPos, newPos);
                bufferPos = checkNewBufferPos(newPos.getValue());
                return r;
            } catch (Exception e) {
                throw DsonIOException.wrap(e, "buffer overflow");
            }
        }

        @Override
        public long readUint64() {
            try {
                long r = CodedUtils.readUint64(buffer, bufferPos, newPos);
                bufferPos = checkNewBufferPos(newPos.getValue());
                return r;
            } catch (Exception e) {
                throw DsonIOException.wrap(e, "buffer overflow");
            }
        }

        @Override
        public long readSint64() {
            try {
                long r = CodedUtils.readSint64(buffer, bufferPos, newPos);
                bufferPos = checkNewBufferPos(newPos.getValue());
                return r;
            } catch (Exception e) {
                throw DsonIOException.wrap(e, "buffer overflow");
            }
        }

        @Override
        public long readFixed64() {
            try {
                long r = CodedUtils.readFixed64(buffer, bufferPos, newPos);
                bufferPos = checkNewBufferPos(newPos.getValue());
                return r;
            } catch (Exception e) {
                throw DsonIOException.wrap(e, "buffer overflow");
            }
        }

        @Override
        public float readFloat() {
            try {
                float r = CodedUtils.readFloat(buffer, bufferPos, newPos);
                bufferPos = checkNewBufferPos(newPos.getValue());
                return r;
            } catch (Exception e) {
                throw DsonIOException.wrap(e, "buffer overflow");
            }
        }

        @Override
        public double readDouble() {
            try {
                double r = CodedUtils.readDouble(buffer, bufferPos, newPos);
                bufferPos = checkNewBufferPos(newPos.getValue());
                return r;
            } catch (Exception e) {
                throw DsonIOException.wrap(e, "buffer overflow");
            }
        }

        @Override
        public boolean readBool() {
            checkNewBufferPos(bufferPos + 1);
            return buffer[bufferPos++] != 0;
        }

        @Override
        public String readString() {
            try {
                int len = CodedUtils.readUint32(buffer, bufferPos, newPos); // 字符串长度
                checkNewBufferPos(newPos.getValue() + len); // 先检查,避免构建无效字符串

                String r = new String(buffer, newPos.getValue(), len, StandardCharsets.UTF_8);
                bufferPos = newPos.getValue() + len;
                return r;
            } catch (Exception e) {
                throw DsonIOException.wrap(e, "buffer overflow");
            }
        }

        @Override
        public byte[] readRawBytes(int count) {
            checkNewBufferPos(bufferPos + count);
            byte[] bytes = new byte[count];
            System.arraycopy(buffer, bufferPos, bytes, 0, count);
            bufferPos += count;
            return bytes;
        }

        @Override
        public void skipRawBytes(int n) {
            if (n < 0) throw new IllegalArgumentException("n");
            if (n == 0) return;
            bufferPos = checkNewBufferPos(bufferPos + n);
        }
        // endregion

        //region sp

        @Override
        public int getPosition() {
            return bufferPos - rawOffset;
        }

        @Override
        public void setPosition(int value) {
            ByteBufferUtils.checkBuffer(rawLimit - rawOffset, value);
            bufferPos = rawOffset + value;
        }

        @Override
        public byte getByte(int pos) {
            ByteBufferUtils.checkBuffer(rawLimit - rawOffset, pos, 1);
            int bufferPos = rawOffset + pos;
            return buffer[bufferPos];
        }

        @Override
        public int getFixed32(int pos) {
            ByteBufferUtils.checkBuffer(rawLimit - rawOffset, pos, 4);
            int bufferPos = rawOffset + pos;
            return ByteBufferUtils.getInt32LE(buffer, bufferPos);
        }

        @Override
        public int pushLimit(int byteLimit) {
            if (byteLimit < 0) throw new IllegalArgumentException("byteLimit");
            int oldPosLimit = bufferPosLimit;
            int newPosLimit = bufferPos + byteLimit;

            // 不可超过原始限制
            ByteBufferUtils.checkBuffer(rawLimit, rawOffset, newPosLimit - rawOffset);
            bufferPosLimit = newPosLimit;
            return oldPosLimit;
        }

        @Override
        public void popLimit(int oldLimit) {
            // 不可超过原始限制
            ByteBufferUtils.checkBuffer(rawLimit, rawOffset, oldLimit - rawOffset);
            bufferPosLimit = oldLimit;
        }

        @Override
        public int getBytesUntilLimit() {
            return (bufferPosLimit - bufferPos);
        }

        @Override
        public boolean isAtEnd() {
            return bufferPos >= bufferPosLimit;
        }

        @Override
        public void close() {

        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy