| /* |
| * 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.builder; |
| |
| import java.sql.Time; |
| import java.sql.Timestamp; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.Map; |
| import org.apache.ignite.binary.BinaryObjectException; |
| import org.apache.ignite.internal.binary.BinaryContext; |
| import org.apache.ignite.internal.binary.BinaryObjectImpl; |
| import org.apache.ignite.internal.binary.BinaryPositionReadable; |
| import org.apache.ignite.internal.binary.BinaryPrimitives; |
| import org.apache.ignite.internal.binary.BinaryReaderExImpl; |
| import org.apache.ignite.internal.binary.BinarySchema; |
| import org.apache.ignite.internal.binary.BinaryUtils; |
| import org.apache.ignite.internal.binary.BinaryWriterExImpl; |
| import org.apache.ignite.internal.binary.GridBinaryMarshaller; |
| import org.apache.ignite.internal.binary.streams.BinaryHeapInputStream; |
| import org.apache.ignite.internal.util.typedef.internal.U; |
| |
| import static java.nio.charset.StandardCharsets.UTF_8; |
| |
| /** |
| * |
| */ |
| public class BinaryBuilderReader implements BinaryPositionReadable { |
| /** */ |
| private final BinaryContext ctx; |
| |
| /** */ |
| private final byte[] arr; |
| |
| /** */ |
| private final BinaryReaderExImpl reader; |
| |
| /** */ |
| private final Map<Integer, BinaryObjectBuilderImpl> objMap; |
| |
| /** */ |
| private int pos; |
| |
| /** |
| * Constructor. |
| * |
| * @param objImpl Binary object |
| */ |
| BinaryBuilderReader(BinaryObjectImpl objImpl) { |
| ctx = objImpl.context(); |
| arr = objImpl.array(); |
| pos = objImpl.start(); |
| |
| reader = new BinaryReaderExImpl(ctx, |
| BinaryHeapInputStream.create(arr, pos), |
| ctx.configuration().getClassLoader(), |
| false); |
| |
| objMap = new HashMap<>(); |
| } |
| |
| /** |
| * Copying constructor. |
| * |
| * @param other Other reader. |
| * @param start Start position. |
| */ |
| BinaryBuilderReader(BinaryBuilderReader other, int start) { |
| this.ctx = other.ctx; |
| this.arr = other.arr; |
| this.pos = start; |
| |
| reader = new BinaryReaderExImpl(ctx, |
| BinaryHeapInputStream.create(arr, start), |
| null, |
| other.reader.handles(), |
| false); |
| |
| this.objMap = other.objMap; |
| } |
| |
| /** |
| * @return Binary context. |
| */ |
| public BinaryContext binaryContext() { |
| return ctx; |
| } |
| |
| /** |
| * @param obj Mutable binary object. |
| */ |
| public void registerObject(BinaryObjectBuilderImpl obj) { |
| objMap.put(obj.start(), obj); |
| } |
| |
| /** |
| * Get schema of the object, starting at the given position. |
| * |
| * @return Object's schema. |
| */ |
| public BinarySchema schema() { |
| return reader.getOrCreateSchema(); |
| } |
| |
| /** |
| * @return Read int value. |
| */ |
| public int readInt() { |
| int res = readInt(0); |
| |
| pos += 4; |
| |
| return res; |
| } |
| |
| /** |
| * @return Read int value. |
| */ |
| public byte readByte() { |
| return arr[pos++]; |
| } |
| |
| /** |
| * @return Read boolean value. |
| */ |
| public boolean readBoolean() { |
| return readByte() == 1; |
| } |
| |
| /** |
| * @return Read int value. |
| */ |
| public byte readByte(int off) { |
| return arr[pos + off]; |
| } |
| |
| /** |
| * @param off Offset related to {@link #pos} |
| * @return Read int value. |
| */ |
| public int readInt(int off) { |
| return BinaryPrimitives.readInt(arr, pos + off); |
| } |
| |
| /** |
| * @param pos Position in the source array. |
| * @return Read byte value. |
| */ |
| @Override public byte readBytePositioned(int pos) { |
| return BinaryPrimitives.readByte(arr, pos); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public short readShortPositioned(int pos) { |
| return BinaryPrimitives.readShort(arr, pos); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int readIntPositioned(int pos) { |
| return BinaryPrimitives.readInt(arr, pos); |
| } |
| |
| /** |
| * @return Read length of array. |
| */ |
| public int readLength() { |
| return BinaryPrimitives.readInt(arr, pos); |
| } |
| |
| /** |
| * Read string length. |
| * |
| * @return String length. |
| */ |
| public int readStringLength() { |
| return BinaryPrimitives.readInt(arr, pos); |
| } |
| |
| /** |
| * Reads string. |
| * |
| * @return String. |
| */ |
| public String readString() { |
| byte flag = readByte(); |
| |
| if (flag == GridBinaryMarshaller.NULL) |
| return null; |
| |
| if (flag != GridBinaryMarshaller.STRING) |
| throw new BinaryObjectException("Failed to deserialize String."); |
| |
| int len = readInt(); |
| |
| String str = new String(arr, pos, len, UTF_8); |
| |
| pos += len; |
| |
| return str; |
| } |
| |
| /** |
| * |
| */ |
| public void skipValue() { |
| byte type = arr[pos++]; |
| |
| int len; |
| |
| switch (type) { |
| case GridBinaryMarshaller.NULL: |
| return; |
| |
| case GridBinaryMarshaller.OBJ: |
| pos += readInt(GridBinaryMarshaller.TOTAL_LEN_POS - 1) - 1; |
| |
| return; |
| |
| case GridBinaryMarshaller.BOOLEAN: |
| case GridBinaryMarshaller.BYTE: |
| len = 1; |
| break; |
| |
| case GridBinaryMarshaller.CHAR: |
| case GridBinaryMarshaller.SHORT: |
| len = 2; |
| |
| break; |
| |
| case GridBinaryMarshaller.HANDLE: |
| case GridBinaryMarshaller.FLOAT: |
| case GridBinaryMarshaller.INT: |
| len = 4; |
| |
| break; |
| |
| case GridBinaryMarshaller.ENUM: |
| //skipping type id and ordinal value |
| len = 8; |
| |
| break; |
| |
| case GridBinaryMarshaller.LONG: |
| case GridBinaryMarshaller.DOUBLE: |
| len = 8; |
| |
| break; |
| |
| case GridBinaryMarshaller.BYTE_ARR: |
| case GridBinaryMarshaller.BOOLEAN_ARR: |
| len = 4 + readLength(); |
| |
| break; |
| |
| case GridBinaryMarshaller.STRING: |
| len = 4 + readStringLength(); |
| |
| break; |
| |
| case GridBinaryMarshaller.DECIMAL: |
| len = /** scale */ 4 + /** mag len */ 4 + /** mag bytes count */ readInt(4); |
| |
| break; |
| |
| case GridBinaryMarshaller.UUID: |
| len = 8 + 8; |
| |
| break; |
| |
| case GridBinaryMarshaller.DATE: |
| len = 8; |
| |
| break; |
| |
| case GridBinaryMarshaller.TIMESTAMP: |
| len = 8 + 4; |
| |
| break; |
| |
| case GridBinaryMarshaller.TIME: |
| len = 8; |
| |
| break; |
| |
| case GridBinaryMarshaller.CHAR_ARR: |
| case GridBinaryMarshaller.SHORT_ARR: |
| len = 4 + readLength() * 2; |
| |
| break; |
| |
| case GridBinaryMarshaller.INT_ARR: |
| case GridBinaryMarshaller.FLOAT_ARR: |
| len = 4 + readLength() * 4; |
| |
| break; |
| |
| case GridBinaryMarshaller.LONG_ARR: |
| case GridBinaryMarshaller.DOUBLE_ARR: |
| len = 4 + readLength() * 8; |
| |
| break; |
| |
| case GridBinaryMarshaller.DECIMAL_ARR: |
| case GridBinaryMarshaller.DATE_ARR: |
| case GridBinaryMarshaller.TIMESTAMP_ARR: |
| case GridBinaryMarshaller.TIME_ARR: |
| case GridBinaryMarshaller.OBJ_ARR: |
| case GridBinaryMarshaller.ENUM_ARR: |
| case GridBinaryMarshaller.UUID_ARR: |
| case GridBinaryMarshaller.STRING_ARR: { |
| int size = readInt(); |
| |
| for (int i = 0; i < size; i++) |
| skipValue(); |
| |
| return; |
| } |
| |
| case GridBinaryMarshaller.COL: { |
| int size = readInt(); |
| |
| pos++; // skip collection type |
| |
| for (int i = 0; i < size; i++) |
| skipValue(); |
| |
| return; |
| } |
| |
| case GridBinaryMarshaller.MAP: { |
| int size = readInt(); |
| |
| pos++; // skip collection type |
| |
| for (int i = 0; i < size; i++) { |
| skipValue(); // skip key. |
| skipValue(); // skip value. |
| } |
| |
| return; |
| } |
| |
| case GridBinaryMarshaller.BINARY_OBJ: |
| len = readInt() + 4; |
| |
| break; |
| |
| default: |
| throw new BinaryObjectException("Invalid flag value: " + type); |
| } |
| |
| pos += len; |
| } |
| |
| /** |
| * @param pos Position. |
| * @param len Length. |
| * @return Object. |
| */ |
| public Object getValueQuickly(int pos, int len) { |
| byte type = arr[pos]; |
| |
| switch (type) { |
| case GridBinaryMarshaller.NULL: |
| return null; |
| |
| case GridBinaryMarshaller.HANDLE: { |
| int objStart = pos - readIntPositioned(pos + 1); |
| |
| BinaryObjectBuilderImpl res = objMap.get(objStart); |
| |
| if (res == null) { |
| res = new BinaryObjectBuilderImpl(new BinaryBuilderReader(this, objStart), objStart); |
| |
| objMap.put(objStart, res); |
| } |
| |
| return res; |
| } |
| |
| case GridBinaryMarshaller.OBJ: { |
| BinaryObjectBuilderImpl res = objMap.get(pos); |
| |
| if (res == null) { |
| res = new BinaryObjectBuilderImpl(new BinaryBuilderReader(this, pos), pos); |
| |
| objMap.put(pos, res); |
| } |
| |
| return res; |
| } |
| |
| case GridBinaryMarshaller.BYTE: |
| return arr[pos + 1]; |
| |
| case GridBinaryMarshaller.SHORT: |
| return BinaryPrimitives.readShort(arr, pos + 1); |
| |
| case GridBinaryMarshaller.INT: |
| return BinaryPrimitives.readInt(arr, pos + 1); |
| |
| case GridBinaryMarshaller.LONG: |
| return BinaryPrimitives.readLong(arr, pos + 1); |
| |
| case GridBinaryMarshaller.FLOAT: |
| return BinaryPrimitives.readFloat(arr, pos + 1); |
| |
| case GridBinaryMarshaller.DOUBLE: |
| return BinaryPrimitives.readDouble(arr, pos + 1); |
| |
| case GridBinaryMarshaller.CHAR: |
| return BinaryPrimitives.readChar(arr, pos + 1); |
| |
| case GridBinaryMarshaller.BOOLEAN: |
| return arr[pos + 1] != 0; |
| |
| case GridBinaryMarshaller.DECIMAL: |
| case GridBinaryMarshaller.STRING: |
| case GridBinaryMarshaller.UUID: |
| case GridBinaryMarshaller.DATE: |
| case GridBinaryMarshaller.TIMESTAMP: |
| case GridBinaryMarshaller.TIME: |
| return new BinaryPlainLazyValue(this, pos, len); |
| |
| case GridBinaryMarshaller.BYTE_ARR: |
| case GridBinaryMarshaller.SHORT_ARR: |
| case GridBinaryMarshaller.INT_ARR: |
| case GridBinaryMarshaller.LONG_ARR: |
| case GridBinaryMarshaller.FLOAT_ARR: |
| case GridBinaryMarshaller.DOUBLE_ARR: |
| case GridBinaryMarshaller.CHAR_ARR: |
| case GridBinaryMarshaller.BOOLEAN_ARR: |
| case GridBinaryMarshaller.DECIMAL_ARR: |
| case GridBinaryMarshaller.DATE_ARR: |
| case GridBinaryMarshaller.TIMESTAMP_ARR: |
| case GridBinaryMarshaller.TIME_ARR: |
| case GridBinaryMarshaller.UUID_ARR: |
| case GridBinaryMarshaller.STRING_ARR: |
| case GridBinaryMarshaller.ENUM_ARR: |
| case GridBinaryMarshaller.OBJ_ARR: |
| case GridBinaryMarshaller.COL: |
| case GridBinaryMarshaller.MAP: |
| return new LazyCollection(pos); |
| |
| case GridBinaryMarshaller.ENUM: { |
| if (len == 1) { |
| assert readByte(pos) == GridBinaryMarshaller.NULL; |
| |
| return null; |
| } |
| |
| int mark = position(); |
| position(pos + 1); |
| |
| BinaryBuilderEnum builderEnum = new BinaryBuilderEnum(this); |
| |
| position(mark); |
| |
| return builderEnum; |
| } |
| |
| case GridBinaryMarshaller.BINARY_OBJ: { |
| int size = readIntPositioned(pos + 1); |
| |
| int start = readIntPositioned(pos + 4 + size); |
| |
| BinaryObjectImpl binaryObj = new BinaryObjectImpl(ctx, arr, pos + 4 + start); |
| |
| return new BinaryPlainBinaryObject(binaryObj); |
| } |
| |
| case GridBinaryMarshaller.OPTM_MARSH: { |
| final BinaryHeapInputStream bin = BinaryHeapInputStream.create(arr, pos + 1); |
| |
| final Object obj = BinaryUtils.doReadOptimized(bin, ctx, U.resolveClassLoader(ctx.configuration())); |
| |
| return obj; |
| } |
| |
| default: |
| throw new BinaryObjectException("Invalid flag value: " + type); |
| } |
| } |
| |
| /** |
| * @return Parsed value. |
| */ |
| public Object parseValue() { |
| int valPos = pos; |
| |
| byte type = arr[pos++]; |
| |
| int plainLazyValLen; |
| |
| boolean modifiableLazyVal = false; |
| |
| switch (type) { |
| case GridBinaryMarshaller.NULL: |
| return null; |
| |
| case GridBinaryMarshaller.HANDLE: { |
| int objStart = pos - 1 - readInt(); |
| |
| BinaryObjectBuilderImpl res = objMap.get(objStart); |
| |
| if (res == null) { |
| res = new BinaryObjectBuilderImpl(new BinaryBuilderReader(this, objStart), objStart); |
| |
| objMap.put(objStart, res); |
| } |
| |
| return res; |
| } |
| |
| case GridBinaryMarshaller.OBJ: { |
| pos--; |
| |
| BinaryObjectBuilderImpl res = objMap.get(pos); |
| |
| if (res == null) { |
| res = new BinaryObjectBuilderImpl(new BinaryBuilderReader(this, pos), pos); |
| |
| objMap.put(pos, res); |
| } |
| |
| pos += readInt(GridBinaryMarshaller.TOTAL_LEN_POS); |
| |
| return res; |
| } |
| |
| case GridBinaryMarshaller.BYTE: |
| return arr[pos++]; |
| |
| case GridBinaryMarshaller.SHORT: { |
| Object res = BinaryPrimitives.readShort(arr, pos); |
| pos += 2; |
| return res; |
| } |
| |
| case GridBinaryMarshaller.INT: |
| return readInt(); |
| |
| case GridBinaryMarshaller.LONG: |
| plainLazyValLen = 8; |
| |
| break; |
| |
| case GridBinaryMarshaller.FLOAT: |
| plainLazyValLen = 4; |
| |
| break; |
| |
| case GridBinaryMarshaller.DOUBLE: |
| plainLazyValLen = 8; |
| |
| break; |
| |
| case GridBinaryMarshaller.CHAR: |
| plainLazyValLen = 2; |
| |
| break; |
| |
| case GridBinaryMarshaller.BOOLEAN: |
| return arr[pos++] != 0; |
| |
| case GridBinaryMarshaller.DECIMAL: |
| plainLazyValLen = /** scale */ 4 + /** mag len */ 4 + /** mag bytes count */ readInt(4); |
| |
| break; |
| |
| case GridBinaryMarshaller.STRING: |
| plainLazyValLen = 4 + readStringLength(); |
| |
| break; |
| |
| case GridBinaryMarshaller.UUID: |
| plainLazyValLen = 8 + 8; |
| |
| break; |
| |
| case GridBinaryMarshaller.DATE: |
| plainLazyValLen = 8; |
| |
| break; |
| |
| case GridBinaryMarshaller.TIMESTAMP: |
| plainLazyValLen = 8 + 4; |
| |
| break; |
| |
| case GridBinaryMarshaller.TIME: |
| plainLazyValLen = 8; |
| |
| break; |
| |
| case GridBinaryMarshaller.BYTE_ARR: |
| plainLazyValLen = 4 + readLength(); |
| modifiableLazyVal = true; |
| |
| break; |
| |
| case GridBinaryMarshaller.SHORT_ARR: |
| plainLazyValLen = 4 + readLength() * 2; |
| modifiableLazyVal = true; |
| |
| break; |
| |
| case GridBinaryMarshaller.INT_ARR: |
| plainLazyValLen = 4 + readLength() * 4; |
| modifiableLazyVal = true; |
| |
| break; |
| |
| case GridBinaryMarshaller.LONG_ARR: |
| plainLazyValLen = 4 + readLength() * 8; |
| modifiableLazyVal = true; |
| |
| break; |
| |
| case GridBinaryMarshaller.FLOAT_ARR: |
| plainLazyValLen = 4 + readLength() * 4; |
| modifiableLazyVal = true; |
| |
| break; |
| |
| case GridBinaryMarshaller.DOUBLE_ARR: |
| plainLazyValLen = 4 + readLength() * 8; |
| modifiableLazyVal = true; |
| |
| break; |
| |
| case GridBinaryMarshaller.CHAR_ARR: |
| plainLazyValLen = 4 + readLength() * 2; |
| modifiableLazyVal = true; |
| |
| break; |
| |
| case GridBinaryMarshaller.BOOLEAN_ARR: |
| plainLazyValLen = 4 + readLength(); |
| modifiableLazyVal = true; |
| |
| break; |
| |
| case GridBinaryMarshaller.OBJ_ARR: |
| return new BinaryObjectArrayLazyValue(this); |
| |
| case GridBinaryMarshaller.DATE_ARR: { |
| int size = readInt(); |
| |
| Date[] res = new Date[size]; |
| |
| for (int i = 0; i < res.length; i++) { |
| byte flag = arr[pos++]; |
| |
| if (flag == GridBinaryMarshaller.NULL) continue; |
| |
| if (flag != GridBinaryMarshaller.DATE) |
| throw new BinaryObjectException("Invalid flag value: " + flag); |
| |
| long time = BinaryPrimitives.readLong(arr, pos); |
| |
| pos += 8; |
| |
| res[i] = new Date(time); |
| } |
| |
| return res; |
| } |
| |
| case GridBinaryMarshaller.TIMESTAMP_ARR: { |
| int size = readInt(); |
| |
| Timestamp[] res = new Timestamp[size]; |
| |
| for (int i = 0; i < res.length; i++) { |
| byte flag = arr[pos++]; |
| |
| if (flag == GridBinaryMarshaller.NULL) |
| continue; |
| |
| if (flag != GridBinaryMarshaller.TIMESTAMP) |
| throw new BinaryObjectException("Invalid flag value: " + flag); |
| |
| long time = BinaryPrimitives.readLong(arr, pos); |
| |
| pos += 8; |
| |
| int nano = BinaryPrimitives.readInt(arr, pos); |
| |
| pos += 4; |
| |
| Timestamp ts = new Timestamp(time); |
| |
| ts.setNanos(ts.getNanos() + nano); |
| |
| res[i] = ts; |
| } |
| |
| return res; |
| } |
| |
| case GridBinaryMarshaller.TIME_ARR: { |
| int size = readInt(); |
| |
| Time[] res = new Time[size]; |
| |
| for (int i = 0; i < res.length; i++) { |
| byte flag = arr[pos++]; |
| |
| if (flag == GridBinaryMarshaller.NULL) continue; |
| |
| if (flag != GridBinaryMarshaller.TIME) |
| throw new BinaryObjectException("Invalid flag value: " + flag); |
| |
| long time = BinaryPrimitives.readLong(arr, pos); |
| |
| pos += 8; |
| |
| res[i] = new Time(time); |
| } |
| |
| return res; |
| } |
| |
| case GridBinaryMarshaller.UUID_ARR: |
| case GridBinaryMarshaller.STRING_ARR: |
| case GridBinaryMarshaller.DECIMAL_ARR: { |
| int size = readInt(); |
| |
| for (int i = 0; i < size; i++) { |
| byte flag = arr[pos++]; |
| |
| if (flag == GridBinaryMarshaller.UUID) |
| pos += 8 + 8; |
| else if (flag == GridBinaryMarshaller.STRING) |
| pos += 4 + readStringLength(); |
| else if (flag == GridBinaryMarshaller.DECIMAL) { |
| pos += 4; // scale value |
| pos += 4 + readLength(); |
| } |
| else |
| assert flag == GridBinaryMarshaller.NULL; |
| } |
| |
| return new BinaryModifiableLazyValue(this, valPos, pos - valPos); |
| } |
| |
| case GridBinaryMarshaller.COL: { |
| int size = readInt(); |
| byte colType = arr[pos++]; |
| |
| switch (colType) { |
| case GridBinaryMarshaller.USER_COL: |
| case GridBinaryMarshaller.ARR_LIST: |
| return new BinaryLazyArrayList(this, size); |
| |
| case GridBinaryMarshaller.LINKED_LIST: |
| return new BinaryLazyLinkedList(this, size); |
| |
| case GridBinaryMarshaller.HASH_SET: |
| case GridBinaryMarshaller.LINKED_HASH_SET: |
| return new BinaryLazySet(this, size); |
| } |
| |
| throw new BinaryObjectException("Unknown collection type: " + colType); |
| } |
| |
| case GridBinaryMarshaller.MAP: |
| return BinaryLazyMap.parseMap(this); |
| |
| case GridBinaryMarshaller.ENUM: |
| return new BinaryBuilderEnum(this); |
| |
| case GridBinaryMarshaller.ENUM_ARR: |
| return new BinaryEnumArrayLazyValue(this); |
| |
| case GridBinaryMarshaller.BINARY_OBJ: { |
| int size = readInt(); |
| |
| pos += size; |
| |
| int start = readInt(); |
| |
| BinaryObjectImpl binaryObj = new BinaryObjectImpl(ctx, arr, |
| pos - 4 - size + start); |
| |
| return new BinaryPlainBinaryObject(binaryObj); |
| } |
| |
| case GridBinaryMarshaller.OPTM_MARSH: { |
| final BinaryHeapInputStream bin = BinaryHeapInputStream.create(arr, pos); |
| |
| final Object obj = BinaryUtils.doReadOptimized(bin, ctx, U.resolveClassLoader(ctx.configuration())); |
| |
| pos = bin.position(); |
| |
| return obj; |
| } |
| |
| default: |
| throw new BinaryObjectException("Invalid flag value: " + type); |
| } |
| |
| BinaryAbstractLazyValue res; |
| |
| if (modifiableLazyVal) |
| res = new BinaryModifiableLazyValue(this, valPos, 1 + plainLazyValLen); |
| else |
| res = new BinaryPlainLazyValue(this, valPos, 1 + plainLazyValLen); |
| |
| pos += plainLazyValLen; |
| |
| return res; |
| } |
| |
| /** |
| * @return Array. |
| */ |
| public byte[] array() { |
| return arr; |
| } |
| |
| /** |
| * @return Position of reader. |
| */ |
| public int position() { |
| return pos; |
| } |
| |
| /** |
| * @param pos New pos. |
| */ |
| public void position(int pos) { |
| this.pos = pos; |
| } |
| |
| /** |
| * @param n Number of bytes to skip. |
| */ |
| public void skip(int n) { |
| pos += n; |
| } |
| |
| /** |
| * @return Reader. |
| */ |
| BinaryReaderExImpl reader() { |
| return reader; |
| } |
| |
| /** |
| * |
| */ |
| private class LazyCollection implements BinaryLazyValue { |
| /** */ |
| private final int valOff; |
| |
| /** */ |
| private Object col; |
| |
| /** |
| * @param valOff Value. |
| */ |
| protected LazyCollection(int valOff) { |
| this.valOff = valOff; |
| } |
| |
| /** |
| * @return Object. |
| */ |
| private Object wrappedCollection() { |
| if (col == null) { |
| position(valOff); |
| |
| col = parseValue(); |
| } |
| |
| return col; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void writeTo(BinaryWriterExImpl writer, BinaryBuilderSerializer ctx) { |
| ctx.writeValue(writer, wrappedCollection()); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public Object value() { |
| return BinaryUtils.unwrapLazy(wrappedCollection()); |
| } |
| } |
| } |