| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF 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 org.apache.ignite.internal.binary; |
| |
| import java.io.EOFException; |
| import java.io.IOException; |
| import java.io.ObjectInput; |
| import java.math.BigDecimal; |
| import java.sql.Time; |
| import java.sql.Timestamp; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.UUID; |
| import org.apache.ignite.binary.BinaryCollectionFactory; |
| import org.apache.ignite.binary.BinaryInvalidTypeException; |
| import org.apache.ignite.binary.BinaryMapFactory; |
| import org.apache.ignite.binary.BinaryObject; |
| import org.apache.ignite.binary.BinaryObjectException; |
| import org.apache.ignite.binary.BinaryRawReader; |
| import org.apache.ignite.binary.BinaryReader; |
| import org.apache.ignite.internal.binary.streams.BinaryInputStream; |
| import org.apache.ignite.internal.util.IgniteUtils; |
| import org.apache.ignite.internal.util.typedef.internal.S; |
| import org.apache.ignite.internal.util.typedef.internal.SB; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.BINARY_ENUM; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.BINARY_OBJ; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.BOOLEAN; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.BOOLEAN_ARR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.BYTE; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.BYTE_ARR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.CHAR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.CHAR_ARR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.CLASS; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.COL; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.DATE; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.DATE_ARR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.DECIMAL; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.DECIMAL_ARR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.DFLT_HDR_LEN; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.DOUBLE; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.DOUBLE_ARR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.ENUM; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.ENUM_ARR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.FLOAT; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.FLOAT_ARR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.HANDLE; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.INT; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.INT_ARR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.LONG; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.LONG_ARR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.MAP; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.NULL; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.OBJ; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.OBJ_ARR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.OPTM_MARSH; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.PROXY; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.SHORT; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.SHORT_ARR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.STRING; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.STRING_ARR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.TIME; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.TIMESTAMP; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.TIMESTAMP_ARR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.TIME_ARR; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.UNREGISTERED_TYPE_ID; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.UUID; |
| import static org.apache.ignite.internal.binary.GridBinaryMarshaller.UUID_ARR; |
| |
| /** |
| * Binary reader implementation. |
| */ |
| @SuppressWarnings("unchecked") |
| public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, BinaryReaderHandlesHolder, ObjectInput { |
| /** Binary context. */ |
| private final BinaryContext ctx; |
| |
| /** Input stream. */ |
| private final BinaryInputStream in; |
| |
| /** Class loaded. */ |
| private final ClassLoader ldr; |
| |
| /** Reader context which is constantly passed between objects. */ |
| private BinaryReaderHandles hnds; |
| |
| /** */ |
| private final int start; |
| |
| /** Start of actual data. Positioned right after the header. */ |
| private final int dataStart; |
| |
| /** Type ID. */ |
| private final int typeId; |
| |
| /** Raw offset. */ |
| private final int rawOff; |
| |
| /** Footer start. */ |
| private final int footerStart; |
| |
| /** Footer end. */ |
| private final int footerLen; |
| |
| /** Class descriptor. */ |
| private BinaryClassDescriptor desc; |
| |
| /** Mapper. */ |
| private final BinaryInternalMapper mapper; |
| |
| /** Schema Id. */ |
| private final int schemaId; |
| |
| /** Whether this is user type or not. */ |
| private final boolean userType; |
| |
| /** Whether field IDs exist. */ |
| private final int fieldIdLen; |
| |
| /** Offset size in bytes. */ |
| private final int fieldOffLen; |
| |
| /** Object schema. */ |
| private final BinarySchema schema; |
| |
| /** Whether passed IDs matches schema order. Reset to false as soon as a single mismatch detected. */ |
| private boolean matching = true; |
| |
| /** Order of a field whose match is expected. */ |
| private int matchingOrder; |
| |
| /** Whether stream is in raw mode. */ |
| private boolean raw; |
| |
| /** |
| * Constructor. |
| * |
| * @param ctx Context. |
| * @param in Input stream. |
| * @param ldr Class loader. |
| * @param forUnmarshal {@code True} if reader is needed to unmarshal object. |
| */ |
| public BinaryReaderExImpl(BinaryContext ctx, BinaryInputStream in, ClassLoader ldr, boolean forUnmarshal) { |
| this(ctx, |
| in, |
| ldr, |
| null, |
| forUnmarshal); |
| } |
| |
| /** |
| * Constructor. |
| * |
| * @param ctx Context. |
| * @param in Input stream. |
| * @param ldr Class loader. |
| * @param hnds Context. |
| * @param forUnmarshal {@code True} if reader is need to unmarshal object. |
| */ |
| public BinaryReaderExImpl(BinaryContext ctx, |
| BinaryInputStream in, |
| ClassLoader ldr, |
| @Nullable BinaryReaderHandles hnds, |
| boolean forUnmarshal) { |
| this(ctx, |
| in, |
| ldr, |
| hnds, |
| false, |
| forUnmarshal); |
| } |
| |
| /** |
| * Constructor. |
| * |
| * @param ctx Context. |
| * @param in Input stream. |
| * @param ldr Class loader. |
| * @param hnds Context. |
| * @param skipHdrCheck Whether to skip header check. |
| * @param forUnmarshal {@code True} if reader is need to unmarshal object. |
| */ |
| public BinaryReaderExImpl(BinaryContext ctx, |
| BinaryInputStream in, |
| ClassLoader ldr, |
| @Nullable BinaryReaderHandles hnds, |
| boolean skipHdrCheck, |
| boolean forUnmarshal) { |
| // Initialize base members. |
| this.ctx = ctx; |
| this.in = in; |
| this.ldr = ldr; |
| this.hnds = hnds; |
| |
| start = in.position(); |
| |
| // Perform full header parsing in case of binary object. |
| if (!skipHdrCheck && (in.readByte() == GridBinaryMarshaller.OBJ)) { |
| // Ensure protocol is fine. |
| BinaryUtils.checkProtocolVersion(in.readByte()); |
| |
| // Read header content. |
| short flags = in.readShort(); |
| int typeId0 = in.readInt(); |
| |
| in.readInt(); // Skip hash code. |
| |
| int len = in.readInt(); |
| schemaId = in.readInt(); |
| int offset = in.readInt(); |
| |
| // Get trivial flag values. |
| userType = BinaryUtils.isUserType(flags); |
| fieldIdLen = BinaryUtils.fieldIdLength(flags); |
| fieldOffLen = BinaryUtils.fieldOffsetLength(flags); |
| |
| // Calculate footer borders and raw offset. |
| if (BinaryUtils.hasSchema(flags)) { |
| // Schema exists. |
| footerStart = start + offset; |
| |
| if (BinaryUtils.hasRaw(flags)) { |
| footerLen = len - offset; |
| rawOff = start + in.readIntPositioned(start + len - 4); |
| } |
| else { |
| footerLen = len - offset; |
| rawOff = start + len; |
| } |
| } |
| else { |
| // No schema. |
| footerStart = start + len; |
| footerLen = 0; |
| |
| if (BinaryUtils.hasRaw(flags)) |
| rawOff = start + offset; |
| else |
| rawOff = start + len; |
| } |
| |
| // Finally, we have to resolve real type ID. |
| if (typeId0 == UNREGISTERED_TYPE_ID) { |
| int off = in.position(); |
| |
| if (forUnmarshal) { |
| // Registers class by type ID, at least locally if the cache is not ready yet. |
| desc = ctx.descriptorForClass(BinaryUtils.doReadClass(in, ctx, ldr, typeId0), false, false); |
| |
| typeId = desc.typeId(); |
| } |
| else |
| typeId = ctx.typeId(BinaryUtils.doReadClassName(in)); |
| |
| int clsNameLen = in.position() - off; |
| |
| dataStart = start + DFLT_HDR_LEN + clsNameLen; |
| } |
| else { |
| typeId = typeId0; |
| |
| dataStart = start + DFLT_HDR_LEN; |
| } |
| |
| mapper = userType ? ctx.userTypeMapper(typeId) : BinaryContext.defaultMapper(); |
| schema = BinaryUtils.hasSchema(flags) ? getOrCreateSchema() : null; |
| } |
| else { |
| dataStart = 0; |
| typeId = 0; |
| rawOff = 0; |
| footerStart = 0; |
| footerLen = 0; |
| mapper = null; |
| schemaId = 0; |
| userType = false; |
| fieldIdLen = 0; |
| fieldOffLen = 0; |
| schema = null; |
| } |
| |
| streamPosition(start); |
| } |
| |
| /** |
| * @return Input stream. |
| */ |
| public BinaryInputStream in() { |
| return in; |
| } |
| |
| /** |
| * @return Descriptor. |
| */ |
| BinaryClassDescriptor descriptor() { |
| if (desc == null) |
| desc = ctx.descriptorForTypeId(userType, typeId, ldr, true); |
| |
| return desc; |
| } |
| |
| /** |
| * @param offset Offset in the array. |
| * @return Unmarshalled value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| public Object unmarshal(int offset) throws BinaryObjectException { |
| streamPosition(offset); |
| |
| return in.position() >= 0 ? BinaryUtils.unmarshal(in, ctx, ldr, this) : null; |
| } |
| |
| /** |
| * @param fieldName Field name. |
| * @return Unmarshalled value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Object unmarshalField(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? BinaryUtils.unmarshal(in, ctx, ldr, this) : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Unmarshalled value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Object unmarshalField(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? BinaryUtils.unmarshal(in, ctx, ldr, this) : null; |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Binary object. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable BinaryObject readBinaryObject(int fieldId) throws BinaryObjectException { |
| if (findFieldById(fieldId)) { |
| if (checkFlag(BINARY_OBJ) == Flag.NULL) |
| return null; |
| |
| return new BinaryObjectImpl(ctx, BinaryUtils.doReadByteArray(in), in.readInt()); |
| } |
| else |
| return null; |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Field class. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Class<?> readClass(int fieldId) throws BinaryObjectException { |
| if (findFieldById(fieldId)) { |
| if (checkFlag(CLASS) == Flag.NULL) |
| return null; |
| |
| return BinaryUtils.doReadClass(in, ctx, ldr); |
| } |
| |
| return null; |
| } |
| |
| /** |
| * @param obj Object. |
| */ |
| void setHandle(Object obj) { |
| setHandle(obj, start); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void setHandle(Object obj, int pos) { |
| handles().put(pos, obj); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public Object getHandle(int pos) { |
| return hnds != null ? hnds.get(pos) : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public BinaryReaderHandles handles() { |
| if (hnds == null) |
| hnds = new BinaryReaderHandles(); |
| |
| return hnds; |
| } |
| |
| /** |
| * Recreating field value from a handle. |
| * |
| * @param <T> Field type. |
| * @return Field. |
| */ |
| private <T> T readHandleField() { |
| int handlePos = BinaryUtils.positionForHandle(in) - in.readInt(); |
| |
| Object obj = getHandle(handlePos); |
| |
| if (obj == null) { |
| int retPos = in.position(); |
| |
| streamPosition(handlePos); |
| |
| obj = BinaryUtils.doReadObject(in, ctx, ldr, this); |
| |
| streamPosition(retPos); |
| } |
| |
| return (T)obj; |
| } |
| |
| /** |
| * Wraps an exception by adding the fieldName |
| * |
| * @param fieldName the name of the field, causes failure |
| * @param e the cause of the deserialization failure |
| * @return wrapping exception |
| */ |
| private BinaryObjectException wrapFieldException(String fieldName, Exception e) { |
| if (S.INCLUDE_SENSITIVE) |
| return new BinaryObjectException("Failed to read field: " + fieldName, e); |
| else |
| return new BinaryObjectException("Failed to read field.", e); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public byte readByte(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) && checkFlagNoHandles(BYTE) == Flag.NORMAL ? in.readByte() : 0; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException If failed. |
| */ |
| byte readByte(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(BYTE) == Flag.NORMAL ? in.readByte() : 0; |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Byte readByteNullable(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(BYTE) == Flag.NORMAL ? in.readByte() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public byte readByte() throws BinaryObjectException { |
| return in.readByte(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public byte[] readByteArray(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readByteArray() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable byte[] readByteArray(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readByteArray() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public byte[] readByteArray() throws BinaryObjectException { |
| switch (checkFlag(BYTE_ARR)) { |
| case NORMAL: |
| return BinaryUtils.doReadByteArray(in); |
| |
| case HANDLE: |
| return readHandleField(); |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean readBoolean(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) && checkFlagNoHandles(BOOLEAN) == Flag.NORMAL && in.readBoolean(); |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException If failed. |
| */ |
| boolean readBoolean(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(BOOLEAN) == Flag.NORMAL && in.readBoolean(); |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Boolean readBooleanNullable(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(BOOLEAN) == Flag.NORMAL ? in.readBoolean() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean readBoolean() throws BinaryObjectException { |
| return in.readBoolean(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public boolean[] readBooleanArray(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readBooleanArray() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable boolean[] readBooleanArray(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readBooleanArray() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public boolean[] readBooleanArray() throws BinaryObjectException { |
| switch (checkFlag(BOOLEAN_ARR)) { |
| case NORMAL: |
| return BinaryUtils.doReadBooleanArray(in); |
| |
| case HANDLE: |
| return readHandleField(); |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public short readShort(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) && checkFlagNoHandles(SHORT) == Flag.NORMAL ? in.readShort() : 0; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException If failed. |
| */ |
| short readShort(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(SHORT) == Flag.NORMAL ? in.readShort() : 0; |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Short readShortNullable(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(SHORT) == Flag.NORMAL ? in.readShort() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public short readShort() throws BinaryObjectException { |
| return in.readShort(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public short[] readShortArray(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readShortArray() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable short[] readShortArray(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readShortArray() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public short[] readShortArray() throws BinaryObjectException { |
| switch (checkFlag(SHORT_ARR)) { |
| case NORMAL: |
| return BinaryUtils.doReadShortArray(in); |
| |
| case HANDLE: |
| return readHandleField(); |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public char readChar(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) && checkFlagNoHandles(CHAR) == Flag.NORMAL ? in.readChar() : 0; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException If failed. |
| */ |
| char readChar(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(CHAR) == Flag.NORMAL ? in.readChar() : 0; |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Character readCharNullable(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(CHAR) == Flag.NORMAL ? in.readChar() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public char readChar() throws BinaryObjectException { |
| return in.readChar(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public char[] readCharArray(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readCharArray() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable char[] readCharArray(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readCharArray() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public char[] readCharArray() throws BinaryObjectException { |
| switch (checkFlag(CHAR_ARR)) { |
| case NORMAL: |
| return BinaryUtils.doReadCharArray(in); |
| |
| case HANDLE: |
| return readHandleField(); |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int readInt(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) && checkFlagNoHandles(INT) == Flag.NORMAL ? in.readInt() : 0; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException If failed. |
| */ |
| int readInt(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(INT) == Flag.NORMAL ? in.readInt() : 0; |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Integer readIntNullable(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(INT) == Flag.NORMAL ? in.readInt() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int readInt() throws BinaryObjectException { |
| return in.readInt(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public int[] readIntArray(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readIntArray() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable int[] readIntArray(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readIntArray() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public int[] readIntArray() throws BinaryObjectException { |
| switch (checkFlag(INT_ARR)) { |
| case NORMAL: |
| return BinaryUtils.doReadIntArray(in); |
| |
| case HANDLE: |
| return readHandleField(); |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public long readLong(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) && checkFlagNoHandles(LONG) == Flag.NORMAL ? in.readLong() : 0; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException If failed. |
| */ |
| long readLong(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(LONG) == Flag.NORMAL ? in.readLong() : 0; |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Long readLongNullable(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(LONG) == Flag.NORMAL ? in.readLong() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public long readLong() throws BinaryObjectException { |
| return in.readLong(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public long[] readLongArray(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readLongArray() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable long[] readLongArray(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readLongArray() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public long[] readLongArray() throws BinaryObjectException { |
| switch (checkFlag(LONG_ARR)) { |
| case NORMAL: |
| return BinaryUtils.doReadLongArray(in); |
| |
| case HANDLE: |
| return readHandleField(); |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public float readFloat(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) && checkFlagNoHandles(FLOAT) == Flag.NORMAL ? in.readFloat() : 0; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException If failed. |
| */ |
| float readFloat(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(FLOAT) == Flag.NORMAL ? in.readFloat() : 0; |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Float readFloatNullable(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(FLOAT) == Flag.NORMAL ? in.readFloat() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public float readFloat() throws BinaryObjectException { |
| return in.readFloat(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public float[] readFloatArray(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readFloatArray() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable float[] readFloatArray(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readFloatArray() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public float[] readFloatArray() throws BinaryObjectException { |
| switch (checkFlag(FLOAT_ARR)) { |
| case NORMAL: |
| return BinaryUtils.doReadFloatArray(in); |
| |
| case HANDLE: |
| return readHandleField(); |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public double readDouble(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) && checkFlagNoHandles(DOUBLE) == Flag.NORMAL ? in.readDouble() : 0; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException If failed. |
| */ |
| double readDouble(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(DOUBLE) == Flag.NORMAL ? in.readDouble() : 0; |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Double readDoubleNullable(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) && checkFlagNoHandles(DOUBLE) == Flag.NORMAL ? in.readDouble() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public double readDouble() throws BinaryObjectException { |
| return in.readDouble(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public double[] readDoubleArray(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readDoubleArray() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable double[] readDoubleArray(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readDoubleArray() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public double[] readDoubleArray() throws BinaryObjectException { |
| switch (checkFlag(DOUBLE_ARR)) { |
| case NORMAL: |
| return BinaryUtils.doReadDoubleArray(in); |
| |
| case HANDLE: |
| return readHandleField(); |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public BigDecimal readDecimal(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readDecimal() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable BigDecimal readDecimal(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readDecimal() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public BigDecimal readDecimal() throws BinaryObjectException { |
| return checkFlagNoHandles(DECIMAL) == Flag.NORMAL ? BinaryUtils.doReadDecimal(in) : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public BigDecimal[] readDecimalArray(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readDecimalArray() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable BigDecimal[] readDecimalArray(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readDecimalArray() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public BigDecimal[] readDecimalArray() throws BinaryObjectException { |
| switch (checkFlag(DECIMAL_ARR)) { |
| case NORMAL: |
| return BinaryUtils.doReadDecimalArray(in); |
| |
| case HANDLE: |
| return readHandleField(); |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public String readString(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readString() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable String readString(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readString() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public String readString() throws BinaryObjectException { |
| return checkFlagNoHandles(STRING) == Flag.NORMAL ? BinaryUtils.doReadString(in) : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public String[] readStringArray(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readStringArray() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable String[] readStringArray(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readStringArray() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public String[] readStringArray() throws BinaryObjectException { |
| switch (checkFlag(STRING_ARR)) { |
| case NORMAL: |
| return BinaryUtils.doReadStringArray(in); |
| |
| case HANDLE: |
| return readHandleField(); |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public UUID readUuid(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readUuid() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable UUID readUuid(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readUuid() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public UUID readUuid() throws BinaryObjectException { |
| return checkFlagNoHandles(UUID) == Flag.NORMAL ? BinaryUtils.doReadUuid(in) : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public UUID[] readUuidArray(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readUuidArray() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable UUID[] readUuidArray(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readUuidArray() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public UUID[] readUuidArray() throws BinaryObjectException { |
| switch (checkFlag(UUID_ARR)) { |
| case NORMAL: |
| return BinaryUtils.doReadUuidArray(in); |
| |
| case HANDLE: |
| return readHandleField(); |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public Date readDate(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readDate() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Date readDate(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readDate() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public Date readDate() throws BinaryObjectException { |
| return checkFlagNoHandles(DATE) == Flag.NORMAL ? BinaryUtils.doReadDate(in) : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public Date[] readDateArray(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readDateArray() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Date[] readDateArray(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readDateArray() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public Date[] readDateArray() throws BinaryObjectException { |
| switch (checkFlag(DATE_ARR)) { |
| case NORMAL: |
| return BinaryUtils.doReadDateArray(in); |
| |
| case HANDLE: |
| return readHandleField(); |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public Timestamp readTimestamp(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readTimestamp() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Timestamp readTimestamp(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readTimestamp() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public Timestamp readTimestamp() throws BinaryObjectException { |
| return checkFlagNoHandles(TIMESTAMP) == Flag.NORMAL ? BinaryUtils.doReadTimestamp(in) : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public Timestamp[] readTimestampArray(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readTimestampArray() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Timestamp[] readTimestampArray(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readTimestampArray() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public Timestamp[] readTimestampArray() throws BinaryObjectException { |
| switch (checkFlag(TIMESTAMP_ARR)) { |
| case NORMAL: |
| return BinaryUtils.doReadTimestampArray(in); |
| |
| case HANDLE: |
| return readHandleField(); |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public Time readTime(String fieldName) throws BinaryObjectException { |
| return findFieldByName(fieldName) ? this.readTime() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public Time readTime() throws BinaryObjectException { |
| return checkFlagNoHandles(TIME) == Flag.NORMAL ? BinaryUtils.doReadTime(in) : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public Time[] readTimeArray(String fieldName) throws BinaryObjectException { |
| return findFieldByName(fieldName) ? this.readTimeArray() : null; |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Time readTime(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readTime() : null; |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Time[] readTimeArray(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readTimeArray() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override @Nullable public Time[] readTimeArray() throws BinaryObjectException { |
| switch (checkFlag(TIME_ARR)) { |
| case NORMAL: |
| return BinaryUtils.doReadTimeArray(in); |
| case HANDLE: |
| return readHandleField(); |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @SuppressWarnings("unchecked") |
| @Nullable @Override public <T> T readObject(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? (T)BinaryUtils.doReadObject(in, ctx, ldr, this) : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Object readObject(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? BinaryUtils.doReadObject(in, ctx, ldr, this) : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public Object readObject() throws BinaryObjectException { |
| return BinaryUtils.doReadObject(in, ctx, ldr, this); |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public Object readObjectDetached() throws BinaryObjectException { |
| return BinaryUtils.unmarshal(in, ctx, ldr, this, true); |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public Object[] readObjectArray(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? this.readObjectArray() : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Object[] readObjectArray(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? this.readObjectArray() : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public Object[] readObjectArray() throws BinaryObjectException { |
| switch (checkFlag(OBJ_ARR)) { |
| case NORMAL: |
| return BinaryUtils.doReadObjectArray(in, ctx, ldr, this, true); |
| |
| case HANDLE: |
| return readHandleField(); |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public <T extends Enum<?>> T readEnum(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? (T)readEnum0(null) : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @param cls Class. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Enum<?> readEnum(int fieldId, @Nullable Class<?> cls) throws BinaryObjectException { |
| return findFieldById(fieldId) ? readEnum0(cls) : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public <T extends Enum<?>> T readEnum() throws BinaryObjectException { |
| return (T)readEnum0(null); |
| } |
| |
| /** |
| * Internal routine to read enum for named field. |
| * |
| * @param cls Class. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| private Enum<?> readEnum0(@Nullable Class<?> cls) throws BinaryObjectException { |
| if (checkFlagNoHandles(ENUM) == Flag.NORMAL) { |
| // Read class even if we know it in advance to set correct stream position. |
| Class<?> cls0 = BinaryUtils.doReadClass(in, ctx, ldr); |
| |
| if (cls == null) |
| cls = cls0; |
| |
| return BinaryUtils.doReadEnum(in, cls); |
| } |
| else |
| return null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public <T extends Enum<?>> T[] readEnumArray(String fieldName) |
| throws BinaryObjectException { |
| |
| try { |
| return findFieldByName(fieldName) ? (T[])readEnumArray0(null) : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Binary Enum |
| * @throws BinaryObjectException If failed. |
| */ |
| @Nullable BinaryEnumObjectImpl readBinaryEnum(int fieldId) throws BinaryObjectException { |
| return findFieldById(fieldId) ? BinaryUtils.doReadBinaryEnum(in, ctx) : null; |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @param cls Class. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Object[] readEnumArray(int fieldId, @Nullable Class<?> cls) throws BinaryObjectException { |
| return findFieldById(fieldId) ? readEnumArray0(cls) : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public <T extends Enum<?>> T[] readEnumArray() throws BinaryObjectException { |
| return (T[])readEnumArray0(null); |
| } |
| |
| /** |
| * Internal routine to read enum for named field. |
| * |
| * @param cls Class. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| private Object[] readEnumArray0(@Nullable Class<?> cls) throws BinaryObjectException { |
| switch (checkFlag(ENUM_ARR)) { |
| case NORMAL: |
| // Read class even if we know it in advance to set correct stream position. |
| Class<?> cls0 = BinaryUtils.doReadClass(in, ctx, ldr); |
| |
| if (cls == null) |
| cls = cls0; |
| |
| return BinaryUtils.doReadEnumArray(in, ctx, ldr, cls); |
| |
| case HANDLE: |
| return readHandleField(); |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public <T> Collection<T> readCollection(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? (Collection<T>)readCollection0(null) : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public <T> Collection<T> readCollection(String fieldName, BinaryCollectionFactory<T> factory) |
| throws BinaryObjectException { |
| |
| try { |
| return findFieldByName(fieldName) ? readCollection0(factory) : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @param factory Collection factory. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable <T> Collection<T> readCollection(int fieldId, @Nullable BinaryCollectionFactory<T> factory) |
| throws BinaryObjectException { |
| return findFieldById(fieldId) ? (Collection<T>)readCollection0(factory) : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public <T> Collection<T> readCollection() throws BinaryObjectException { |
| return readCollection0(null); |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public <T> Collection<T> readCollection(BinaryCollectionFactory<T> factory) |
| throws BinaryObjectException { |
| return readCollection0(factory); |
| } |
| |
| /** |
| * Internal read collection routine. |
| * |
| * @param factory Collection factory. |
| * @return Value. |
| * @throws BinaryObjectException If failed. |
| */ |
| private Collection readCollection0(@Nullable BinaryCollectionFactory factory) |
| throws BinaryObjectException { |
| switch (checkFlag(COL)) { |
| case NORMAL: |
| return (Collection)BinaryUtils.doReadCollection(in, ctx, ldr, this, true, factory); |
| |
| case HANDLE: { |
| int handlePos = BinaryUtils.positionForHandle(in) - in.readInt(); |
| |
| Object obj = getHandle(handlePos); |
| |
| if (obj == null) { |
| int retPos = in.position(); |
| |
| streamPosition(handlePos); |
| |
| obj = readCollection0(factory); |
| |
| streamPosition(retPos); |
| } |
| |
| return (Collection)obj; |
| } |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public <K, V> Map<K, V> readMap(String fieldName) throws BinaryObjectException { |
| try { |
| return findFieldByName(fieldName) ? (Map<K, V>)readMap0(null) : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public <K, V> Map<K, V> readMap(String fieldName, BinaryMapFactory<K, V> factory) |
| throws BinaryObjectException { |
| |
| try { |
| return findFieldByName(fieldName) ? readMap0(factory) : null; |
| } |
| catch (Exception ex) { |
| throw wrapFieldException(fieldName, ex); |
| } |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @param factory Factory. |
| * @return Value. |
| * @throws BinaryObjectException In case of error. |
| */ |
| @Nullable Map<?, ?> readMap(int fieldId, @Nullable BinaryMapFactory factory) throws BinaryObjectException { |
| return findFieldById(fieldId) ? readMap0(factory) : null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public <K, V> Map<K, V> readMap() throws BinaryObjectException { |
| return readMap0(null); |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public <K, V> Map<K, V> readMap(BinaryMapFactory<K, V> factory) |
| throws BinaryObjectException { |
| return readMap0(factory); |
| } |
| |
| /** |
| * Internal read map routine. |
| * |
| * @param factory Factory. |
| * @return Value. |
| * @throws BinaryObjectException If failed. |
| */ |
| private Map readMap0(@Nullable BinaryMapFactory factory) throws BinaryObjectException { |
| switch (checkFlag(MAP)) { |
| case NORMAL: |
| return (Map)BinaryUtils.doReadMap(in, ctx, ldr, this, true, factory); |
| |
| case HANDLE: { |
| int handlePos = BinaryUtils.positionForHandle(in) - in.readInt(); |
| |
| Object obj = getHandle(handlePos); |
| |
| if (obj == null) { |
| int retPos = in.position(); |
| |
| streamPosition(handlePos); |
| |
| obj = readMap0(factory); |
| |
| streamPosition(retPos); |
| } |
| |
| return (Map)obj; |
| } |
| |
| default: |
| return null; |
| } |
| } |
| |
| /** |
| * Ensure that type flag is either null, handle or contains expected value. |
| * |
| * @param expFlag Expected value. |
| * @return Flag mode. |
| * @throws BinaryObjectException If flag is neither null, nor handle or expected. |
| */ |
| private Flag checkFlag(byte expFlag) { |
| byte flag = in.readByte(); |
| |
| if (flag == expFlag) |
| return Flag.NORMAL; |
| else if (flag == NULL) |
| return Flag.NULL; |
| else if (flag == HANDLE) |
| return Flag.HANDLE; |
| |
| int pos = BinaryUtils.positionForHandle(in); |
| |
| throw new BinaryObjectException("Unexpected field type [pos=" + pos + ", expected=" + fieldFlagName(expFlag) + |
| ", actual=" + fieldFlagName(flag) + ']'); |
| } |
| |
| /** |
| * Ensure that type flag is either null or contains expected value. |
| * |
| * @param expFlag Expected value. |
| * @return Flag mode. |
| * @throws BinaryObjectException If flag is neither null, nor expected. |
| */ |
| private Flag checkFlagNoHandles(byte expFlag) { |
| byte flag = in.readByte(); |
| |
| if (flag == expFlag) |
| return Flag.NORMAL; |
| else if (flag == NULL) |
| return Flag.NULL; |
| |
| int pos = BinaryUtils.positionForHandle(in); |
| |
| throw new BinaryObjectException("Unexpected field type [pos=" + pos + ", expected=" + fieldFlagName(expFlag) + |
| ", actual=" + fieldFlagName(flag) + ']'); |
| } |
| |
| /** |
| * Gets a flag name |
| * |
| * @param flag a flag value |
| * @return string representation of the flag (type name, handle, else number) |
| */ |
| private String fieldFlagName(byte flag) { |
| String typeName = BinaryUtils.fieldTypeName(flag); |
| |
| return typeName == null ? String.valueOf(flag) : typeName; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public BinaryRawReader rawReader() { |
| if (!raw) { |
| streamPositionRandom(rawOff); |
| |
| raw = true; |
| |
| return this; |
| } |
| else |
| throw new BinaryObjectException("Method \"rawReader\" can be called only once."); |
| } |
| |
| /** |
| * @return Deserialized object. |
| * @throws BinaryObjectException If failed. |
| */ |
| @Nullable Object deserialize() throws BinaryObjectException { |
| String newName = ctx.configuration().getIgniteInstanceName(); |
| String oldName = IgniteUtils.setCurrentIgniteName(newName); |
| |
| try { |
| return deserialize0(); |
| } |
| finally { |
| IgniteUtils.restoreOldIgniteName(oldName, newName); |
| } |
| } |
| |
| /** |
| * @return Deserialized object. |
| * @throws BinaryObjectException If failed. |
| */ |
| @Nullable private Object deserialize0() throws BinaryObjectException { |
| Object obj; |
| |
| byte flag = in.readByte(); |
| |
| switch (flag) { |
| case NULL: |
| obj = null; |
| |
| break; |
| |
| case HANDLE: |
| int handlePos = start - in.readInt(); |
| |
| obj = getHandle(handlePos); |
| |
| if (obj == null) { |
| int retPos = in.position(); |
| |
| streamPosition(handlePos); |
| |
| obj = BinaryUtils.doReadObject(in, ctx, ldr, this); |
| |
| streamPosition(retPos); |
| } |
| |
| break; |
| |
| case OBJ: |
| if (desc == null) |
| desc = ctx.descriptorForTypeId(userType, typeId, ldr, true); |
| |
| streamPosition(dataStart); |
| |
| if (desc == null) |
| throw new BinaryInvalidTypeException("Unknown type ID: " + typeId); |
| |
| obj = desc.read(this); |
| |
| streamPosition(footerStart + footerLen); |
| |
| break; |
| |
| case BYTE: |
| obj = in.readByte(); |
| |
| break; |
| |
| case SHORT: |
| obj = in.readShort(); |
| |
| break; |
| |
| case INT: |
| obj = in.readInt(); |
| |
| break; |
| |
| case LONG: |
| obj = in.readLong(); |
| |
| break; |
| |
| case FLOAT: |
| obj = in.readFloat(); |
| |
| break; |
| |
| case DOUBLE: |
| obj = in.readDouble(); |
| |
| break; |
| |
| case CHAR: |
| obj = in.readChar(); |
| |
| break; |
| |
| case BOOLEAN: |
| obj = in.readBoolean(); |
| |
| break; |
| |
| case DECIMAL: |
| obj = BinaryUtils.doReadDecimal(in); |
| |
| break; |
| |
| case STRING: |
| obj = BinaryUtils.doReadString(in); |
| |
| break; |
| |
| case UUID: |
| obj = BinaryUtils.doReadUuid(in); |
| |
| break; |
| |
| case DATE: |
| obj = BinaryUtils.doReadDate(in); |
| |
| break; |
| |
| case TIMESTAMP: |
| obj = BinaryUtils.doReadTimestamp(in); |
| |
| break; |
| |
| case TIME: |
| obj = BinaryUtils.doReadTime(in); |
| |
| break; |
| |
| case BYTE_ARR: |
| obj = BinaryUtils.doReadByteArray(in); |
| |
| break; |
| |
| case SHORT_ARR: |
| obj = BinaryUtils.doReadShortArray(in); |
| |
| break; |
| |
| case INT_ARR: |
| obj = BinaryUtils.doReadIntArray(in); |
| |
| break; |
| |
| case LONG_ARR: |
| obj = BinaryUtils.doReadLongArray(in); |
| |
| break; |
| |
| case FLOAT_ARR: |
| obj = BinaryUtils.doReadFloatArray(in); |
| |
| break; |
| |
| case DOUBLE_ARR: |
| obj = BinaryUtils.doReadDoubleArray(in); |
| |
| break; |
| |
| case CHAR_ARR: |
| obj = BinaryUtils.doReadCharArray(in); |
| |
| break; |
| |
| case BOOLEAN_ARR: |
| obj = BinaryUtils.doReadBooleanArray(in); |
| |
| break; |
| |
| case DECIMAL_ARR: |
| obj = BinaryUtils.doReadDecimalArray(in); |
| |
| break; |
| |
| case STRING_ARR: |
| obj = BinaryUtils.doReadStringArray(in); |
| |
| break; |
| |
| case UUID_ARR: |
| obj = BinaryUtils.doReadUuidArray(in); |
| |
| break; |
| |
| case DATE_ARR: |
| obj = BinaryUtils.doReadDateArray(in); |
| |
| break; |
| |
| case TIMESTAMP_ARR: |
| obj = BinaryUtils.doReadTimestampArray(in); |
| |
| break; |
| |
| case TIME_ARR: |
| obj = BinaryUtils.doReadTimeArray(in); |
| |
| break; |
| |
| case OBJ_ARR: |
| obj = BinaryUtils.doReadObjectArray(in, ctx, ldr, this, true); |
| |
| break; |
| |
| case COL: |
| obj = BinaryUtils.doReadCollection(in, ctx, ldr, this, true, null); |
| |
| break; |
| |
| case MAP: |
| obj = BinaryUtils.doReadMap(in, ctx, ldr, this, true, null); |
| |
| break; |
| |
| case BINARY_OBJ: |
| obj = BinaryUtils.doReadBinaryObject(in, ctx, false); |
| |
| ((BinaryObjectImpl)obj).context(ctx); |
| |
| if (!GridBinaryMarshaller.KEEP_BINARIES.get()) |
| obj = ((BinaryObject)obj).deserialize(); |
| |
| break; |
| |
| case ENUM: |
| obj = BinaryUtils.doReadEnum(in, BinaryUtils.doReadClass(in, ctx, ldr)); |
| |
| break; |
| |
| case ENUM_ARR: |
| obj = BinaryUtils.doReadEnumArray(in, ctx, ldr, BinaryUtils.doReadClass(in, ctx, ldr)); |
| |
| break; |
| |
| case BINARY_ENUM: |
| obj = BinaryUtils.doReadBinaryEnum(in, ctx); |
| |
| if (!GridBinaryMarshaller.KEEP_BINARIES.get()) |
| obj = ((BinaryObject)obj).deserialize(); |
| |
| break; |
| |
| case CLASS: |
| obj = BinaryUtils.doReadClass(in, ctx, ldr); |
| |
| break; |
| |
| case PROXY: |
| obj = BinaryUtils.doReadProxy(in, ctx, ldr, this); |
| |
| break; |
| |
| case OPTM_MARSH: |
| obj = BinaryUtils.doReadOptimized(in, ctx, ldr); |
| |
| break; |
| |
| default: |
| throw new BinaryObjectException("Invalid flag value: " + flag); |
| } |
| |
| return obj; |
| } |
| |
| /** |
| * @param fieldId Field ID. |
| * @return Deserialized object. |
| * @throws BinaryObjectException If failed. |
| */ |
| @Nullable Object readField(int fieldId) throws BinaryObjectException { |
| if (!findFieldById(fieldId)) |
| return null; |
| |
| return new BinaryReaderExImpl(ctx, in, ldr, hnds, true).deserialize(); |
| } |
| |
| /** |
| * @param name Field name. |
| * @return Field offset. |
| */ |
| private int fieldId(String name) { |
| assert name != null; |
| |
| return mapper.fieldId(typeId, name); |
| } |
| |
| /** |
| * Get or create object schema. |
| * |
| * @return Schema. |
| */ |
| public BinarySchema getOrCreateSchema() { |
| BinarySchema schema = ctx.schemaRegistry(typeId).schema(schemaId); |
| |
| if (schema == null) { |
| if (fieldIdLen != BinaryUtils.FIELD_ID_LEN) { |
| BinaryTypeImpl type = (BinaryTypeImpl) ctx.metadata(typeId, schemaId); |
| |
| BinaryMetadata meta = type != null ? type.metadata() : null; |
| |
| if (type == null || meta == null) |
| throw new BinaryObjectException("Cannot find metadata for object with compact footer: " + |
| typeId); |
| |
| Collection<BinarySchema> existingSchemas = meta.schemas(); |
| |
| for (BinarySchema existingSchema : existingSchemas) { |
| if (schemaId == existingSchema.schemaId()) { |
| schema = existingSchema; |
| |
| break; |
| } |
| } |
| |
| if (schema == null) { |
| List<Integer> existingSchemaIds = new ArrayList<>(existingSchemas.size()); |
| |
| for (BinarySchema existingSchema : existingSchemas) |
| existingSchemaIds.add(existingSchema.schemaId()); |
| |
| |
| throw new BinaryObjectException("Cannot find schema for object with compact footer" + |
| " [typeName=" + type.typeName() + |
| ", typeId=" + typeId + |
| ", missingSchemaId=" + schemaId + |
| ", existingSchemaIds=" + existingSchemaIds + ']' |
| ); |
| } |
| } |
| else |
| schema = createSchema(); |
| |
| assert schema != null; |
| |
| ctx.schemaRegistry(typeId).addSchema(schemaId, schema); |
| } |
| |
| return schema; |
| } |
| |
| /** |
| * Create schema. |
| * |
| * @return Schema. |
| */ |
| private BinarySchema createSchema() { |
| assert fieldIdLen == BinaryUtils.FIELD_ID_LEN; |
| |
| BinarySchema.Builder builder = BinarySchema.Builder.newBuilder(); |
| |
| int searchPos = footerStart; |
| int searchEnd = searchPos + footerLen; |
| |
| while (searchPos < searchEnd) { |
| int fieldId = in.readIntPositioned(searchPos); |
| |
| builder.addField(fieldId); |
| |
| searchPos += BinaryUtils.FIELD_ID_LEN + fieldOffLen; |
| } |
| |
| return builder.build(); |
| } |
| |
| /** |
| * Try finding the field by name. |
| * |
| * @param name Field name. |
| * @return Offset. |
| */ |
| public boolean findFieldByName(String name) { |
| if (raw) |
| throw new BinaryObjectException("Failed to read named field because reader is in raw mode."); |
| |
| assert dataStart != start; |
| |
| if (footerLen == 0) |
| return false; |
| |
| if (userType) { |
| int order; |
| |
| if (matching) { |
| int expOrder = matchingOrder++; |
| |
| BinarySchema.Confirmation confirm = schema.confirmOrder(expOrder, name); |
| |
| switch (confirm) { |
| case CONFIRMED: |
| // The best case: got order without ID calculation and (ID -> order) lookup. |
| if (expOrder == 0) |
| // When we read the very first field, position is set to start, hence this re-positioning. |
| streamPosition(dataStart); |
| |
| return true; |
| |
| case REJECTED: |
| // Rejected, no more speculations are possible. Fallback to the slowest scenario. |
| matching = false; |
| |
| order = schema.order(fieldId(name)); |
| |
| break; |
| |
| default: |
| // Field name is not know for this order. Need to calculate ID and repeat speculation. |
| assert confirm == BinarySchema.Confirmation.CLARIFY; |
| |
| int id = fieldId(name); |
| int realId = schema.fieldId(expOrder); |
| |
| if (id == realId) { |
| // IDs matched, cache field name inside schema. |
| schema.clarifyFieldName(expOrder, name); |
| |
| if (expOrder == 0) |
| streamPosition(dataStart); |
| |
| return true; |
| } |
| else { |
| // No match, stop further speculations. |
| matching = false; |
| |
| order = schema.order(id); |
| } |
| |
| break; |
| } |
| } |
| else |
| order = schema.order(fieldId(name)); |
| |
| return trySetUserFieldPosition(order); |
| } |
| else |
| return trySetSystemFieldPosition(fieldId(name)); |
| } |
| |
| /** |
| * Try finding the field by ID. Used for types with stable schema (Serializable) to avoid |
| * (string -> ID) calculations. |
| * |
| * @param id Field ID. |
| * @return {@code True} if field was found and stream was positioned accordingly. |
| */ |
| private boolean findFieldById(int id) { |
| assert !raw; // Assert, not exception, because this is called only from internals for Serializable types. |
| assert dataStart != start; |
| |
| if (footerLen == 0) |
| return false; |
| |
| if (userType) { |
| int order; |
| |
| if (matching) { |
| // Trying to get field order speculatively. |
| int expOrder = matchingOrder++; |
| |
| int realId = schema.fieldId(expOrder); |
| |
| if (realId == id) { |
| if (expOrder == 0) |
| streamPosition(dataStart); |
| |
| return true; |
| } |
| else { |
| // Mismatch detected, no need for further speculations. |
| matching = false; |
| |
| order = schema.order(id); |
| } |
| } |
| else |
| order = schema.order(id); |
| |
| return trySetUserFieldPosition(order); |
| } |
| else |
| return trySetSystemFieldPosition(id); |
| } |
| |
| /** |
| * Set position for the given user field order. |
| * |
| * @param order Order. |
| * @return {@code True} if field was found and stream was positioned accordingly. |
| */ |
| private boolean trySetUserFieldPosition(int order) { |
| if (order != BinarySchema.ORDER_NOT_FOUND) { |
| int offsetPos = footerStart + order * (fieldIdLen + fieldOffLen) + fieldIdLen; |
| |
| int pos = start + BinaryUtils.fieldOffsetRelative(in, offsetPos, fieldOffLen); |
| |
| streamPosition(pos); |
| |
| return true; |
| } |
| else |
| return false; |
| } |
| |
| /** |
| * Set position for the given system field ID. |
| * |
| * @param id Field ID. |
| * @return {@code True} if field was found and stream was positioned accordingly. |
| */ |
| private boolean trySetSystemFieldPosition(int id) { |
| // System types are never written with compact footers because they do not have metadata. |
| assert fieldIdLen == BinaryUtils.FIELD_ID_LEN; |
| |
| int searchPos = footerStart; |
| int searchTail = searchPos + footerLen; |
| |
| while (true) { |
| if (searchPos >= searchTail) |
| return false; |
| |
| int id0 = in.readIntPositioned(searchPos); |
| |
| if (id0 == id) { |
| int pos = start + BinaryUtils.fieldOffsetRelative(in, searchPos + BinaryUtils.FIELD_ID_LEN, |
| fieldOffLen); |
| |
| streamPosition(pos); |
| |
| return true; |
| } |
| |
| searchPos += BinaryUtils.FIELD_ID_LEN + fieldOffLen; |
| } |
| } |
| |
| /** |
| * Set stream position. |
| * |
| * @param pos Position. |
| */ |
| private void streamPosition(int pos) { |
| in.position(pos); |
| } |
| |
| /** |
| * Set stream position as a part of some random read. Further speculations will be disabled after this call. |
| * |
| * @param pos Position. |
| */ |
| private void streamPositionRandom(int pos) { |
| streamPosition(pos); |
| |
| matching = false; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int readUnsignedByte() throws IOException { |
| return readByte() & 0xff; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int readUnsignedShort() throws IOException { |
| return readShort() & 0xffff; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public String readLine() throws IOException { |
| SB sb = new SB(); |
| |
| int b; |
| |
| while ((b = read()) >= 0) { |
| char c = (char)b; |
| |
| switch (c) { |
| case '\n': |
| return sb.toString(); |
| |
| case '\r': |
| b = read(); |
| |
| if (b < 0 || b == '\n') |
| return sb.toString(); |
| else |
| sb.a((char)b); |
| |
| break; |
| |
| default: |
| sb.a(c); |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| /** {@inheritDoc} */ |
| @SuppressWarnings("ConstantConditions") |
| @NotNull @Override public String readUTF() throws IOException { |
| return readString(); |
| } |
| |
| /** {@inheritDoc} */ |
| @SuppressWarnings("NullableProblems") |
| @Override public void readFully(byte[] b) throws IOException { |
| readFully(b, 0, b.length); |
| } |
| |
| /** {@inheritDoc} */ |
| @SuppressWarnings("NullableProblems") |
| @Override public void readFully(byte[] b, int off, int len) throws IOException { |
| int cnt = in.read(b, off, len); |
| |
| if (cnt < len) |
| throw new EOFException(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int skipBytes(int n) throws IOException { |
| int toSkip = Math.min(in.remaining(), n); |
| |
| streamPositionRandom(in.position() + toSkip); |
| |
| return toSkip; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int read() throws IOException { |
| return readByte(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int read(byte[] b) throws IOException { |
| return read(b, 0, b.length); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int read(byte[] b, int off, int len) throws IOException { |
| return in.read(b, off, len); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public long skip(long n) throws IOException { |
| return skipBytes((int) n); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int available() throws IOException { |
| return in.remaining(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void close() throws IOException { |
| // No-op. |
| } |
| |
| /** |
| * @return Binary context. |
| */ |
| public BinaryContext context() { |
| return ctx; |
| } |
| |
| /** |
| * Flag. |
| */ |
| private enum Flag { |
| /** Regular. */ |
| NORMAL, |
| |
| /** Handle. */ |
| HANDLE, |
| |
| /** Null. */ |
| NULL |
| } |
| } |