/*
* 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.direct.stream.v1;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.UUID;
import org.apache.ignite.internal.direct.stream.DirectByteBufferStream;
import org.apache.ignite.internal.util.GridUnsafe;
import org.apache.ignite.internal.util.tostring.GridToStringExclude;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteUuid;
import org.apache.ignite.plugin.extensions.communication.Message;
import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
import org.apache.ignite.plugin.extensions.communication.MessageFactory;
import org.apache.ignite.plugin.extensions.communication.MessageReader;
import org.apache.ignite.plugin.extensions.communication.MessageWriter;
import sun.nio.ch.DirectBuffer;
/**
* Direct marshalling I/O stream (version 1).
*/
public class DirectByteBufferStreamImplV1 implements DirectByteBufferStream {
/** */
private static final byte[] BYTE_ARR_EMPTY = new byte[0];
/** */
private static final short[] SHORT_ARR_EMPTY = new short[0];
/** */
private static final int[] INT_ARR_EMPTY = U.EMPTY_INTS;
/** */
private static final long[] LONG_ARR_EMPTY = U.EMPTY_LONGS;
/** */
private static final float[] FLOAT_ARR_EMPTY = new float[0];
/** */
private static final double[] DOUBLE_ARR_EMPTY = new double[0];
/** */
private static final char[] CHAR_ARR_EMPTY = new char[0];
/** */
private static final boolean[] BOOLEAN_ARR_EMPTY = new boolean[0];
/** */
private static final ArrayCreator<byte[]> BYTE_ARR_CREATOR = new ArrayCreator<byte[]>() {
@Override public byte[] create(int len) {
assert len >= 0;
switch (len) {
case 0:
return BYTE_ARR_EMPTY;
default:
return new byte[len];
}
}
};
/** */
private static final ArrayCreator<short[]> SHORT_ARR_CREATOR = new ArrayCreator<short[]>() {
@Override public short[] create(int len) {
assert len >= 0;
switch (len) {
case 0:
return SHORT_ARR_EMPTY;
default:
return new short[len];
}
}
};
/** */
private static final ArrayCreator<int[]> INT_ARR_CREATOR = new ArrayCreator<int[]>() {
@Override public int[] create(int len) {
assert len >= 0;
switch (len) {
case 0:
return INT_ARR_EMPTY;
default:
return new int[len];
}
}
};
/** */
private static final ArrayCreator<long[]> LONG_ARR_CREATOR = new ArrayCreator<long[]>() {
@Override public long[] create(int len) {
assert len >= 0;
switch (len) {
case 0:
return LONG_ARR_EMPTY;
default:
return new long[len];
}
}
};
/** */
private static final ArrayCreator<float[]> FLOAT_ARR_CREATOR = new ArrayCreator<float[]>() {
@Override public float[] create(int len) {
assert len >= 0;
switch (len) {
case 0:
return FLOAT_ARR_EMPTY;
default:
return new float[len];
}
}
};
/** */
private static final ArrayCreator<double[]> DOUBLE_ARR_CREATOR = new ArrayCreator<double[]>() {
@Override public double[] create(int len) {
assert len >= 0;
switch (len) {
case 0:
return DOUBLE_ARR_EMPTY;
default:
return new double[len];
}
}
};
/** */
private static final ArrayCreator<char[]> CHAR_ARR_CREATOR = new ArrayCreator<char[]>() {
@Override public char[] create(int len) {
assert len >= 0;
switch (len) {
case 0:
return CHAR_ARR_EMPTY;
default:
return new char[len];
}
}
};
/** */
private static final ArrayCreator<boolean[]> BOOLEAN_ARR_CREATOR = new ArrayCreator<boolean[]>() {
@Override public boolean[] create(int len) {
assert len >= 0;
switch (len) {
case 0:
return BOOLEAN_ARR_EMPTY;
default:
return new boolean[len];
}
}
};
/** */
private static final Object NULL = new Object();
/** */
@GridToStringExclude
private final MessageFactory msgFactory;
/** */
private ByteBuffer buf;
/** */
private byte[] heapArr;
/** */
private long baseOff;
/** */
private int arrOff = -1;
/** */
private Object tmpArr;
/** */
private int tmpArrOff;
/** */
private int tmpArrBytes;
/** */
private boolean msgTypeDone;
/** */
private Message msg;
/** */
private Iterator<?> mapIt;
/** */
private Iterator<?> it;
/** */
private Iterator<?> arrIt;
/** */
private Object arrCur = NULL;
/** */
private Object mapCur = NULL;
/** */
private Object cur = NULL;
/** */
private boolean keyDone;
/** */
private int readSize = -1;
/** */
private int readItems;
/** */
private Object[] objArr;
/** */
private Collection<Object> col;
/** */
private Map<Object, Object> map;
/** */
private boolean lastFinished;
/**
* @param msgFactory Message factory.
*/
public DirectByteBufferStreamImplV1(MessageFactory msgFactory) {
this.msgFactory = msgFactory;
}
/** {@inheritDoc} */
@Override public void setBuffer(ByteBuffer buf) {
assert buf != null;
if (this.buf != buf) {
this.buf = buf;
heapArr = buf.isDirect() ? null : buf.array();
baseOff = buf.isDirect() ? ((DirectBuffer)buf).address() : GridUnsafe.BYTE_ARR_OFF;
}
}
/** {@inheritDoc} */
@Override public int remaining() {
return buf.remaining();
}
/** {@inheritDoc} */
@Override public boolean lastFinished() {
return lastFinished;
}
/** {@inheritDoc} */
@Override public void writeByte(byte val) {
lastFinished = buf.remaining() >= 1;
if (lastFinished) {
int pos = buf.position();
GridUnsafe.putByte(heapArr, baseOff + pos, val);
buf.position(pos + 1);
}
}
/** {@inheritDoc} */
@Override public void writeShort(short val) {
lastFinished = buf.remaining() >= 2;
if (lastFinished) {
int pos = buf.position();
GridUnsafe.putShort(heapArr, baseOff + pos, val);
buf.position(pos + 2);
}
}
/** {@inheritDoc} */
@Override public void writeInt(int val) {
lastFinished = buf.remaining() >= 4;
if (lastFinished) {
int pos = buf.position();
GridUnsafe.putInt(heapArr, baseOff + pos, val);
buf.position(pos + 4);
}
}
/** {@inheritDoc} */
@Override public void writeLong(long val) {
lastFinished = buf.remaining() >= 8;
if (lastFinished) {
int pos = buf.position();
GridUnsafe.putLong(heapArr, baseOff + pos, val);
buf.position(pos + 8);
}
}
/**
* @param val Value.
*/
@Override public void writeFloat(float val) {
lastFinished = buf.remaining() >= 4;
if (lastFinished) {
int pos = buf.position();
GridUnsafe.putFloat(heapArr, baseOff + pos, val);
buf.position(pos + 4);
}
}
/** {@inheritDoc} */
@Override public void writeDouble(double val) {
lastFinished = buf.remaining() >= 8;
if (lastFinished) {
int pos = buf.position();
GridUnsafe.putDouble(heapArr, baseOff + pos, val);
buf.position(pos + 8);
}
}
/** {@inheritDoc} */
@Override public void writeChar(char val) {
lastFinished = buf.remaining() >= 2;
if (lastFinished) {
int pos = buf.position();
GridUnsafe.putChar(heapArr, baseOff + pos, val);
buf.position(pos + 2);
}
}
/** {@inheritDoc} */
@Override public void writeBoolean(boolean val) {
lastFinished = buf.remaining() >= 1;
if (lastFinished) {
int pos = buf.position();
GridUnsafe.putBoolean(heapArr, baseOff + pos, val);
buf.position(pos + 1);
}
}
/** {@inheritDoc} */
@Override public void writeByteArray(byte[] val) {
if (val != null)
lastFinished = writeArray(val, GridUnsafe.BYTE_ARR_OFF, val.length, val.length);
else
writeInt(-1);
}
/** {@inheritDoc} */
@Override public void writeByteArray(byte[] val, long off, int len) {
if (val != null)
lastFinished = writeArray(val, GridUnsafe.BYTE_ARR_OFF + off, len, len);
else
writeInt(-1);
}
/** {@inheritDoc} */
@Override public void writeShortArray(short[] val) {
if (val != null)
lastFinished = writeArray(val, GridUnsafe.SHORT_ARR_OFF, val.length, val.length << 1);
else
writeInt(-1);
}
/** {@inheritDoc} */
@Override public void writeIntArray(int[] val) {
if (val != null)
lastFinished = writeArray(val, GridUnsafe.INT_ARR_OFF, val.length, val.length << 2);
else
writeInt(-1);
}
/** {@inheritDoc} */
@Override public void writeLongArray(long[] val) {
if (val != null)
lastFinished = writeArray(val, GridUnsafe.LONG_ARR_OFF, val.length, val.length << 3);
else
writeInt(-1);
}
/** {@inheritDoc} */
@Override public void writeFloatArray(float[] val) {
if (val != null)
lastFinished = writeArray(val, GridUnsafe.FLOAT_ARR_OFF, val.length, val.length << 2);
else
writeInt(-1);
}
/** {@inheritDoc} */
@Override public void writeDoubleArray(double[] val) {
if (val != null)
lastFinished = writeArray(val, GridUnsafe.DOUBLE_ARR_OFF, val.length, val.length << 3);
else
writeInt(-1);
}
/** {@inheritDoc} */
@Override public void writeCharArray(char[] val) {
if (val != null)
lastFinished = writeArray(val, GridUnsafe.CHAR_ARR_OFF, val.length, val.length << 1);
else
writeInt(-1);
}
/** {@inheritDoc} */
@Override public void writeBooleanArray(boolean[] val) {
if (val != null)
lastFinished = writeArray(val, GridUnsafe.BOOLEAN_ARR_OFF, val.length, val.length);
else
writeInt(-1);
}
/** {@inheritDoc} */
@Override public void writeString(String val) {
writeByteArray(val != null ? val.getBytes() : null);
}
/** {@inheritDoc} */
@Override public void writeBitSet(BitSet val) {
writeLongArray(val != null ? val.toLongArray() : null);
}
/** {@inheritDoc} */
@Override public void writeUuid(UUID val) {
writeByteArray(val != null ? U.uuidToBytes(val) : null);
}
/** {@inheritDoc} */
@Override public void writeIgniteUuid(IgniteUuid val) {
writeByteArray(val != null ? U.igniteUuidToBytes(val) : null);
}
/** {@inheritDoc} */
@Override public void writeMessage(Message msg, MessageWriter writer) {
if (msg != null) {
if (buf.hasRemaining()) {
try {
writer.beforeInnerMessageWrite();
writer.setCurrentWriteClass(msg.getClass());
lastFinished = msg.writeTo(buf, writer);
}
finally {
writer.afterInnerMessageWrite(lastFinished);
}
}
else
lastFinished = false;
}
else
writeShort(Short.MIN_VALUE);
}
/** {@inheritDoc} */
@Override public <T> void writeObjectArray(T[] arr, MessageCollectionItemType itemType, MessageWriter writer) {
if (arr != null) {
if (arrIt == null) {
writeInt(arr.length);
if (!lastFinished)
return;
arrIt = arrayIterator(arr);
}
while (arrIt.hasNext() || arrCur != NULL) {
if (arrCur == NULL)
arrCur = arrIt.next();
write(itemType, arrCur, writer);
if (!lastFinished)
return;
arrCur = NULL;
}
arrIt = null;
}
else
writeInt(-1);
}
/** {@inheritDoc} */
@Override public <T> void writeCollection(Collection<T> col, MessageCollectionItemType itemType,
MessageWriter writer) {
if (col != null) {
if (it == null) {
writeInt(col.size());
if (!lastFinished)
return;
it = col.iterator();
}
while (it.hasNext() || cur != NULL) {
if (cur == NULL)
cur = it.next();
write(itemType, cur, writer);
if (!lastFinished)
return;
cur = NULL;
}
it = null;
}
else
writeInt(-1);
}
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override public <K, V> void writeMap(Map<K, V> map, MessageCollectionItemType keyType,
MessageCollectionItemType valType, MessageWriter writer) {
if (map != null) {
if (mapIt == null) {
writeInt(map.size());
if (!lastFinished)
return;
mapIt = map.entrySet().iterator();
}
while (mapIt.hasNext() || mapCur != NULL) {
Map.Entry<K, V> e;
if (mapCur == NULL)
mapCur = mapIt.next();
e = (Map.Entry<K, V>)mapCur;
if (!keyDone) {
write(keyType, e.getKey(), writer);
if (!lastFinished)
return;
keyDone = true;
}
write(valType, e.getValue(), writer);
if (!lastFinished)
return;
mapCur = NULL;
keyDone = false;
}
mapIt = null;
}
else
writeInt(-1);
}
/** {@inheritDoc} */
@Override public byte readByte() {
lastFinished = buf.remaining() >= 1;
if (lastFinished) {
int pos = buf.position();
buf.position(pos + 1);
return GridUnsafe.getByte(heapArr, baseOff + pos);
}
else
return 0;
}
/** {@inheritDoc} */
@Override public short readShort() {
lastFinished = buf.remaining() >= 2;
if (lastFinished) {
int pos = buf.position();
buf.position(pos + 2);
return GridUnsafe.getShort(heapArr, baseOff + pos);
}
else
return 0;
}
/** {@inheritDoc} */
@Override public int readInt() {
lastFinished = buf.remaining() >= 4;
if (lastFinished) {
int pos = buf.position();
buf.position(pos + 4);
return GridUnsafe.getInt(heapArr, baseOff + pos);
}
else
return 0;
}
/** {@inheritDoc} */
@Override public long readLong() {
lastFinished = buf.remaining() >= 8;
if (lastFinished) {
int pos = buf.position();
buf.position(pos + 8);
return GridUnsafe.getLong(heapArr, baseOff + pos);
}
else
return 0;
}
/** {@inheritDoc} */
@Override public float readFloat() {
lastFinished = buf.remaining() >= 4;
if (lastFinished) {
int pos = buf.position();
buf.position(pos + 4);
return GridUnsafe.getFloat(heapArr, baseOff + pos);
}
else
return 0;
}
/** {@inheritDoc} */
@Override public double readDouble() {
lastFinished = buf.remaining() >= 8;
if (lastFinished) {
int pos = buf.position();
buf.position(pos + 8);
return GridUnsafe.getDouble(heapArr, baseOff + pos);
}
else
return 0;
}
/** {@inheritDoc} */
@Override public char readChar() {
lastFinished = buf.remaining() >= 2;
if (lastFinished) {
int pos = buf.position();
buf.position(pos + 2);
return GridUnsafe.getChar(heapArr, baseOff + pos);
}
else
return 0;
}
/** {@inheritDoc} */
@Override public boolean readBoolean() {
lastFinished = buf.hasRemaining();
if (lastFinished) {
int pos = buf.position();
buf.position(pos + 1);
return GridUnsafe.getBoolean(heapArr, baseOff + pos);
}
else
return false;
}
/** {@inheritDoc} */
@Override public byte[] readByteArray() {
return readArray(BYTE_ARR_CREATOR, 0, GridUnsafe.BYTE_ARR_OFF);
}
/** {@inheritDoc} */
@Override public short[] readShortArray() {
return readArray(SHORT_ARR_CREATOR, 1, GridUnsafe.SHORT_ARR_OFF);
}
/** {@inheritDoc} */
@Override public int[] readIntArray() {
return readArray(INT_ARR_CREATOR, 2, GridUnsafe.INT_ARR_OFF);
}
/** {@inheritDoc} */
@Override public long[] readLongArray() {
return readArray(LONG_ARR_CREATOR, 3, GridUnsafe.LONG_ARR_OFF);
}
/** {@inheritDoc} */
@Override public float[] readFloatArray() {
return readArray(FLOAT_ARR_CREATOR, 2, GridUnsafe.FLOAT_ARR_OFF);
}
/** {@inheritDoc} */
@Override public double[] readDoubleArray() {
return readArray(DOUBLE_ARR_CREATOR, 3, GridUnsafe.DOUBLE_ARR_OFF);
}
/** {@inheritDoc} */
@Override public char[] readCharArray() {
return readArray(CHAR_ARR_CREATOR, 1, GridUnsafe.CHAR_ARR_OFF);
}
/** {@inheritDoc} */
@Override public boolean[] readBooleanArray() {
return readArray(BOOLEAN_ARR_CREATOR, 0, GridUnsafe.BOOLEAN_ARR_OFF);
}
/** {@inheritDoc} */
@Override public String readString() {
byte[] arr = readByteArray();
return arr != null ? new String(arr) : null;
}
/** {@inheritDoc} */
@Override public BitSet readBitSet() {
long[] arr = readLongArray();
return arr != null ? BitSet.valueOf(arr) : null;
}
/** {@inheritDoc} */
@Override public UUID readUuid() {
byte[] arr = readByteArray();
return arr != null ? U.bytesToUuid(arr, 0) : null;
}
/** {@inheritDoc} */
@Override public IgniteUuid readIgniteUuid() {
byte[] arr = readByteArray();
return arr != null ? U.bytesToIgniteUuid(arr, 0) : null;
}
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override public <T extends Message> T readMessage(MessageReader reader) {
if (!msgTypeDone) {
if (buf.remaining() < Message.DIRECT_TYPE_SIZE) {
lastFinished = false;
return null;
}
short type = readShort();
msg = type == Short.MIN_VALUE ? null : msgFactory.create(type);
msgTypeDone = true;
}
if (msg != null) {
try {
reader.beforeInnerMessageRead();
reader.setCurrentReadClass(msg.getClass());
lastFinished = msg.readFrom(buf, reader);
}
finally {
reader.afterInnerMessageRead(lastFinished);
}
}
else
lastFinished = true;
if (lastFinished) {
Message msg0 = msg;
msgTypeDone = false;
msg = null;
return (T)msg0;
}
else
return null;
}
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override public <T> T[] readObjectArray(MessageCollectionItemType itemType, Class<T> itemCls,
MessageReader reader) {
if (readSize == -1) {
int size = readInt();
if (!lastFinished)
return null;
readSize = size;
}
if (readSize >= 0) {
if (objArr == null)
objArr = itemCls != null ? (Object[])Array.newInstance(itemCls, readSize) : new Object[readSize];
for (int i = readItems; i < readSize; i++) {
Object item = read(itemType, reader);
if (!lastFinished)
return null;
objArr[i] = item;
readItems++;
}
}
readSize = -1;
readItems = 0;
cur = null;
T[] objArr0 = (T[])objArr;
objArr = null;
return objArr0;
}
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override public <C extends Collection<?>> C readCollection(MessageCollectionItemType itemType,
MessageReader reader) {
if (readSize == -1) {
int size = readInt();
if (!lastFinished)
return null;
readSize = size;
}
if (readSize >= 0) {
if (col == null)
col = new ArrayList<>(readSize);
for (int i = readItems; i < readSize; i++) {
Object item = read(itemType, reader);
if (!lastFinished)
return null;
col.add(item);
readItems++;
}
}
readSize = -1;
readItems = 0;
cur = null;
C col0 = (C)col;
col = null;
return col0;
}
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override public <M extends Map<?, ?>> M readMap(MessageCollectionItemType keyType,
MessageCollectionItemType valType, boolean linked, MessageReader reader) {
if (readSize == -1) {
int size = readInt();
if (!lastFinished)
return null;
readSize = size;
}
if (readSize >= 0) {
if (map == null)
map = linked ? U.newLinkedHashMap(readSize) : U.newHashMap(readSize);
for (int i = readItems; i < readSize; i++) {
if (!keyDone) {
Object key = read(keyType, reader);
if (!lastFinished)
return null;
mapCur = key;
keyDone = true;
}
Object val = read(valType, reader);
if (!lastFinished)
return null;
map.put(mapCur, val);
keyDone = false;
readItems++;
}
}
readSize = -1;
readItems = 0;
mapCur = null;
M map0 = (M)map;
map = null;
return map0;
}
/**
* @param arr Array.
* @param off Offset.
* @param len Length.
* @param bytes Length in bytes.
* @return Whether array was fully written
*/
private boolean writeArray(Object arr, long off, int len, int bytes) {
assert arr != null;
assert arr.getClass().isArray() && arr.getClass().getComponentType().isPrimitive();
assert off > 0;
assert len >= 0;
assert bytes >= 0;
assert bytes >= arrOff;
if (arrOff == -1) {
if (buf.remaining() < 4)
return false;
writeInt(len);
arrOff = 0;
}
int toWrite = bytes - arrOff;
int pos = buf.position();
int remaining = buf.remaining();
if (toWrite <= remaining) {
GridUnsafe.copyMemory(arr, off + arrOff, heapArr, baseOff + pos, toWrite);
pos += toWrite;
buf.position(pos);
arrOff = -1;
return true;
}
else {
GridUnsafe.copyMemory(arr, off + arrOff, heapArr, baseOff + pos, remaining);
pos += remaining;
buf.position(pos);
arrOff += remaining;
return false;
}
}
/**
* @param creator Array creator.
* @param lenShift Array length shift size.
* @param off Base offset.
* @return Array or special value if it was not fully read.
*/
@SuppressWarnings("unchecked")
private <T> T readArray(ArrayCreator<T> creator, int lenShift, long off) {
assert creator != null;
if (tmpArr == null) {
if (buf.remaining() < 4) {
lastFinished = false;
return null;
}
int len = readInt();
switch (len) {
case -1:
lastFinished = true;
return null;
case 0:
lastFinished = true;
return creator.create(0);
default:
tmpArr = creator.create(len);
tmpArrBytes = len << lenShift;
}
}
int toRead = tmpArrBytes - tmpArrOff;
int remaining = buf.remaining();
int pos = buf.position();
lastFinished = toRead <= remaining;
if (lastFinished) {
GridUnsafe.copyMemory(heapArr, baseOff + pos, tmpArr, off + tmpArrOff, toRead);
buf.position(pos + toRead);
T arr = (T)tmpArr;
tmpArr = null;
tmpArrBytes = 0;
tmpArrOff = 0;
return arr;
}
else {
GridUnsafe.copyMemory(heapArr, baseOff + pos, tmpArr, off + tmpArrOff, remaining);
buf.position(pos + remaining);
tmpArrOff += remaining;
return null;
}
}
/**
* @param type Type.
* @param val Value.
* @param writer Writer.
*/
private void write(MessageCollectionItemType type, Object val, MessageWriter writer) {
switch (type) {
case BYTE:
writeByte((Byte)val);
break;
case SHORT:
writeShort((Short)val);
break;
case INT:
writeInt((Integer)val);
break;
case LONG:
writeLong((Long)val);
break;
case FLOAT:
writeFloat((Float)val);
break;
case DOUBLE:
writeDouble((Double)val);
break;
case CHAR:
writeChar((Character)val);
break;
case BOOLEAN:
writeBoolean((Boolean)val);
break;
case BYTE_ARR:
writeByteArray((byte[])val);
break;
case SHORT_ARR:
writeShortArray((short[])val);
break;
case INT_ARR:
writeIntArray((int[])val);
break;
case LONG_ARR:
writeLongArray((long[])val);
break;
case FLOAT_ARR:
writeFloatArray((float[])val);
break;
case DOUBLE_ARR:
writeDoubleArray((double[])val);
break;
case CHAR_ARR:
writeCharArray((char[])val);
break;
case BOOLEAN_ARR:
writeBooleanArray((boolean[])val);
break;
case STRING:
writeString((String)val);
break;
case BIT_SET:
writeBitSet((BitSet)val);
break;
case UUID:
writeUuid((UUID)val);
break;
case IGNITE_UUID:
writeIgniteUuid((IgniteUuid)val);
break;
case MSG:
try {
if (val != null)
writer.beforeInnerMessageWrite();
writeMessage((Message)val, writer);
}
finally {
if (val != null)
writer.afterInnerMessageWrite(lastFinished);
}
break;
default:
throw new IllegalArgumentException("Unknown type: " + type);
}
}
/**
* @param type Type.
* @param reader Reader.
* @return Value.
*/
private Object read(MessageCollectionItemType type, MessageReader reader) {
switch (type) {
case BYTE:
return readByte();
case SHORT:
return readShort();
case INT:
return readInt();
case LONG:
return readLong();
case FLOAT:
return readFloat();
case DOUBLE:
return readDouble();
case CHAR:
return readChar();
case BOOLEAN:
return readBoolean();
case BYTE_ARR:
return readByteArray();
case SHORT_ARR:
return readShortArray();
case INT_ARR:
return readIntArray();
case LONG_ARR:
return readLongArray();
case FLOAT_ARR:
return readFloatArray();
case DOUBLE_ARR:
return readDoubleArray();
case CHAR_ARR:
return readCharArray();
case BOOLEAN_ARR:
return readBooleanArray();
case STRING:
return readString();
case BIT_SET:
return readBitSet();
case UUID:
return readUuid();
case IGNITE_UUID:
return readIgniteUuid();
case MSG:
return readMessage(reader);
default:
throw new IllegalArgumentException("Unknown type: " + type);
}
}
/**
* @param arr Array.
* @return Array iterator.
*/
private Iterator<?> arrayIterator(final Object[] arr) {
return new Iterator<Object>() {
private int idx;
@Override public boolean hasNext() {
return idx < arr.length;
}
@Override public Object next() {
if (!hasNext())
throw new NoSuchElementException();
return arr[idx++];
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
};
}
/** {@inheritDoc} */
public String toString() {
return S.toString(DirectByteBufferStreamImplV1.class, this);
}
/**
* Array creator.
*/
private interface ArrayCreator<T> {
/**
* @param len Array length or {@code -1} if array was not fully read.
* @return New array.
*/
public T create(int len);
}
}